diff options
Diffstat (limited to 'board')
54 files changed, 6119 insertions, 396 deletions
diff --git a/board/amcc/yellowstone/yellowstone.c b/board/amcc/yellowstone/yellowstone.c index 20965c8..86d0db7 100644 --- a/board/amcc/yellowstone/yellowstone.c +++ b/board/amcc/yellowstone/yellowstone.c @@ -79,8 +79,8 @@ int board_early_init_f(void) out32(GPIO1_ISR2L, in32(GPIO1_ISR2L) | 0x00010000); /* external interrupts IRQ0...3 */ - out32(GPIO1_TCR, in32(GPIO1_TCR) & ~0x0f000000); - out32(GPIO1_TSRL, in32(GPIO1_TSRL) & ~0x00005500); + out32(GPIO1_TCR, in32(GPIO1_TCR) & ~0x00f00000); + out32(GPIO1_TSRL, in32(GPIO1_TSRL) & ~0x0000ff00); out32(GPIO1_ISR1L, in32(GPIO1_ISR1L) | 0x00005500); #if 0 /* test-only */ diff --git a/board/amcc/yosemite/yosemite.c b/board/amcc/yosemite/yosemite.c index 392d0dc..6742441 100644 --- a/board/amcc/yosemite/yosemite.c +++ b/board/amcc/yosemite/yosemite.c @@ -79,8 +79,8 @@ int board_early_init_f(void) out32(GPIO1_ISR2L, in32(GPIO1_ISR2L) | 0x00010000); /* external interrupts IRQ0...3 */ - out32(GPIO1_TCR, in32(GPIO1_TCR) & ~0x0f000000); - out32(GPIO1_TSRL, in32(GPIO1_TSRL) & ~0x00005500); + out32(GPIO1_TCR, in32(GPIO1_TCR) & ~0x00f00000); + out32(GPIO1_TSRL, in32(GPIO1_TSRL) & ~0x0000ff00); out32(GPIO1_ISR1L, in32(GPIO1_ISR1L) | 0x00005500); /*setup USB 2.0 */ diff --git a/board/mpc8349ads/Makefile b/board/bc3450/Makefile index f865f9c..4dec44f 100644 --- a/board/mpc8349ads/Makefile +++ b/board/bc3450/Makefile @@ -1,5 +1,6 @@ # -# Copyright 2004 Freescale Semiconductor, Inc. +# (C) Copyright 2003-2004 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. # # See file CREDITS for list of people who contributed to this # project. @@ -24,7 +25,7 @@ include $(TOPDIR)/config.mk LIB = lib$(BOARD).a -OBJS := $(BOARD).o pci.o +OBJS := $(BOARD).o cmd_bc3450.o $(LIB): $(OBJS) $(SOBJS) $(AR) crv $@ $(OBJS) diff --git a/board/bc3450/bc3450.c b/board/bc3450/bc3450.c new file mode 100644 index 0000000..0d86518 --- /dev/null +++ b/board/bc3450/bc3450.c @@ -0,0 +1,672 @@ +/* + * (C) Copyright 2003-2004 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * (C) Copyright 2004 + * Mark Jonas, Freescale Semiconductor, mark.jonas@motorola.com. + * + * (C) Copyright 2004-2005 + * Martin Krause, TQ-Systems GmbH, martin.krause@tqs.de + * + * (C) Copyright 2006 + * Stefan Strobl, GERSYS GmbH, stefan.strobl@gersys.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 <mpc5xxx.h> +#include <pci.h> + +#ifdef CONFIG_VIDEO_SM501 +#include <sm501.h> +#endif + +#if defined(CONFIG_MPC5200_DDR) +#include "mt46v16m16-75.h" +#else +#include "mt48lc16m16a2-75.h" +#endif + +#ifdef CONFIG_RTC_MPC5200 +#include <rtc.h> +#endif + +#ifdef CONFIG_PS2MULT +void ps2mult_early_init(void); +#endif + +#ifndef CFG_RAMBOOT +static void sdram_start (int hi_addr) +{ + long hi_addr_bit = hi_addr ? 0x01000000 : 0; + + /* unlock mode register */ + *(vu_long *)MPC5XXX_SDRAM_CTRL = SDRAM_CONTROL | 0x80000000 | + hi_addr_bit; + __asm__ volatile ("sync"); + + /* precharge all banks */ + *(vu_long *)MPC5XXX_SDRAM_CTRL = SDRAM_CONTROL | 0x80000002 | + hi_addr_bit; + __asm__ volatile ("sync"); + +#if SDRAM_DDR + /* set mode register: extended mode */ + *(vu_long *)MPC5XXX_SDRAM_MODE = SDRAM_EMODE; + __asm__ volatile ("sync"); + + /* set mode register: reset DLL */ + *(vu_long *)MPC5XXX_SDRAM_MODE = SDRAM_MODE | 0x04000000; + __asm__ volatile ("sync"); +#endif + + /* precharge all banks */ + *(vu_long *)MPC5XXX_SDRAM_CTRL = SDRAM_CONTROL | 0x80000002 | + hi_addr_bit; + __asm__ volatile ("sync"); + + /* auto refresh */ + *(vu_long *)MPC5XXX_SDRAM_CTRL = SDRAM_CONTROL | 0x80000004 | + hi_addr_bit; + __asm__ volatile ("sync"); + + /* set mode register */ + *(vu_long *)MPC5XXX_SDRAM_MODE = SDRAM_MODE; + __asm__ volatile ("sync"); + + /* normal operation */ + *(vu_long *)MPC5XXX_SDRAM_CTRL = SDRAM_CONTROL | hi_addr_bit; + __asm__ volatile ("sync"); +} +#endif + +/* + * ATTENTION: Although partially referenced initdram does NOT make real use + * use of CFG_SDRAM_BASE. The code does not work if CFG_SDRAM_BASE + * is something else than 0x00000000. + */ + +#if defined(CONFIG_MPC5200) +long int initdram (int board_type) +{ + ulong dramsize = 0; + ulong dramsize2 = 0; +#ifndef CFG_RAMBOOT + ulong test1, test2; + + /* setup SDRAM chip selects */ + *(vu_long *)MPC5XXX_SDRAM_CS0CFG = 0x0000001c; /* 512MB at 0x0 */ + *(vu_long *)MPC5XXX_SDRAM_CS1CFG = 0x40000000; /* disabled */ + __asm__ volatile ("sync"); + + /* setup config registers */ + *(vu_long *)MPC5XXX_SDRAM_CONFIG1 = SDRAM_CONFIG1; + *(vu_long *)MPC5XXX_SDRAM_CONFIG2 = SDRAM_CONFIG2; + __asm__ volatile ("sync"); + +#if SDRAM_DDR + /* set tap delay */ + *(vu_long *)MPC5XXX_CDM_PORCFG = SDRAM_TAPDELAY; + __asm__ volatile ("sync"); +#endif + + /* find RAM size using SDRAM CS0 only */ + sdram_start(0); + test1 = get_ram_size((long *)CFG_SDRAM_BASE, 0x20000000); + sdram_start(1); + test2 = get_ram_size((long *)CFG_SDRAM_BASE, 0x20000000); + if (test1 > test2) { + sdram_start(0); + dramsize = test1; + } else { + dramsize = test2; + } + + /* memory smaller than 1MB is impossible */ + if (dramsize < (1 << 20)) { + dramsize = 0; + } + + /* set SDRAM CS0 size according to the amount of RAM found */ + if (dramsize > 0) { + *(vu_long *)MPC5XXX_SDRAM_CS0CFG = 0x13 + + __builtin_ffs(dramsize >> 20) - 1; + } else { + *(vu_long *)MPC5XXX_SDRAM_CS0CFG = 0; /* disabled */ + } + + /* let SDRAM CS1 start right after CS0 */ + *(vu_long *)MPC5XXX_SDRAM_CS1CFG = dramsize + 0x0000001c; /* 512MB */ + + /* find RAM size using SDRAM CS1 only */ + sdram_start(0); + test1 = get_ram_size((long *)(CFG_SDRAM_BASE + dramsize), 0x20000000); + sdram_start(1); + test2 = get_ram_size((long *)(CFG_SDRAM_BASE + dramsize), 0x20000000); + if (test1 > test2) { + sdram_start(0); + dramsize2 = test1; + } else { + dramsize2 = test2; + } + + /* memory smaller than 1MB is impossible */ + if (dramsize2 < (1 << 20)) { + dramsize2 = 0; + } + + /* set SDRAM CS1 size according to the amount of RAM found */ + if (dramsize2 > 0) { + *(vu_long *)MPC5XXX_SDRAM_CS1CFG = dramsize + | (0x13 + __builtin_ffs(dramsize2 >> 20) - 1); + } else { + *(vu_long *)MPC5XXX_SDRAM_CS1CFG = dramsize; /* disabled */ + } + +#else /* CFG_RAMBOOT */ + + /* retrieve size of memory connected to SDRAM CS0 */ + dramsize = *(vu_long *)MPC5XXX_SDRAM_CS0CFG & 0xFF; + if (dramsize >= 0x13) { + dramsize = (1 << (dramsize - 0x13)) << 20; + } else { + dramsize = 0; + } + + /* retrieve size of memory connected to SDRAM CS1 */ + dramsize2 = *(vu_long *)MPC5XXX_SDRAM_CS1CFG & 0xFF; + if (dramsize2 >= 0x13) { + dramsize2 = (1 << (dramsize2 - 0x13)) << 20; + } else { + dramsize2 = 0; + } + +#endif /* CFG_RAMBOOT */ + + return dramsize; +} + +#elif defined(CONFIG_MGT5100) + +long int initdram (int board_type) +{ + ulong dramsize = 0; +#ifndef CFG_RAMBOOT + ulong test1, test2; + + /* setup and enable SDRAM chip selects */ + *(vu_long *)MPC5XXX_SDRAM_START = 0x00000000; + *(vu_long *)MPC5XXX_SDRAM_STOP = 0x0000ffff; /* 2G */ + *(vu_long *)MPC5XXX_ADDECR |= (1 << 22); /* Enable SDRAM */ + __asm__ volatile ("sync"); + + /* setup config registers */ + *(vu_long *)MPC5XXX_SDRAM_CONFIG1 = SDRAM_CONFIG1; + *(vu_long *)MPC5XXX_SDRAM_CONFIG2 = SDRAM_CONFIG2; + + /* address select register */ + *(vu_long *)MPC5XXX_SDRAM_XLBSEL = SDRAM_ADDRSEL; + __asm__ volatile ("sync"); + + /* find RAM size */ + sdram_start(0); + test1 = get_ram_size((ulong *)CFG_SDRAM_BASE, 0x80000000); + sdram_start(1); + test2 = get_ram_size((ulong *)CFG_SDRAM_BASE, 0x80000000); + if (test1 > test2) { + sdram_start(0); + dramsize = test1; + } else { + dramsize = test2; + } + + /* set SDRAM end address according to size */ + *(vu_long *)MPC5XXX_SDRAM_STOP = ((dramsize - 1) >> 15); + +#else /* CFG_RAMBOOT */ + + /* Retrieve amount of SDRAM available */ + dramsize = ((*(vu_long *)MPC5XXX_SDRAM_STOP + 1) << 15); + +#endif /* CFG_RAMBOOT */ + + return dramsize; +} + +#else +#error Neither CONFIG_MPC5200 or CONFIG_MGT5100 defined +#endif + +int checkboard (void) +{ +#if defined (CONFIG_TQM5200) + puts ("Board: TQM5200 (TQ-Components GmbH)\n"); +#endif + +#if defined (CONFIG_BC3450) + puts ("Dev: GERSYS BC3450\n"); +#endif + + return 0; +} + +void flash_preinit(void) +{ + /* + * Now, when we are in RAM, enable flash write + * access for detection process. + * Note that CS_BOOT cannot be cleared when + * executing in flash. + */ +#if defined(CONFIG_MGT5100) + *(vu_long *)MPC5XXX_ADDECR &= ~(1 << 25); /* disable CS_BOOT */ + *(vu_long *)MPC5XXX_ADDECR |= (1 << 16); /* enable CS0 */ +#endif + *(vu_long *)MPC5XXX_BOOTCS_CFG &= ~0x1; /* clear RO */ +} + + +#ifdef CONFIG_PCI +static struct pci_controller hose; + +extern void pci_mpc5xxx_init(struct pci_controller *); + +void pci_init_board(void) +{ + pci_mpc5xxx_init(&hose); +} +#endif + +#if defined (CFG_CMD_IDE) && defined (CONFIG_IDE_RESET) +#define GPIO_PSC1_4 0x01000000UL + +void init_ide_reset (void) +{ + debug ("init_ide_reset\n"); + + /* Configure PSC1_4 as GPIO output for ATA reset */ + *(vu_long *) MPC5XXX_WU_GPIO_ENABLE |= GPIO_PSC1_4; + *(vu_long *) MPC5XXX_WU_GPIO_DIR |= GPIO_PSC1_4; +} + +void ide_set_reset (int idereset) +{ + debug ("ide_reset(%d)\n", idereset); + + if (idereset) { + *(vu_long *) MPC5XXX_WU_GPIO_DATA &= ~GPIO_PSC1_4; + } else { + *(vu_long *) MPC5XXX_WU_GPIO_DATA |= GPIO_PSC1_4; + } +} +#endif /* defined (CFG_CMD_IDE) && defined (CONFIG_IDE_RESET) */ + +#ifdef CONFIG_POST +/* + * Reads GPIO pin PSC6_3. A keypress is reported, if PSC6_3 is low. If PSC6_3 + * is left open, no keypress is detected. + */ +int post_hotkeys_pressed(void) +{ + struct mpc5xxx_gpio *gpio; + + gpio = (struct mpc5xxx_gpio*) MPC5XXX_GPIO; + + /* + * Configure PSC6_1 and PSC6_3 as GPIO. PSC6 then couldn't be used in + * CODEC or UART mode. Consumer IrDA should still be possible. + */ + gpio->port_config &= ~(0x07000000); + gpio->port_config |= 0x03000000; + + /* Enable GPIO for GPIO_IRDA_1 (IR_USB_CLK pin) = PSC6_3 */ + gpio->simple_gpioe |= 0x20000000; + + /* Configure GPIO_IRDA_1 as input */ + gpio->simple_ddr &= ~(0x20000000); + + return ((gpio->simple_ival & 0x20000000) ? 0 : 1); +} +#endif + +#if defined(CONFIG_POST) || defined(CONFIG_LOGBUFFER) + +void post_word_store (ulong a) +{ + volatile ulong *save_addr = + (volatile ulong *)(MPC5XXX_SRAM + MPC5XXX_SRAM_POST_SIZE); + + *save_addr = a; +} + +ulong post_word_load (void) +{ + volatile ulong *save_addr = + (volatile ulong *)(MPC5XXX_SRAM + MPC5XXX_SRAM_POST_SIZE); + + return *save_addr; +} +#endif /* CONFIG_POST || CONFIG_LOGBUFFER*/ + + +#ifdef CONFIG_BOARD_EARLY_INIT_R +int board_early_init_r (void) +{ +#ifdef CONFIG_RTC_MPC5200 + struct rtc_time t; + + /* set to Wed Dec 31 19:00:00 1969 */ + t.tm_sec = t.tm_min = 0; + t.tm_hour = 19; + t.tm_mday = 31; + t.tm_mon = 12; + t.tm_year = 1969; + t.tm_wday = 3; + + rtc_set(&t); +#endif /* CONFIG_RTC_MPC5200 */ + +#ifdef CONFIG_PS2MULT + ps2mult_early_init(); +#endif /* CONFIG_PS2MULT */ + return (0); +} +#endif /* CONFIG_BOARD_EARLY_INIT_R */ + + +int last_stage_init (void) +{ + /* + * auto scan for really existing devices and re-set chip select + * configuration. + */ + u16 save, tmp; + int restore; + + /* + * Check for SRAM and SRAM size + */ + + /* save original SRAM content */ + save = *(volatile u16 *)CFG_CS2_START; + restore = 1; + + /* write test pattern to SRAM */ + *(volatile u16 *)CFG_CS2_START = 0xA5A5; + __asm__ volatile ("sync"); + /* + * Put a different pattern on the data lines: otherwise they may float + * long enough to read back what we wrote. + */ + tmp = *(volatile u16 *)CFG_FLASH_BASE; + if (tmp == 0xA5A5) + puts ("!! possible error in SRAM detection\n"); + + if (*(volatile u16 *)CFG_CS2_START != 0xA5A5) { + /* no SRAM at all, disable cs */ + *(vu_long *)MPC5XXX_ADDECR &= ~(1 << 18); + *(vu_long *)MPC5XXX_CS2_START = 0x0000FFFF; + *(vu_long *)MPC5XXX_CS2_STOP = 0x0000FFFF; + restore = 0; + __asm__ volatile ("sync"); + } else if (*(volatile u16 *)(CFG_CS2_START + (1<<19)) == 0xA5A5) { + /* make sure that we access a mirrored address */ + *(volatile u16 *)CFG_CS2_START = 0x1111; + __asm__ volatile ("sync"); + if (*(volatile u16 *)(CFG_CS2_START + (1<<19)) == 0x1111) { + /* SRAM size = 512 kByte */ + *(vu_long *)MPC5XXX_CS2_STOP = STOP_REG(CFG_CS2_START, + 0x80000); + __asm__ volatile ("sync"); + puts ("SRAM: 512 kB\n"); + } + else + puts ("!! possible error in SRAM detection\n"); + } else { + puts ("SRAM: 1 MB\n"); + } + /* restore origianl SRAM content */ + if (restore) { + *(volatile u16 *)CFG_CS2_START = save; + __asm__ volatile ("sync"); + } + + /* + * Check for Grafic Controller + */ + + /* save origianl FB content */ + save = *(volatile u16 *)CFG_CS1_START; + restore = 1; + + /* write test pattern to FB memory */ + *(volatile u16 *)CFG_CS1_START = 0xA5A5; + __asm__ volatile ("sync"); + /* + * Put a different pattern on the data lines: otherwise they may float + * long enough to read back what we wrote. + */ + tmp = *(volatile u16 *)CFG_FLASH_BASE; + if (tmp == 0xA5A5) + puts ("!! possible error in grafic controller detection\n"); + + if (*(volatile u16 *)CFG_CS1_START != 0xA5A5) { + /* no grafic controller at all, disable cs */ + *(vu_long *)MPC5XXX_ADDECR &= ~(1 << 17); + *(vu_long *)MPC5XXX_CS1_START = 0x0000FFFF; + *(vu_long *)MPC5XXX_CS1_STOP = 0x0000FFFF; + restore = 0; + __asm__ volatile ("sync"); + } else { + puts ("VGA: SMI501 (Voyager) with 8 MB\n"); + } + /* restore origianl FB content */ + if (restore) { + *(volatile u16 *)CFG_CS1_START = save; + __asm__ volatile ("sync"); + } + + return 0; +} + +#ifdef CONFIG_VIDEO_SM501 + +#define DISPLAY_WIDTH 640 +#define DISPLAY_HEIGHT 480 + +#ifdef CONFIG_VIDEO_SM501_8BPP +#error CONFIG_VIDEO_SM501_8BPP not supported. +#endif /* CONFIG_VIDEO_SM501_8BPP */ + +#ifdef CONFIG_VIDEO_SM501_16BPP +#error CONFIG_VIDEO_SM501_16BPP not supported. +#endif /* CONFIG_VIDEO_SM501_16BPP */ + +#ifdef CONFIG_VIDEO_SM501_32BPP +static const SMI_REGS init_regs [] = +{ +#if defined (CONFIG_BC3450_FP) && !defined (CONFIG_BC3450_CRT) + /* FP only */ + {0x00004, 0x0}, + {0x00048, 0x00021807}, + {0x0004C, 0x091a0a01}, + {0x00054, 0x1}, + {0x00040, 0x00021807}, + {0x00044, 0x091a0a01}, + {0x00054, 0x0}, + {0x80000, 0x01013106}, + {0x80004, 0xc428bb17}, + {0x80000, 0x03013106}, + {0x8000C, 0x00000000}, + {0x80010, 0x0a000a00}, + {0x80014, 0x02800000}, + {0x80018, 0x01e00000}, + {0x8001C, 0x00000000}, + {0x80020, 0x01e00280}, + {0x80024, 0x02fa027f}, + {0x80028, 0x004a028b}, + {0x8002C, 0x020c01df}, + {0x80030, 0x000201e9}, + {0x80200, 0x00010200}, + {0x80000, 0x0f013106}, +#elif defined (CONFIG_BC3450_CRT) && !defined (CONFIG_BC3450_FP) + /* CRT only */ + {0x00004, 0x0}, + {0x00048, 0x00021807}, + {0x0004C, 0x10090a01}, + {0x00054, 0x1}, + {0x00040, 0x00021807}, + {0x00044, 0x10090a01}, + {0x00054, 0x0}, + {0x80200, 0x00010000}, + {0x80204, 0x0}, + {0x80208, 0x0A000A00}, + {0x8020C, 0x02fa027f}, + {0x80210, 0x004a028b}, + {0x80214, 0x020c01df}, + {0x80218, 0x000201e9}, + {0x80200, 0x00013306}, +#else /* panel + CRT */ + {0x00004, 0x0}, + {0x00048, 0x00021807}, + {0x0004C, 0x091a0a01}, + {0x00054, 0x1}, + {0x00040, 0x00021807}, + {0x00044, 0x091a0a01}, + {0x00054, 0x0}, + {0x80000, 0x0f013106}, + {0x80004, 0xc428bb17}, + {0x8000C, 0x00000000}, + {0x80010, 0x0a000a00}, + {0x80014, 0x02800000}, + {0x80018, 0x01e00000}, + {0x8001C, 0x00000000}, + {0x80020, 0x01e00280}, + {0x80024, 0x02fa027f}, + {0x80028, 0x004a028b}, + {0x8002C, 0x020c01df}, + {0x80030, 0x000201e9}, + {0x80200, 0x00010000}, +#endif + {0, 0} +}; +#endif /* CONFIG_VIDEO_SM501_32BPP */ + +#ifdef CONFIG_CONSOLE_EXTRA_INFO +/* + * Return text to be printed besides the logo. + */ +void video_get_info_str (int line_number, char *info) +{ + if (line_number == 1) { +#if defined (CONFIG_TQM5200) + strcpy (info, " Board: TQM5200 (TQ-Components GmbH)"); +#else +#error No supported board selected +#endif /* CONFIG_TQM5200 */ + +#if defined (CONFIG_BC3450) + } else if (line_number == 2) { + strcpy (info, " Dev: GERSYS BC3450"); +#endif /* CONFIG_BC3450 */ + } + else { + info [0] = '\0'; + } +} +#endif + +/* + * Returns SM501 register base address. First thing called in the + * driver. Checks if SM501 is physically present. + */ +unsigned int board_video_init (void) +{ + u16 save, tmp; + int restore, ret; + + /* + * Check for Grafic Controller + */ + + /* save origianl FB content */ + save = *(volatile u16 *)CFG_CS1_START; + restore = 1; + + /* write test pattern to FB memory */ + *(volatile u16 *)CFG_CS1_START = 0xA5A5; + __asm__ volatile ("sync"); + /* + * Put a different pattern on the data lines: otherwise they may float + * long enough to read back what we wrote. + */ + tmp = *(volatile u16 *)CFG_FLASH_BASE; + if (tmp == 0xA5A5) + puts ("!! possible error in grafic controller detection\n"); + + if (*(volatile u16 *)CFG_CS1_START != 0xA5A5) { + /* no grafic controller found */ + restore = 0; + ret = 0; + } else { + ret = SM501_MMIO_BASE; + } + + if (restore) { + *(volatile u16 *)CFG_CS1_START = save; + __asm__ volatile ("sync"); + } + return ret; +} + +/* + * Returns SM501 framebuffer address + */ +unsigned int board_video_get_fb (void) +{ + return SM501_FB_BASE; +} + +/* + * Called after initializing the SM501 and before clearing the screen. + */ +void board_validate_screen (unsigned int base) +{ +} + +/* + * Return a pointer to the initialization sequence. + */ +const SMI_REGS *board_get_regs (void) +{ + return init_regs; +} + +int board_get_width (void) +{ + return DISPLAY_WIDTH; +} + +int board_get_height (void) +{ + return DISPLAY_HEIGHT; +} + +#endif /* CONFIG_VIDEO_SM501 */ diff --git a/board/bc3450/cmd_bc3450.c b/board/bc3450/cmd_bc3450.c new file mode 100644 index 0000000..6bbe4e6 --- /dev/null +++ b/board/bc3450/cmd_bc3450.c @@ -0,0 +1,827 @@ +/* + * (C) Copyright 2005 + * Stefan Strobl, GERSYS GmbH, stefan.strobl@gersys.de + * + * (C) Copyright 2005 + * Martin Krause, TQ-Systems GmbH, martin.krause@tqs.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <command.h> + +/* + * BC3450 specific commands + */ +#if (CONFIG_COMMANDS & CFG_CMD_BSP) + +#undef DEBUG +#ifdef DEBUG +# define dprintf(fmt,args...) printf(fmt, ##args) +#else +# define dprintf(fmt,args...) +#endif + +/* + * Definitions for DS1620 chip + */ +#define THERM_START_CONVERT 0xee +#define THERM_RESET 0xaf +#define THERM_READ_CONFIG 0xac +#define THERM_READ_TEMP 0xaa +#define THERM_READ_TL 0xa2 +#define THERM_READ_TH 0xa1 +#define THERM_WRITE_CONFIG 0x0c +#define THERM_WRITE_TL 0x02 +#define THERM_WRITE_TH 0x01 + +#define CFG_CPU 2 +#define CFG_1SHOT 1 +#define CFG_STANDALONE 0 + +struct therm { + int hi; + int lo; +}; + +/* + * SM501 Register + */ +#define SM501_GPIO_CTRL_LOW 0x00000008UL /* gpio pins 0..31 */ +#define SM501_GPIO_CTRL_HIGH 0x0000000CUL /* gpio pins 32..63 */ +#define SM501_POWER_MODE0_GATE 0x00000040UL +#define SM501_POWER_MODE1_GATE 0x00000048UL +#define POWER_MODE_GATE_GPIO_PWM_I2C 0x00000040UL +#define SM501_GPIO_DATA_LOW 0x00010000UL +#define SM501_GPIO_DATA_HIGH 0x00010004UL +#define SM501_GPIO_DATA_DIR_LOW 0x00010008UL +#define SM501_GPIO_DATA_DIR_HIGH 0x0001000CUL +#define SM501_PANEL_DISPLAY_CONTROL 0x00080000UL +#define SM501_CRT_DISPLAY_CONTROL 0x00080200UL + +/* SM501 CRT Display Control Bits */ +#define SM501_CDC_SEL (1 << 9) +#define SM501_CDC_TE (1 << 8) +#define SM501_CDC_E (1 << 2) + +/* SM501 Panel Display Control Bits */ +#define SM501_PDC_FPEN (1 << 27) +#define SM501_PDC_BIAS (1 << 26) +#define SM501_PDC_DATA (1 << 25) +#define SM501_PDC_VDDEN (1 << 24) + +/* SM501 GPIO Data LOW Bits */ +#define SM501_GPIO24 0x01000000 +#define SM501_GPIO25 0x02000000 +#define SM501_GPIO26 0x04000000 +#define SM501_GPIO27 0x08000000 +#define SM501_GPIO28 0x10000000 +#define SM501_GPIO29 0x20000000 +#define SM501_GPIO30 0x40000000 +#define SM501_GPIO31 0x80000000 + +/* SM501 GPIO Data HIGH Bits */ +#define SM501_GPIO46 0x00004000 +#define SM501_GPIO47 0x00008000 +#define SM501_GPIO48 0x00010000 +#define SM501_GPIO49 0x00020000 +#define SM501_GPIO50 0x00040000 +#define SM501_GPIO51 0x00080000 + +/* BC3450 GPIOs @ SM501 Data LOW */ +#define DIP (SM501_GPIO24 | SM501_GPIO25 | SM501_GPIO26 | SM501_GPIO27) +#define DS1620_DQ SM501_GPIO29 /* I/O */ +#define DS1620_CLK SM501_GPIO30 /* High active O/P */ +#define DS1620_RES SM501_GPIO31 /* Low active O/P */ +/* BC3450 GPIOs @ SM501 Data HIGH */ +#define BUZZER SM501_GPIO47 /* Low active O/P */ +#define DS1620_TLOW SM501_GPIO48 /* High active I/P */ +#define PWR_OFF SM501_GPIO49 /* Low active O/P */ +#define FP_DATA_TRI SM501_GPIO50 /* High active O/P */ + + +/* + * Initialise GPIO on SM501 + * + * This function may be called from several other functions. + * Yet, the initialisation sequence is executed only the first + * time the function is called. + */ +int sm501_gpio_init (void) +{ + static int init_done = 0; + + if (init_done) { +/* dprintf("sm501_gpio_init: nothing to be done.\n"); */ + return 1; + } + + /* enable SM501 GPIO control (in both power modes) */ + *(vu_long *) (SM501_MMIO_BASE + SM501_POWER_MODE0_GATE) |= + POWER_MODE_GATE_GPIO_PWM_I2C; + *(vu_long *) (SM501_MMIO_BASE + SM501_POWER_MODE1_GATE) |= + POWER_MODE_GATE_GPIO_PWM_I2C; + + /* set up default O/Ps */ + *(vu_long *) (SM501_MMIO_BASE + SM501_GPIO_DATA_LOW) &= + ~(DS1620_RES | DS1620_CLK); + *(vu_long *) (SM501_MMIO_BASE + SM501_GPIO_DATA_LOW) |= DS1620_DQ; + *(vu_long *) (SM501_MMIO_BASE + SM501_GPIO_DATA_HIGH) &= + ~(FP_DATA_TRI); + *(vu_long *) (SM501_MMIO_BASE + SM501_GPIO_DATA_HIGH) |= + (BUZZER | PWR_OFF); + + /* configure directions for SM501 GPIO pins */ + *(vu_long *) (SM501_MMIO_BASE + SM501_GPIO_CTRL_LOW) &= ~(0xFF << 24); + *(vu_long *) (SM501_MMIO_BASE + SM501_GPIO_CTRL_HIGH) &= + ~(0x3F << 14); + *(vu_long *) (SM501_MMIO_BASE + SM501_GPIO_DATA_DIR_LOW) &= + ~(DIP | DS1620_DQ); + *(vu_long *) (SM501_MMIO_BASE + SM501_GPIO_DATA_DIR_LOW) |= + (DS1620_RES | DS1620_CLK); + *(vu_long *) (SM501_MMIO_BASE + SM501_GPIO_DATA_DIR_HIGH) &= + ~DS1620_TLOW; + *(vu_long *) (SM501_MMIO_BASE + SM501_GPIO_DATA_DIR_HIGH) |= + (PWR_OFF | BUZZER | FP_DATA_TRI); + + init_done = 1; +/* dprintf("sm501_gpio_init: done.\n"); */ + return 0; +} + + +/* + * dip - read Config Inputs + * + * read and prints the dip switch + * and/or external config inputs (4bits) 0...0x0F + */ +int cmd_dip (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) +{ + vu_long rc = 0; + + sm501_gpio_init (); + + /* read dip switch */ + rc = *(vu_long *) (SM501_MMIO_BASE + SM501_GPIO_DATA_LOW); + rc = ~rc; + rc &= DIP; + rc = (int) (rc >> 24); + + /* plausibility check */ + if (rc > 0x0F) + return -1; + + printf ("0x%x\n", rc); + return 0; +} + +U_BOOT_CMD (dip, 1, 1, cmd_dip, + "dip - read dip switch and config inputs\n", + "\n" + " - prints the state of the dip switch and/or\n" + " external configuration inputs as hex value.\n" + " - \"Config 1\" is the LSB\n"); + + +/* + * buz - turns Buzzer on/off + */ +#ifdef CONFIG_BC3450_BUZZER +static int cmd_buz (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) +{ + if (argc != 2) { + printf ("Usage:\nspecify one argument: \"on\" or \"off\"\n"); + return 1; + } + + sm501_gpio_init (); + + if (strncmp (argv[1], "on", 2) == 0) { + *(vu_long *) (SM501_MMIO_BASE + SM501_GPIO_DATA_HIGH) &= + ~(BUZZER); + return 0; + } else if (strncmp (argv[1], "off", 3) == 0) { + *(vu_long *) (SM501_MMIO_BASE + SM501_GPIO_DATA_HIGH) |= + BUZZER; + return 0; + } + printf ("Usage:\nspecify one argument: \"on\" or \"off\"\n"); + return 1; +} + +U_BOOT_CMD (buz, 2, 1, cmd_buz, + "buz - turns buzzer on/off\n", + "\n" "buz <on/off>\n" " - turns the buzzer on or off\n"); +#endif /* CONFIG_BC3450_BUZZER */ + + +/* + * fp - front panel commands + */ +static int cmd_fp (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) +{ + sm501_gpio_init (); + + if (strncmp (argv[1], "on", 2) == 0) { + /* turn on VDD first */ + *(vu_long *) (SM501_MMIO_BASE + + SM501_PANEL_DISPLAY_CONTROL) |= SM501_PDC_VDDEN; + udelay (1000); + /* then put data on */ + *(vu_long *) (SM501_MMIO_BASE + + SM501_PANEL_DISPLAY_CONTROL) |= SM501_PDC_DATA; + /* wait some time and enable backlight */ + udelay (1000); + *(vu_long *) (SM501_MMIO_BASE + + SM501_PANEL_DISPLAY_CONTROL) |= SM501_PDC_BIAS; + udelay (1000); + *(vu_long *) (SM501_MMIO_BASE + + SM501_PANEL_DISPLAY_CONTROL) |= SM501_PDC_FPEN; + return 0; + } else if (strncmp (argv[1], "off", 3) == 0) { + /* turn off the backlight first */ + *(vu_long *) (SM501_MMIO_BASE + + SM501_PANEL_DISPLAY_CONTROL) &= ~SM501_PDC_FPEN; + udelay (1000); + *(vu_long *) (SM501_MMIO_BASE + + SM501_PANEL_DISPLAY_CONTROL) &= ~SM501_PDC_BIAS; + udelay (200000); + /* wait some time, then remove data */ + *(vu_long *) (SM501_MMIO_BASE + + SM501_PANEL_DISPLAY_CONTROL) &= ~SM501_PDC_DATA; + udelay (1000); + /* and remove VDD last */ + *(vu_long *) (SM501_MMIO_BASE + + SM501_PANEL_DISPLAY_CONTROL) &= + ~SM501_PDC_VDDEN; + return 0; + } else if (strncmp (argv[1], "bl", 2) == 0) { + /* turn on/off backlight only */ + if (strncmp (argv[2], "on", 2) == 0) { + *(vu_long *) (SM501_MMIO_BASE + + SM501_PANEL_DISPLAY_CONTROL) |= + SM501_PDC_BIAS; + udelay (1000); + *(vu_long *) (SM501_MMIO_BASE + + SM501_PANEL_DISPLAY_CONTROL) |= + SM501_PDC_FPEN; + return 0; + } else if (strncmp (argv[2], "off", 3) == 0) { + *(vu_long *) (SM501_MMIO_BASE + + SM501_PANEL_DISPLAY_CONTROL) &= + ~SM501_PDC_FPEN; + udelay (1000); + *(vu_long *) (SM501_MMIO_BASE + + SM501_PANEL_DISPLAY_CONTROL) &= + ~SM501_PDC_BIAS; + return 0; + } + } +#ifdef CONFIG_BC3450_CRT + else if (strncmp (argv[1], "crt", 3) == 0) { + /* enables/disables the crt output (debug only) */ + if (strncmp (argv[2], "on", 2) == 0) { + *(vu_long *) (SM501_MMIO_BASE + + SM501_CRT_DISPLAY_CONTROL) |= + (SM501_CDC_TE | SM501_CDC_E); + *(vu_long *) (SM501_MMIO_BASE + + SM501_CRT_DISPLAY_CONTROL) &= + ~SM501_CDC_SEL; + return 0; + } else if (strncmp (argv[2], "off", 3) == 0) { + *(vu_long *) (SM501_MMIO_BASE + + SM501_CRT_DISPLAY_CONTROL) &= + ~(SM501_CDC_TE | SM501_CDC_E); + *(vu_long *) (SM501_MMIO_BASE + + SM501_CRT_DISPLAY_CONTROL) |= + SM501_CDC_SEL; + return 0; + } + } +#endif /* CONFIG_BC3450_CRT */ + printf ("Usage:%s\n", cmdtp->help); + return 1; +} + +U_BOOT_CMD (fp, 3, 1, cmd_fp, + "fp - front panes access functions\n", + "\n" + "fp bl <on/off>\n" + " - turns the CCFL backlight of the display on/off\n" + "fp <on/off>\n" " - turns the whole display on/off\n" +#ifdef CONFIG_BC3450_CRT + "fp crt <on/off>\n" + " - enables/disables the crt output (debug only)\n" +#endif /* CONFIG_BC3450_CRT */ + ); + + +/* + * temp - DS1620 thermometer + */ +/* GERSYS BC3450 specific functions */ +static inline void bc_ds1620_set_clk (int clk) +{ + if (clk) + *(vu_long *) (SM501_MMIO_BASE + SM501_GPIO_DATA_LOW) |= + DS1620_CLK; + else + *(vu_long *) (SM501_MMIO_BASE + SM501_GPIO_DATA_LOW) &= + ~DS1620_CLK; +} + +static inline void bc_ds1620_set_data (int dat) +{ + if (dat) + *(vu_long *) (SM501_MMIO_BASE + SM501_GPIO_DATA_LOW) |= + DS1620_DQ; + else + *(vu_long *) (SM501_MMIO_BASE + SM501_GPIO_DATA_LOW) &= + ~DS1620_DQ; +} + +static inline int bc_ds1620_get_data (void) +{ + vu_long rc; + + rc = *(vu_long *) (SM501_MMIO_BASE + SM501_GPIO_DATA_LOW); + rc &= DS1620_DQ; + if (rc != 0) + rc = 1; + return (int) rc; +} + +static inline void bc_ds1620_set_data_dir (int dir) +{ + if (dir) /* in */ + *(vu_long *) (SM501_MMIO_BASE + SM501_GPIO_DATA_DIR_LOW) &= ~DS1620_DQ; + else /* out */ + *(vu_long *) (SM501_MMIO_BASE + SM501_GPIO_DATA_DIR_LOW) |= DS1620_DQ; +} + +static inline void bc_ds1620_set_reset (int res) +{ + if (res) + *(vu_long *) (SM501_MMIO_BASE + SM501_GPIO_DATA_LOW) |= DS1620_RES; + else + *(vu_long *) (SM501_MMIO_BASE + SM501_GPIO_DATA_LOW) &= ~DS1620_RES; +} + +/* hardware independent functions */ +static void ds1620_send_bits (int nr, int value) +{ + int i; + + for (i = 0; i < nr; i++) { + bc_ds1620_set_data (value & 1); + bc_ds1620_set_clk (0); + udelay (1); + bc_ds1620_set_clk (1); + udelay (1); + + value >>= 1; + } +} + +static unsigned int ds1620_recv_bits (int nr) +{ + unsigned int value = 0, mask = 1; + int i; + + bc_ds1620_set_data (0); + + for (i = 0; i < nr; i++) { + bc_ds1620_set_clk (0); + udelay (1); + + if (bc_ds1620_get_data ()) + value |= mask; + + mask <<= 1; + + bc_ds1620_set_clk (1); + udelay (1); + } + + return value; +} + +static void ds1620_out (int cmd, int bits, int value) +{ + bc_ds1620_set_clk (1); + bc_ds1620_set_data_dir (0); + + bc_ds1620_set_reset (0); + udelay (1); + bc_ds1620_set_reset (1); + + udelay (1); + + ds1620_send_bits (8, cmd); + if (bits) + ds1620_send_bits (bits, value); + + udelay (1); + + /* go stand alone */ + bc_ds1620_set_data_dir (1); + bc_ds1620_set_reset (0); + bc_ds1620_set_clk (0); + + udelay (10000); +} + +static unsigned int ds1620_in (int cmd, int bits) +{ + unsigned int value; + + bc_ds1620_set_clk (1); + bc_ds1620_set_data_dir (0); + + bc_ds1620_set_reset (0); + udelay (1); + bc_ds1620_set_reset (1); + + udelay (1); + + ds1620_send_bits (8, cmd); + + bc_ds1620_set_data_dir (1); + value = ds1620_recv_bits (bits); + + /* go stand alone */ + bc_ds1620_set_data_dir (1); + bc_ds1620_set_reset (0); + bc_ds1620_set_clk (0); + + return value; +} + +static int cvt_9_to_int (unsigned int val) +{ + if (val & 0x100) + val |= 0xfffffe00; + + return val; +} + +/* set thermostate thresholds */ +static void ds1620_write_state (struct therm *therm) +{ + ds1620_out (THERM_WRITE_TL, 9, therm->lo); + ds1620_out (THERM_WRITE_TH, 9, therm->hi); + ds1620_out (THERM_START_CONVERT, 0, 0); +} + +static int cmd_temp (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) +{ + int i; + struct therm therm; + + sm501_gpio_init (); + + /* print temperature */ + if (argc == 1) { + i = cvt_9_to_int (ds1620_in (THERM_READ_TEMP, 9)); + printf ("%d.%d C\n", i >> 1, i & 1 ? 5 : 0); + return 0; + } + + /* set to default operation */ + if (strncmp (argv[1], "set", 3) == 0) { + if (strncmp (argv[2], "default", 3) == 0) { + therm.hi = +88; + therm.lo = -20; + therm.hi <<= 1; + therm.lo <<= 1; + ds1620_write_state (&therm); + ds1620_out (THERM_WRITE_CONFIG, 8, CFG_STANDALONE); + return 0; + } + } + + printf ("Usage:%s\n", cmdtp->help); + return 1; +} + +U_BOOT_CMD (temp, 3, 1, cmd_temp, + "temp - print current temperature\n", + "\n" "temp\n" " - print current temperature\n"); + +#ifdef CONFIG_BC3450_CAN +/* + * Initialise CAN interface + * + * return 1 on CAN initialization failure + * return 0 if no failure + */ +int can_init (void) +{ + static int init_done = 0; + int i; + struct mpc5xxx_mscan *can1 = + (struct mpc5xxx_mscan *) (CFG_MBAR + 0x0900); + struct mpc5xxx_mscan *can2 = + (struct mpc5xxx_mscan *) (CFG_MBAR + 0x0980); + + /* GPIO configuration of the CAN pins is done in BC3450.h */ + + if (!init_done) { + /* init CAN 1 */ + can1->canctl1 |= 0x80; /* CAN enable */ + udelay (100); + + i = 0; + can1->canctl0 |= 0x02; /* sleep mode */ + /* wait until sleep mode reached */ + while (!(can1->canctl1 & 0x02)) { + udelay (10); + i++; + if (i == 10) { + printf ("%s: CAN1 initialize error, " + "can not enter sleep mode!\n", + __FUNCTION__); + return 1; + } + } + i = 0; + can1->canctl0 = 0x01; /* enter init mode */ + /* wait until init mode reached */ + while (!(can1->canctl1 & 0x01)) { + udelay (10); + i++; + if (i == 10) { + printf ("%s: CAN1 initialize error, " + "can not enter init mode!\n", + __FUNCTION__); + return 1; + } + } + can1->canctl1 = 0x80; + can1->canctl1 |= 0x40; + can1->canbtr0 = 0x0F; + can1->canbtr1 = 0x7F; + can1->canidac &= ~(0x30); + can1->canidar1 = 0x00; + can1->canidar3 = 0x00; + can1->canidar5 = 0x00; + can1->canidar7 = 0x00; + can1->canidmr0 = 0xFF; + can1->canidmr1 = 0xFF; + can1->canidmr2 = 0xFF; + can1->canidmr3 = 0xFF; + can1->canidmr4 = 0xFF; + can1->canidmr5 = 0xFF; + can1->canidmr6 = 0xFF; + can1->canidmr7 = 0xFF; + + i = 0; + can1->canctl0 &= ~(0x01); /* leave init mode */ + can1->canctl0 &= ~(0x02); + /* wait until init and sleep mode left */ + while ((can1->canctl1 & 0x01) || (can1->canctl1 & 0x02)) { + udelay (10); + i++; + if (i == 10) { + printf ("%s: CAN1 initialize error, " + "can not leave init/sleep mode!\n", + __FUNCTION__); + return 1; + } + } + + /* init CAN 2 */ + can2->canctl1 |= 0x80; /* CAN enable */ + udelay (100); + + i = 0; + can2->canctl0 |= 0x02; /* sleep mode */ + /* wait until sleep mode reached */ + while (!(can2->canctl1 & 0x02)) { + udelay (10); + i++; + if (i == 10) { + printf ("%s: CAN2 initialize error, " + "can not enter sleep mode!\n", + __FUNCTION__); + return 1; + } + } + i = 0; + can2->canctl0 = 0x01; /* enter init mode */ + /* wait until init mode reached */ + while (!(can2->canctl1 & 0x01)) { + udelay (10); + i++; + if (i == 10) { + printf ("%s: CAN2 initialize error, " + "can not enter init mode!\n", + __FUNCTION__); + return 1; + } + } + can2->canctl1 = 0x80; + can2->canctl1 |= 0x40; + can2->canbtr0 = 0x0F; + can2->canbtr1 = 0x7F; + can2->canidac &= ~(0x30); + can2->canidar1 = 0x00; + can2->canidar3 = 0x00; + can2->canidar5 = 0x00; + can2->canidar7 = 0x00; + can2->canidmr0 = 0xFF; + can2->canidmr1 = 0xFF; + can2->canidmr2 = 0xFF; + can2->canidmr3 = 0xFF; + can2->canidmr4 = 0xFF; + can2->canidmr5 = 0xFF; + can2->canidmr6 = 0xFF; + can2->canidmr7 = 0xFF; + can2->canctl0 &= ~(0x01); /* leave init mode */ + can2->canctl0 &= ~(0x02); + + i = 0; + /* wait until init mode left */ + while ((can2->canctl1 & 0x01) || (can2->canctl1 & 0x02)) { + udelay (10); + i++; + if (i == 10) { + printf ("%s: CAN2 initialize error, " + "can not leave init/sleep mode!\n", + __FUNCTION__); + return 1; + } + } + init_done = 1; + } + return 0; +} + +/* + * Do CAN test + * by sending message between CAN1 and CAN2 + * + * return 1 on CAN failure + * return 0 if no failure + */ +int do_can (char *argv[]) +{ + int i; + struct mpc5xxx_mscan *can1 = + (struct mpc5xxx_mscan *) (CFG_MBAR + 0x0900); + struct mpc5xxx_mscan *can2 = + (struct mpc5xxx_mscan *) (CFG_MBAR + 0x0980); + + /* send a message on CAN1 */ + can1->cantbsel = 0x01; + can1->cantxfg.idr[0] = 0x55; + can1->cantxfg.idr[1] = 0x00; + can1->cantxfg.idr[1] &= ~0x8; + can1->cantxfg.idr[1] &= ~0x10; + can1->cantxfg.dsr[0] = 0xCC; + can1->cantxfg.dlr = 1; + can1->cantxfg.tbpr = 0; + can1->cantflg = 0x01; + + i = 0; + while ((can1->cantflg & 0x01) == 0) { + i++; + if (i == 10) { + printf ("%s: CAN1 send timeout, " + "can not send message!\n", __FUNCTION__); + return 1; + } + udelay (1000); + } + udelay (1000); + + i = 0; + while (!(can2->canrflg & 0x01)) { + i++; + if (i == 10) { + printf ("%s: CAN2 receive timeout, " + "no message received!\n", __FUNCTION__); + return 1; + } + udelay (1000); + } + + if (can2->canrxfg.dsr[0] != 0xCC) { + printf ("%s: CAN2 receive error, " + "data mismatch!\n", __FUNCTION__); + return 1; + } + + /* send a message on CAN2 */ + can2->cantbsel = 0x01; + can2->cantxfg.idr[0] = 0x55; + can2->cantxfg.idr[1] = 0x00; + can2->cantxfg.idr[1] &= ~0x8; + can2->cantxfg.idr[1] &= ~0x10; + can2->cantxfg.dsr[0] = 0xCC; + can2->cantxfg.dlr = 1; + can2->cantxfg.tbpr = 0; + can2->cantflg = 0x01; + + i = 0; + while ((can2->cantflg & 0x01) == 0) { + i++; + if (i == 10) { + printf ("%s: CAN2 send error, " + "can not send message!\n", __FUNCTION__); + return 1; + } + udelay (1000); + } + udelay (1000); + + i = 0; + while (!(can1->canrflg & 0x01)) { + i++; + if (i == 10) { + printf ("%s: CAN1 receive timeout, " + "no message received!\n", __FUNCTION__); + return 1; + } + udelay (1000); + } + + if (can1->canrxfg.dsr[0] != 0xCC) { + printf ("%s: CAN1 receive error 0x%02x\n", + __FUNCTION__, (can1->canrxfg.dsr[0])); + return 1; + } + + return 0; +} +#endif /* CONFIG_BC3450_CAN */ + +/* + * test - BC3450 HW test routines + */ +int cmd_test (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) +{ +#ifdef CONFIG_BC3450_CAN + int rcode; + + can_init (); +#endif /* CONFIG_BC3450_CAN */ + + sm501_gpio_init (); + + if (argc != 2) { + printf ("Usage:%s\n", cmdtp->help); + return 1; + } + + if (strncmp (argv[1], "unit-off", 8) == 0) { + printf ("waiting 2 seconds...\n"); + udelay (2000000); + *(vu_long *) (SM501_MMIO_BASE + SM501_GPIO_DATA_HIGH) &= + ~PWR_OFF; + return 0; + } +#ifdef CONFIG_BC3450_CAN + else if (strncmp (argv[1], "can", 2) == 0) { + rcode = do_can (argv); + if (simple_strtoul (argv[2], NULL, 10) == 2) { + if (rcode == 0) + printf ("OK\n"); + else + printf ("Error\n"); + } + return rcode; + } +#endif /* CONFIG_BC3450_CAN */ + + printf ("Usage:%s\n", cmdtp->help); + return 1; +} + +U_BOOT_CMD (test, 2, 1, cmd_test, "test - unit test routines\n", "\n" +#ifdef CONFIG_BC3450_CAN + "test can\n" + " - connect CAN1 (X8) with CAN2 (X9) for this test\n" +#endif /* CONFIG_BC3450_CAN */ + "test unit-off\n" + " - turns off the BC3450 unit\n" + " WARNING: Unsaved environment variables will be lost!\n"); +#endif /* CFG_CMD_BSP */ diff --git a/board/bc3450/config.mk b/board/bc3450/config.mk new file mode 100644 index 0000000..47e9955 --- /dev/null +++ b/board/bc3450/config.mk @@ -0,0 +1,41 @@ +# +# (C) Copyright 2004 +# 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 +# + +# +# BC3450 board: +# +# Valid values for TEXT_BASE are: +# +# 0xFC000000 boot low (standard configuration with room for max 64 MByte +# Flash ROM) +# 0x00100000 boot from RAM (for testing only) +# + +ifndef TEXT_BASE +## Standard: boot low +TEXT_BASE = 0xFC000000 +## For testing: boot from RAM +# TEXT_BASE = 0x00100000 +endif + +PLATFORM_CPPFLAGS += -DTEXT_BASE=$(TEXT_BASE) -I$(TOPDIR)/board diff --git a/board/bc3450/mt48lc16m16a2-75.h b/board/bc3450/mt48lc16m16a2-75.h new file mode 100644 index 0000000..3f1e169 --- /dev/null +++ b/board/bc3450/mt48lc16m16a2-75.h @@ -0,0 +1,47 @@ +/* + * (C) Copyright 2004 + * Mark Jonas, Freescale Semiconductor, mark.jonas@motorola.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 + */ + +#define SDRAM_DDR 0 /* is SDR */ + +#if defined(CONFIG_MPC5200) +/* Settings for XLB = 132 MHz */ +#define SDRAM_MODE 0x00CD0000 +/* #define SDRAM_MODE 0x008D0000 */ /* CAS latency 2 */ +#define SDRAM_CONTROL 0x504F0000 +#define SDRAM_CONFIG1 0xD2322800 +/* #define SDRAM_CONFIG1 0xD2222800 */ /* CAS latency 2 */ +/*#define SDRAM_CONFIG1 0xD7322800 */ /* SDRAM controller bug workaround */ +#define SDRAM_CONFIG2 0x8AD70000 +/*#define SDRAM_CONFIG2 0xDDD70000 */ /* SDRAM controller bug workaround */ + +#elif defined(CONFIG_MGT5100) +/* Settings for XLB = 66 MHz */ +#define SDRAM_MODE 0x008D0000 +#define SDRAM_CONTROL 0x504F0000 +#define SDRAM_CONFIG1 0xC2222600 +#define SDRAM_CONFIG2 0x88B70004 +#define SDRAM_ADDRSEL 0x02000000 + +#else +#error Neither CONFIG_MPC5200 or CONFIG_MGT5100 defined +#endif diff --git a/board/mpc8349ads/u-boot.lds b/board/bc3450/u-boot.lds index 020cfa6..93b98a8 100644 --- a/board/mpc8349ads/u-boot.lds +++ b/board/bc3450/u-boot.lds @@ -1,5 +1,6 @@ /* - * Copyright 2004 Freescale Semiconductor, Inc. + * (C) Copyright 2003-2004 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. * * See file CREDITS for list of people who contributed to this * project. @@ -21,6 +22,9 @@ */ OUTPUT_ARCH(powerpc) +SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/usr/local/powerpc-any-elf/lib); +/* Do we need any of these for elf? + __DYNAMIC = 0; */ SECTIONS { /* Read-only sections, merged into text segment: */ @@ -49,7 +53,7 @@ SECTIONS .plt : { *(.plt) } .text : { - cpu/mpc83xx/start.o (.text) + cpu/mpc5xxx/start.o (.text) *(.text) *(.fixup) *(.got1) @@ -57,7 +61,6 @@ SECTIONS *(.rodata) *(.rodata1) *(.rodata.str1.4) - *(.eh_frame) } .fini : { *(.fini) } =0 .ctors : { *(.ctors) } @@ -119,4 +122,3 @@ SECTIONS _end = . ; PROVIDE (end = .); } -ENTRY(_start) diff --git a/board/cobra5272/flash.c b/board/cobra5272/flash.c index 73cc2f2..82452e2 100644 --- a/board/cobra5272/flash.c +++ b/board/cobra5272/flash.c @@ -65,6 +65,7 @@ void flash_print_info (flash_info_t * info) printf ("\n"); Done: + return; } diff --git a/board/delta/delta.c b/board/delta/delta.c index b7671dd..b127ac8 100644 --- a/board/delta/delta.c +++ b/board/delta/delta.c @@ -28,6 +28,8 @@ #include <common.h> #include <i2c.h> #include <da9030.h> +#include <malloc.h> +#include <command.h> #include <asm/arch/pxa-regs.h> DECLARE_GLOBAL_DATA_PTR; @@ -35,6 +37,9 @@ DECLARE_GLOBAL_DATA_PTR; /* ------------------------------------------------------------------------- */ static void init_DA9030(void); +static void keys_init(void); +static void get_pressed_keys(uchar *s); +static uchar *key_match(uchar *kbd_data); /* * Miscelaneous platform dependent initialisations @@ -56,13 +61,216 @@ int board_init (void) int board_late_init(void) { +#ifdef DELTA_CHECK_KEYBD + uchar kbd_data[KEYBD_DATALEN]; + char keybd_env[2 * KEYBD_DATALEN + 1]; + char *str; + int i; +#endif /* DELTA_CHECK_KEYBD */ + setenv("stdout", "serial"); setenv("stderr", "serial"); + +#ifdef DELTA_CHECK_KEYBD + keys_init(); + + memset(kbd_data, '\0', KEYBD_DATALEN); + + /* check for pressed keys and setup keybd_env */ + get_pressed_keys(kbd_data); + + for (i = 0; i < KEYBD_DATALEN; ++i) { + sprintf (keybd_env + i + i, "%02X", kbd_data[i]); + } + setenv ("keybd", keybd_env); + + str = strdup ((char *)key_match (kbd_data)); /* decode keys */ + +# ifdef CONFIG_PREBOOT /* automatically configure "preboot" command on key match */ + setenv ("preboot", str); /* set or delete definition */ +# endif /* CONFIG_PREBOOT */ + if (str != NULL) { + free (str); + } +#endif /* DELTA_CHECK_KEYBD */ + init_DA9030(); return 0; } +/* + * Magic Key Handling, mainly copied from board/lwmon/lwmon.c + */ +#ifdef DELTA_CHECK_KEYBD + +static uchar kbd_magic_prefix[] = "key_magic"; +static uchar kbd_command_prefix[] = "key_cmd"; + +/* + * Get pressed keys + * s is a buffer of size KEYBD_DATALEN-1 + */ +static void get_pressed_keys(uchar *s) +{ + unsigned long val; + val = GPLR3; + + if(val & (1<<31)) + *s++ = KEYBD_KP_DKIN0; + if(val & (1<<18)) + *s++ = KEYBD_KP_DKIN1; + if(val & (1<<29)) + *s++ = KEYBD_KP_DKIN2; + if(val & (1<<22)) + *s++ = KEYBD_KP_DKIN5; +} + +static void keys_init() +{ + CKENB |= CKENB_7_GPIO; + udelay(100); + + /* Configure GPIOs */ + GPIO127 = 0xa840; /* KP_DKIN0 */ + GPIO114 = 0xa840; /* KP_DKIN1 */ + GPIO125 = 0xa840; /* KP_DKIN2 */ + GPIO118 = 0xa840; /* KP_DKIN5 */ + + /* Configure GPIOs as inputs */ + GPDR3 &= ~(1<<31 | 1<<18 | 1<<29 | 1<<22); + GCDR3 = (1<<31 | 1<<18 | 1<<29 | 1<<22); + + udelay(100); +} + +static int compare_magic (uchar *kbd_data, uchar *str) +{ + /* uchar compare[KEYBD_DATALEN-1]; */ + uchar compare[KEYBD_DATALEN]; + char *nxt; + int i; + + /* Don't include modifier byte */ + /* memcpy (compare, kbd_data+1, KEYBD_DATALEN-1); */ + memcpy (compare, kbd_data, KEYBD_DATALEN); + + for (; str != NULL; str = (*nxt) ? (uchar *)(nxt+1) : (uchar *)nxt) { + uchar c; + int k; + + c = (uchar) simple_strtoul ((char *)str, (char **) (&nxt), 16); + + if (str == (uchar *)nxt) { /* invalid character */ + break; + } + + /* + * Check if this key matches the input. + * Set matches to zero, so they match only once + * and we can find duplicates or extra keys + */ + for (k = 0; k < sizeof(compare); ++k) { + if (compare[k] == '\0') /* only non-zero entries */ + continue; + if (c == compare[k]) { /* found matching key */ + compare[k] = '\0'; + break; + } + } + if (k == sizeof(compare)) { + return -1; /* unmatched key */ + } + } + + /* + * A full match leaves no keys in the `compare' array, + */ + for (i = 0; i < sizeof(compare); ++i) { + if (compare[i]) + { + return -1; + } + } + + return 0; +} + + +static uchar *key_match (uchar *kbd_data) +{ + char magic[sizeof (kbd_magic_prefix) + 1]; + uchar *suffix; + char *kbd_magic_keys; + + /* + * The following string defines the characters that can pe appended + * to "key_magic" to form the names of environment variables that + * hold "magic" key codes, i. e. such key codes that can cause + * pre-boot actions. If the string is empty (""), then only + * "key_magic" is checked (old behaviour); the string "125" causes + * checks for "key_magic1", "key_magic2" and "key_magic5", etc. + */ + if ((kbd_magic_keys = getenv ("magic_keys")) == NULL) + kbd_magic_keys = ""; + + /* loop over all magic keys; + * use '\0' suffix in case of empty string + */ + for (suffix=(uchar *)kbd_magic_keys; *suffix || suffix==(uchar *)kbd_magic_keys; ++suffix) { + sprintf (magic, "%s%c", kbd_magic_prefix, *suffix); +#if 0 + printf ("### Check magic \"%s\"\n", magic); +#endif + if (compare_magic(kbd_data, (uchar *)getenv(magic)) == 0) { + char cmd_name[sizeof (kbd_command_prefix) + 1]; + char *cmd; + + sprintf (cmd_name, "%s%c", kbd_command_prefix, *suffix); + + cmd = getenv (cmd_name); +#if 0 + printf ("### Set PREBOOT to $(%s): \"%s\"\n", + cmd_name, cmd ? cmd : "<<NULL>>"); +#endif + *kbd_data = *suffix; + return ((uchar *)cmd); + } + } +#if 0 + printf ("### Delete PREBOOT\n"); +#endif + *kbd_data = '\0'; + return (NULL); +} + +int do_kbd (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + uchar kbd_data[KEYBD_DATALEN]; + char keybd_env[2 * KEYBD_DATALEN + 1]; + int i; + + /* Read keys */ + get_pressed_keys(kbd_data); + puts ("Keys:"); + for (i = 0; i < KEYBD_DATALEN; ++i) { + sprintf (keybd_env + i + i, "%02X", kbd_data[i]); + printf (" %02x", kbd_data[i]); + } + putc ('\n'); + setenv ("keybd", keybd_env); + return 0; +} + +U_BOOT_CMD( + kbd, 1, 1, do_kbd, + "kbd - read keyboard status\n", + NULL +); + +#endif /* DELTA_CHECK_KEYBD */ + + int dram_init (void) { gd->bd->bi_dram[0].start = PHYS_SDRAM_1; diff --git a/board/ixdp425/Makefile b/board/ixdp425/Makefile index e4282c4..59d6964 100644 --- a/board/ixdp425/Makefile +++ b/board/ixdp425/Makefile @@ -25,7 +25,7 @@ include $(TOPDIR)/config.mk LIB = lib$(BOARD).a -OBJS := ixdp425.o flash.o +OBJS := ixdp425.o $(LIB): $(OBJS) $(SOBJS) $(AR) crv $@ $^ diff --git a/board/ixdp425/config.mk b/board/ixdp425/config.mk index 9f616f3..3420586 100644 --- a/board/ixdp425/config.mk +++ b/board/ixdp425/config.mk @@ -1,2 +1,4 @@ -#TEXT_BASE = 0x00100000 TEXT_BASE = 0x00f80000 + +# include NPE ethernet driver +BOARDLIBS = cpu/ixp/npe/libnpe.a diff --git a/board/ixdp425/ixdp425.c b/board/ixdp425/ixdp425.c index aa96591..eaf7cde 100644 --- a/board/ixdp425/ixdp425.c +++ b/board/ixdp425/ixdp425.c @@ -1,4 +1,7 @@ /* + * (C) Copyright 2006 + * Stefan Roese, DENX Software Engineering, sr@denx.de. + * * (C) Copyright 2002 * Kyle Harris, Nexus Technologies, Inc. kharris@nexus-tech.net * @@ -25,24 +28,21 @@ * MA 02111-1307 USA */ -#include <asm/arch/ixp425.h> #include <common.h> +#include <command.h> +#include <malloc.h> +#include <asm/arch/ixp425.h> DECLARE_GLOBAL_DATA_PTR; /* * Miscelaneous platform dependent initialisations */ - -/**********************************************************/ - int board_post_init (void) { return (0); } -/**********************************************************/ - int board_init (void) { /* arch number of IXDP */ @@ -51,10 +51,58 @@ int board_init (void) /* adress of boot parameters */ gd->bd->bi_boot_params = 0x00000100; +#ifdef CONFIG_IXDPG425 + /* arch number of IXDP */ + gd->bd->bi_arch_number = MACH_TYPE_IXDPG425; + + /* + * Get realtek RTL8305 switch and SLIC out of reset + */ + GPIO_OUTPUT_SET(CFG_GPIO_SWITCH_RESET_N); + GPIO_OUTPUT_ENABLE(CFG_GPIO_SWITCH_RESET_N); + GPIO_OUTPUT_SET(CFG_GPIO_SLIC_RESET_N); + GPIO_OUTPUT_ENABLE(CFG_GPIO_SLIC_RESET_N); + + /* + * Setup GPIO's for PCI INTA & INTB + */ + GPIO_OUTPUT_DISABLE(CFG_GPIO_PCI_INTA_N); + GPIO_INT_ACT_LOW_SET(CFG_GPIO_PCI_INTA_N); + GPIO_OUTPUT_DISABLE(CFG_GPIO_PCI_INTB_N); + GPIO_INT_ACT_LOW_SET(CFG_GPIO_PCI_INTB_N); + + /* + * Setup GPIO's for 33MHz clock output + */ + *IXP425_GPIO_GPCLKR = 0x01FF01FF; + GPIO_OUTPUT_ENABLE(CFG_GPIO_PCI_CLK); + GPIO_OUTPUT_ENABLE(CFG_GPIO_EXTBUS_CLK); +#endif + return 0; } -/**********************************************************/ +/* + * Check Board Identity + */ +int checkboard(void) +{ + char *s = getenv("serial#"); + +#ifdef CONFIG_IXDPG425 + puts("Board: IXDPG425 - Intel Network Gateway Reference Platform"); +#else + puts("Board: IXDP425 - Intel Development Platform"); +#endif + + if (s != NULL) { + puts(", serial# "); + puts(s); + } + putc('\n'); + + return (0); +} int dram_init (void) { @@ -64,8 +112,7 @@ int dram_init (void) return (0); } -/**********************************************************/ - +#if (CONFIG_COMMANDS & CFG_CMD_PCI) || defined(CONFIG_PCI) extern struct pci_controller hose; extern void pci_ixp_init(struct pci_controller * hose); @@ -75,3 +122,4 @@ void pci_init_board(void) pci_ixp_init(&hose); } +#endif diff --git a/board/m5271evb/Makefile b/board/m5271evb/Makefile new file mode 100644 index 0000000..34de983 --- /dev/null +++ b/board/m5271evb/Makefile @@ -0,0 +1,40 @@ +# +# (C) Copyright 2000-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# See file CREDITS for list of people who contributed to this +# project. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +include $(TOPDIR)/config.mk + +LIB = lib$(BOARD).a + +OBJS = $(BOARD).o + +$(LIB): .depend $(OBJS) + $(AR) crv $@ $(OBJS) + +######################################################################### + +.depend: Makefile $(SOBJS:.o=.S) $(OBJS:.o=.c) + $(CC) -M $(CFLAGS) $(SOBJS:.o=.S) $(OBJS:.o=.c) > $@ + +sinclude .depend + +######################################################################### diff --git a/board/mpc8349ads/config.mk b/board/m5271evb/config.mk index 4602169..9a7af7c 100644 --- a/board/mpc8349ads/config.mk +++ b/board/m5271evb/config.mk @@ -1,5 +1,7 @@ # -# Copyright 2004 Freescale Semiconductor, Inc. +# (C) Copyright 2000-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# Coldfire contribution by Bernhard Kuhn <bkuhn@metrowerks.com> # # See file CREDITS for list of people who contributed to this # project. @@ -20,8 +22,4 @@ # MA 02111-1307 USA # -# -# MPC83xxADS -# - -TEXT_BASE = 0xFE700000 +TEXT_BASE = 0xffe00000 diff --git a/board/m5271evb/m5271evb.c b/board/m5271evb/m5271evb.c new file mode 100644 index 0000000..c26c91d --- /dev/null +++ b/board/m5271evb/m5271evb.c @@ -0,0 +1,124 @@ +/* + * (C) Copyright 2000-2006 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <asm/m5271.h> +#include <asm/immap_5271.h> + +int checkboard (void) { + puts ("Board: Freescale M5271EVB\n"); + return 0; +}; + +long int initdram (int board_type) { + + int i; + + /* Enable Address lines 23-21 and lower 16bits of data path */ + mbar_writeByte(MCF_GPIO_PAR_AD, MCF_GPIO_AD_ADDR23 | + MCF_GPIO_AD_ADDR22 | MCF_GPIO_AD_ADDR21 | + MCF_GPIO_AD_DATAL); + + /* Set CS2 pin to be SD_CS0 */ + mbar_writeByte(MCF_GPIO_PAR_CS, mbar_readByte(MCF_GPIO_PAR_CS) + | MCF_GPIO_PAR_CS_PAR_CS2); + + /* Configure SDRAM Control Pin Assignemnt Register */ + mbar_writeByte(MCF_GPIO_PAR_SDRAM, MCF_GPIO_SDRAM_CSSDCS_00 | + MCF_GPIO_SDRAM_SDWE | MCF_GPIO_SDRAM_SCAS | + MCF_GPIO_SDRAM_SRAS | MCF_GPIO_SDRAM_SCKE | + MCF_GPIO_SDRAM_SDCS_11); + + /* + * Check to see if the SDRAM has already been initialized + * by a run control tool + */ + if (!(mbar_readLong(MCF_SDRAMC_DACR0) & MCF_SDRAMC_DACRn_RE)) { + /* Initialize DRAM Control Register: DCR */ + mbar_writeShort(MCF_SDRAMC_DCR, + MCF_SDRAMC_DCR_RTIM(0x01) + | MCF_SDRAMC_DCR_RC(0x30)); + + /* + * Initialize DACR0 + * + * CASL: 01 + * CBM: cmd at A20, bank select bits 21 and up + * PS: 32bit port size + */ + mbar_writeLong(MCF_SDRAMC_DACR0, + MCF_SDRAMC_DACRn_BA(CFG_SDRAM_BASE>>18) + | MCF_SDRAMC_DACRn_CASL(1) + | MCF_SDRAMC_DACRn_CBM(3) + | MCF_SDRAMC_DACRn_PS(0)); + + /* Initialize DMR0 */ + mbar_writeLong(MCF_SDRAMC_DMR0, + MCF_SDRAMC_DMRn_BAM_16M + | MCF_SDRAMC_DMRn_V); + + /* Set IP bit in DACR */ + mbar_writeLong(MCF_SDRAMC_DACR0, mbar_readLong(MCF_SDRAMC_DACR0) + | MCF_SDRAMC_DACRn_IP); + + /* Wait at least 20ns to allow banks to precharge */ + for (i = 0; i < 5; i++) + asm(" nop"); + + /* Write to this block to initiate precharge */ + *(u32 *)(CFG_SDRAM_BASE) = 0xa5a5a5a5; + + /* Set RE bit in DACR */ + mbar_writeLong(MCF_SDRAMC_DACR0, mbar_readLong(MCF_SDRAMC_DACR0) + | MCF_SDRAMC_DACRn_RE); + + /* Wait for at least 8 auto refresh cycles to occur */ + for (i = 0; i < 2000; i++) + asm(" nop"); + + /* Finish the configuration by issuing the MRS */ + mbar_writeLong(MCF_SDRAMC_DACR0, mbar_readLong(MCF_SDRAMC_DACR0) + | MCF_SDRAMC_DACRn_MRS); + + /* + * Write to the SDRAM Mode Register A0-A11 = 0x400 + * + * Write Burst Mode = Programmed Burst Length + * Op Mode = Standard Op + * CAS Latency = 2 + * Burst Type = Sequential + * Burst Length = 1 + */ + *(u32 *)(CFG_SDRAM_BASE + 0x400) = 0xa5a5a5a5; + } + + return CFG_SDRAM_SIZE * 1024 * 1024; +}; + +int testdram (void) { + + /* TODO: XXX XXX XXX */ + printf ("DRAM test not implemented!\n"); + + return (0); +} diff --git a/board/m5271evb/u-boot.lds b/board/m5271evb/u-boot.lds new file mode 100644 index 0000000..69f3179 --- /dev/null +++ b/board/m5271evb/u-boot.lds @@ -0,0 +1,145 @@ +/* + * (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 + */ + +OUTPUT_ARCH(m68k) +SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); +/* Do we need any of these for elf? + __DYNAMIC = 0; */ +GROUP(libgcc.a) +SECTIONS +{ + /* Read-only sections, merged into text segment: */ + . = + SIZEOF_HEADERS; + .interp : { *(.interp) } + .hash : { *(.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .rel.text : { *(.rel.text) } + .rela.text : { *(.rela.text) } + .rel.data : { *(.rel.data) } + .rela.data : { *(.rela.data) } + .rel.rodata : { *(.rel.rodata) } + .rela.rodata : { *(.rela.rodata) } + .rel.got : { *(.rel.got) } + .rela.got : { *(.rela.got) } + .rel.ctors : { *(.rel.ctors) } + .rela.ctors : { *(.rela.ctors) } + .rel.dtors : { *(.rel.dtors) } + .rela.dtors : { *(.rela.dtors) } + .rel.bss : { *(.rel.bss) } + .rela.bss : { *(.rela.bss) } + .rel.plt : { *(.rel.plt) } + .rela.plt : { *(.rela.plt) } + .init : { *(.init) } + .plt : { *(.plt) } + .text : + { + /* WARNING - the following is hand-optimized to fit within */ + /* the sector layout of our flash chips! XXX FIXME XXX */ + + cpu/mcf52x2/start.o (.text) + lib_m68k/traps.o (.text) + cpu/mcf52x2/interrupts.o (.text) + common/dlmalloc.o (.text) + lib_generic/zlib.o (.text) + + . = DEFINED(env_offset) ? env_offset : .; + common/environment.o (.ppcenv) + + *(.text) + *(.fixup) + *(.got1) + } + _etext = .; + PROVIDE (etext = .); + .rodata : + { + *(.rodata) + *(.rodata1) + } + .fini : { *(.fini) } =0 + .ctors : { *(.ctors) } + .dtors : { *(.dtors) } + + /* Read-write section, merged into data segment: */ + . = (. + 0x00FF) & 0xFFFFFF00; + _erotext = .; + PROVIDE (erotext = .); + + .reloc : + { + __got_start = .; + *(.got) + __got_end = .; + _GOT2_TABLE_ = .; + *(.got2) + _FIXUP_TABLE_ = .; + *(.fixup) + } + __got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >>2; + __fixup_entries = (. - _FIXUP_TABLE_)>>2; + + .data : + { + *(.data) + *(.data1) + *(.sdata) + *(.sdata2) + *(.dynamic) + CONSTRUCTORS + } + _edata = .; + PROVIDE (edata = .); + + . = .; + __u_boot_cmd_start = .; + .u_boot_cmd : { *(.u_boot_cmd) } + __u_boot_cmd_end = .; + + + . = .; + __start___ex_table = .; + __ex_table : { *(__ex_table) } + __stop___ex_table = .; + + . = ALIGN(256); + __init_begin = .; + .text.init : { *(.text.init) } + .data.init : { *(.data.init) } + . = ALIGN(256); + __init_end = .; + + __bss_start = .; + .bss : + { + _sbss = .; + *(.sbss) *(.scommon) + *(.dynbss) + *(.bss) + *(COMMON) + . = ALIGN(4); + _ebss = .; + } + _end = . ; + PROVIDE (end = .); +} diff --git a/board/m5272c3/flash.c b/board/m5272c3/flash.c index f156342..ea0b1fd 100644 --- a/board/m5272c3/flash.c +++ b/board/m5272c3/flash.c @@ -65,6 +65,7 @@ void flash_print_info (flash_info_t * info) printf ("\n"); Done: + return; } diff --git a/board/m5282evb/flash.c b/board/m5282evb/flash.c index 95f35ad..36a7c31 100644 --- a/board/m5282evb/flash.c +++ b/board/m5282evb/flash.c @@ -65,6 +65,7 @@ void flash_print_info (flash_info_t * info) printf ("\n"); Done: + return; } diff --git a/board/mcc200/mcc200.c b/board/mcc200/mcc200.c index 5fe239f..87427e4 100644 --- a/board/mcc200/mcc200.c +++ b/board/mcc200/mcc200.c @@ -242,7 +242,7 @@ int misc_init_r (void) /* Unprotect the upper bank of the Flash */ *(volatile int*)MPC5XXX_CS0_CFG |= (1 << 6); flash_protect (FLAG_PROTECT_CLEAR, - flash_info[0].start[0], + flash_info[0].start[0] + flash_info[0].size / 2, (flash_info[0].start[0] + flash_info[0].size) / 2 - 1, &flash_info[0]); *(volatile int*)MPC5XXX_CS0_CFG &= ~(1 << 6); diff --git a/board/mpc8349ads/mpc8349ads.c b/board/mpc8349ads/mpc8349ads.c deleted file mode 100644 index 9841298..0000000 --- a/board/mpc8349ads/mpc8349ads.c +++ /dev/null @@ -1,235 +0,0 @@ -/* - * Copyright Freescale Semiconductor, 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 - * - * Change log: - * 20050101: Eran Liberty (liberty@freescale.com) - * Initial file creating (porting from 85XX & 8260) - */ - -#include <common.h> -#include <ioports.h> -#include <mpc83xx.h> -#include <asm/mpc8349_pci.h> -#include <i2c.h> -#include <spd.h> -#include <miiphy.h> -#if defined(CONFIG_PCI) -#include <pci.h> -#endif -#if defined(CONFIG_SPD_EEPROM) -#include <spd_sdram.h> -#endif -int fixed_sdram(void); -void sdram_init(void); - -int board_early_init_f (void) -{ - volatile u8* bcsr = (volatile u8*)CFG_BCSR; - - /* Enable flash write */ - bcsr[1] &= ~0x01; - - return 0; -} - - -#define ns2clk(ns) (ns / (1000000000 / CONFIG_8349_CLKIN) + 1) - -long int initdram (int board_type) -{ - volatile immap_t *im = (immap_t *)CFG_IMMRBAR; - u32 msize = 0; - - if ((im->sysconf.immrbar & IMMRBAR_BASE_ADDR) != (u32)im) - return -1; - - /* DDR SDRAM - Main SODIMM */ - im->sysconf.ddrlaw[0].bar = CFG_DDR_BASE & LAWBAR_BAR; -#if defined(CONFIG_SPD_EEPROM) - msize = spd_sdram(); -#else - msize = fixed_sdram(); -#endif - /* - * Initialize SDRAM if it is on local bus. - */ - sdram_init(); - puts(" DDR RAM: "); - /* return total bus SDRAM size(bytes) -- DDR */ - return (msize * 1024 * 1024); -} - - -#if !defined(CONFIG_SPD_EEPROM) -/************************************************************************* - * fixed sdram init -- doesn't use serial presence detect. - ************************************************************************/ -int fixed_sdram(void) -{ - volatile immap_t *im = (immap_t *)CFG_IMMRBAR; - u32 msize = 0; - u32 ddr_size; - u32 ddr_size_log2; - - msize = CFG_DDR_SIZE; - for (ddr_size = msize << 20, ddr_size_log2 = 0; - (ddr_size > 1); - ddr_size = ddr_size>>1, ddr_size_log2++) { - if (ddr_size & 1) { - return -1; - } - } - im->sysconf.ddrlaw[0].ar = LAWAR_EN | ((ddr_size_log2 - 1) & LAWAR_SIZE); -#if (CFG_DDR_SIZE != 256) -#warning Currenly any ddr size other than 256 is not supported -#endif - - im->ddr.csbnds[0].csbnds = 0x00100017; - im->ddr.csbnds[1].csbnds = 0x0018001f; - im->ddr.csbnds[2].csbnds = 0x00000007; - im->ddr.csbnds[3].csbnds = 0x0008000f; - im->ddr.cs_config[0] = CFG_DDR_CONFIG; - im->ddr.cs_config[1] = CFG_DDR_CONFIG; - im->ddr.cs_config[2] = CFG_DDR_CONFIG; - im->ddr.cs_config[3] = CFG_DDR_CONFIG; - im->ddr.timing_cfg_1 = - 3 << TIMING_CFG1_PRETOACT_SHIFT | - 7 << TIMING_CFG1_ACTTOPRE_SHIFT | - 3 << TIMING_CFG1_ACTTORW_SHIFT | - 4 << TIMING_CFG1_CASLAT_SHIFT | - 3 << TIMING_CFG1_REFREC_SHIFT | - 3 << TIMING_CFG1_WRREC_SHIFT | - 2 << TIMING_CFG1_ACTTOACT_SHIFT | - 1 << TIMING_CFG1_WRTORD_SHIFT; - im->ddr.timing_cfg_2 = 2 << TIMING_CFG2_WR_DATA_DELAY_SHIFT; - im->ddr.sdram_cfg = - SDRAM_CFG_SREN -#if defined(CONFIG_DDR_2T_TIMING) - | SDRAM_CFG_2T_EN -#endif - | 2 << SDRAM_CFG_SDRAM_TYPE_SHIFT; - im->ddr.sdram_mode = - 0x2000 << SDRAM_MODE_ESD_SHIFT | - 0x0162 << SDRAM_MODE_SD_SHIFT; - - im->ddr.sdram_interval = 0x045B << SDRAM_INTERVAL_REFINT_SHIFT | - 0x0100 << SDRAM_INTERVAL_BSTOPRE_SHIFT; - udelay(200); - - im->ddr.sdram_cfg |= SDRAM_CFG_MEM_EN; - - return msize; -} -#endif/*!CFG_SPD_EEPROM*/ - - -int checkboard (void) -{ - puts("Board: Freescale MPC8349ADS\n"); - return 0; -} - -/* - * if MPC8349ADS is soldered with SDRAM - */ -#if defined(CFG_BR2_PRELIM) \ - && defined(CFG_OR2_PRELIM) \ - && defined(CFG_LBLAWBAR2_PRELIM) \ - && defined(CFG_LBLAWAR2_PRELIM) -/* - * Initialize SDRAM memory on the Local Bus. - */ - -void -sdram_init(void) -{ - volatile immap_t *immap = (immap_t *)CFG_IMMRBAR; - volatile lbus8349_t *lbc= &immap->lbus; - uint *sdram_addr = (uint *)CFG_LBC_SDRAM_BASE; - - puts("\n SDRAM on Local Bus: "); - print_size (CFG_LBC_SDRAM_SIZE * 1024 * 1024, "\n"); - - /* - * Setup SDRAM Base and Option Registers, already done in cpu_init.c - */ - - /*setup mtrpt, lsrt and lbcr for LB bus*/ - lbc->lbcr = CFG_LBC_LBCR; - lbc->mrtpr = CFG_LBC_MRTPR; - lbc->lsrt = CFG_LBC_LSRT; - asm("sync"); - - /* - * Configure the SDRAM controller Machine Mode Register. - */ - lbc->lsdmr = CFG_LBC_LSDMR_5; /* 0x40636733; normal operation*/ - - lbc->lsdmr = CFG_LBC_LSDMR_1; /*0x68636733;precharge all the banks*/ - asm("sync"); - *sdram_addr = 0xff; - udelay(100); - - lbc->lsdmr = CFG_LBC_LSDMR_2;/*0x48636733;auto refresh*/ - asm("sync"); - /*1 times*/ - *sdram_addr = 0xff; - udelay(100); - /*2 times*/ - *sdram_addr = 0xff; - udelay(100); - /*3 times*/ - *sdram_addr = 0xff; - udelay(100); - /*4 times*/ - *sdram_addr = 0xff; - udelay(100); - /*5 times*/ - *sdram_addr = 0xff; - udelay(100); - /*6 times*/ - *sdram_addr = 0xff; - udelay(100); - /*7 times*/ - *sdram_addr = 0xff; - udelay(100); - /*8 times*/ - *sdram_addr = 0xff; - udelay(100); - - /* 0x58636733;mode register write operation */ - lbc->lsdmr = CFG_LBC_LSDMR_4; - asm("sync"); - *sdram_addr = 0xff; - udelay(100); - - lbc->lsdmr = CFG_LBC_LSDMR_5; /*0x40636733;normal operation*/ - asm("sync"); - *sdram_addr = 0xff; - udelay(100); -} -#else -void -sdram_init(void) -{ - put("SDRAM on Local Bus is NOT available!\n"); -} -#endif diff --git a/board/mpc8349emds/mpc8349emds.c b/board/mpc8349emds/mpc8349emds.c index 7ece7db..b5ccb53 100644 --- a/board/mpc8349emds/mpc8349emds.c +++ b/board/mpc8349emds/mpc8349emds.c @@ -30,9 +30,6 @@ #include <spd.h> #include <miiphy.h> #include <command.h> -#if defined(CONFIG_PCI) -#include <pci.h> -#endif #if defined(CONFIG_SPD_EEPROM) #include <spd_sdram.h> #endif @@ -50,6 +47,11 @@ int board_early_init_f (void) /* Enable flash write */ bcsr[1] &= ~0x01; +#ifdef CFG_USE_MPC834XSYS_USB_PHY + /* Use USB PHY on SYS board */ + bcsr[5] |= 0x02; +#endif + return 0; } @@ -152,44 +154,6 @@ int checkboard (void) return 0; } -#if defined(CONFIG_PCI) -/* - * Initialize PCI Devices, report devices found - */ -#ifndef CONFIG_PCI_PNP -static struct pci_config_table pci_mpc8349emds_config_table[] = { - {PCI_ANY_ID,PCI_ANY_ID,PCI_ANY_ID,PCI_ANY_ID, - pci_cfgfunc_config_device, {PCI_ENET0_IOADDR, - PCI_ENET0_MEMADDR, - PCI_COMMON_MEMORY | PCI_COMMAND_MASTER - } }, - {} -} -#endif - -volatile static struct pci_controller hose[] = { - { -#ifndef CONFIG_PCI_PNP - config_table:pci_mpc8349emds_config_table, -#endif - }, - { -#ifndef CONFIG_PCI_PNP - config_table:pci_mpc8349emds_config_table, -#endif - } -}; -#endif /* CONFIG_PCI */ - -void pci_init_board(void) -{ -#ifdef CONFIG_PCI - extern void pci_mpc83xx_init(volatile struct pci_controller *hose); - - pci_mpc83xx_init(hose); -#endif /* CONFIG_PCI */ -} - /* * if MPC8349EMDS is soldered with SDRAM */ diff --git a/board/mpc8349ads/pci.c b/board/mpc8349emds/pci.c index 319e35c..63e4405 100644 --- a/board/mpc8349ads/pci.c +++ b/board/mpc8349emds/pci.c @@ -35,7 +35,7 @@ DECLARE_GLOBAL_DATA_PTR; #define CONFIG_PCI_SYS_MEM_PHYS CFG_SDRAM_BASE #ifndef CONFIG_PCI_PNP -static struct pci_config_table pci_mpc83xxads_config_table[] = { +static struct pci_config_table pci_mpc8349emds_config_table[] = { {PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_IDSEL_NUMBER, PCI_ANY_ID, pci_cfgfunc_config_device, {PCI_ENET0_IOADDR, @@ -50,12 +50,12 @@ static struct pci_config_table pci_mpc83xxads_config_table[] = { static struct pci_controller pci_hose[] = { { #ifndef CONFIG_PCI_PNP - config_table:pci_mpc83xxads_config_table, + config_table:pci_mpc8349emds_config_table, #endif }, { #ifndef CONFIG_PCI_PNP - config_table:pci_mpc83xxads_config_table, + config_table:pci_mpc8349emds_config_table, #endif } }; @@ -188,7 +188,7 @@ pci_init_board(void) pci_law[0].ar = LAWAR_EN | LAWAR_SIZE_1G; pci_law[1].bar = CFG_PCI1_IO_PHYS & LAWBAR_BAR; - pci_law[1].ar = LAWAR_EN | LAWAR_SIZE_32M; + pci_law[1].ar = LAWAR_EN | LAWAR_SIZE_4M; /* * Configure PCI Outbound Translation Windows @@ -378,4 +378,5 @@ pci_init_board(void) #endif } + #endif /* CONFIG_PCI */ diff --git a/board/nc650/Makefile b/board/nc650/Makefile index a4dd85f..8dc4934 100644 --- a/board/nc650/Makefile +++ b/board/nc650/Makefile @@ -1,4 +1,5 @@ # +# (C) Copyright 2006 Detlev Zundel, dzu@denx.de # (C) Copyright 2004 # Wolfgang Denk, DENX Software Engineering, wd@denx.de. # @@ -25,7 +26,7 @@ include $(TOPDIR)/config.mk LIB = lib$(BOARD).a -OBJS = $(BOARD).o flash.o +OBJS = $(BOARD).o nand.o flash.o $(LIB): .depend $(OBJS) $(AR) crv $@ $(OBJS) diff --git a/board/nc650/config.mk b/board/nc650/config.mk index fa8ba31..5b2284a 100644 --- a/board/nc650/config.mk +++ b/board/nc650/config.mk @@ -1,4 +1,5 @@ # +# (C) Copyright 2006 Detlev Zundel, dzu@denx.de # (C) Copyright 2004 # Wolfgang Denk, DENX Software Engineering, wd@denx.de. # @@ -26,3 +27,4 @@ # TEXT_BASE = 0x40700000 +BOARDLIBS = drivers/nand/libnand.a diff --git a/board/nc650/nand.c b/board/nc650/nand.c new file mode 100644 index 0000000..de54386 --- /dev/null +++ b/board/nc650/nand.c @@ -0,0 +1,117 @@ +/* + * (C) Copyright 2006 Detlev Zundel, dzu@denx.de + * (C) Copyright 2006 DENX Software Engineering + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> + + +#if (CONFIG_COMMANDS & CFG_CMD_NAND) + +#include <nand.h> + +#if defined(CONFIG_IDS852_REV1) +/* + * hardware specific access to control-lines + */ +static void nc650_hwcontrol(struct mtd_info *mtd, int cmd) +{ + struct nand_chip *this = mtd->priv; + + switch(cmd) { + case NAND_CTL_SETCLE: + this->IO_ADDR_W += 2; + break; + case NAND_CTL_CLRCLE: + this->IO_ADDR_W -= 2; + break; + case NAND_CTL_SETALE: + this->IO_ADDR_W += 1; + break; + case NAND_CTL_CLRALE: + this->IO_ADDR_W -= 1; + break; + case NAND_CTL_SETNCE: + case NAND_CTL_CLRNCE: + /* nop */ + break; + } +} +#elif defined(CONFIG_IDS852_REV2) +/* + * hardware specific access to control-lines + */ +static void nc650_hwcontrol(struct mtd_info *mtd, int cmd) +{ + struct nand_chip *this = mtd->priv; + + switch(cmd) { + case NAND_CTL_SETCLE: + *(((volatile __u8 *) this->IO_ADDR_W) + 0xa) = 0; + break; + case NAND_CTL_CLRCLE: + *(((volatile __u8 *) this->IO_ADDR_W) + 0x8) = 0; + break; + case NAND_CTL_SETALE: + *(((volatile __u8 *) this->IO_ADDR_W) + 0x9) = 0; + break; + case NAND_CTL_CLRALE: + *(((volatile __u8 *) this->IO_ADDR_W) + 0x8) = 0; + break; + case NAND_CTL_SETNCE: + *(((volatile __u8 *) this->IO_ADDR_W) + 0x8) = 0; + break; + case NAND_CTL_CLRNCE: + *(((volatile __u8 *) this->IO_ADDR_W) + 0xc) = 0; + break; + } +} +#else +#error Unknown IDS852 module revision +#endif + +/* + * Board-specific NAND initialization. The following members of the + * argument are board-specific (per include/linux/mtd/nand.h): + * - IO_ADDR_R?: address to read the 8 I/O lines of the flash device + * - IO_ADDR_W?: address to write the 8 I/O lines of the flash device + * - hwcontrol: hardwarespecific function for accesing control-lines + * - dev_ready: hardwarespecific function for accesing device ready/busy line + * - enable_hwecc?: function to enable (reset) hardware ecc generator. Must + * only be provided if a hardware ECC is available + * - eccmode: mode of ecc, see defines + * - chip_delay: chip dependent delay for transfering data from array to + * read regs (tR) + * - options: various chip options. They can partly be set to inform + * nand_scan about special functionality. See the defines for further + * explanation + * Members with a "?" were not set in the merged testing-NAND branch, + * so they are not set here either. + */ +void board_nand_init(struct nand_chip *nand) +{ + + nand->hwcontrol = nc650_hwcontrol; + nand->eccmode = NAND_ECC_SOFT; + nand->chip_delay = 12; +/* nand->options = NAND_SAMSUNG_LP_OPTIONS;*/ +} +#endif /* (CONFIG_COMMANDS & CFG_CMD_NAND) */ diff --git a/board/nc650/nc650.c b/board/nc650/nc650.c index fe96b93..8a6b5b0 100644 --- a/board/nc650/nc650.c +++ b/board/nc650/nc650.c @@ -1,4 +1,5 @@ /* + * (C) Copyright 2006 Detlev Zundel, dzu@denx.de * (C) Copyright 2001 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. * @@ -108,7 +109,16 @@ const uint nand_flash_table[] = { int checkboard (void) { - puts ("Board: NC650\n"); +#if !defined(CONFIG_CP850) + puts ("Board: NC650"); +#else + puts ("Board: CP850"); +#endif +#if defined(CONFIG_IDS852_REV1) + puts (" with IDS852 rev 1 module\n"); +#elif defined(CONFIG_IDS852_REV2) + puts (" with IDS852 rev 2 module\n"); +#endif return 0; } @@ -241,13 +251,61 @@ static long int dram_size (long int mamr_value, long int *base, long int maxsize return (get_ram_size(base, maxsize)); } -#if (CONFIG_COMMANDS & CFG_CMD_NAND) -void nand_init(void) + +#if defined(CONFIG_CP850) + +#define DPRAM_VARNAME "KP850DIP" +#define PARAM_ADDR 0x7C0 +#define NAME_ADDR 0x7F8 +#define BOARD_NAME "KP01" +#define DEFAULT_LB "241111" + +int misc_init_r(void) { - extern unsigned long nand_probe(unsigned long physadr); + int iCompatMode = 0; + char *pParam = NULL; + char *envlb; - unsigned long totlen = nand_probe(CFG_NAND_BASE); + /* + First byte in CPLD read address space signals compatibility mode + 0 - cp850 + 1 - kp852 + */ + pParam = (char*)(CFG_CPLD_BASE); + if( *pParam != 0) + iCompatMode = 1; + + if ( iCompatMode != 0) { + /* + In KP852 compatibility mode we have to write to + DPRAM as early as possible the binary coded + line config and board name. + The line config is derived from the environment + variable DPRAM_VARNAME by converting from ASCII + to binary per character. + */ + if ( (envlb = getenv ( DPRAM_VARNAME )) == 0) { + setenv( DPRAM_VARNAME, DEFAULT_LB); + envlb = DEFAULT_LB; + } + + /* Status string */ + printf("Mode: KP852(LB=%s)\n", envlb); + + /* copy appl init */ + pParam = (char*)(DPRAM_BASE_ADDR + PARAM_ADDR); + while (*envlb) { + *(pParam++) = *(envlb++) - '0'; + } + *pParam = '\0'; + + /* copy board id */ + pParam = (char*)(DPRAM_BASE_ADDR + NAME_ADDR); + strcpy( pParam, BOARD_NAME); + } else { + puts("Mode: CP850\n"); + } - printf ("%4lu MB\n", totlen >> 20); + return 0; } #endif diff --git a/board/omap1610inn/lowlevel_init.S b/board/omap1610inn/lowlevel_init.S index eaf1742..cc8347f 100644 --- a/board/omap1610inn/lowlevel_init.S +++ b/board/omap1610inn/lowlevel_init.S @@ -382,7 +382,7 @@ REG_WATCHDOG: .word 0xfffec808 REG_MPU_LOAD_TIMER: - .word 0xfffec600 + .word 0xfffec504 REG_MPU_CNTL_TIMER: .word 0xfffec500 diff --git a/board/omap5912osk/lowlevel_init.S b/board/omap5912osk/lowlevel_init.S index 3b9633a..a1fa097 100644 --- a/board/omap5912osk/lowlevel_init.S +++ b/board/omap5912osk/lowlevel_init.S @@ -41,6 +41,13 @@ _TEXT_BASE: .globl lowlevel_init lowlevel_init: + /*------------------------------------------------------* + * Ensure i-cache is enabled * + * To configure TC regs without fetching instruction * + *------------------------------------------------------*/ + mrc p15, 0, r0, c1, c0 + orr r0, r0, #0x1000 + mcr p15, 0, r0, c1, c0 /*------------------------------------------------------* *mask all IRQs by setting all bits in the INTMR default* @@ -59,33 +66,34 @@ lowlevel_init: str r1, [r0] /*------------------------------------------------------* - * Set up ARM CLM registers (IDLECT2) * + * Set up ARM CLM registers (IDLECT2) * *------------------------------------------------------*/ ldr r0, REG_ARM_IDLECT2 ldr r1, VAL_ARM_IDLECT2 str r1, [r0] /*------------------------------------------------------* - * Set up ARM CLM registers (IDLECT3) * + * Set up ARM CLM registers (IDLECT3) * *------------------------------------------------------*/ ldr r0, REG_ARM_IDLECT3 ldr r1, VAL_ARM_IDLECT3 str r1, [r0] - - mov r1, #0x01 /* PER_EN bit */ + mov r1, #0x01 /* PER_EN bit */ ldr r0, REG_ARM_RSTCT2 - strh r1, [r0] /* CLKM; Peripheral reset. */ + strh r1, [r0] /* CLKM; Peripheral reset. */ - /* Set CLKM to Sync-Scalable */ - /* I supposedly need to enable the dsp clock before switching */ - mov r1, #0x0000 + /* Set CLKM to Sync-Scalable */ + mov r1, #0x1000 ldr r0, REG_ARM_SYSST - strh r1, [r0] - mov r0, #0x400 -1: - subs r0, r0, #0x1 /* wait for any bubbles to finish */ + + mov r2, #0 +1: cmp r2, #1 + streqh r1, [r0] + add r2, r2, #1 + cmp r2, #0x100 /* wait for any bubbles to finish */ bne 1b + ldr r1, VAL_ARM_CKCTL ldr r0, REG_ARM_CKCTL strh r1, [r0] @@ -107,17 +115,16 @@ lowlevel_init: ldr r1, VAL_DPLL1_CTL ldr r0, REG_DPLL1_CTL strh r1, [r0] - ands r1, r1, #0x10 /* Check if PLL is enabled. */ - beq lock_end /* Do not look for lock if BYPASS selected */ + ands r1, r1, #0x10 /* Check if PLL is enabled. */ + beq lock_end /* Do not look for lock if BYPASS selected */ 2: ldrh r1, [r0] - ands r1, r1, #0x01 /* Check the LOCK bit.*/ - beq 2b /* loop until bit goes hi. */ + ands r1, r1, #0x01 /* Check the LOCK bit.*/ + beq 2b /* loop until bit goes hi. */ lock_end: - /*------------------------------------------------------* - * Turn off the watchdog during init... * + * Turn off the watchdog during init... * *------------------------------------------------------*/ ldr r0, REG_WATCHDOG ldr r1, WATCHDOG_VAL1 @@ -143,30 +150,49 @@ watch2Wait: tst r1, #0x10 bne watch2Wait - /* Set memory timings corresponding to the new clock speed */ + ldr r3, VAL_SDRAM_CONFIG_SDF0 /* Check execution location to determine current execution location * and branch to appropriate initialization code. */ - /* Load physical SDRAM base. */ - mov r0, #0x10000000 - /* Get current execution location. */ - mov r1, pc - /* Compare. */ - cmp r1, r0 - /* Skip over EMIF-fast initialization if running from SDRAM. */ - bge skip_sdram + mov r0, #0x10000000 /* Load physical SDRAM base. */ + mov r1, pc /* Get current execution location. */ + cmp r1, r0 /* Compare. */ + bge skip_sdram /* Skip over EMIF-fast initialization if running from SDRAM. */ + + /* identify the device revision, -- TMX or TMP(TMS) */ + ldr r0, REG_DEVICE_ID + ldr r1, [r0] + + ldr r0, VAL_DEVICE_ID_TMP + mov r1, r1, lsl #15 + mov r1, r1, lsr #16 + cmp r0, r1 + bne skip_TMP_Patch + + /* Enable TMP/TMS device new features */ + mov r0, #1 + ldr r1, REG_TC_EMIFF_DOUBLER + str r0, [r1] + + /* Enable new ac parameters */ + mov r0, #0x0b + ldr r1, REG_SDRAM_CONFIG2 + str r0, [r1] + + ldr r3, VAL_SDRAM_CONFIG_SDF1 + +skip_TMP_Patch: /* * Delay for SDRAM initialization. */ - mov r3, #0x1800 /* value should be checked */ + mov r0, #0x1800 /* value should be checked */ 3: - subs r3, r3, #0x1 /* Decrement count */ + subs r0, r0, #0x1 /* Decrement count */ bne 3b - /* * Set SDRAM control values. Disable refresh before MRS command. */ @@ -178,14 +204,15 @@ watch2Wait: /* config register */ ldr r0, REG_SDRAM_CONFIG - ldr r1, SDRAM_CONFIG_VAL - str r1, [r0] + str r3, [r0] /* manual command register */ ldr r0, REG_SDRAM_MANUAL_CMD + /* issue set cke high */ mov r1, #CMD_SDRAM_CKE_SET_HIGH str r1, [r0] + /* issue nop */ mov r1, #CMD_SDRAM_NOP str r1, [r0] @@ -228,25 +255,23 @@ waitMDDR1: str r1, [r0] /* delay loop */ - mov r2, #0x0100 + mov r0, #0x0100 waitMDDR2: - subs r2, r2, #1 + subs r0, r0, #1 bne waitMDDR2 /* * Delay for SDRAM initialization. */ - mov r3, #0x1800 + mov r0, #0x1800 4: - subs r3, r3, #1 /* Decrement count. */ + subs r0, r0, #1 /* Decrement count. */ bne 4b b common_tc skip_sdram: - ldr r0, REG_SDRAM_CONFIG - ldr r1, SDRAM_CONFIG_VAL - str r1, [r0] + str r3, [r0] common_tc: /* slow interface */ @@ -257,10 +282,15 @@ common_tc: ldr r1, VAL_TC_EMIFS_CS1_CONFIG ldr r0, REG_TC_EMIFS_CS1_CONFIG str r1, [r0] /* Chip Select 1 */ + ldr r1, VAL_TC_EMIFS_CS3_CONFIG ldr r0, REG_TC_EMIFS_CS3_CONFIG str r1, [r0] /* Chip Select 3 */ + ldr r1, VAL_TC_EMIFS_DWS + ldr r0, REG_TC_EMIFS_DWS + str r1, [r0] /* Enable EMIFS.RDY for CS1 (ether) */ + #ifdef CONFIG_H2_OMAP1610 /* inserting additional 2 clock cycle hold time for LAN */ ldr r0, REG_TC_EMIFS_CS1_ADVANCED @@ -282,8 +312,9 @@ common_tc: /* the literal pools origin */ .ltorg - -REG_TC_EMIFS_CONFIG: /* 32 bits */ +REG_DEVICE_ID: /* 32 bits */ + .word 0xfffe2004 +REG_TC_EMIFS_CONFIG: .word 0xfffecc0c REG_TC_EMIFS_CS0_CONFIG: /* 32 bits */ .word 0xfffecc10 @@ -293,7 +324,8 @@ REG_TC_EMIFS_CS2_CONFIG: /* 32 bits */ .word 0xfffecc18 REG_TC_EMIFS_CS3_CONFIG: /* 32 bits */ .word 0xfffecc1c - +REG_TC_EMIFS_DWS: /* 32 bits */ + .word 0xfffecc40 #ifdef CONFIG_H2_OMAP1610 REG_TC_EMIFS_CS1_ADVANCED: /* 32 bits */ .word 0xfffecc54 @@ -302,18 +334,17 @@ REG_TC_EMIFS_CS1_ADVANCED: /* 32 bits */ /* MPU clock/reset/power mode control registers */ REG_ARM_CKCTL: /* 16 bits */ .word 0xfffece00 - REG_ARM_IDLECT3: /* 16 bits */ .word 0xfffece24 REG_ARM_IDLECT2: /* 16 bits */ .word 0xfffece08 REG_ARM_IDLECT1: /* 16 bits */ .word 0xfffece04 - REG_ARM_RSTCT2: /* 16 bits */ .word 0xfffece14 REG_ARM_SYSST: /* 16 bits */ .word 0xfffece18 + /* DPLL control registers */ REG_DPLL1_CTL: /* 16 bits */ .word 0xfffecf00 @@ -335,6 +366,10 @@ WSPRDOG_VAL2: counter @8192 rows, 10 ns, 8 burst */ REG_SDRAM_CONFIG: .word 0xfffecc20 +REG_SDRAM_CONFIG2: + .word 0xfffecc3c +REG_TC_EMIFF_DOUBLER: /* 32 bits */ + .word 0xfffecc60 /* Operation register */ REG_SDRAM_OPERATION: @@ -356,35 +391,47 @@ REG_SDRAM_EMRS1: REG_DLL_WRT_CONTROL: .word 0xfffecc68 DLL_WRT_CONTROL_VAL: - .word 0x03f00002 + .word 0x03f00002 /* Phase of 72deg, write offset +31 */ /* URD DLL register */ REG_DLL_URD_CONTROL: .word 0xfffeccc0 DLL_URD_CONTROL_VAL: - .word 0x00800002 + .word 0x00800002 /* Phase of 72deg, read offset +31 */ /* LRD DLL register */ REG_DLL_LRD_CONTROL: .word 0xfffecccc +DLL_LRD_CONTROL_VAL: + .word 0x00800002 /* read offset +31 */ REG_WATCHDOG: .word 0xfffec808 +WATCHDOG_VAL1: + .word 0x000000f5 +WATCHDOG_VAL2: + .word 0x000000a0 REG_MPU_LOAD_TIMER: - .word 0xfffec600 + .word 0xfffec504 REG_MPU_CNTL_TIMER: .word 0xfffec500 +VAL_MPU_LOAD_TIMER: + .word 0xffffffff +VAL_MPU_CNTL_TIMER: + .word 0xffffffa1 /* 96 MHz Samsung Mobile DDR */ -SDRAM_CONFIG_VAL: - .word 0x001200f4 +/* Original setting for TMX device */ +VAL_SDRAM_CONFIG_SDF0: + .word 0x0014e6fe -DLL_LRD_CONTROL_VAL: - .word 0x00800002 +/* NEW_SYS_FREQ mode (valid only TMP/TMS devices) */ +VAL_SDRAM_CONFIG_SDF1: + .word 0x0114e6fe VAL_ARM_CKCTL: - .word 0x3000 + .word 0x2000 /* was: 0x3000, now use CLK_REF for timer input */ VAL_DPLL1_CTL: .word 0x2830 @@ -392,11 +439,15 @@ VAL_DPLL1_CTL: VAL_TC_EMIFS_CS0_CONFIG: .word 0x002130b0 VAL_TC_EMIFS_CS1_CONFIG: - .word 0x00001131 + .word 0x00001133 VAL_TC_EMIFS_CS2_CONFIG: .word 0x000055f0 VAL_TC_EMIFS_CS3_CONFIG: - .word 0x88011131 + .word 0x88013141 +VAL_TC_EMIFS_DWS: /* Enable EMIFS.RDY for CS1 access (ether) */ + .word 0x000000c0 +VAL_DEVICE_ID_TMP: /* TMP/TMS=0xb65f, TMX=0xb58c */ + .word 0xb65f #endif #ifdef CONFIG_H2_OMAP1610 @@ -407,36 +458,20 @@ VAL_TC_EMIFS_CS1_CONFIG: VAL_TC_EMIFS_CS2_CONFIG: .word 0xf800f22a VAL_TC_EMIFS_CS3_CONFIG: - .word 0x88011131 + .word 0x88013141 VAL_TC_EMIFS_CS1_ADVANCED: .word 0x00000022 #endif -VAL_TC_EMIFF_SDRAM_CONFIG: - .word 0x010290fc -VAL_TC_EMIFF_MRS: - .word 0x00000027 - VAL_ARM_IDLECT1: .word 0x00000400 - VAL_ARM_IDLECT2: .word 0x00000886 VAL_ARM_IDLECT3: .word 0x00000015 -WATCHDOG_VAL1: - .word 0x000000f5 -WATCHDOG_VAL2: - .word 0x000000a0 - -VAL_MPU_LOAD_TIMER: - .word 0xffffffff -VAL_MPU_CNTL_TIMER: - .word 0xffffffa1 - /* command values */ -.equ CMD_SDRAM_NOP, 0x00000000 -.equ CMD_SDRAM_PRECHARGE, 0x00000001 -.equ CMD_SDRAM_AUTOREFRESH, 0x00000002 -.equ CMD_SDRAM_CKE_SET_HIGH, 0x00000007 +.equ CMD_SDRAM_NOP, 0x00000000 +.equ CMD_SDRAM_PRECHARGE, 0x00000001 +.equ CMD_SDRAM_AUTOREFRESH, 0x00000002 +.equ CMD_SDRAM_CKE_SET_HIGH, 0x00000007 diff --git a/board/omap5912osk/omap5912osk.c b/board/omap5912osk/omap5912osk.c index e9e6b0e..6993b13 100644 --- a/board/omap5912osk/omap5912osk.c +++ b/board/omap5912osk/omap5912osk.c @@ -288,3 +288,21 @@ void peripheral_power_enable (void) *SW_CLOCK_REQUEST |= UART1_48MHZ_ENABLE; } + +/* + * Check Board Identity + */ +int checkboard(void) +{ + char *s = getenv("serial#"); + + puts("Board: OSK5912"); + + if (s != NULL) { + puts(", serial# "); + puts(s); + } + putc('\n'); + + return (0); +} diff --git a/board/omap730p2/lowlevel_init.S b/board/omap730p2/lowlevel_init.S index 6c6f482..9ab71cf 100644 --- a/board/omap730p2/lowlevel_init.S +++ b/board/omap730p2/lowlevel_init.S @@ -317,7 +317,7 @@ REG_WATCHDOG: .word 0xfffec808 REG_MPU_LOAD_TIMER: - .word 0xfffec600 + .word 0xfffec504 REG_MPU_CNTL_TIMER: .word 0xfffec500 diff --git a/board/pcs440ep/Makefile b/board/pcs440ep/Makefile new file mode 100644 index 0000000..4a2a388 --- /dev/null +++ b/board/pcs440ep/Makefile @@ -0,0 +1,47 @@ +# +# (C) Copyright 2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# See file CREDITS for list of people who contributed to this +# project. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +include $(TOPDIR)/config.mk + +LIB = lib$(BOARD).a + +OBJS = $(BOARD).o flash.o +SOBJS = init.o + +$(LIB): $(OBJS) $(SOBJS) + $(AR) crv $@ $(OBJS) + +clean: + rm -f $(SOBJS) $(OBJS) + +distclean: clean + rm -f $(LIB) core *.bak .depend + +######################################################################### + +.depend: Makefile $(SOBJS:.o=.S) $(OBJS:.o=.c) + $(CC) -M $(CFLAGS) $(SOBJS:.o=.S) $(OBJS:.o=.c) > $@ + +sinclude .depend + +######################################################################### diff --git a/board/pcs440ep/config.mk b/board/pcs440ep/config.mk new file mode 100644 index 0000000..319c4fa --- /dev/null +++ b/board/pcs440ep/config.mk @@ -0,0 +1,44 @@ +# +# (C) Copyright 2006 +# 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 +# + +# +# PCS440EP board +# + +#TEXT_BASE = 0x00001000 + +ifeq ($(ramsym),1) +TEXT_BASE = 0xFBD00000 +else +TEXT_BASE = 0xFFFA0000 +endif + +PLATFORM_CPPFLAGS += -DCONFIG_440=1 + +ifeq ($(debug),1) +PLATFORM_CPPFLAGS += -DDEBUG +endif + +ifeq ($(dbcr),1) +PLATFORM_CPPFLAGS += -DCFG_INIT_DBCR=0x8cff0000 +endif diff --git a/board/pcs440ep/flash.c b/board/pcs440ep/flash.c new file mode 100644 index 0000000..ece5478 --- /dev/null +++ b/board/pcs440ep/flash.c @@ -0,0 +1,608 @@ +/* + * (C) Copyright 2006 + * Stefan Roese, DENX Software Engineering, sr@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <asm/processor.h> + +#ifndef CFG_FLASH_READ0 +#define CFG_FLASH_READ0 0x0000 /* 0 is standard */ +#define CFG_FLASH_READ1 0x0001 /* 1 is standard */ +#define CFG_FLASH_READ2 0x0002 /* 2 is standard */ +#endif + +flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips */ + +/* + * Functions + */ +static int write_word(flash_info_t *info, ulong dest, ulong data); +static ulong flash_get_size(vu_long *addr, flash_info_t *info); + +unsigned long flash_init(void) +{ + unsigned long size_b0, size_b1; + int i; + 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]); + + return (size_b0 + size_b1); +} + +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; + case FLASH_MAN_EXCEL: printf ("Excel Semiconductor "); 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_AM040: printf ("AM29LV040B (4 Mbit, uniform sector size)\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_AM320T: printf ("AM29LV320T (32 M, top sector)\n"); + break; + case FLASH_AM320B: printf ("AM29LV320B (32 M, bottom sector)\n"); + break; + case FLASH_AMDL322T: printf ("AM29DL322T (32 M, top sector)\n"); + break; + case FLASH_AMDL322B: printf ("AM29DL322B (32 M, bottom sector)\n"); + break; + case FLASH_AMDL323T: printf ("AM29DL323T (32 M, top sector)\n"); + break; + case FLASH_AMDL323B: printf ("AM29DL323B (32 M, bottom sector)\n"); + break; + case FLASH_SST020: printf ("SST39LF/VF020 (2 Mbit, uniform sector size)\n"); + break; + case FLASH_SST040: printf ("SST39LF/VF040 (4 Mbit, uniform sector size)\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) { +#ifdef CFG_FLASH_EMPTY_INFO + /* + * 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 "); + /* print empty and read-only info */ + printf (" %08lX%s%s", + info->start[i], + erased ? " E" : " ", + info->protect[i] ? "RO " : " "); +#else + if ((i % 5) == 0) + printf ("\n "); + printf (" %08lX%s", + info->start[i], + 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; + short n; + volatile CFG_FLASH_WORD_SIZE value; + ulong base = (ulong)addr; + volatile CFG_FLASH_WORD_SIZE *addr2 = (volatile CFG_FLASH_WORD_SIZE *)addr; + + /* Write auto select command: read Manufacturer ID */ + addr2[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00AA00AA; + addr2[CFG_FLASH_ADDR1] = (CFG_FLASH_WORD_SIZE)0x00550055; + addr2[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00900090; + + value = addr2[CFG_FLASH_READ0]; + + switch (value) { + case (CFG_FLASH_WORD_SIZE)AMD_MANUFACT: + info->flash_id = FLASH_MAN_AMD; + break; + case (CFG_FLASH_WORD_SIZE)FUJ_MANUFACT: + info->flash_id = FLASH_MAN_FUJ; + break; + case (CFG_FLASH_WORD_SIZE)SST_MANUFACT: + info->flash_id = FLASH_MAN_SST; + break; + case (CFG_FLASH_WORD_SIZE)EXCEL_MANUFACT: + info->flash_id = FLASH_MAN_EXCEL; + break; + default: + info->flash_id = FLASH_UNKNOWN; + info->sector_count = 0; + info->size = 0; + return (0); /* no or unknown flash */ + } + + value = addr2[CFG_FLASH_READ1]; /* device ID */ + + switch (value) { + case (CFG_FLASH_WORD_SIZE)AMD_ID_LV400T: + info->flash_id += FLASH_AM400T; + info->sector_count = 11; + info->size = 0x00080000; + break; /* => 0.5 MB */ + + case (CFG_FLASH_WORD_SIZE)AMD_ID_LV400B: + info->flash_id += FLASH_AM400B; + info->sector_count = 11; + info->size = 0x00080000; + break; /* => 0.5 MB */ + + case (CFG_FLASH_WORD_SIZE)AMD_ID_LV040B: + info->flash_id += FLASH_AM040; + info->sector_count = 8; + info->size = 0x0080000; /* => 0.5 MB */ + break; + + case (CFG_FLASH_WORD_SIZE)AMD_ID_LV800T: + info->flash_id += FLASH_AM800T; + info->sector_count = 19; + info->size = 0x00100000; + break; /* => 1 MB */ + + case (CFG_FLASH_WORD_SIZE)AMD_ID_LV800B: + info->flash_id += FLASH_AM800B; + info->sector_count = 19; + info->size = 0x00100000; + break; /* => 1 MB */ + + case (CFG_FLASH_WORD_SIZE)AMD_ID_LV160T: + info->flash_id += FLASH_AM160T; + info->sector_count = 35; + info->size = 0x00200000; + break; /* => 2 MB */ + + case (CFG_FLASH_WORD_SIZE)AMD_ID_LV160B: + info->flash_id += FLASH_AM160B; + info->sector_count = 35; + info->size = 0x00200000; + break; /* => 2 MB */ + + case (CFG_FLASH_WORD_SIZE)AMD_ID_LV320T: + info->flash_id += FLASH_AM320T; + info->sector_count = 71; + info->size = 0x00400000; + break; /* => 4 MB */ + + case (CFG_FLASH_WORD_SIZE)AMD_ID_LV320B: + info->flash_id += FLASH_AM320B; + info->sector_count = 71; + info->size = 0x00400000; + break; /* => 4 MB */ + + case (CFG_FLASH_WORD_SIZE)AMD_ID_DL322T: + info->flash_id += FLASH_AMDL322T; + info->sector_count = 71; + info->size = 0x00400000; + break; /* => 4 MB */ + + case (CFG_FLASH_WORD_SIZE)AMD_ID_DL322B: + info->flash_id += FLASH_AMDL322B; + info->sector_count = 71; + info->size = 0x00400000; + break; /* => 4 MB */ + + case (CFG_FLASH_WORD_SIZE)AMD_ID_DL323T: + info->flash_id += FLASH_AMDL323T; + info->sector_count = 71; + info->size = 0x00400000; + break; /* => 4 MB */ + + case (CFG_FLASH_WORD_SIZE)AMD_ID_DL323B: + info->flash_id += FLASH_AMDL323B; + info->sector_count = 71; + info->size = 0x00400000; + break; /* => 4 MB */ + + case (CFG_FLASH_WORD_SIZE)SST_ID_xF020: + info->flash_id += FLASH_SST020; + info->sector_count = 64; + info->size = 0x00040000; + break; /* => 256 kB */ + + case (CFG_FLASH_WORD_SIZE)SST_ID_xF040: + info->flash_id += FLASH_SST040; + info->sector_count = 128; + info->size = 0x00080000; + break; /* => 512 kB */ + + 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_TYPEMASK) == FLASH_AM640U)) { + for (i = 0; i < info->sector_count; i++) + info->start[i] = base + (i * 0x00001000); + } else if ((info->flash_id & FLASH_TYPEMASK) == FLASH_AM040) { + for (i = 0; i < info->sector_count; i++) + info->start[i] = base + (i * 0x00010000); + } else if (((info->flash_id & FLASH_TYPEMASK) == FLASH_AMDL322B) || + ((info->flash_id & FLASH_TYPEMASK) == FLASH_AMDL323B) || + ((info->flash_id & FLASH_TYPEMASK) == FLASH_AM320B) || + ((info->flash_id & FLASH_TYPEMASK) == FLASH_AMDL324B)) { + /* set sector offsets for bottom boot block type */ + for (i=0; i<8; ++i) { /* 8 x 8k boot sectors */ + info->start[i] = base; + base += 8 << 10; + } + while (i < info->sector_count) { /* 64k regular sectors */ + info->start[i] = base; + base += 64 << 10; + ++i; + } + } else if (((info->flash_id & FLASH_TYPEMASK) == FLASH_AMDL322T) || + ((info->flash_id & FLASH_TYPEMASK) == FLASH_AMDL323T) || + ((info->flash_id & FLASH_TYPEMASK) == FLASH_AM320T) || + ((info->flash_id & FLASH_TYPEMASK) == FLASH_AMDL324T)) { + /* set sector offsets for top boot block type */ + base += info->size; + i = info->sector_count; + for (n=0; n<8; ++n) { /* 8 x 8k boot sectors */ + base -= 8 << 10; + --i; + info->start[i] = base; + } + while (i > 0) { /* 64k regular sectors */ + base -= 64 << 10; + --i; + info->start[i] = base; + } + } 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 CFG_FLASH_WORD_SIZE *)(info->start[i]); + if ((info->flash_id & FLASH_VENDMASK) != FLASH_MAN_AMD) + info->protect[i] = 0; + else + info->protect[i] = addr2[CFG_FLASH_READ2] & 1; + } + + /* + * Prevent writes to uninitialized FLASH. + */ + if (info->flash_id != FLASH_UNKNOWN) { + addr2 = (CFG_FLASH_WORD_SIZE *)info->start[0]; + *addr2 = (CFG_FLASH_WORD_SIZE)0x00F000F0; /* reset bank */ + } + + return (info->size); +} + + +int flash_erase(flash_info_t *info, int s_first, int s_last) +{ + volatile CFG_FLASH_WORD_SIZE *addr = (CFG_FLASH_WORD_SIZE *)(info->start[0]); + volatile CFG_FLASH_WORD_SIZE *addr2; + 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) { + 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 = (CFG_FLASH_WORD_SIZE *)(info->start[sect]); + if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST) { + addr[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00AA00AA; + addr[CFG_FLASH_ADDR1] = (CFG_FLASH_WORD_SIZE)0x00550055; + addr[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00800080; + addr[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00AA00AA; + addr[CFG_FLASH_ADDR1] = (CFG_FLASH_WORD_SIZE)0x00550055; + addr2[0] = (CFG_FLASH_WORD_SIZE)0x00300030; /* sector erase */ + + /* re-enable interrupts if necessary */ + if (flag) { + enable_interrupts(); + flag = 0; + } + + /* data polling for D7 */ + start = get_timer (0); + while ((addr2[0] & (CFG_FLASH_WORD_SIZE)0x00800080) != + (CFG_FLASH_WORD_SIZE)0x00800080) { + if (get_timer(start) > CFG_FLASH_WRITE_TOUT) + return (1); + } + } else { + if (sect == s_first) { + addr[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00AA00AA; + addr[CFG_FLASH_ADDR1] = (CFG_FLASH_WORD_SIZE)0x00550055; + addr[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00800080; + addr[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00AA00AA; + addr[CFG_FLASH_ADDR1] = (CFG_FLASH_WORD_SIZE)0x00550055; + } + addr2[0] = (CFG_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 = (CFG_FLASH_WORD_SIZE *)(info->start[l_sect]); + while ((addr[0] & (CFG_FLASH_WORD_SIZE)0x00800080) != (CFG_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; + } + } + +DONE: + /* reset to read mode */ + addr = (CFG_FLASH_WORD_SIZE *)info->start[0]; + addr[0] = (CFG_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 CFG_FLASH_WORD_SIZE *addr2 = (CFG_FLASH_WORD_SIZE *)(info->start[0]); + volatile CFG_FLASH_WORD_SIZE *dest2 = (CFG_FLASH_WORD_SIZE *)dest; + volatile CFG_FLASH_WORD_SIZE *data2 = (CFG_FLASH_WORD_SIZE *)&data; + ulong start; + int flag; + int i; + + /* 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(); + + for (i=0; i<4/sizeof(CFG_FLASH_WORD_SIZE); i++) { + addr2[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00AA00AA; + addr2[CFG_FLASH_ADDR1] = (CFG_FLASH_WORD_SIZE)0x00550055; + addr2[CFG_FLASH_ADDR0] = (CFG_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] & (CFG_FLASH_WORD_SIZE)0x00800080) != + (data2[i] & (CFG_FLASH_WORD_SIZE)0x00800080)) { + if (get_timer(start) > CFG_FLASH_WRITE_TOUT) + return (1); + } + } + + return (0); +} diff --git a/board/pcs440ep/init.S b/board/pcs440ep/init.S new file mode 100644 index 0000000..0eee4d8 --- /dev/null +++ b/board/pcs440ep/init.S @@ -0,0 +1,113 @@ +/* + * (C) Copyright 2006 + * Stefan Roese, DENX Software Engineering, sr@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 <ppc_asm.tmpl> +#include <config.h> + +/* General */ +#define TLB_VALID 0x00000200 + +/* Supported page sizes */ + +#define SZ_1K 0x00000000 +#define SZ_4K 0x00000010 +#define SZ_16K 0x00000020 +#define SZ_64K 0x00000030 +#define SZ_256K 0x00000040 +#define SZ_1M 0x00000050 +#define SZ_8M 0x00000060 +#define SZ_16M 0x00000070 +#define SZ_256M 0x00000090 + +/* Storage attributes */ +#define SA_W 0x00000800 /* Write-through */ +#define SA_I 0x00000400 /* Caching inhibited */ +#define SA_M 0x00000200 /* Memory coherence */ +#define SA_G 0x00000100 /* Guarded */ +#define SA_E 0x00000080 /* Endian */ + +/* Access control */ +#define AC_X 0x00000024 /* Execute */ +#define AC_W 0x00000012 /* Write */ +#define AC_R 0x00000009 /* Read */ + +/* Some handy macros */ + +#define EPN(e) ((e) & 0xfffffc00) +#define TLB0(epn,sz) ( (EPN((epn)) | (sz) | TLB_VALID ) ) +#define TLB1(rpn,erpn) ( ((rpn)&0xfffffc00) | (erpn) ) +#define TLB2(a) ( (a)&0x00000fbf ) + +#define tlbtab_start\ + mflr r1 ;\ + bl 0f ; + +#define tlbtab_end\ + .long 0, 0, 0 ; \ +0: mflr r0 ; \ + mtlr r1 ; \ + blr ; + +#define tlbentry(epn,sz,rpn,erpn,attr)\ + .long TLB0(epn,sz),TLB1(rpn,erpn),TLB2(attr) + + +/************************************************************************** + * TLB TABLE + * + * This table is used by the cpu boot code to setup the initial tlb + * entries. Rather than make broad assumptions in the cpu source tree, + * this table lets each board set things up however they like. + * + * Pointer to the table is returned in r1 + * + *************************************************************************/ + + .section .bootpg,"ax" + .globl tlbtab + +tlbtab: + tlbtab_start + + /* + * BOOT_CS (FLASH) must be first. Before relocation SA_I can be off to use the + * speed up boot process. It is patched after relocation to enable SA_I + */ + tlbentry( CFG_BOOT_BASE_ADDR, SZ_256M, CFG_BOOT_BASE_ADDR, 0, AC_R|AC_W|AC_X|SA_G/*|SA_I*/) + + /* TLB-entry for init-ram in dcache (SA_I must be turned off!) */ + tlbentry( CFG_INIT_RAM_ADDR, SZ_64K, CFG_INIT_RAM_ADDR, 0, AC_R|AC_W|AC_X|SA_G ) + + tlbentry( CFG_SDRAM_BASE, SZ_256M, CFG_SDRAM_BASE, 0, AC_R|AC_W|AC_X|SA_G|SA_I ) + tlbentry( CFG_PCI_BASE, SZ_256M, CFG_PCI_BASE, 0, AC_R|AC_W|SA_G|SA_I ) + + /* PCI */ + tlbentry( CFG_PCI_MEMBASE, SZ_256M, CFG_PCI_MEMBASE, 0, AC_R|AC_W|SA_G|SA_I ) + tlbentry( CFG_PCI_MEMBASE1, SZ_256M, CFG_PCI_MEMBASE1, 0, AC_R|AC_W|SA_G|SA_I ) + tlbentry( CFG_PCI_MEMBASE2, SZ_256M, CFG_PCI_MEMBASE2, 0, AC_R|AC_W|SA_G|SA_I ) + tlbentry( CFG_PCI_MEMBASE3, SZ_256M, CFG_PCI_MEMBASE3, 0, AC_R|AC_W|SA_G|SA_I ) + + /* USB 2.0 Device */ + tlbentry( CFG_USB_DEVICE, SZ_1K, 0x50000000, 0, AC_R|AC_W|SA_G|SA_I ) + + tlbtab_end diff --git a/board/pcs440ep/pcs440ep.c b/board/pcs440ep/pcs440ep.c new file mode 100644 index 0000000..8858f0a --- /dev/null +++ b/board/pcs440ep/pcs440ep.c @@ -0,0 +1,379 @@ +/* + * (C) Copyright 2006 + * Stefan Roese, DENX Software Engineering, sr@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> +#include <spd_sdram.h> + +DECLARE_GLOBAL_DATA_PTR; + +extern flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips */ + +static void set_leds(int val) +{ + unsigned char led[16] = {0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe, + 0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf}; + out32(GPIO0_OR, (in32(GPIO0_OR) & ~0x78000000) | (led[val] << 27)); +} + +int board_early_init_f(void) +{ + register uint reg; + + set_leds(0); /* display boot info counter */ + + /*-------------------------------------------------------------------- + * Setup the external bus controller/chip selects + *-------------------------------------------------------------------*/ + mtdcr(ebccfga, xbcfg); + reg = mfdcr(ebccfgd); + mtdcr(ebccfgd, reg | 0x04000000); /* Set ATC */ + + /*-------------------------------------------------------------------- + * GPIO's are alreay setup in cpu/ppc4xx/cpu_init.c + * via define from board config file. + *-------------------------------------------------------------------*/ + + /*-------------------------------------------------------------------- + * Setup the interrupt controller polarities, triggers, etc. + *-------------------------------------------------------------------*/ + mtdcr(uic0sr, 0xffffffff); /* clear all */ + mtdcr(uic0er, 0x00000000); /* disable all */ + mtdcr(uic0cr, 0x00000001); /* UIC1 crit is critical */ + mtdcr(uic0pr, 0xfffffe1f); /* per ref-board manual */ + mtdcr(uic0tr, 0x01c00000); /* per ref-board manual */ + mtdcr(uic0vr, 0x00000001); /* int31 highest, base=0x000 */ + mtdcr(uic0sr, 0xffffffff); /* clear all */ + + mtdcr(uic1sr, 0xffffffff); /* clear all */ + mtdcr(uic1er, 0x00000000); /* disable all */ + mtdcr(uic1cr, 0x00000000); /* all non-critical */ + mtdcr(uic1pr, 0xffffe0ff); /* per ref-board manual */ + mtdcr(uic1tr, 0x00ffc000); /* per ref-board manual */ + mtdcr(uic1vr, 0x00000001); /* int31 highest, base=0x000 */ + mtdcr(uic1sr, 0xffffffff); /* clear all */ + + /*-------------------------------------------------------------------- + * Setup other serial configuration + *-------------------------------------------------------------------*/ + mfsdr(sdr_pci0, reg); + mtsdr(sdr_pci0, 0x80000000 | reg); /* PCI arbiter enabled */ + mtsdr(sdr_pfc0, 0x00000100); /* Pin function: enable GPIO49-63 */ + mtsdr(sdr_pfc1, 0x00048000); /* Pin function: UART0 has 4 pins, select IRQ5 */ + + return 0; +} + +int misc_init_r (void) +{ + uint pbcr; + int size_val = 0; + + /* Re-do sizing to get full correct info */ + mtdcr(ebccfga, pb0cr); + pbcr = mfdcr(ebccfgd); + switch (gd->bd->bi_flashsize) { + case 1 << 20: + size_val = 0; + break; + case 2 << 20: + size_val = 1; + break; + case 4 << 20: + size_val = 2; + break; + case 8 << 20: + size_val = 3; + break; + case 16 << 20: + size_val = 4; + break; + case 32 << 20: + size_val = 5; + break; + case 64 << 20: + size_val = 6; + break; + case 128 << 20: + size_val = 7; + break; + } + pbcr = (pbcr & 0x0001ffff) | gd->bd->bi_flashstart | (size_val << 17); + mtdcr(ebccfga, pb0cr); + mtdcr(ebccfgd, pbcr); + + /* adjust flash start and offset */ + gd->bd->bi_flashstart = 0 - gd->bd->bi_flashsize; + gd->bd->bi_flashoffset = 0; + + /* Monitor protection ON by default */ + (void)flash_protect(FLAG_PROTECT_SET, + -CFG_MONITOR_LEN, + 0xffffffff, + &flash_info[1]); + + /* Env protection ON by default */ + (void)flash_protect(FLAG_PROTECT_SET, + CFG_ENV_ADDR_REDUND, + CFG_ENV_ADDR_REDUND + 2*CFG_ENV_SECT_SIZE - 1, + &flash_info[1]); + + return 0; +} + +int checkboard(void) +{ + char *s = getenv("serial#"); + + printf("Board: PCS440EP"); + if (s != NULL) { + puts(", serial# "); + puts(s); + } + putc('\n'); + + return (0); +} + +long int initdram (int board_type) +{ + long dram_size = 0; + + set_leds(1); /* display boot info counter */ + dram_size = spd_sdram(); + set_leds(2); /* display boot info counter */ + + return dram_size; +} + +#if defined(CFG_DRAM_TEST) +int testdram(void) +{ + unsigned long *mem = (unsigned long *)0; + const unsigned long kend = (1024 / sizeof(unsigned long)); + unsigned long k, n; + + mtmsr(0); + + for (k = 0; k < CFG_KBYTES_SDRAM; + ++k, mem += (1024 / sizeof(unsigned long))) { + if ((k & 1023) == 0) { + printf("%3d MB\r", k / 1024); + } + + memset(mem, 0xaaaaaaaa, 1024); + for (n = 0; n < kend; ++n) { + if (mem[n] != 0xaaaaaaaa) { + printf("SDRAM test fails at: %08x\n", + (uint) & mem[n]); + return 1; + } + } + + memset(mem, 0x55555555, 1024); + for (n = 0; n < kend; ++n) { + if (mem[n] != 0x55555555) { + printf("SDRAM test fails at: %08x\n", + (uint) & mem[n]); + return 1; + } + } + } + printf("SDRAM test passes\n"); + return 0; +} +#endif + +/************************************************************************* + * pci_pre_init + * + * This routine is called just prior to registering the hose and gives + * the board the opportunity to check things. Returning a value of zero + * indicates that things are bad & PCI initialization should be aborted. + * + * Different boards may wish to customize the pci controller structure + * (add regions, override default access routines, etc) or perform + * certain pre-initialization actions. + * + ************************************************************************/ +#if defined(CONFIG_PCI) && defined(CFG_PCI_PRE_INIT) +int pci_pre_init(struct pci_controller *hose) +{ + unsigned long addr; + + /*-------------------------------------------------------------------------+ + | Set priority for all PLB3 devices to 0. + | Set PLB3 arbiter to fair mode. + +-------------------------------------------------------------------------*/ + mfsdr(sdr_amp1, addr); + mtsdr(sdr_amp1, (addr & 0x000000FF) | 0x0000FF00); + addr = mfdcr(plb3_acr); + mtdcr(plb3_acr, addr | 0x80000000); + + /*-------------------------------------------------------------------------+ + | Set priority for all PLB4 devices to 0. + +-------------------------------------------------------------------------*/ + mfsdr(sdr_amp0, addr); + mtsdr(sdr_amp0, (addr & 0x000000FF) | 0x0000FF00); + addr = mfdcr(plb4_acr) | 0xa0000000; /* Was 0x8---- */ + mtdcr(plb4_acr, addr); + + /*-------------------------------------------------------------------------+ + | Set Nebula PLB4 arbiter to fair mode. + +-------------------------------------------------------------------------*/ + /* Segment0 */ + addr = (mfdcr(plb0_acr) & ~plb0_acr_ppm_mask) | plb0_acr_ppm_fair; + addr = (addr & ~plb0_acr_hbu_mask) | plb0_acr_hbu_enabled; + addr = (addr & ~plb0_acr_rdp_mask) | plb0_acr_rdp_4deep; + addr = (addr & ~plb0_acr_wrp_mask) | plb0_acr_wrp_2deep; + mtdcr(plb0_acr, addr); + + /* Segment1 */ + addr = (mfdcr(plb1_acr) & ~plb1_acr_ppm_mask) | plb1_acr_ppm_fair; + addr = (addr & ~plb1_acr_hbu_mask) | plb1_acr_hbu_enabled; + addr = (addr & ~plb1_acr_rdp_mask) | plb1_acr_rdp_4deep; + addr = (addr & ~plb1_acr_wrp_mask) | plb1_acr_wrp_2deep; + mtdcr(plb1_acr, addr); + + return 1; +} +#endif /* defined(CONFIG_PCI) && defined(CFG_PCI_PRE_INIT) */ + +/************************************************************************* + * pci_target_init + * + * The bootstrap configuration provides default settings for the pci + * inbound map (PIM). But the bootstrap config choices are limited and + * may not be sufficient for a given board. + * + ************************************************************************/ +#if defined(CONFIG_PCI) && defined(CFG_PCI_TARGET_INIT) +void pci_target_init(struct pci_controller *hose) +{ + /*--------------------------------------------------------------------------+ + * Set up Direct MMIO registers + *--------------------------------------------------------------------------*/ + /*--------------------------------------------------------------------------+ + | PowerPC440 EP PCI Master configuration. + | Map one 1Gig range of PLB/processor addresses to PCI memory space. + | PLB address 0xA0000000-0xDFFFFFFF ==> PCI address 0xA0000000-0xDFFFFFFF + | Use byte reversed out routines to handle endianess. + | Make this region non-prefetchable. + +--------------------------------------------------------------------------*/ + out32r(PCIX0_PMM0MA, 0x00000000); /* PMM0 Mask/Attribute - disabled b4 setting */ + out32r(PCIX0_PMM0LA, CFG_PCI_MEMBASE); /* PMM0 Local Address */ + out32r(PCIX0_PMM0PCILA, CFG_PCI_MEMBASE); /* PMM0 PCI Low Address */ + out32r(PCIX0_PMM0PCIHA, 0x00000000); /* PMM0 PCI High Address */ + out32r(PCIX0_PMM0MA, 0xE0000001); /* 512M + No prefetching, and enable region */ + + out32r(PCIX0_PMM1MA, 0x00000000); /* PMM0 Mask/Attribute - disabled b4 setting */ + out32r(PCIX0_PMM1LA, CFG_PCI_MEMBASE2); /* PMM0 Local Address */ + out32r(PCIX0_PMM1PCILA, CFG_PCI_MEMBASE2); /* PMM0 PCI Low Address */ + out32r(PCIX0_PMM1PCIHA, 0x00000000); /* PMM0 PCI High Address */ + out32r(PCIX0_PMM1MA, 0xE0000001); /* 512M + No prefetching, and enable region */ + + out32r(PCIX0_PTM1MS, 0x00000001); /* Memory Size/Attribute */ + out32r(PCIX0_PTM1LA, 0); /* Local Addr. Reg */ + out32r(PCIX0_PTM2MS, 0); /* Memory Size/Attribute */ + out32r(PCIX0_PTM2LA, 0); /* Local Addr. Reg */ + + /*--------------------------------------------------------------------------+ + * Set up Configuration registers + *--------------------------------------------------------------------------*/ + + /* Program the board's subsystem id/vendor id */ + pci_write_config_word(0, PCI_SUBSYSTEM_VENDOR_ID, + CFG_PCI_SUBSYS_VENDORID); + pci_write_config_word(0, PCI_SUBSYSTEM_ID, CFG_PCI_SUBSYS_ID); + + /* Configure command register as bus master */ + pci_write_config_word(0, PCI_COMMAND, PCI_COMMAND_MASTER); + + /* 240nS PCI clock */ + pci_write_config_word(0, PCI_LATENCY_TIMER, 1); + + /* No error reporting */ + pci_write_config_word(0, PCI_ERREN, 0); + + pci_write_config_dword(0, PCI_BRDGOPT2, 0x00000101); + +} +#endif /* defined(CONFIG_PCI) && defined(CFG_PCI_TARGET_INIT) */ + +/************************************************************************* + * pci_master_init + * + ************************************************************************/ +#if defined(CONFIG_PCI) && defined(CFG_PCI_MASTER_INIT) +void pci_master_init(struct pci_controller *hose) +{ + unsigned short temp_short; + + /*--------------------------------------------------------------------------+ + | Write the PowerPC440 EP PCI Configuration regs. + | Enable PowerPC440 EP to be a master on the PCI bus (PMM). + | Enable PowerPC440 EP to act as a PCI memory target (PTM). + +--------------------------------------------------------------------------*/ + pci_read_config_word(0, PCI_COMMAND, &temp_short); + pci_write_config_word(0, PCI_COMMAND, + temp_short | PCI_COMMAND_MASTER | + PCI_COMMAND_MEMORY); +} +#endif /* defined(CONFIG_PCI) && defined(CFG_PCI_MASTER_INIT) */ + +/************************************************************************* + * is_pci_host + * + * This routine is called to determine if a pci scan should be + * performed. With various hardware environments (especially cPCI and + * PPMC) it's insufficient to depend on the state of the arbiter enable + * bit in the strap register, or generic host/adapter assumptions. + * + * Rather than hard-code a bad assumption in the general 440 code, the + * 440 pci code requires the board to decide at runtime. + * + * Return 0 for adapter mode, non-zero for host (monarch) mode. + * + * + ************************************************************************/ +#if defined(CONFIG_PCI) +int is_pci_host(struct pci_controller *hose) +{ + /* PCS440EP is always configured as host. */ + return (1); +} +#endif /* defined(CONFIG_PCI) */ + +/************************************************************************* + * hw_watchdog_reset + * + * This routine is called to reset (keep alive) the watchdog timer + * + ************************************************************************/ +#if defined(CONFIG_HW_WATCHDOG) +void hw_watchdog_reset(void) +{ + +} +#endif diff --git a/board/pcs440ep/u-boot.lds b/board/pcs440ep/u-boot.lds new file mode 100644 index 0000000..6ab476a --- /dev/null +++ b/board/pcs440ep/u-boot.lds @@ -0,0 +1,141 @@ +/* + * (C) Copyright 2006 + * 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 + */ + +OUTPUT_ARCH(powerpc) +SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/usr/local/powerpc-any-elf/lib); +/* Do we need any of these for elf? + __DYNAMIC = 0; */ +SECTIONS +{ + .resetvec 0xFFFFFFFC : + { + *(.resetvec) + } = 0xffff + + .bootpg 0xFFFFF000 : + { + cpu/ppc4xx/start.o (.bootpg) + } = 0xffff + + /* Read-only sections, merged into text segment: */ + . = + SIZEOF_HEADERS; + .interp : { *(.interp) } + .hash : { *(.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .rel.text : { *(.rel.text) } + .rela.text : { *(.rela.text) } + .rel.data : { *(.rel.data) } + .rela.data : { *(.rela.data) } + .rel.rodata : { *(.rel.rodata) } + .rela.rodata : { *(.rela.rodata) } + .rel.got : { *(.rel.got) } + .rela.got : { *(.rela.got) } + .rel.ctors : { *(.rel.ctors) } + .rela.ctors : { *(.rela.ctors) } + .rel.dtors : { *(.rel.dtors) } + .rela.dtors : { *(.rela.dtors) } + .rel.bss : { *(.rel.bss) } + .rela.bss : { *(.rela.bss) } + .rel.plt : { *(.rel.plt) } + .rela.plt : { *(.rela.plt) } + .init : { *(.init) } + .plt : { *(.plt) } + .text : + { + cpu/ppc4xx/start.o (.text) + board/pcs440ep/init.o (.text) + + *(.text) + *(.fixup) + *(.got1) + } + _etext = .; + PROVIDE (etext = .); + .rodata : + { + *(.rodata) + *(.rodata1) + *(.rodata.str1.4) + *(.eh_frame) + } + .fini : { *(.fini) } =0 + .ctors : { *(.ctors) } + .dtors : { *(.dtors) } + + /* Read-write section, merged into data segment: */ + . = (. + 0x00FF) & 0xFFFFFF00; + _erotext = .; + PROVIDE (erotext = .); + .reloc : + { + *(.got) + _GOT2_TABLE_ = .; + *(.got2) + _FIXUP_TABLE_ = .; + *(.fixup) + } + __got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >> 2; + __fixup_entries = (. - _FIXUP_TABLE_) >> 2; + + .data : + { + *(.data) + *(.data1) + *(.sdata) + *(.sdata2) + *(.dynamic) + CONSTRUCTORS + } + _edata = .; + PROVIDE (edata = .); + + . = .; + __u_boot_cmd_start = .; + .u_boot_cmd : { *(.u_boot_cmd) } + __u_boot_cmd_end = .; + + . = .; + __start___ex_table = .; + __ex_table : { *(__ex_table) } + __stop___ex_table = .; + + . = ALIGN(256); + __init_begin = .; + .text.init : { *(.text.init) } + .data.init : { *(.data.init) } + . = ALIGN(256); + __init_end = .; + + __bss_start = .; + .bss : + { + *(.sbss) *(.scommon) + *(.dynbss) + *(.bss) + *(COMMON) + } + + _end = . ; + PROVIDE (end = .); +} diff --git a/board/prodrive/common/flash.c b/board/prodrive/common/flash.c new file mode 100644 index 0000000..8630cc1 --- /dev/null +++ b/board/prodrive/common/flash.c @@ -0,0 +1,556 @@ +/* + * (C) Copyright 2006 + * Stefan Roese, DENX Software Engineering, sr@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <asm/processor.h> + +flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips */ + +/* + * Functions + */ +static int write_word(flash_info_t *info, ulong dest, ulong data); + +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; + case FLASH_MAN_EXCEL: printf ("Excel Semiconductor "); 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_AM320T: printf ("AM29LV320T (32 M, top sector)\n"); + break; + case FLASH_AM320B: printf ("AM29LV320B (32 M, bottom sector)\n"); + break; + case FLASH_AMDL322T: printf ("AM29DL322T (32 M, top sector)\n"); + break; + case FLASH_AMDL322B: printf ("AM29DL322B (32 M, bottom sector)\n"); + break; + case FLASH_AMDL323T: printf ("AM29DL323T (32 M, top sector)\n"); + break; + case FLASH_AMDL323B: printf ("AM29DL323B (32 M, bottom sector)\n"); + break; + case FLASH_SST020: printf ("SST39LF/VF020 (2 Mbit, uniform sector size)\n"); + break; + case FLASH_SST040: printf ("SST39LF/VF040 (4 Mbit, uniform sector size)\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) { +#ifdef CFG_FLASH_EMPTY_INFO + /* + * 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 "); + /* print empty and read-only info */ + printf (" %08lX%s%s", + info->start[i], + erased ? " E" : " ", + info->protect[i] ? "RO " : " "); +#else + if ((i % 5) == 0) + printf ("\n "); + printf (" %08lX%s", + info->start[i], + 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; + short n; + CFG_FLASH_WORD_SIZE value; + ulong base = (ulong)addr; + volatile CFG_FLASH_WORD_SIZE *addr2 = (CFG_FLASH_WORD_SIZE *)addr; + + /* Write auto select command: read Manufacturer ID */ + addr2[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00AA00AA; + addr2[CFG_FLASH_ADDR1] = (CFG_FLASH_WORD_SIZE)0x00550055; + addr2[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00900090; + + value = addr2[CFG_FLASH_READ0]; + + switch (value) { + case (CFG_FLASH_WORD_SIZE)AMD_MANUFACT: + info->flash_id = FLASH_MAN_AMD; + break; + case (CFG_FLASH_WORD_SIZE)FUJ_MANUFACT: + info->flash_id = FLASH_MAN_FUJ; + break; + case (CFG_FLASH_WORD_SIZE)SST_MANUFACT: + info->flash_id = FLASH_MAN_SST; + break; + case (CFG_FLASH_WORD_SIZE)EXCEL_MANUFACT: + info->flash_id = FLASH_MAN_EXCEL; + break; + default: + info->flash_id = FLASH_UNKNOWN; + info->sector_count = 0; + info->size = 0; + return (0); /* no or unknown flash */ + } + + value = addr2[CFG_FLASH_READ1]; /* device ID */ + + switch (value) { + case (CFG_FLASH_WORD_SIZE)AMD_ID_LV400T: + info->flash_id += FLASH_AM400T; + info->sector_count = 11; + info->size = 0x00080000; + break; /* => 0.5 MB */ + + case (CFG_FLASH_WORD_SIZE)AMD_ID_LV400B: + info->flash_id += FLASH_AM400B; + info->sector_count = 11; + info->size = 0x00080000; + break; /* => 0.5 MB */ + + case (CFG_FLASH_WORD_SIZE)AMD_ID_LV800T: + info->flash_id += FLASH_AM800T; + info->sector_count = 19; + info->size = 0x00100000; + break; /* => 1 MB */ + + case (CFG_FLASH_WORD_SIZE)AMD_ID_LV800B: + info->flash_id += FLASH_AM800B; + info->sector_count = 19; + info->size = 0x00100000; + break; /* => 1 MB */ + + case (CFG_FLASH_WORD_SIZE)AMD_ID_LV160T: + info->flash_id += FLASH_AM160T; + info->sector_count = 35; + info->size = 0x00200000; + break; /* => 2 MB */ + + case (CFG_FLASH_WORD_SIZE)AMD_ID_LV160B: + info->flash_id += FLASH_AM160B; + info->sector_count = 35; + info->size = 0x00200000; + break; /* => 2 MB */ + + case (CFG_FLASH_WORD_SIZE)AMD_ID_LV320T: + info->flash_id += FLASH_AM320T; + info->sector_count = 71; + info->size = 0x00400000; break; /* => 4 MB */ + + case (CFG_FLASH_WORD_SIZE)AMD_ID_LV320B: + info->flash_id += FLASH_AM320B; + info->sector_count = 71; + info->size = 0x00400000; break; /* => 4 MB */ + + case (CFG_FLASH_WORD_SIZE)AMD_ID_DL322T: + info->flash_id += FLASH_AMDL322T; + info->sector_count = 71; + info->size = 0x00400000; break; /* => 4 MB */ + + case (CFG_FLASH_WORD_SIZE)AMD_ID_DL322B: + info->flash_id += FLASH_AMDL322B; + info->sector_count = 71; + info->size = 0x00400000; break; /* => 4 MB */ + + case (CFG_FLASH_WORD_SIZE)AMD_ID_DL323T: + info->flash_id += FLASH_AMDL323T; + info->sector_count = 71; + info->size = 0x00400000; break; /* => 4 MB */ + + case (CFG_FLASH_WORD_SIZE)AMD_ID_DL323B: + info->flash_id += FLASH_AMDL323B; + info->sector_count = 71; + info->size = 0x00400000; break; /* => 4 MB */ + + case (CFG_FLASH_WORD_SIZE)SST_ID_xF020: + info->flash_id += FLASH_SST020; + info->sector_count = 64; + info->size = 0x00040000; + break; /* => 256 kB */ + + case (CFG_FLASH_WORD_SIZE)SST_ID_xF040: + info->flash_id += FLASH_SST040; + info->sector_count = 128; + info->size = 0x00080000; + break; /* => 512 kB */ + + 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) { + for (i = 0; i < info->sector_count; i++) + info->start[i] = base + (i * 0x00001000); + } else if (((info->flash_id & FLASH_TYPEMASK) == FLASH_AMDL322B) || + ((info->flash_id & FLASH_TYPEMASK) == FLASH_AMDL323B) || + ((info->flash_id & FLASH_TYPEMASK) == FLASH_AM320B) || + ((info->flash_id & FLASH_TYPEMASK) == FLASH_AMDL324B)) { + /* set sector offsets for bottom boot block type */ + for (i=0; i<8; ++i) { /* 8 x 8k boot sectors */ + info->start[i] = base; + base += 8 << 10; + } + while (i < info->sector_count) { /* 64k regular sectors */ + info->start[i] = base; + base += 64 << 10; + ++i; + } + } else if (((info->flash_id & FLASH_TYPEMASK) == FLASH_AMDL322T) || + ((info->flash_id & FLASH_TYPEMASK) == FLASH_AMDL323T) || + ((info->flash_id & FLASH_TYPEMASK) == FLASH_AM320T) || + ((info->flash_id & FLASH_TYPEMASK) == FLASH_AMDL324T)) { + /* set sector offsets for top boot block type */ + base += info->size; + i = info->sector_count; + for (n=0; n<8; ++n) { /* 8 x 8k boot sectors */ + base -= 8 << 10; + --i; + info->start[i] = base; + } + while (i > 0) { /* 64k regular sectors */ + base -= 64 << 10; + --i; + info->start[i] = base; + } + } 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 CFG_FLASH_WORD_SIZE *)(info->start[i]); + if ((info->flash_id & FLASH_VENDMASK) != FLASH_MAN_AMD) + info->protect[i] = 0; + else + info->protect[i] = addr2[CFG_FLASH_READ2] & 1; + } + + /* + * Prevent writes to uninitialized FLASH. + */ + if (info->flash_id != FLASH_UNKNOWN) { + addr2 = (CFG_FLASH_WORD_SIZE *)info->start[0]; + *addr2 = (CFG_FLASH_WORD_SIZE)0x00F000F0; /* reset bank */ + } + + return (info->size); +} + + +int flash_erase(flash_info_t *info, int s_first, int s_last) +{ + volatile CFG_FLASH_WORD_SIZE *addr = (CFG_FLASH_WORD_SIZE *)(info->start[0]); + volatile CFG_FLASH_WORD_SIZE *addr2; + 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) { + 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 = (CFG_FLASH_WORD_SIZE *)(info->start[sect]); + if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST) { + addr[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00AA00AA; + addr[CFG_FLASH_ADDR1] = (CFG_FLASH_WORD_SIZE)0x00550055; + addr[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00800080; + addr[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00AA00AA; + addr[CFG_FLASH_ADDR1] = (CFG_FLASH_WORD_SIZE)0x00550055; + addr2[0] = (CFG_FLASH_WORD_SIZE)0x00300030; /* sector erase */ + + /* re-enable interrupts if necessary */ + if (flag) { + enable_interrupts(); + flag = 0; + } + + /* data polling for D7 */ + start = get_timer (0); + while ((addr2[0] & (CFG_FLASH_WORD_SIZE)0x00800080) != + (CFG_FLASH_WORD_SIZE)0x00800080) { + if (get_timer(start) > CFG_FLASH_WRITE_TOUT) + return (1); + } + } else { + if (sect == s_first) { + addr[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00AA00AA; + addr[CFG_FLASH_ADDR1] = (CFG_FLASH_WORD_SIZE)0x00550055; + addr[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00800080; + addr[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00AA00AA; + addr[CFG_FLASH_ADDR1] = (CFG_FLASH_WORD_SIZE)0x00550055; + } + addr2[0] = (CFG_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 = (CFG_FLASH_WORD_SIZE *)(info->start[l_sect]); + while ((addr[0] & (CFG_FLASH_WORD_SIZE)0x00800080) != (CFG_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; + } + } + +DONE: + /* reset to read mode */ + addr = (CFG_FLASH_WORD_SIZE *)info->start[0]; + addr[0] = (CFG_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 CFG_FLASH_WORD_SIZE *addr2 = (CFG_FLASH_WORD_SIZE *)(info->start[0]); + volatile CFG_FLASH_WORD_SIZE *dest2 = (CFG_FLASH_WORD_SIZE *)dest; + volatile CFG_FLASH_WORD_SIZE *data2 = (CFG_FLASH_WORD_SIZE *)&data; + ulong start; + int flag; + int i; + + /* 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(); + + for (i=0; i<4/sizeof(CFG_FLASH_WORD_SIZE); i++) { + addr2[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00AA00AA; + addr2[CFG_FLASH_ADDR1] = (CFG_FLASH_WORD_SIZE)0x00550055; + addr2[CFG_FLASH_ADDR0] = (CFG_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] & (CFG_FLASH_WORD_SIZE)0x00800080) != + (data2[i] & (CFG_FLASH_WORD_SIZE)0x00800080)) { + if (get_timer(start) > CFG_FLASH_WRITE_TOUT) + return (1); + } + } + + return (0); +} diff --git a/board/prodrive/common/fpga.c b/board/prodrive/common/fpga.c new file mode 100644 index 0000000..f9412a2 --- /dev/null +++ b/board/prodrive/common/fpga.c @@ -0,0 +1,183 @@ +/* + * (C) Copyright 2006 + * Stefan Roese, DENX Software Engineering, sr@denx.de. + * + * (C) Copyright 2001-2004 + * Matthias Fuchs, esd gmbh germany, matthias.fuchs@esd-electronics.com + * 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 <asm/processor.h> +#include <command.h> + +/* ------------------------------------------------------------------------- */ + +#ifdef FPGA_DEBUG +#define DBG(x...) printf(x) +#else +#define DBG(x...) +#endif /* DEBUG */ + +#define FPGA_PRG CFG_FPGA_PRG /* FPGA program pin (cpu output)*/ +#define FPGA_CLK CFG_FPGA_CLK /* FPGA clk pin (cpu output) */ +#define FPGA_DATA CFG_FPGA_DATA /* FPGA data pin (cpu output) */ +#define FPGA_DONE CFG_FPGA_DONE /* FPGA done pin (cpu input) */ +#define FPGA_INIT CFG_FPGA_INIT /* FPGA init pin (cpu input) */ + +#define ERROR_FPGA_PRG_INIT_LOW -1 /* Timeout after PRG* asserted */ +#define ERROR_FPGA_PRG_INIT_HIGH -2 /* Timeout after PRG* deasserted */ +#define ERROR_FPGA_PRG_DONE -3 /* Timeout after programming */ + +#ifndef OLD_VAL +# define OLD_VAL 0 +#endif + +#if 0 /* test-only */ +#define FPGA_WRITE_1 { \ + SET_FPGA(OLD_VAL | FPGA_PRG | 0 | FPGA_DATA); /* set clock to 0 */ \ + SET_FPGA(OLD_VAL | FPGA_PRG | 0 | FPGA_DATA); /* set data to 1 */ \ + SET_FPGA(OLD_VAL | FPGA_PRG | FPGA_CLK | FPGA_DATA); /* set clock to 1 */ \ + SET_FPGA(OLD_VAL | FPGA_PRG | FPGA_CLK | FPGA_DATA);} /* set data to 1 */ + +#define FPGA_WRITE_0 { \ + SET_FPGA(OLD_VAL | FPGA_PRG | 0 | FPGA_DATA); /* set clock to 0 */ \ + SET_FPGA(OLD_VAL | FPGA_PRG | 0 | 0 ); /* set data to 0 */ \ + SET_FPGA(OLD_VAL | FPGA_PRG | FPGA_CLK | 0 ); /* set clock to 1 */ \ + SET_FPGA(OLD_VAL | FPGA_PRG | FPGA_CLK | FPGA_DATA);} /* set data to 1 */ +#else +#define FPGA_WRITE_1 { \ + SET_FPGA(OLD_VAL | FPGA_PRG | 0 | FPGA_DATA); /* set data to 1 */ \ + SET_FPGA(OLD_VAL | FPGA_PRG | FPGA_CLK | FPGA_DATA);} /* set data to 1 */ + +#define FPGA_WRITE_0 { \ + SET_FPGA(OLD_VAL | FPGA_PRG | 0 | 0 ); /* set data to 0 */ \ + SET_FPGA(OLD_VAL | FPGA_PRG | FPGA_CLK | 0 );} /* set data to 1 */ +#endif + +static int fpga_boot(unsigned char *fpgadata, int size) +{ + int i,index,len; + int count; + int j; + + /* display infos on fpgaimage */ + index = 15; + for (i=0; i<4; i++) { + len = fpgadata[index]; + DBG("FPGA: %s\n", &(fpgadata[index+1])); + index += len+3; + } + + /* search for preamble 0xFFFFFFFF */ + while (1) { + if ((fpgadata[index] == 0xff) && (fpgadata[index+1] == 0xff) && + (fpgadata[index+2] == 0xff) && (fpgadata[index+3] == 0xff)) + break; /* preamble found */ + else + index++; + } + + DBG("FPGA: configdata starts at position 0x%x\n",index); + DBG("FPGA: length of fpga-data %d\n", size-index); + + /* + * Setup port pins for fpga programming + */ + SET_FPGA(FPGA_PRG | FPGA_CLK | FPGA_DATA); /* set pins to high */ + + DBG("%s, ",(FPGA_DONE_STATE == 0) ? "NOT DONE" : "DONE" ); + DBG("%s\n",(FPGA_INIT_STATE == 0) ? "NOT INIT" : "INIT" ); + + /* + * Init fpga by asserting and deasserting PROGRAM* + */ + SET_FPGA(0 | FPGA_CLK | FPGA_DATA); /* set prog active */ + + /* Wait for FPGA init line low */ + count = 0; + while (FPGA_INIT_STATE) { + udelay(1000); /* wait 1ms */ + /* Check for timeout - 100us max, so use 3ms */ + if (count++ > 3) { + DBG("FPGA: Booting failed!\n"); + return ERROR_FPGA_PRG_INIT_LOW; + } + } + + DBG("%s, ",(FPGA_DONE_STATE == 0) ? "NOT DONE" : "DONE" ); + DBG("%s\n",(FPGA_INIT_STATE == 0) ? "NOT INIT" : "INIT" ); + + /* deassert PROGRAM* */ + SET_FPGA(FPGA_PRG | FPGA_CLK | FPGA_DATA); /* set prog inactive */ + + /* Wait for FPGA end of init period . */ + count = 0; + while (!(FPGA_INIT_STATE)) { + udelay(1000); /* wait 1ms */ + /* Check for timeout */ + if (count++ > 3) { + DBG("FPGA: Booting failed!\n"); + return ERROR_FPGA_PRG_INIT_HIGH; + } + } + + DBG("%s, ",(FPGA_DONE_STATE == 0) ? "NOT DONE" : "DONE" ); + DBG("%s\n",(FPGA_INIT_STATE == 0) ? "NOT INIT" : "INIT" ); + + DBG("write configuration data into fpga\n"); + /* write configuration-data into fpga... */ + + /* + * Load uncompressed image into fpga + */ + for (i=index; i<size; i++) { + for (j=0; j<8; j++) { + if ((fpgadata[i] & 0x80) == 0x80) { + FPGA_WRITE_1; + } else { + FPGA_WRITE_0; + } + fpgadata[i] <<= 1; + } + } + + DBG("%s, ",(FPGA_DONE_STATE == 0) ? "NOT DONE" : "DONE" ); + DBG("%s\n",(FPGA_INIT_STATE == 0) ? "NOT INIT" : "INIT" ); + + /* + * Check if fpga's DONE signal - correctly booted ? + */ + + /* Wait for FPGA end of programming period . */ + count = 0; + while (!(FPGA_DONE_STATE)) { + udelay(1000); /* wait 1ms */ + /* Check for timeout */ + if (count++ > 3) { + DBG("FPGA: Booting failed!\n"); + return ERROR_FPGA_PRG_DONE; + } + } + + DBG("FPGA: Booting successful!\n"); + return 0; +} diff --git a/board/prodrive/pdnb3/Makefile b/board/prodrive/pdnb3/Makefile new file mode 100644 index 0000000..f3cd5a3 --- /dev/null +++ b/board/prodrive/pdnb3/Makefile @@ -0,0 +1,46 @@ +# +# (C) Copyright 2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# See file CREDITS for list of people who contributed to this +# project. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +include $(TOPDIR)/config.mk + +LIB = lib$(BOARD).a + +OBJS := flash.o pdnb3.o nand.o + +$(LIB): $(OBJS) $(SOBJS) + $(AR) crv $@ $^ + +clean: + rm -f $(SOBJS) $(OBJS) + +distclean: clean + rm -f $(LIB) core *.bak .depend + +######################################################################### + +.depend: Makefile $(SOBJS:.o=.S) $(OBJS:.o=.c) + $(CC) -M $(CPPFLAGS) $(SOBJS:.o=.S) $(OBJS:.o=.c) > $@ + +-include .depend + +######################################################################### diff --git a/board/prodrive/pdnb3/config.mk b/board/prodrive/pdnb3/config.mk new file mode 100644 index 0000000..6b0f18b --- /dev/null +++ b/board/prodrive/pdnb3/config.mk @@ -0,0 +1,4 @@ +TEXT_BASE = 0x01f00000 + +# include NPE ethernet driver +BOARDLIBS = cpu/ixp/npe/libnpe.a diff --git a/board/prodrive/pdnb3/flash.c b/board/prodrive/pdnb3/flash.c new file mode 100644 index 0000000..d0e5fe7 --- /dev/null +++ b/board/prodrive/pdnb3/flash.c @@ -0,0 +1,85 @@ +/* + * (C) Copyright 2006 + * Stefan Roese, DENX Software Engineering, sr@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <asm/arch/ixp425.h> + +/* + * include common flash code (for esd boards) + */ +#include "../common/flash.c" + +/* + * Prototypes + */ +static ulong flash_get_size (vu_long * addr, flash_info_t * info); + +static inline ulong ld(ulong x) +{ + ulong k = 0; + + while (x >>= 1) + ++k; + + return k; +} + +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; + + size = 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, size<<20); + + /* Reconfigure CS0 to actual FLASH size */ + *IXP425_EXP_CS0 = (*IXP425_EXP_CS0 & ~0x00003C00) | ((ld(size) - 9) << 10); + + /* Monitor protection ON by default */ + flash_protect(FLAG_PROTECT_SET, + CFG_MONITOR_BASE, CFG_MONITOR_BASE + monitor_flash_len - 1, + &flash_info[CFG_MAX_FLASH_BANKS - 1]); + + /* Environment protection ON by default */ + flash_protect(FLAG_PROTECT_SET, + CFG_ENV_ADDR, + CFG_ENV_ADDR + CFG_ENV_SECT_SIZE - 1, + &flash_info[CFG_MAX_FLASH_BANKS - 1]); + + /* Redundant environment protection ON by default */ + flash_protect(FLAG_PROTECT_SET, + CFG_ENV_ADDR_REDUND, + CFG_ENV_ADDR_REDUND + CFG_ENV_SIZE_REDUND - 1, + &flash_info[CFG_MAX_FLASH_BANKS - 1]); + + flash_info[0].size = size; + + return size; +} diff --git a/board/prodrive/pdnb3/nand.c b/board/prodrive/pdnb3/nand.c new file mode 100644 index 0000000..1931d64 --- /dev/null +++ b/board/prodrive/pdnb3/nand.c @@ -0,0 +1,171 @@ +/* + * (C) Copyright 2006 + * Stefan Roese, DENX Software Engineering, sr@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> + +#if (CONFIG_COMMANDS & CFG_CMD_NAND) + +#include <nand.h> + +struct pdnb3_ndfc_regs { + uchar cmd; + uchar wait; + uchar addr; + uchar term; + uchar data; +}; + +static u8 hwctl; +static struct pdnb3_ndfc_regs *pdnb3_ndfc; + +#define readb(addr) *(volatile u_char *)(addr) +#define readl(addr) *(volatile u_long *)(addr) +#define writeb(d,addr) *(volatile u_char *)(addr) = (d) + +/* + * The PDNB3 has a NAND Flash Controller (NDFC) that handles all accesses to + * the NAND devices. The NDFC has command, address and data registers that + * when accessed will set up the NAND flash pins appropriately. We'll use the + * hwcontrol function to save the configuration in a global variable. + * We can then use this information in the read and write functions to + * determine which NDFC register to access. + * + * There is one NAND devices on the board, a Hynix HY27US08561A (32 MByte). + */ +static void pdnb3_nand_hwcontrol(struct mtd_info *mtd, int cmd) +{ + switch (cmd) { + case NAND_CTL_SETCLE: + hwctl |= 0x1; + break; + case NAND_CTL_CLRCLE: + hwctl &= ~0x1; + break; + + case NAND_CTL_SETALE: + hwctl |= 0x2; + break; + case NAND_CTL_CLRALE: + hwctl &= ~0x2; + break; + + case NAND_CTL_SETNCE: + break; + case NAND_CTL_CLRNCE: + writeb(0x00, &(pdnb3_ndfc->term)); + break; + } +} + +static void pdnb3_nand_write_byte(struct mtd_info *mtd, u_char byte) +{ + if (hwctl & 0x1) + writeb(byte, &(pdnb3_ndfc->cmd)); + else if (hwctl & 0x2) + writeb(byte, &(pdnb3_ndfc->addr)); + else + writeb(byte, &(pdnb3_ndfc->data)); +} + +static u_char pdnb3_nand_read_byte(struct mtd_info *mtd) +{ + return readb(&(pdnb3_ndfc->data)); +} + +static void pdnb3_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len) +{ + int i; + + for (i = 0; i < len; i++) { + if (hwctl & 0x1) + writeb(buf[i], &(pdnb3_ndfc->cmd)); + else if (hwctl & 0x2) + writeb(buf[i], &(pdnb3_ndfc->addr)); + else + writeb(buf[i], &(pdnb3_ndfc->data)); + } +} + +static void pdnb3_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len) +{ + int i; + + if (len % 4) { + for (i = 0; i < len; i++) + buf[i] = readb(&(pdnb3_ndfc->data)); + } else { + ulong *ptr = (ulong *)buf; + int count = len >> 2; + + for (i = 0; i < count; i++) + *ptr++ = readl(&(pdnb3_ndfc->data)); + } +} + +static int pdnb3_nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len) +{ + int i; + + for (i = 0; i < len; i++) + if (buf[i] != readb(&(pdnb3_ndfc->data))) + return i; + + return 0; +} + +static int pdnb3_nand_dev_ready(struct mtd_info *mtd) +{ + volatile u_char val; + + /* + * Blocking read to wait for NAND to be ready + */ + val = readb(&(pdnb3_ndfc->wait)); + + /* + * Return always true + */ + return 1; +} + +void board_nand_init(struct nand_chip *nand) +{ + pdnb3_ndfc = (struct pdnb3_ndfc_regs *)CFG_NAND_BASE; + + nand->eccmode = NAND_ECC_SOFT; + + /* Set address of NAND IO lines (Using Linear Data Access Region) */ + nand->IO_ADDR_R = (void __iomem *) ((ulong) pdnb3_ndfc + 0x4); + nand->IO_ADDR_W = (void __iomem *) ((ulong) pdnb3_ndfc + 0x4); + /* Reference hardware control function */ + nand->hwcontrol = pdnb3_nand_hwcontrol; + /* Set command delay time */ + nand->hwcontrol = pdnb3_nand_hwcontrol; + nand->write_byte = pdnb3_nand_write_byte; + nand->read_byte = pdnb3_nand_read_byte; + nand->write_buf = pdnb3_nand_write_buf; + nand->read_buf = pdnb3_nand_read_buf; + nand->verify_buf = pdnb3_nand_verify_buf; + nand->dev_ready = pdnb3_nand_dev_ready; +} +#endif diff --git a/board/prodrive/pdnb3/pdnb3.c b/board/prodrive/pdnb3/pdnb3.c new file mode 100644 index 0000000..e2fed5d --- /dev/null +++ b/board/prodrive/pdnb3/pdnb3.c @@ -0,0 +1,249 @@ +/* + * (C) Copyright 2006 + * Stefan Roese, DENX Software Engineering, sr@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <command.h> +#include <malloc.h> +#include <asm/arch/ixp425.h> + +DECLARE_GLOBAL_DATA_PTR; + +/* Prototypes */ +int gunzip(void *, int, unsigned char *, unsigned long *); +int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); + +/* predefine these here for FPGA programming (before including fpga.c) */ +#define SET_FPGA(data) *IXP425_GPIO_GPOUTR = (data) +#define FPGA_DONE_STATE (*IXP425_GPIO_GPINR & CFG_FPGA_DONE) +#define FPGA_INIT_STATE (*IXP425_GPIO_GPINR & CFG_FPGA_INIT) +#define OLD_VAL old_val + +static unsigned long old_val = 0; + +/* + * include common fpga code (for prodrive boards) + */ +#include "../common/fpga.c" + +/* + * Miscelaneous platform dependent initialisations + */ +int board_post_init(void) +{ + return (0); +} + +int board_init(void) +{ + /* arch number of PDNB3 */ + gd->bd->bi_arch_number = MACH_TYPE_PDNB3; + + /* adress of boot parameters */ + gd->bd->bi_boot_params = 0x00000100; + + GPIO_OUTPUT_SET(CFG_GPIO_FPGA_RESET); + GPIO_OUTPUT_ENABLE(CFG_GPIO_FPGA_RESET); + + GPIO_OUTPUT_SET(CFG_GPIO_SYS_RUNNING); + GPIO_OUTPUT_ENABLE(CFG_GPIO_SYS_RUNNING); + + /* + * Setup GPIO's for FPGA programming + */ + GPIO_OUTPUT_CLEAR(CFG_GPIO_PRG); + GPIO_OUTPUT_CLEAR(CFG_GPIO_CLK); + GPIO_OUTPUT_CLEAR(CFG_GPIO_DATA); + GPIO_OUTPUT_ENABLE(CFG_GPIO_PRG); + GPIO_OUTPUT_ENABLE(CFG_GPIO_CLK); + GPIO_OUTPUT_ENABLE(CFG_GPIO_DATA); + GPIO_OUTPUT_DISABLE(CFG_GPIO_INIT); + GPIO_OUTPUT_DISABLE(CFG_GPIO_DONE); + + /* + * Setup GPIO's for interrupts + */ + GPIO_OUTPUT_DISABLE(CFG_GPIO_PCI_INTA); + GPIO_INT_ACT_LOW_SET(CFG_GPIO_PCI_INTA); + GPIO_OUTPUT_DISABLE(CFG_GPIO_PCI_INTB); + GPIO_INT_ACT_LOW_SET(CFG_GPIO_PCI_INTB); + GPIO_OUTPUT_DISABLE(CFG_GPIO_RESTORE_INT); + GPIO_INT_ACT_LOW_SET(CFG_GPIO_RESTORE_INT); + GPIO_OUTPUT_DISABLE(CFG_GPIO_RESTART_INT); + GPIO_INT_ACT_LOW_SET(CFG_GPIO_RESTART_INT); + + /* + * Setup GPIO's for 33MHz clock output + */ + *IXP425_GPIO_GPCLKR = 0x01FF0000; + GPIO_OUTPUT_ENABLE(CFG_GPIO_CLK_33M); + + /* + * Setup other chip select's + */ + *IXP425_EXP_CS1 = CFG_EXP_CS1; + + return 0; +} + +/* + * Check Board Identity + */ +int checkboard(void) +{ + char *s = getenv("serial#"); + + puts("Board: PDNB3"); + + if (s != NULL) { + puts(", serial# "); + puts(s); + } + putc('\n'); + + return (0); +} + +int dram_init(void) +{ + gd->bd->bi_dram[0].start = PHYS_SDRAM_1; + gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE; + + return (0); +} + +int do_fpga_boot(unsigned char *fpgadata) +{ + unsigned char *dst; + int status; + int index; + int i; + ulong len = CFG_MALLOC_LEN; + + /* + * Setup GPIO's for FPGA programming + */ + GPIO_OUTPUT_CLEAR(CFG_GPIO_PRG); + GPIO_OUTPUT_CLEAR(CFG_GPIO_CLK); + GPIO_OUTPUT_CLEAR(CFG_GPIO_DATA); + + /* + * Save value so no readback is required upon programming + */ + old_val = *IXP425_GPIO_GPOUTR; + + /* + * First try to decompress fpga image (gzip compressed?) + */ + dst = malloc(CFG_FPGA_MAX_SIZE); + if (gunzip(dst, CFG_FPGA_MAX_SIZE, (uchar *)fpgadata, &len) != 0) { + printf("Error: Image has to be gzipp'ed!\n"); + return -1; + } + + status = fpga_boot(dst, len); + if (status != 0) { + printf("\nFPGA: Booting failed "); + switch (status) { + case ERROR_FPGA_PRG_INIT_LOW: + printf("(Timeout: INIT not low after asserting PROGRAM*)\n "); + break; + case ERROR_FPGA_PRG_INIT_HIGH: + printf("(Timeout: INIT not high after deasserting PROGRAM*)\n "); + break; + case ERROR_FPGA_PRG_DONE: + printf("(Timeout: DONE not high after programming FPGA)\n "); + break; + } + + /* display infos on fpgaimage */ + index = 15; + for (i=0; i<4; i++) { + len = dst[index]; + printf("FPGA: %s\n", &(dst[index+1])); + index += len+3; + } + putc ('\n'); + /* delayed reboot */ + for (i=5; i>0; i--) { + printf("Rebooting in %2d seconds \r",i); + for (index=0;index<1000;index++) + udelay(1000); + } + putc('\n'); + do_reset(NULL, 0, 0, NULL); + } + + puts("FPGA: "); + + /* display infos on fpgaimage */ + index = 15; + for (i=0; i<4; i++) { + len = dst[index]; + printf("%s ", &(dst[index+1])); + index += len+3; + } + putc('\n'); + + free(dst); + + /* + * Reset FPGA + */ + GPIO_OUTPUT_CLEAR(CFG_GPIO_FPGA_RESET); + udelay(10); + GPIO_OUTPUT_SET(CFG_GPIO_FPGA_RESET); + + return (0); +} + +int do_fpga(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + ulong addr; + + if (argc < 2) { + printf ("Usage:\n%s\n", cmdtp->usage); + return 1; + } + + addr = simple_strtoul(argv[1], NULL, 16); + + return do_fpga_boot((unsigned char *)addr); +} + +U_BOOT_CMD( + fpga, 2, 0, do_fpga, + "fpga - boot FPGA\n", + "address size\n - boot FPGA with gzipped image at <address>\n" +); + +#if (CONFIG_COMMANDS & CFG_CMD_PCI) || defined(CONFIG_PCI) +extern struct pci_controller hose; +extern void pci_ixp_init(struct pci_controller * hose); + +void pci_init_board(void) +{ + extern void pci_ixp_init (struct pci_controller *hose); + + pci_ixp_init(&hose); +} +#endif diff --git a/board/prodrive/pdnb3/u-boot.lds b/board/prodrive/pdnb3/u-boot.lds new file mode 100644 index 0000000..f05f093 --- /dev/null +++ b/board/prodrive/pdnb3/u-boot.lds @@ -0,0 +1,56 @@ +/* + * (C) Copyright 2006 + * 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 + */ + +OUTPUT_FORMAT("elf32-bigarm", "elf32-bigarm", "elf32-bigarm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ + . = 0x00000000; + + . = ALIGN(4); + .text : + { + cpu/ixp/start.o (.text) + *(.text) + } + + . = ALIGN(4); + .rodata : { *(.rodata) } + + . = ALIGN(4); + .data : { *(.data) } + + . = ALIGN(4); + .got : { *(.got) } + + . = .; + __u_boot_cmd_start = .; + .u_boot_cmd : { *(.u_boot_cmd) } + __u_boot_cmd_end = .; + + . = ALIGN(4); + __bss_start = .; + .bss : { *(.bss) } + _end = .; +} diff --git a/board/r5200/Makefile b/board/r5200/Makefile new file mode 100644 index 0000000..d0364ed --- /dev/null +++ b/board/r5200/Makefile @@ -0,0 +1,40 @@ +# +# (C) Copyright 2000-2003 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# See file CREDITS for list of people who contributed to this +# project. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +include $(TOPDIR)/config.mk + +LIB = lib$(BOARD).a + +OBJS = $(BOARD).o + +$(LIB): .depend $(OBJS) + $(AR) crv $@ $(OBJS) + +######################################################################### + +.depend: Makefile $(SOBJS:.o=.S) $(OBJS:.o=.c) + $(CC) -M $(CFLAGS) $(SOBJS:.o=.S) $(OBJS:.o=.c) > $@ + +sinclude .depend + +######################################################################### diff --git a/board/r5200/config.mk b/board/r5200/config.mk new file mode 100644 index 0000000..8fc5319 --- /dev/null +++ b/board/r5200/config.mk @@ -0,0 +1,25 @@ +# +# (C) Copyright 2000-2003 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# Coldfire contribution by Bernhard Kuhn <bkuhn@metrowerks.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 +# + +TEXT_BASE = 0x10000000 diff --git a/board/r5200/r5200.c b/board/r5200/r5200.c new file mode 100644 index 0000000..69f3a76 --- /dev/null +++ b/board/r5200/r5200.c @@ -0,0 +1,124 @@ +/* + * (C) Copyright 2000-2003 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <asm/m5271.h> +#include <asm/immap_5271.h> + + +int checkboard (void) { + puts ("Board: R5200 Ethernet Module\n"); + return 0; +}; + +long int initdram (int board_type) { + int i; + + /* + * Set CS2 pin to be SD_CS0 + */ + mbar_writeByte(MCF_GPIO_PAR_CS, mbar_readByte(MCF_GPIO_PAR_CS) + | MCF_GPIO_PAR_CS_PAR_CS2); + + mbar_writeByte(MCF_GPIO_PAR_SDRAM, mbar_readByte(MCF_GPIO_PAR_SDRAM) + | MCF_GPIO_PAR_SDRAM_PAR_CSSDCS(0x01)); + + /* + * Check to see if the SDRAM has already been initialized + * by a run control tool + */ + if (!(mbar_readLong(MCF_SDRAMC_DACR0) & MCF_SDRAMC_DACRn_RE)) { + /* + * Initialize DRAM Control Register: DCR + */ + mbar_writeShort(MCF_SDRAMC_DCR, MCF_SDRAMC_DCR_RTIM(0x01) + | MCF_SDRAMC_DCR_RC(0x30)); + + /* + * Initialize DACR0 + */ + mbar_writeLong(MCF_SDRAMC_DACR0, + MCF_SDRAMC_DACRn_BA(CFG_SDRAM_BASE>>18) + | MCF_SDRAMC_DACRn_CASL(0) + | MCF_SDRAMC_DACRn_CBM(3) + | MCF_SDRAMC_DACRn_PS(2)); + + /* + * Initialize DMR0 + */ + mbar_writeLong(MCF_SDRAMC_DMR0, + MCF_SDRAMC_DMRn_BAM_8M + | MCF_SDRAMC_DMRn_V); + + /* + * Set IP bit in DACR + */ + mbar_writeLong(MCF_SDRAMC_DACR0, mbar_readLong(MCF_SDRAMC_DACR0) + | MCF_SDRAMC_DACRn_IP); + + /* + * Wait at least 20ns to allow banks to precharge + */ + for (i = 0; i < 5; i++) + asm(" nop"); + + /* + * Write to this block to initiate precharge + */ + *(u16 *)(CFG_SDRAM_BASE) = 0x9696; + + /* + * Set RE bit in DACR + */ + mbar_writeLong(MCF_SDRAMC_DACR0, mbar_readLong(MCF_SDRAMC_DACR0) + | MCF_SDRAMC_DACRn_RE); + + + /* + * Wait for at least 8 auto refresh cycles to occur + */ + for (i = 0; i < 2000; i++) + asm(" nop"); + + /* + * Finish the configuration by issuing the MRS. + */ + mbar_writeLong(MCF_SDRAMC_DACR0, mbar_readLong(MCF_SDRAMC_DACR0) + | MCF_SDRAMC_DACRn_MRS); + + + /* + * Write to the SDRAM Mode Register + */ + *(u16 *)(CFG_SDRAM_BASE + 0x1000) = 0x9696; + } + + return CFG_SDRAM_SIZE * 1024 * 1024; +}; + +int testdram (void) { + /* TODO: XXX XXX XXX */ + printf ("DRAM test not implemented!\n"); + + return (0); +} diff --git a/board/r5200/u-boot.lds b/board/r5200/u-boot.lds new file mode 100644 index 0000000..f7dc070 --- /dev/null +++ b/board/r5200/u-boot.lds @@ -0,0 +1,144 @@ +/* + * (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 + */ + +OUTPUT_ARCH(m68k) +SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); +/* Do we need any of these for elf? + __DYNAMIC = 0; */ +SECTIONS +{ + /* Read-only sections, merged into text segment: */ + . = + SIZEOF_HEADERS; + .interp : { *(.interp) } + .hash : { *(.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .rel.text : { *(.rel.text) } + .rela.text : { *(.rela.text) } + .rel.data : { *(.rel.data) } + .rela.data : { *(.rela.data) } + .rel.rodata : { *(.rel.rodata) } + .rela.rodata : { *(.rela.rodata) } + .rel.got : { *(.rel.got) } + .rela.got : { *(.rela.got) } + .rel.ctors : { *(.rel.ctors) } + .rela.ctors : { *(.rela.ctors) } + .rel.dtors : { *(.rel.dtors) } + .rela.dtors : { *(.rela.dtors) } + .rel.bss : { *(.rel.bss) } + .rela.bss : { *(.rela.bss) } + .rel.plt : { *(.rel.plt) } + .rela.plt : { *(.rela.plt) } + .init : { *(.init) } + .plt : { *(.plt) } + .text : + { + /* WARNING - the following is hand-optimized to fit within */ + /* the sector layout of our flash chips! XXX FIXME XXX */ + + cpu/mcf52x2/start.o (.text) + lib_m68k/traps.o (.text) + cpu/mcf52x2/interrupts.o (.text) + common/dlmalloc.o (.text) + lib_generic/zlib.o (.text) + + . = DEFINED(env_offset) ? env_offset : .; + common/environment.o (.text) + + *(.text) + *(.fixup) + *(.got1) + } + _etext = .; + PROVIDE (etext = .); + .rodata : + { + *(.rodata) + *(.rodata1) + } + .fini : { *(.fini) } =0 + .ctors : { *(.ctors) } + .dtors : { *(.dtors) } + + /* Read-write section, merged into data segment: */ + . = (. + 0x00FF) & 0xFFFFFF00; + _erotext = .; + PROVIDE (erotext = .); + + .reloc : + { + __got_start = .; + *(.got) + __got_end = .; + _GOT2_TABLE_ = .; + *(.got2) + _FIXUP_TABLE_ = .; + *(.fixup) + } + __got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >>2; + __fixup_entries = (. - _FIXUP_TABLE_)>>2; + + .data : + { + *(.data) + *(.data1) + *(.sdata) + *(.sdata2) + *(.dynamic) + CONSTRUCTORS + } + _edata = .; + PROVIDE (edata = .); + + . = .; + __u_boot_cmd_start = .; + .u_boot_cmd : { *(.u_boot_cmd) } + __u_boot_cmd_end = .; + + + . = .; + __start___ex_table = .; + __ex_table : { *(__ex_table) } + __stop___ex_table = .; + + . = ALIGN(256); + __init_begin = .; + .text.init : { *(.text.init) } + .data.init : { *(.data.init) } + . = ALIGN(256); + __init_end = .; + + __bss_start = .; + .bss : + { + _sbss = .; + *(.sbss) *(.scommon) + *(.dynbss) + *(.bss) + *(COMMON) + . = ALIGN(4); + _ebss = .; + } + _end = . ; + PROVIDE (end = .); +} diff --git a/board/tqm8xx/tqm8xx.c b/board/tqm8xx/tqm8xx.c index 520bea8..b292231 100644 --- a/board/tqm8xx/tqm8xx.c +++ b/board/tqm8xx/tqm8xx.c @@ -1,5 +1,5 @@ /* - * (C) Copyright 2000-2004 + * (C) Copyright 2000-2006 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. * * See file CREDITS for list of people who contributed to this @@ -124,6 +124,9 @@ int checkboard (void) break; putc (*s); } +#ifdef CONFIG_VIRTLAB2 + puts (" (Virtlab2)"); +#endif putc ('\n'); return (0); diff --git a/board/zylonite/Makefile b/board/zylonite/Makefile index 999647f..f3ad674 100644 --- a/board/zylonite/Makefile +++ b/board/zylonite/Makefile @@ -1,4 +1,3 @@ - # # (C) Copyright 2000 # Wolfgang Denk, DENX Software Engineering, wd@denx.de. @@ -21,12 +20,11 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, # MA 02111-1307 USA # - include $(TOPDIR)/config.mk LIB = lib$(BOARD).a -OBJS := zylonite.o flash.o +OBJS := zylonite.o nand.o SOBJS := lowlevel_init.o $(LIB): $(OBJS) $(SOBJS) diff --git a/board/zylonite/config.mk b/board/zylonite/config.mk index 09b0f71..b5d5955 100644 --- a/board/zylonite/config.mk +++ b/board/zylonite/config.mk @@ -2,3 +2,5 @@ #TEXT_BASE = 0xa1700000 #TEXT_BASE = 0xa3080000 TEXT_BASE = 0xa3008000 + +BOARDLIBS = drivers/nand/libnand.a diff --git a/board/zylonite/lowlevel_init.S b/board/zylonite/lowlevel_init.S index c3bb4eb..da01765 100644 --- a/board/zylonite/lowlevel_init.S +++ b/board/zylonite/lowlevel_init.S @@ -235,6 +235,7 @@ mem_init: orr r1, r1, #0x40000000 @ enable SDRAM for Normal Access str r1, [r0] +#ifndef CFG_SKIP_DRAM_SCRUB /* scrub/init SDRAM if enabled/present */ /* ldr r11, =0xa0000000 /\* base address of SDRAM (CFG_DRAM_BASE) *\/ */ /* ldr r12, =0x04000000 /\* size of memory to scrub (CFG_DRAM_SIZE) *\/ */ @@ -254,6 +255,7 @@ mem_init: stmia r8!, {r0-r7} beq 15f b 10b +#endif /* CFG_SKIP_DRAM_SCRUB */ 15: /* Mask all interrupts */ diff --git a/board/zylonite/nand.c b/board/zylonite/nand.c new file mode 100644 index 0000000..5d2cd65 --- /dev/null +++ b/board/zylonite/nand.c @@ -0,0 +1,584 @@ +/* + * (C) Copyright 2006 DENX Software Engineering + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> + +#if (CONFIG_COMMANDS & CFG_CMD_NAND) +#ifdef CONFIG_NEW_NAND_CODE + +#include <nand.h> +#include <asm/arch/pxa-regs.h> + +#ifdef CFG_DFC_DEBUG1 +# define DFC_DEBUG1(fmt, args...) printf(fmt, ##args) +#else +# define DFC_DEBUG1(fmt, args...) +#endif + +#ifdef CFG_DFC_DEBUG2 +# define DFC_DEBUG2(fmt, args...) printf(fmt, ##args) +#else +# define DFC_DEBUG2(fmt, args...) +#endif + +#ifdef CFG_DFC_DEBUG3 +# define DFC_DEBUG3(fmt, args...) printf(fmt, ##args) +#else +# define DFC_DEBUG3(fmt, args...) +#endif + +#define MIN(x, y) ((x < y) ? x : y) + +/* These really don't belong here, as they are specific to the NAND Model */ +static uint8_t scan_ff_pattern[] = { 0xff, 0xff }; + +static struct nand_bbt_descr delta_bbt_descr = { + .options = 0, + .offs = 0, + .len = 2, + .pattern = scan_ff_pattern +}; + +static struct nand_oobinfo delta_oob = { + .useecc = MTD_NANDECC_AUTOPL_USR, /* MTD_NANDECC_PLACEONLY, */ + .eccbytes = 6, + .eccpos = {2, 3, 4, 5, 6, 7}, + .oobfree = { {8, 2}, {12, 4} } +}; + + +/* + * not required for Monahans DFC + */ +static void dfc_hwcontrol(struct mtd_info *mtdinfo, int cmd) +{ + return; +} + +#if 0 +/* read device ready pin */ +static int dfc_device_ready(struct mtd_info *mtdinfo) +{ + if(NDSR & NDSR_RDY) + return 1; + else + return 0; + return 0; +} +#endif + +/* + * Write buf to the DFC Controller Data Buffer + */ +static void dfc_write_buf(struct mtd_info *mtd, const u_char *buf, int len) +{ + unsigned long bytes_multi = len & 0xfffffffc; + unsigned long rest = len & 0x3; + unsigned long *long_buf; + int i; + + DFC_DEBUG2("dfc_write_buf: writing %d bytes starting with 0x%x.\n", len, *((unsigned long*) buf)); + if(bytes_multi) { + for(i=0; i<bytes_multi; i+=4) { + long_buf = (unsigned long*) &buf[i]; + NDDB = *long_buf; + } + } + if(rest) { + printf("dfc_write_buf: ERROR, writing non 4-byte aligned data.\n"); + } + return; +} + + +/* + * These functions are quite problematic for the DFC. Luckily they are + * not used in the current nand code, except for nand_command, which + * we've defined our own anyway. The problem is, that we always need + * to write 4 bytes to the DFC Data Buffer, but in these functions we + * don't know if to buffer the bytes/half words until we've gathered 4 + * bytes or if to send them straight away. + * + * Solution: Don't use these with Mona's DFC and complain loudly. + */ +static void dfc_write_word(struct mtd_info *mtd, u16 word) +{ + printf("dfc_write_word: WARNING, this function does not work with the Monahans DFC!\n"); +} +static void dfc_write_byte(struct mtd_info *mtd, u_char byte) +{ + printf("dfc_write_byte: WARNING, this function does not work with the Monahans DFC!\n"); +} + +/* The original: + * static void dfc_read_buf(struct mtd_info *mtd, const u_char *buf, int len) + * + * Shouldn't this be "u_char * const buf" ? + */ +static void dfc_read_buf(struct mtd_info *mtd, u_char* const buf, int len) +{ + int i=0, j; + + /* we have to be carefull not to overflow the buffer if len is + * not a multiple of 4 */ + unsigned long bytes_multi = len & 0xfffffffc; + unsigned long rest = len & 0x3; + unsigned long *long_buf; + + DFC_DEBUG3("dfc_read_buf: reading %d bytes.\n", len); + /* if there are any, first copy multiple of 4 bytes */ + if(bytes_multi) { + for(i=0; i<bytes_multi; i+=4) { + long_buf = (unsigned long*) &buf[i]; + *long_buf = NDDB; + } + } + + /* ...then the rest */ + if(rest) { + unsigned long rest_data = NDDB; + for(j=0;j<rest; j++) + buf[i+j] = (u_char) ((rest_data>>j) & 0xff); + } + + return; +} + +/* + * read a word. Not implemented as not used in NAND code. + */ +static u16 dfc_read_word(struct mtd_info *mtd) +{ + printf("dfc_write_byte: UNIMPLEMENTED.\n"); + return 0; +} + +/* global var, too bad: mk@tbd: move to ->priv pointer */ +static unsigned long read_buf = 0; +static int bytes_read = -1; + +/* + * read a byte from NDDB Because we can only read 4 bytes from NDDB at + * a time, we buffer the remaining bytes. The buffer is reset when a + * new command is sent to the chip. + * + * WARNING: + * This function is currently only used to read status and id + * bytes. For these commands always 8 bytes need to be read from + * NDDB. So we read and discard these bytes right now. In case this + * function is used for anything else in the future, we must check + * what was the last command issued and read the appropriate amount of + * bytes respectively. + */ +static u_char dfc_read_byte(struct mtd_info *mtd) +{ + unsigned char byte; + unsigned long dummy; + + if(bytes_read < 0) { + read_buf = NDDB; + dummy = NDDB; + bytes_read = 0; + } + byte = (unsigned char) (read_buf>>(8 * bytes_read++)); + if(bytes_read >= 4) + bytes_read = -1; + + DFC_DEBUG2("dfc_read_byte: byte %u: 0x%x of (0x%x).\n", bytes_read - 1, byte, read_buf); + return byte; +} + +/* calculate delta between OSCR values start and now */ +static unsigned long get_delta(unsigned long start) +{ + unsigned long cur = OSCR; + + if(cur < start) /* OSCR overflowed */ + return (cur + (start^0xffffffff)); + else + return (cur - start); +} + +/* delay function, this doesn't belong here */ +static void wait_us(unsigned long us) +{ + unsigned long start = OSCR; + us *= OSCR_CLK_FREQ; + + while (get_delta(start) < us) { + /* do nothing */ + } +} + +static void dfc_clear_nddb(void) +{ + NDCR &= ~NDCR_ND_RUN; + wait_us(CFG_NAND_OTHER_TO); +} + +/* wait_event with timeout */ +static unsigned long dfc_wait_event(unsigned long event) +{ + unsigned long ndsr, timeout, start = OSCR; + + if(!event) + return 0xff000000; + else if(event & (NDSR_CS0_CMDD | NDSR_CS0_BBD)) + timeout = CFG_NAND_PROG_ERASE_TO * OSCR_CLK_FREQ; + else + timeout = CFG_NAND_OTHER_TO * OSCR_CLK_FREQ; + + while(1) { + ndsr = NDSR; + if(ndsr & event) { + NDSR |= event; + break; + } + if(get_delta(start) > timeout) { + DFC_DEBUG1("dfc_wait_event: TIMEOUT waiting for event: 0x%x.\n", event); + return 0xff000000; + } + + } + return ndsr; +} + +/* we don't always wan't to do this */ +static void dfc_new_cmd(void) +{ + int retry = 0; + unsigned long status; + + while(retry++ <= CFG_NAND_SENDCMD_RETRY) { + /* Clear NDSR */ + NDSR = 0xFFF; + + /* set NDCR[NDRUN] */ + if(!(NDCR & NDCR_ND_RUN)) + NDCR |= NDCR_ND_RUN; + + status = dfc_wait_event(NDSR_WRCMDREQ); + + if(status & NDSR_WRCMDREQ) + return; + + DFC_DEBUG2("dfc_new_cmd: FAILED to get WRITECMDREQ, retry: %d.\n", retry); + dfc_clear_nddb(); + } + DFC_DEBUG1("dfc_new_cmd: giving up after %d retries.\n", retry); +} + +/* this function is called after Programm and Erase Operations to + * check for success or failure */ +static int dfc_wait(struct mtd_info *mtd, struct nand_chip *this, int state) +{ + unsigned long ndsr=0, event=0; + + if(state == FL_WRITING) { + event = NDSR_CS0_CMDD | NDSR_CS0_BBD; + } else if(state == FL_ERASING) { + event = NDSR_CS0_CMDD | NDSR_CS0_BBD; + } + + ndsr = dfc_wait_event(event); + + if((ndsr & NDSR_CS0_BBD) || (ndsr & 0xff000000)) + return(0x1); /* Status Read error */ + return 0; +} + +/* cmdfunc send commands to the DFC */ +static void dfc_cmdfunc(struct mtd_info *mtd, unsigned command, + int column, int page_addr) +{ + /* register struct nand_chip *this = mtd->priv; */ + unsigned long ndcb0=0, ndcb1=0, ndcb2=0, event=0; + + /* clear the ugly byte read buffer */ + bytes_read = -1; + read_buf = 0; + + switch (command) { + case NAND_CMD_READ0: + DFC_DEBUG3("dfc_cmdfunc: NAND_CMD_READ0, page_addr: 0x%x, column: 0x%x.\n", page_addr, (column>>1)); + dfc_new_cmd(); + ndcb0 = (NAND_CMD_READ0 | (4<<16)); + column >>= 1; /* adjust for 16 bit bus */ + ndcb1 = (((column>>1) & 0xff) | + ((page_addr<<8) & 0xff00) | + ((page_addr<<8) & 0xff0000) | + ((page_addr<<8) & 0xff000000)); /* make this 0x01000000 ? */ + event = NDSR_RDDREQ; + goto write_cmd; + case NAND_CMD_READ1: + DFC_DEBUG2("dfc_cmdfunc: NAND_CMD_READ1 unimplemented!\n"); + goto end; + case NAND_CMD_READOOB: + DFC_DEBUG1("dfc_cmdfunc: NAND_CMD_READOOB unimplemented!\n"); + goto end; + case NAND_CMD_READID: + dfc_new_cmd(); + DFC_DEBUG2("dfc_cmdfunc: NAND_CMD_READID.\n"); + ndcb0 = (NAND_CMD_READID | (3 << 21) | (1 << 16)); /* addr cycles*/ + event = NDSR_RDDREQ; + goto write_cmd; + case NAND_CMD_PAGEPROG: + /* sent as a multicommand in NAND_CMD_SEQIN */ + DFC_DEBUG2("dfc_cmdfunc: NAND_CMD_PAGEPROG empty due to multicmd.\n"); + goto end; + case NAND_CMD_ERASE1: + DFC_DEBUG2("dfc_cmdfunc: NAND_CMD_ERASE1, page_addr: 0x%x, column: 0x%x.\n", page_addr, (column>>1)); + dfc_new_cmd(); + ndcb0 = (0xd060 | (1<<25) | (2<<21) | (1<<19) | (3<<16)); + ndcb1 = (page_addr & 0x00ffffff); + goto write_cmd; + case NAND_CMD_ERASE2: + DFC_DEBUG2("dfc_cmdfunc: NAND_CMD_ERASE2 empty due to multicmd.\n"); + goto end; + case NAND_CMD_SEQIN: + /* send PAGE_PROG command(0x1080) */ + dfc_new_cmd(); + DFC_DEBUG2("dfc_cmdfunc: NAND_CMD_SEQIN/PAGE_PROG, page_addr: 0x%x, column: 0x%x.\n", page_addr, (column>>1)); + ndcb0 = (0x1080 | (1<<25) | (1<<21) | (1<<19) | (4<<16)); + column >>= 1; /* adjust for 16 bit bus */ + ndcb1 = (((column>>1) & 0xff) | + ((page_addr<<8) & 0xff00) | + ((page_addr<<8) & 0xff0000) | + ((page_addr<<8) & 0xff000000)); /* make this 0x01000000 ? */ + event = NDSR_WRDREQ; + goto write_cmd; + case NAND_CMD_STATUS: + DFC_DEBUG2("dfc_cmdfunc: NAND_CMD_STATUS.\n"); + dfc_new_cmd(); + ndcb0 = NAND_CMD_STATUS | (4<<21); + event = NDSR_RDDREQ; + goto write_cmd; + case NAND_CMD_RESET: + DFC_DEBUG2("dfc_cmdfunc: NAND_CMD_RESET.\n"); + ndcb0 = NAND_CMD_RESET | (5<<21); + event = NDSR_CS0_CMDD; + goto write_cmd; + default: + printk("dfc_cmdfunc: error, unsupported command.\n"); + goto end; + } + + write_cmd: + NDCB0 = ndcb0; + NDCB0 = ndcb1; + NDCB0 = ndcb2; + + /* wait_event: */ + dfc_wait_event(event); + end: + return; +} + +static void dfc_gpio_init(void) +{ + DFC_DEBUG2("Setting up DFC GPIO's.\n"); + + /* no idea what is done here, see zylonite.c */ + GPIO4 = 0x1; + + DF_ALE_WE1 = 0x00000001; + DF_ALE_WE2 = 0x00000001; + DF_nCS0 = 0x00000001; + DF_nCS1 = 0x00000001; + DF_nWE = 0x00000001; + DF_nRE = 0x00000001; + DF_IO0 = 0x00000001; + DF_IO8 = 0x00000001; + DF_IO1 = 0x00000001; + DF_IO9 = 0x00000001; + DF_IO2 = 0x00000001; + DF_IO10 = 0x00000001; + DF_IO3 = 0x00000001; + DF_IO11 = 0x00000001; + DF_IO4 = 0x00000001; + DF_IO12 = 0x00000001; + DF_IO5 = 0x00000001; + DF_IO13 = 0x00000001; + DF_IO6 = 0x00000001; + DF_IO14 = 0x00000001; + DF_IO7 = 0x00000001; + DF_IO15 = 0x00000001; + + DF_nWE = 0x1901; + DF_nRE = 0x1901; + DF_CLE_NOE = 0x1900; + DF_ALE_WE1 = 0x1901; + DF_INT_RnB = 0x1900; +} + +/* + * Board-specific NAND initialization. The following members of the + * argument are board-specific (per include/linux/mtd/nand_new.h): + * - IO_ADDR_R?: address to read the 8 I/O lines of the flash device + * - IO_ADDR_W?: address to write the 8 I/O lines of the flash device + * - hwcontrol: hardwarespecific function for accesing control-lines + * - dev_ready: hardwarespecific function for accesing device ready/busy line + * - enable_hwecc?: function to enable (reset) hardware ecc generator. Must + * only be provided if a hardware ECC is available + * - eccmode: mode of ecc, see defines + * - chip_delay: chip dependent delay for transfering data from array to + * read regs (tR) + * - options: various chip options. They can partly be set to inform + * nand_scan about special functionality. See the defines for further + * explanation + * Members with a "?" were not set in the merged testing-NAND branch, + * so they are not set here either. + */ +void board_nand_init(struct nand_chip *nand) +{ + unsigned long tCH, tCS, tWH, tWP, tRH, tRP, tRP_high, tR, tWHR, tAR; + + /* set up GPIO Control Registers */ + dfc_gpio_init(); + + /* turn on the NAND Controller Clock (104 MHz @ D0) */ + CKENA |= (CKENA_4_NAND | CKENA_9_SMC); + +#undef CFG_TIMING_TIGHT +#ifndef CFG_TIMING_TIGHT + tCH = MIN(((unsigned long) (NAND_TIMING_tCH * DFC_CLK_PER_US) + 1), + DFC_MAX_tCH); + tCS = MIN(((unsigned long) (NAND_TIMING_tCS * DFC_CLK_PER_US) + 1), + DFC_MAX_tCS); + tWH = MIN(((unsigned long) (NAND_TIMING_tWH * DFC_CLK_PER_US) + 1), + DFC_MAX_tWH); + tWP = MIN(((unsigned long) (NAND_TIMING_tWP * DFC_CLK_PER_US) + 1), + DFC_MAX_tWP); + tRH = MIN(((unsigned long) (NAND_TIMING_tRH * DFC_CLK_PER_US) + 1), + DFC_MAX_tRH); + tRP = MIN(((unsigned long) (NAND_TIMING_tRP * DFC_CLK_PER_US) + 1), + DFC_MAX_tRP); + tR = MIN(((unsigned long) (NAND_TIMING_tR * DFC_CLK_PER_US) + 1), + DFC_MAX_tR); + tWHR = MIN(((unsigned long) (NAND_TIMING_tWHR * DFC_CLK_PER_US) + 1), + DFC_MAX_tWHR); + tAR = MIN(((unsigned long) (NAND_TIMING_tAR * DFC_CLK_PER_US) + 1), + DFC_MAX_tAR); +#else /* this is the tight timing */ + + tCH = MIN(((unsigned long) (NAND_TIMING_tCH * DFC_CLK_PER_US)), + DFC_MAX_tCH); + tCS = MIN(((unsigned long) (NAND_TIMING_tCS * DFC_CLK_PER_US)), + DFC_MAX_tCS); + tWH = MIN(((unsigned long) (NAND_TIMING_tWH * DFC_CLK_PER_US)), + DFC_MAX_tWH); + tWP = MIN(((unsigned long) (NAND_TIMING_tWP * DFC_CLK_PER_US)), + DFC_MAX_tWP); + tRH = MIN(((unsigned long) (NAND_TIMING_tRH * DFC_CLK_PER_US)), + DFC_MAX_tRH); + tRP = MIN(((unsigned long) (NAND_TIMING_tRP * DFC_CLK_PER_US)), + DFC_MAX_tRP); + tR = MIN(((unsigned long) (NAND_TIMING_tR * DFC_CLK_PER_US) - tCH - 2), + DFC_MAX_tR); + tWHR = MIN(((unsigned long) (NAND_TIMING_tWHR * DFC_CLK_PER_US) - tCH - 2), + DFC_MAX_tWHR); + tAR = MIN(((unsigned long) (NAND_TIMING_tAR * DFC_CLK_PER_US) - 2), + DFC_MAX_tAR); +#endif /* CFG_TIMING_TIGHT */ + + + DFC_DEBUG2("tCH=%u, tCS=%u, tWH=%u, tWP=%u, tRH=%u, tRP=%u, tR=%u, tWHR=%u, tAR=%u.\n", tCH, tCS, tWH, tWP, tRH, tRP, tR, tWHR, tAR); + + /* tRP value is split in the register */ + if(tRP & (1 << 4)) { + tRP_high = 1; + tRP &= ~(1 << 4); + } else { + tRP_high = 0; + } + + NDTR0CS0 = (tCH << 19) | + (tCS << 16) | + (tWH << 11) | + (tWP << 8) | + (tRP_high << 6) | + (tRH << 3) | + (tRP << 0); + + NDTR1CS0 = (tR << 16) | + (tWHR << 4) | + (tAR << 0); + + /* If it doesn't work (unlikely) think about: + * - ecc enable + * - chip select don't care + * - read id byte count + * + * Intentionally enabled by not setting bits: + * - dma (DMA_EN) + * - page size = 512 + * - cs don't care, see if we can enable later! + * - row address start position (after second cycle) + * - pages per block = 32 + * - ND_RDY : clears command buffer + */ + /* NDCR_NCSX | /\* Chip select busy don't care *\/ */ + + NDCR = (NDCR_SPARE_EN | /* use the spare area */ + NDCR_DWIDTH_C | /* 16bit DFC data bus width */ + NDCR_DWIDTH_M | /* 16 bit Flash device data bus width */ + (2 << 16) | /* read id count = 7 ???? mk@tbd */ + NDCR_ND_ARB_EN | /* enable bus arbiter */ + NDCR_RDYM | /* flash device ready ir masked */ + NDCR_CS0_PAGEDM | /* ND_nCSx page done ir masked */ + NDCR_CS1_PAGEDM | + NDCR_CS0_CMDDM | /* ND_CSx command done ir masked */ + NDCR_CS1_CMDDM | + NDCR_CS0_BBDM | /* ND_CSx bad block detect ir masked */ + NDCR_CS1_BBDM | + NDCR_DBERRM | /* double bit error ir masked */ + NDCR_SBERRM | /* single bit error ir masked */ + NDCR_WRDREQM | /* write data request ir masked */ + NDCR_RDDREQM | /* read data request ir masked */ + NDCR_WRCMDREQM); /* write command request ir masked */ + + + /* wait 10 us due to cmd buffer clear reset */ + /* wait(10); */ + + + nand->hwcontrol = dfc_hwcontrol; +/* nand->dev_ready = dfc_device_ready; */ + nand->eccmode = NAND_ECC_SOFT; + nand->options = NAND_BUSWIDTH_16; + nand->waitfunc = dfc_wait; + nand->read_byte = dfc_read_byte; + nand->write_byte = dfc_write_byte; + nand->read_word = dfc_read_word; + nand->write_word = dfc_write_word; + nand->read_buf = dfc_read_buf; + nand->write_buf = dfc_write_buf; + + nand->cmdfunc = dfc_cmdfunc; + nand->autooob = &delta_oob; + nand->badblock_pattern = &delta_bbt_descr; +} + +#else + #error "U-Boot legacy NAND support not available for Monahans DFC." +#endif +#endif |