From e4c09508545d1c45617ba45391c03c03cbc360b9 Mon Sep 17 00:00:00 2001 From: Scott Wood Date: Mon, 30 Jun 2008 14:13:28 -0500 Subject: NAND boot: MPC8313ERDB support Note that with older board revisions, NAND boot may only work after a power-on reset, and not after a warm reset. I don't have a newer board to test on; if you have a board with a 33MHz crystal, please let me know if it works after a warm reset. Signed-off-by: Scott Wood --- nand_spl/board/freescale/mpc8313erdb/Makefile | 101 ++++++++++++++++ nand_spl/board/freescale/mpc8313erdb/u-boot.lds | 52 ++++++++ nand_spl/nand_boot.c | 4 +- nand_spl/nand_boot_fsl_elbc.c | 150 ++++++++++++++++++++++++ 4 files changed, 305 insertions(+), 2 deletions(-) create mode 100644 nand_spl/board/freescale/mpc8313erdb/Makefile create mode 100644 nand_spl/board/freescale/mpc8313erdb/u-boot.lds create mode 100644 nand_spl/nand_boot_fsl_elbc.c (limited to 'nand_spl') diff --git a/nand_spl/board/freescale/mpc8313erdb/Makefile b/nand_spl/board/freescale/mpc8313erdb/Makefile new file mode 100644 index 00000000000..3da1b1fffb8 --- /dev/null +++ b/nand_spl/board/freescale/mpc8313erdb/Makefile @@ -0,0 +1,101 @@ +# +# (C) Copyright 2007 +# Stefan Roese, DENX Software Engineering, sr@denx.de. +# (C) Copyright 2008 Freescale Semiconductor +# +# 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 +# + +NAND_SPL := y +TEXT_BASE := 0xfff00000 +PAD_TO := 0xfff04000 + +include $(TOPDIR)/config.mk + +LDSCRIPT= $(TOPDIR)/nand_spl/board/$(BOARDDIR)/u-boot.lds +LDFLAGS = -Bstatic -T $(LDSCRIPT) -Ttext $(TEXT_BASE) $(PLATFORM_LDFLAGS) +AFLAGS += -DCONFIG_NAND_SPL +CFLAGS += -DCONFIG_NAND_SPL + +SOBJS = start.o ticks.o +COBJS = nand_boot_fsl_elbc.o $(BOARD).o sdram.o ns16550.o nand_init.o time.o + +SRCS := $(addprefix $(obj),$(SOBJS:.o=.S) $(COBJS:.o=.c)) +OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS)) +__OBJS := $(SOBJS) $(COBJS) +LNDIR := $(OBJTREE)/nand_spl/board/$(BOARDDIR) + +nandobj := $(OBJTREE)/nand_spl/ + +ALL = $(nandobj)u-boot-spl $(nandobj)u-boot-spl.bin $(nandobj)u-boot-spl-16k.bin + +all: $(obj).depend $(ALL) + +$(nandobj)u-boot-spl-16k.bin: $(nandobj)u-boot-spl + $(OBJCOPY) ${OBJCFLAGS} --pad-to=$(PAD_TO) -O binary $< $@ + +$(nandobj)u-boot-spl.bin: $(nandobj)u-boot-spl + $(OBJCOPY) ${OBJCFLAGS} -O binary $< $@ + +$(nandobj)u-boot-spl: $(OBJS) + cd $(LNDIR) && $(LD) $(LDFLAGS) $(__OBJS) \ + -Map $(nandobj)u-boot-spl.map \ + -o $(nandobj)u-boot-spl + +# create symbolic links for common files + +$(obj)start.S: + ln -sf $(SRCTREE)/cpu/mpc83xx/start.S $(obj)start.S + +$(obj)nand_boot_fsl_elbc.c: + ln -sf $(SRCTREE)/nand_spl/nand_boot_fsl_elbc.c \ + $(obj)nand_boot_fsl_elbc.c + +$(obj)sdram.c: + ln -sf $(SRCTREE)/board/$(BOARDDIR)/sdram.c $(obj)sdram.c + +$(obj)$(BOARD).c: + ln -sf $(SRCTREE)/board/$(BOARDDIR)/$(BOARD).c $(obj)$(BOARD).c + +$(obj)ns16550.c: + ln -sf $(SRCTREE)/drivers/serial/ns16550.c $(obj)ns16550.c + +$(obj)nand_init.c: + ln -sf $(SRCTREE)/cpu/mpc83xx/nand_init.c $(obj)nand_init.c + +$(obj)time.c: + ln -sf $(SRCTREE)/lib_ppc/time.c $(obj)time.c + +$(obj)ticks.S: + ln -sf $(SRCTREE)/lib_ppc/ticks.S $(obj)ticks.S + +######################################################################### + +$(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/nand_spl/board/freescale/mpc8313erdb/u-boot.lds b/nand_spl/board/freescale/mpc8313erdb/u-boot.lds new file mode 100644 index 00000000000..40c414549ca --- /dev/null +++ b/nand_spl/board/freescale/mpc8313erdb/u-boot.lds @@ -0,0 +1,52 @@ +/* + * (C) Copyright 2006 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * Copyright 2008 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 + */ + +OUTPUT_ARCH(powerpc) +SECTIONS +{ + . = 0xfff00000; + .text : { + *(.text*) + . = ALIGN(16); + *(.rodata*) + *(.eh_frame) + } + + . = ALIGN(8); + .data : { + *(.data*) + *(.sdata*) + _GOT2_TABLE_ = .; + *(.got2) + __got2_entries = (. - _GOT2_TABLE_) >> 2; + } + + . = ALIGN(8); + __bss_start = .; + .bss (NOLOAD) : { *(.*bss) } + _end = .; +} +ENTRY(_start) +ASSERT(_end <= 0xfff01000, "NAND bootstrap too big"); diff --git a/nand_spl/nand_boot.c b/nand_spl/nand_boot.c index 5914d040343..0f56ba52020 100644 --- a/nand_spl/nand_boot.c +++ b/nand_spl/nand_boot.c @@ -235,7 +235,7 @@ void nand_boot(void) struct nand_chip nand_chip; nand_info_t nand_info; int ret; - void (*uboot)(void); + __attribute__((noreturn)) void (*uboot)(void); /* * Init board specific nand support @@ -254,6 +254,6 @@ void nand_boot(void) /* * Jump to U-Boot image */ - uboot = (void (*)(void))CFG_NAND_U_BOOT_START; + uboot = (void *)CFG_NAND_U_BOOT_START; (*uboot)(); } diff --git a/nand_spl/nand_boot_fsl_elbc.c b/nand_spl/nand_boot_fsl_elbc.c new file mode 100644 index 00000000000..0d2378ee894 --- /dev/null +++ b/nand_spl/nand_boot_fsl_elbc.c @@ -0,0 +1,150 @@ +/* + * NAND boot for Freescale Enhanced Local Bus Controller, Flash Control Machine + * + * (C) Copyright 2006-2008 + * Stefan Roese, DENX Software Engineering, sr@denx.de. + * + * Copyright (c) 2008 Freescale Semiconductor, Inc. + * Author: Scott Wood + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include + +#define WINDOW_SIZE 8192 + +static void nand_wait(void) +{ + lbus83xx_t *regs = (lbus83xx_t *)(CFG_IMMR + 0x5000); + + for (;;) { + uint32_t status = in_be32(®s->ltesr); + + if (status == 1) + return; + + if (status & 1) { + puts("read failed (ltesr)\n"); + for (;;); + } + } +} + +static void nand_load(unsigned int offs, int uboot_size, uchar *dst) +{ + lbus83xx_t *regs = (lbus83xx_t *)(CFG_IMMR + 0x5000); + uchar *buf = (uchar *)CFG_NAND_BASE; + int large = in_be32(®s->bank[0].or) & OR_FCM_PGS; + int block_shift = large ? 17 : 14; + int block_size = 1 << block_shift; + int page_size = large ? 2048 : 512; + int bad_marker = large ? page_size + 0 : page_size + 5; + int fmr = (15 << FMR_CWTO_SHIFT) | (2 << FMR_AL_SHIFT) | 2; + int pos = 0; + + if (offs & (block_size - 1)) { + puts("bad offset\n"); + for (;;); + } + + if (large) { + fmr |= FMR_ECCM; + out_be32(®s->fcr, (NAND_CMD_READ0 << FCR_CMD0_SHIFT) | + (NAND_CMD_READSTART << FCR_CMD1_SHIFT)); + out_be32(®s->fir, + (FIR_OP_CW0 << FIR_OP0_SHIFT) | + (FIR_OP_CA << FIR_OP1_SHIFT) | + (FIR_OP_PA << FIR_OP2_SHIFT) | + (FIR_OP_CW1 << FIR_OP3_SHIFT) | + (FIR_OP_RBW << FIR_OP4_SHIFT)); + } else { + out_be32(®s->fcr, NAND_CMD_READ0 << FCR_CMD0_SHIFT); + out_be32(®s->fir, + (FIR_OP_CW0 << FIR_OP0_SHIFT) | + (FIR_OP_CA << FIR_OP1_SHIFT) | + (FIR_OP_PA << FIR_OP2_SHIFT) | + (FIR_OP_RBW << FIR_OP3_SHIFT)); + } + + out_be32(®s->fbcr, 0); + clrsetbits_be32(®s->bank[0].br, BR_DECC, BR_DECC_CHK_GEN); + + while (pos < uboot_size) { + int i = 0; + out_be32(®s->fbar, offs >> block_shift); + + do { + int j; + unsigned int page_offs = (offs & (block_size - 1)) << 1; + + out_be32(®s->ltesr, ~0); + out_be32(®s->lteatr, 0); + out_be32(®s->fpar, page_offs); + out_be32(®s->fmr, fmr); + out_be32(®s->lsor, 0); + nand_wait(); + + page_offs %= WINDOW_SIZE; + + /* + * If either of the first two pages are marked bad, + * continue to the next block. + */ + if (i++ < 2 && buf[page_offs + bad_marker] != 0xff) { + puts("skipping\n"); + offs = (offs + block_size) & ~(block_size - 1); + pos &= ~(block_size - 1); + break; + } + + for (j = 0; j < page_size; j++) + dst[pos + j] = buf[page_offs + j]; + + pos += page_size; + offs += page_size; + } while (offs & (block_size - 1)); + } +} + +/* + * The main entry for NAND booting. It's necessary that SDRAM is already + * configured and available since this code loads the main U-Boot image + * from NAND into SDRAM and starts it from there. + */ +void nand_boot(void) +{ + __attribute__((noreturn)) void (*uboot)(void); + + udelay(1000000); + + /* + * Load U-Boot image from NAND into RAM + */ + nand_load(CFG_NAND_U_BOOT_OFFS, CFG_NAND_U_BOOT_SIZE, + (uchar *)CFG_NAND_U_BOOT_DST); + + /* + * Jump to U-Boot image + */ + puts("transfering control\n"); + uboot = (void *)CFG_NAND_U_BOOT_START; + uboot(); +} -- cgit v1.2.3