diff options
Diffstat (limited to 'roms/u-boot-sam460ex/onenand_ipl')
7 files changed, 466 insertions, 0 deletions
diff --git a/roms/u-boot-sam460ex/onenand_ipl/board/apollon/Makefile b/roms/u-boot-sam460ex/onenand_ipl/board/apollon/Makefile new file mode 100644 index 000000000..6f1df0113 --- /dev/null +++ b/roms/u-boot-sam460ex/onenand_ipl/board/apollon/Makefile @@ -0,0 +1,87 @@ + +include $(TOPDIR)/config.mk +include $(TOPDIR)/onenand_ipl/board/$(BOARDDIR)/config.mk + +LDSCRIPT= $(TOPDIR)/onenand_ipl/board/$(BOARDDIR)/u-boot.onenand.lds +LDFLAGS = -Bstatic -T $(onenandobj)u-boot.lds -Ttext $(TEXT_BASE) $(PLATFORM_LDFLAGS) +AFLAGS += -DCONFIG_PRELOADER -DCONFIG_ONENAND_IPL +CFLAGS += -DCONFIG_PRELOADER -DCONFIG_ONENAND_IPL +OBJCFLAGS += --gap-fill=0x00 + +SOBJS := low_levelinit.o +SOBJS += start.o +COBJS := apollon.o +COBJS += onenand_read.o +COBJS += onenand_boot.o + +SRCS := $(addprefix $(obj),$(SOBJS:.o=.S) $(COBJS:.o=.c)) +OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS)) +__OBJS := $(SOBJS) $(COBJS) +LNDIR := $(OBJTREE)/onenand_ipl/board/$(BOARDDIR) + +onenandobj := $(OBJTREE)/onenand_ipl/ + +ALL = $(onenandobj)onenand-ipl $(onenandobj)onenand-ipl.bin $(onenandobj)onenand-ipl-2k.bin $(onenandobj)onenand-ipl-4k.bin + +all: $(obj).depend $(ALL) + +$(onenandobj)onenand-ipl-2k.bin: $(onenandobj)onenand-ipl + $(OBJCOPY) ${OBJCFLAGS} --pad-to=0x800 -O binary $< $@ + +$(onenandobj)onenand-ipl-4k.bin: $(onenandobj)onenand-ipl + $(OBJCOPY) ${OBJCFLAGS} --pad-to=0x1000 -O binary $< $@ + +$(onenandobj)onenand-ipl.bin: $(onenandobj)onenand-ipl + $(OBJCOPY) ${OBJCFLAGS} -O binary $< $@ + +$(onenandobj)onenand-ipl: $(OBJS) $(onenandobj)u-boot.lds + cd $(LNDIR) && $(LD) $(LDFLAGS) $$UNDEF_SYM $(__OBJS) \ + -Map $@.map -o $@ + +$(onenandobj)u-boot.lds: $(LDSCRIPT) + $(CPP) $(CPPFLAGS) $(LDPPFLAGS) -ansi -D__ASSEMBLY__ -P - <$^ >$@ + +# create symbolic links from common files + +# from cpu directory +$(obj)start.S: + @rm -f $@ + ln -s $(SRCTREE)/$(CPUDIR)/start.S $@ + +# from onenand_ipl directory +$(obj)onenand_ipl.h: + @rm -f $@ + ln -s $(SRCTREE)/onenand_ipl/onenand_ipl.h $@ + +$(obj)onenand_boot.c: $(obj)onenand_ipl.h + @rm -f $@ + ln -s $(SRCTREE)/onenand_ipl/onenand_boot.c $@ + +$(obj)onenand_read.c: $(obj)onenand_ipl.h + @rm -f $@ + ln -s $(SRCTREE)/onenand_ipl/onenand_read.c $@ + +ifneq ($(OBJTREE), $(SRCTREE)) +$(obj)apollon.c: + @rm -f $@ + ln -s $(SRCTREE)/onenand_ipl/board/$(BOARDDIR)/apollon.c $@ + +$(obj)low_levelinit.S: + @rm -f $@ + ln -s $(SRCTREE)/onenand_ipl/board/$(BOARDDIR)/low_levelinit.S $@ +endif + +######################################################################### + +$(obj)%.o: $(obj)%.S + $(CC) $(AFLAGS) -c -o $@ $< + +$(obj)%.o: $(obj)$.c + $(CC) $(CFLAGS) -c -o $@ $< + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/roms/u-boot-sam460ex/onenand_ipl/board/apollon/apollon.c b/roms/u-boot-sam460ex/onenand_ipl/board/apollon/apollon.c new file mode 100644 index 000000000..4936e00f1 --- /dev/null +++ b/roms/u-boot-sam460ex/onenand_ipl/board/apollon/apollon.c @@ -0,0 +1,70 @@ +/* + * (C) Copyright 2005-2008 Samsung Electronics + * Kyungmin Park <kyungmin.park@samsung.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/arch/mux.h> + +#define write_config_reg(reg, value) \ +do { \ + writeb(value, reg); \ +} while (0) + +/***************************************** + * Routine: board_init + * Description: Early hardware init. + *****************************************/ +int board_init(void) +{ + return 0; +} + +#ifdef CONFIG_SYS_PRINTF +/* Pin Muxing registers used for UART1 */ +/**************************************** + * Routine: muxSetupUART1 (ostboot) + * Description: Set up uart1 muxing + *****************************************/ +static void muxSetupUART1(void) +{ + /* UART1_CTS pin configuration, PIN = D21 */ + write_config_reg(CONTROL_PADCONF_UART1_CTS, 0); + /* UART1_RTS pin configuration, PIN = H21 */ + write_config_reg(CONTROL_PADCONF_UART1_RTS, 0); + /* UART1_TX pin configuration, PIN = L20 */ + write_config_reg(CONTROL_PADCONF_UART1_TX, 0); + /* UART1_RX pin configuration, PIN = T21 */ + write_config_reg(CONTROL_PADCONF_UART1_RX, 0); +} +#endif + +/********************************************************** + * Routine: s_init + * Description: Does early system init of muxing and clocks. + * - Called at time when only stack is available. + **********************************************************/ +int s_init(int skip) +{ +#ifdef CONFIG_SYS_PRINTF + muxSetupUART1(); +#endif + return 0; +} diff --git a/roms/u-boot-sam460ex/onenand_ipl/board/apollon/config.mk b/roms/u-boot-sam460ex/onenand_ipl/board/apollon/config.mk new file mode 100644 index 000000000..fd9c506f7 --- /dev/null +++ b/roms/u-boot-sam460ex/onenand_ipl/board/apollon/config.mk @@ -0,0 +1,14 @@ +# +# (C) Copyright 2005-2008 Samsung Electronics +# Kyungmin Park <kyungmin.park@samsung.com> +# +# Samsung Apollon board with OMAP2420 (ARM1136) cpu +# +# Apollon has 1 bank of 128MB mDDR-SDRAM on CS0 +# Physical Address: +# 8000'0000 (bank0) +# 8800'0000 (bank1) +# Linux-Kernel is expected to be at 8000'8000, entry 8000'8000 +# (mem base + reserved) + +TEXT_BASE = 0x00000000 diff --git a/roms/u-boot-sam460ex/onenand_ipl/board/apollon/u-boot.onenand.lds b/roms/u-boot-sam460ex/onenand_ipl/board/apollon/u-boot.onenand.lds new file mode 100644 index 000000000..0960c12ce --- /dev/null +++ b/roms/u-boot-sam460ex/onenand_ipl/board/apollon/u-boot.onenand.lds @@ -0,0 +1,53 @@ +/* + * (C) Copyright 2005-2008 Samsung Electronics + * Kyungmin Park <kyungmin.park@samsung.com> + * + * Derived from X-loader + * + * 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-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ + . = 0x00000000; + + . = ALIGN(4); + .text : + { + start.o (.text) + *(.text) + } + + . = ALIGN(4); + .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) } + + . = ALIGN(4); + .data : { *(.data) } + + . = ALIGN(4); + .got : { *(.got) } + + . = ALIGN(4); + __bss_start = .; + .bss : { *(.bss) . = ALIGN(4); } + _end = .; +} diff --git a/roms/u-boot-sam460ex/onenand_ipl/onenand_boot.c b/roms/u-boot-sam460ex/onenand_ipl/onenand_boot.c new file mode 100644 index 000000000..22baebb31 --- /dev/null +++ b/roms/u-boot-sam460ex/onenand_ipl/onenand_boot.c @@ -0,0 +1,48 @@ +/* + * (C) Copyright 2005-2008 Samsung Electronics + * Kyungmin Park <kyungmin.park@samsung.com> + * + * Derived from x-loader + * + * 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 "onenand_ipl.h" + +typedef int (init_fnc_t)(void); + +void start_oneboot(void) +{ + uchar *buf; + + buf = (uchar *) CONFIG_SYS_LOAD_ADDR; + + onenand_read_block(buf); + + ((init_fnc_t *)CONFIG_SYS_LOAD_ADDR)(); + + /* should never come here */ +} + +void hang(void) +{ + for (;;); +} diff --git a/roms/u-boot-sam460ex/onenand_ipl/onenand_ipl.h b/roms/u-boot-sam460ex/onenand_ipl/onenand_ipl.h new file mode 100644 index 000000000..7ebb3e32d --- /dev/null +++ b/roms/u-boot-sam460ex/onenand_ipl/onenand_ipl.h @@ -0,0 +1,36 @@ +/* + * (C) Copyright 2005-2008 Samsung Electronics + * Kyungmin Park <kyungmin.park@samsung.com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef _ONENAND_IPL_H +#define _ONENAND_IPL_H + +#include <linux/mtd/onenand_regs.h> + +#define onenand_readw(a) readw(THIS_ONENAND(a)) +#define onenand_writew(v, a) writew(v, THIS_ONENAND(a)) + +#define THIS_ONENAND(a) (CONFIG_SYS_ONENAND_BASE + (a)) + +#define READ_INTERRUPT() onenand_readw(ONENAND_REG_INTERRUPT) + +extern int (*onenand_read_page)(ulong block, ulong page, + u_char *buf, int pagesize); +extern int onenand_read_block(unsigned char *buf); +#endif diff --git a/roms/u-boot-sam460ex/onenand_ipl/onenand_read.c b/roms/u-boot-sam460ex/onenand_ipl/onenand_read.c new file mode 100644 index 000000000..8d0df81af --- /dev/null +++ b/roms/u-boot-sam460ex/onenand_ipl/onenand_read.c @@ -0,0 +1,158 @@ +/* + * (C) Copyright 2005-2009 Samsung Electronics + * Kyungmin Park <kyungmin.park@samsung.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/io.h> +#include <asm/string.h> + +#include "onenand_ipl.h" + +#define onenand_block_address(block) (block) +#define onenand_sector_address(page) (page << 2) +#define onenand_buffer_address() ((1 << 3) << 8) +#define onenand_bufferram_address(block) (0) + +#ifdef __HAVE_ARCH_MEMCPY32 +extern void *memcpy32(void *dest, void *src, int size); +#endif + +int (*onenand_read_page)(ulong block, ulong page, u_char *buf, int pagesize); + +/* read a page with ECC */ +static int generic_onenand_read_page(ulong block, ulong page, + u_char * buf, int pagesize) +{ + unsigned long *base; + +#ifndef __HAVE_ARCH_MEMCPY32 + unsigned int offset, value; + unsigned long *p; +#endif + + onenand_writew(onenand_block_address(block), + ONENAND_REG_START_ADDRESS1); + + onenand_writew(onenand_bufferram_address(block), + ONENAND_REG_START_ADDRESS2); + + onenand_writew(onenand_sector_address(page), + ONENAND_REG_START_ADDRESS8); + + onenand_writew(onenand_buffer_address(), + ONENAND_REG_START_BUFFER); + + onenand_writew(ONENAND_INT_CLEAR, ONENAND_REG_INTERRUPT); + + onenand_writew(ONENAND_CMD_READ, ONENAND_REG_COMMAND); + +#ifndef __HAVE_ARCH_MEMCPY32 + p = (unsigned long *) buf; +#endif + base = (unsigned long *) (CONFIG_SYS_ONENAND_BASE + ONENAND_DATARAM); + + while (!(READ_INTERRUPT() & ONENAND_INT_READ)) + continue; + + /* Check for invalid block mark */ + if (page < 2 && (onenand_readw(ONENAND_SPARERAM) != 0xffff)) + return 1; + +#ifdef __HAVE_ARCH_MEMCPY32 + /* 32 bytes boundary memory copy */ + memcpy32(buf, base, pagesize); +#else + for (offset = 0; offset < (pagesize >> 2); offset++) { + value = *(base + offset); + *p++ = value; + } +#endif + + return 0; +} + +#ifndef CONFIG_ONENAND_START_PAGE +#define CONFIG_ONENAND_START_PAGE 1 +#endif +#define ONENAND_PAGES_PER_BLOCK 64 + +static void onenand_generic_init(int *page_is_4KiB, int *page) +{ + int dev_id, density; + + if (onenand_readw(ONENAND_REG_TECHNOLOGY)) + *page_is_4KiB = 1; + dev_id = onenand_readw(ONENAND_REG_DEVICE_ID); + density = dev_id >> ONENAND_DEVICE_DENSITY_SHIFT; + density &= ONENAND_DEVICE_DENSITY_MASK; + if (density >= ONENAND_DEVICE_DENSITY_4Gb && + !(dev_id & ONENAND_DEVICE_IS_DDP)) + *page_is_4KiB = 1; +} + +/** + * onenand_read_block - Read CONFIG_SYS_MONITOR_LEN from begining + * of OneNAND, skipping bad blocks + * @return 0 on success + */ +int onenand_read_block(unsigned char *buf) +{ + int block, nblocks; + int page = CONFIG_ONENAND_START_PAGE, offset = 0; + int pagesize, erasesize, erase_shift; + int page_is_4KiB = 0; + + onenand_read_page = generic_onenand_read_page; + + onenand_generic_init(&page_is_4KiB, &page); + + if (page_is_4KiB) { + pagesize = 4096; /* OneNAND has 4KiB pagesize */ + erase_shift = 18; + } else { + pagesize = 2048; /* OneNAND has 2KiB pagesize */ + erase_shift = 17; + } + + erasesize = (1 << erase_shift); + nblocks = (CONFIG_SYS_MONITOR_LEN + erasesize - 1) >> erase_shift; + + /* NOTE: you must read page from page 1 of block 0 */ + /* read the block page by page */ + for (block = 0; block < nblocks; block++) { + for (; page < ONENAND_PAGES_PER_BLOCK; page++) { + if (onenand_read_page(block, page, buf + offset, + pagesize)) { + /* This block is bad. Skip it + * and read next block */ + offset -= page * pagesize; + nblocks++; + break; + } + offset += pagesize; + } + page = 0; + } + + return 0; +} |