sciphone_g2: NAND SPL functionality added
Implementation of Secondary Program Loader which loads U-Boot from NAND memory to SDRAM memory. SBL is loaded by IPL (Initial Program Loader) at processor startup. Signed-off-by: Marcin Mielczarczyk <marcin.mielczarczyk@tieto.com>
This commit is contained in:
parent
171c69aa43
commit
f920a1e2fe
2
Makefile
2
Makefile
|
@ -972,8 +972,8 @@ omap730p2_cs3boot_config : unconfig
|
|||
|
||||
sciphone_g2_config: unconfig
|
||||
@mkdir -p $(obj)include
|
||||
@ > $(obj)include/config.h
|
||||
@$(MKCONFIG) -n $@ -a sciphone_g2 arm arm926ejs sciphone_g2 mtk mtk
|
||||
@echo "CONFIG_NAND_U_BOOT = y" >> $(obj)include/config.mk
|
||||
|
||||
spear300_config \
|
||||
spear310_config \
|
||||
|
|
|
@ -92,6 +92,24 @@
|
|||
*/
|
||||
#define ECC_SPARE_BYTE_POS 8
|
||||
|
||||
/*
|
||||
* Macro which counts zeroes until first set bit.
|
||||
* This is used to avoid dividing, so no additional library is needed.
|
||||
* It's important as this file is compiled also in SPL and there is no need
|
||||
* to link additional library.
|
||||
*/
|
||||
#ifdef CONFIG_ARM926EJS
|
||||
#define COUNT_ZEROES(x) __builtin_ctz(x)
|
||||
#else
|
||||
#define COUNT_ZEROES(x) (ffs(x) - 1)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PRELOADER
|
||||
#define nand_print(x)
|
||||
#else
|
||||
#define nand_print(x) printk(KERN_ERR (x))
|
||||
#endif
|
||||
|
||||
static void nand_ctrl_change(int cmd, int address, int *addr_cycle,
|
||||
int write_size)
|
||||
{
|
||||
|
@ -192,9 +210,11 @@ static int mt62xx_nand_dev_ready(struct mtd_info *mtd)
|
|||
static void mt62xx_nand_select_chip(struct mtd_info *mtd, int chip)
|
||||
{
|
||||
if (chip > NAND_CHIPS_MAX) {
|
||||
printk(KERN_ERR "Wrong NAND chip number!\n");
|
||||
nand_print("Wrong NAND chip number!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (chip != -1)
|
||||
writel(chip, MTK_NFI_CSEL);
|
||||
}
|
||||
|
||||
|
@ -205,7 +225,7 @@ static void mt62xx_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
|
|||
int i;
|
||||
|
||||
if (len % 4)
|
||||
printk(KERN_ERR "Length parameter is not aligned\n");
|
||||
nand_print("Length parameter is not aligned\n");
|
||||
|
||||
for (i = 0; i < len/4; ++i)
|
||||
buf_32[i] = readl(chip->IO_ADDR_R);
|
||||
|
@ -232,10 +252,10 @@ static void mt62xx_nand_write_ecc(struct mtd_info *mtd, int len)
|
|||
uint8_t ecc[8];
|
||||
|
||||
/*
|
||||
* Two ECC blocks are combined in Sciphone G2 format,
|
||||
* that's why there is division by 2.
|
||||
* Two ECC blocks are combined on MT62xx platform,
|
||||
* that's why writesize is multiplied by 2.
|
||||
*/
|
||||
ecc_blocks = mtd->writesize/chip->ecc.size/2;
|
||||
ecc_blocks = (mtd->writesize * 2) >> COUNT_ZEROES(chip->ecc.size);
|
||||
|
||||
for (ecc_nr = 0; ecc_nr < ecc_blocks; ++ecc_nr) {
|
||||
int ecc_p, ecc_c, pos = 0;
|
||||
|
@ -286,7 +306,7 @@ static void mt62xx_nand_write_buf(struct mtd_info *mtd, const uint8_t *buf,
|
|||
mt62xx_nand_write_ecc(mtd, len);
|
||||
} else {
|
||||
if (len % 4)
|
||||
printk(KERN_ERR "Length parameter is not aligned\n");
|
||||
nand_print("Length parameter is not aligned\n");
|
||||
|
||||
for (i = 0; i < len/4; ++i)
|
||||
writel(buf_32[i], chip->IO_ADDR_W);
|
||||
|
@ -307,7 +327,7 @@ static int mt62xx_nand_ecc_calculate(struct mtd_info *mtd, const uint8_t *dat,
|
|||
* which is currently read. We can use it to calculate which ECC block
|
||||
* has been already read.
|
||||
*/
|
||||
*ecc_code = readw(MTK_NFI_ADDRCNTR)/chip->ecc.size;
|
||||
*ecc_code = readw(MTK_NFI_ADDRCNTR) >> COUNT_ZEROES(chip->ecc.size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -370,6 +390,12 @@ int board_nand_init(struct nand_chip *chip)
|
|||
7 << NFI_ACCCON_LCD2NAND_SHIFT,
|
||||
MTK_NFI_ACCCON);
|
||||
|
||||
/*
|
||||
* Reset NFI page format control register.
|
||||
* After processor reset it's not always zero what renders problems.
|
||||
*/
|
||||
writel(0, MTK_NFI_PAGEFMT);
|
||||
|
||||
/* Flush and reset NFI FIFO */
|
||||
writel(NFI_OPCON_FIFO_FLUSH | NFI_OPCON_FIFO_RST, MTK_NFI_OPCON);
|
||||
while(readl(MTK_NFI_OPCON))
|
||||
|
|
|
@ -20,6 +20,18 @@
|
|||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* U-Boot configuration is split in two parts:
|
||||
* - SPL configuration
|
||||
* - normal configuration
|
||||
*
|
||||
* MT62XX platform has IPL (Initial Program Loader) in ROM.
|
||||
* After processor power up IPL execution is started. IPL tries to load
|
||||
* code from NAND to internal RAM (64KB) and starts executing loaded code.
|
||||
* SBL (Secondary Program Loader) is loaded by IPL. SBL configures basic
|
||||
* peripherals (PLL, SDRAM memory) and loads U-Boot from NAND to SDRAM.
|
||||
*/
|
||||
|
||||
#ifndef __CONFIG_H
|
||||
#define __CONFIG_H
|
||||
|
||||
|
@ -27,6 +39,29 @@
|
|||
|
||||
#define CONFIG_ARM926EJS
|
||||
|
||||
/* DRAM memory related configurations */
|
||||
#define CONFIG_NR_DRAM_BANKS 1
|
||||
#define PHYS_SDRAM_1 0x00000000
|
||||
#define PHYS_SDRAM_1_SIZE 0x04000000 /* 64 MB */
|
||||
#define CONFIG_SYS_SDRAM_BASE PHYS_SDRAM_1
|
||||
|
||||
/* NAND memory related configurations */
|
||||
#define CONFIG_NAND_MT62XX
|
||||
#define CONFIG_SYS_MAX_NAND_DEVICE 1
|
||||
#define CONFIG_SYS_NAND_BASE MTK_NFI_BASE
|
||||
|
||||
/* There is no NOR flash, so undefine these commands */
|
||||
#undef CONFIG_CMD_FLASH
|
||||
#undef CONFIG_CMD_IMLS
|
||||
#define CONFIG_SYS_NO_FLASH
|
||||
|
||||
|
||||
#ifndef CONFIG_PRELOADER
|
||||
|
||||
/*
|
||||
* Configuration of U-Boot when running from DRAM (normal operation).
|
||||
*/
|
||||
|
||||
/* We have already been loaded to RAM */
|
||||
#define CONFIG_SKIP_LOWLEVEL_INIT
|
||||
|
||||
|
@ -40,16 +75,8 @@
|
|||
#define CONFIG_BAUDRATE 115200
|
||||
#define CONFIG_SYS_BAUDRATE_TABLE {9600, 19200, 38400, 57600, 115200}
|
||||
|
||||
/* There is no NOR flash, so undefine these commands */
|
||||
#undef CONFIG_CMD_FLASH
|
||||
#undef CONFIG_CMD_IMLS
|
||||
#define CONFIG_SYS_NO_FLASH
|
||||
|
||||
/* Configure NAND storage */
|
||||
#define CONFIG_NAND_MT62XX
|
||||
/* Turn on some U-Boot commands */
|
||||
#define CONFIG_CMD_NAND
|
||||
#define CONFIG_SYS_MAX_NAND_DEVICE 1
|
||||
#define CONFIG_SYS_NAND_BASE MTK_NFI_BASE
|
||||
#define CONFIG_CMD_MEMORY
|
||||
#define CONFIG_CMD_LOADB
|
||||
#define CONFIG_CMD_RUN
|
||||
|
@ -81,14 +108,6 @@
|
|||
#define CONFIG_BOOTARGS "console=ttyMTK0,115200n8 mem=64M@0"
|
||||
#define CONFIG_BOOTCOMMAND "bootm 0x800000"
|
||||
|
||||
/* Memory related information */
|
||||
#define CONFIG_NR_DRAM_BANKS 1
|
||||
#define PHYS_SDRAM_1 0x00000000
|
||||
#define PHYS_SDRAM_1_SIZE 0x04000000 /* 64 MB */
|
||||
#define CONFIG_SYS_SDRAM_BASE PHYS_SDRAM_1
|
||||
#define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SYS_SDRAM_BASE + 0x1000)
|
||||
#define CONFIG_MAX_RAM_BANK_SIZE 0x10000000
|
||||
|
||||
#define CONFIG_STACKSIZE (128 * 1024)
|
||||
#ifdef CONFIG_USE_IRQ
|
||||
# define CONFIG_STACKSIZE_IRQ (4 * 1024) /* IRQ stack */
|
||||
|
@ -97,8 +116,11 @@
|
|||
|
||||
#define CONFIG_SYS_MEMTEST_START 0x00000000
|
||||
#define CONFIG_SYS_MEMTEST_END 0x02FFFFFF
|
||||
#define CONFIG_SYS_MALLOC_LEN (CONFIG_ENV_SIZE + 256 * 1024)
|
||||
#define CONFIG_SYS_GBL_DATA_SIZE 128
|
||||
#define CONFIG_SYS_MALLOC_LEN (CONFIG_ENV_SIZE + 256 * 1024)
|
||||
|
||||
#define CONFIG_MAX_RAM_BANK_SIZE 0x10000000
|
||||
#define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SYS_SDRAM_BASE + CONFIG_STACKSIZE)
|
||||
|
||||
/* This is needed to make hello_world.c happy */
|
||||
#define CONFIG_SYS_MAX_FLASH_SECT 512
|
||||
|
@ -132,4 +154,22 @@
|
|||
|
||||
#endif /* CONFIG_MMC */
|
||||
|
||||
#else /* CONFIG_PRELOADER */
|
||||
|
||||
/*
|
||||
* Configuration of U-Boot for SPL.
|
||||
*/
|
||||
#define CONFIG_STACKSIZE 1024
|
||||
#define CONFIG_SYS_MALLOC_LEN 1024
|
||||
#define INTERNAL_RAM_BASE 0x40000000
|
||||
#define CONFIG_SYS_INIT_SP_ADDR (INTERNAL_RAM_BASE + CONFIG_STACKSIZE)
|
||||
#define CONFIG_ENV_SIZE 0x0
|
||||
|
||||
/* Address of U-Boot in NAND */
|
||||
#define CONFIG_SYS_NAND_U_BOOT_OFFS 0x20000
|
||||
#define CONFIG_SYS_NAND_U_BOOT_SIZE 1000000 /* 1MB */
|
||||
#define CONFIG_SYS_NAND_U_BOOT_DST 0x500000
|
||||
#define CONFIG_SYS_NAND_U_BOOT_START 0x500000
|
||||
|
||||
#endif /* CONFIG_PRELOADER */
|
||||
#endif /* __CONFIG_H */
|
||||
|
|
|
@ -0,0 +1,82 @@
|
|||
#
|
||||
# (C) Copyright 2006-2007
|
||||
# Stefan Roese, DENX Software Engineering, sr@denx.de.
|
||||
#
|
||||
# (C) Copyright 2008
|
||||
# Guennadi Liakhovetki, DENX Software Engineering, <lg@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
|
||||
#
|
||||
|
||||
CONFIG_NAND_SPL = y
|
||||
|
||||
include $(TOPDIR)/config.mk
|
||||
include $(TOPDIR)/nand_spl/board/$(BOARDDIR)/config.mk
|
||||
|
||||
LDSCRIPT= $(TOPDIR)/nand_spl/board/$(BOARDDIR)/u-boot.lds
|
||||
LDFLAGS = -Bstatic -T $(nandobj)u-boot.lds -Ttext $(CONFIG_SYS_TEXT_BASE) $(PLATFORM_LDFLAGS)
|
||||
AFLAGS += -DCONFIG_PRELOADER -DCONFIG_NAND_SPL -DCONFIG_SYS_TEXT_BASE=$(CONFIG_SYS_TEXT_BASE)
|
||||
CFLAGS += -DCONFIG_PRELOADER -DCONFIG_NAND_SPL -DCONFIG_SYS_TEXT_BASE=$(CONFIG_SYS_TEXT_BASE)
|
||||
|
||||
SOBJS = start.o lowlevel_init.o
|
||||
COBJS = nand_boot_detect.o mt62xx_nand.o nand_ids.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)
|
||||
all: $(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) $(nandobj)u-boot.lds
|
||||
cd $(LNDIR) && $(LD) $(LDFLAGS) $(__OBJS) \
|
||||
-Map $(nandobj)u-boot-spl.map \
|
||||
-o $(nandobj)u-boot-spl
|
||||
|
||||
$(nandobj)u-boot.lds: $(LDSCRIPT)
|
||||
$(CPP) $(CPPFLAGS) $(LDPPFLAGS) -ansi -D__ASSEMBLY__ -P - <$^ >$@
|
||||
|
||||
#########################################################################
|
||||
|
||||
$(obj)%.o: $(SRCTREE)/arch/arm/cpu/arm926ejs/%.S
|
||||
$(CC) $(AFLAGS) -c -o $@ $<
|
||||
|
||||
$(obj)%.o: $(SRCTREE)/nand_spl/%.c
|
||||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
$(obj)%.o: $(SRCTREE)/drivers/mtd/nand/%.c
|
||||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
# defines $(obj).depend target
|
||||
include $(SRCTREE)/rules.mk
|
||||
|
||||
sinclude $(obj).depend
|
||||
|
||||
#########################################################################
|
|
@ -0,0 +1,26 @@
|
|||
#
|
||||
# (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
|
||||
|
||||
# On Siphone G2 the SPL is located in SRAM.
|
||||
# CONFIG_SYS_TEXT_BASE for SPL:
|
||||
|
||||
CONFIG_SYS_TEXT_BASE = 0x40002000
|
|
@ -0,0 +1,221 @@
|
|||
/*
|
||||
* (C) 2010 by Tieto <www.tieto.com>
|
||||
* Marcin Mielczarczyk <marcin.mielczarczyk@tieto.com>
|
||||
*
|
||||
* All Rights Reserved
|
||||
*
|
||||
* 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.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <asm/arch-mtk/mt6235.h>
|
||||
#include <asm/arch-mtk/emi.h>
|
||||
#include <asm/arch-mtk/system.h>
|
||||
|
||||
.globl lowlevel_init
|
||||
.type lowlevel_init,function
|
||||
lowlevel_init:
|
||||
|
||||
/* -----------------------------
|
||||
* Initialize PLL
|
||||
* -----------------------------
|
||||
*/
|
||||
/* Power on PLL */
|
||||
ldr r0, =MTK_PLL_PDN_CON
|
||||
mov r1, #0
|
||||
str r1, [r0]
|
||||
/* Turn on MCU and DSP dividers, mark that SYSCLK is 26MHz */
|
||||
ldr r0, =MTK_PLL_CLK_CON
|
||||
mov r1, #0x83
|
||||
str r1, [r0]
|
||||
/* Reset PLL */
|
||||
ldr r0, =MTK_PLL_PLL
|
||||
mov r1, #0x80
|
||||
str r1, [r0]
|
||||
mov r1, #0
|
||||
str r1, [r0]
|
||||
mov r1, #0xFF
|
||||
PLL_DELAY_loop:
|
||||
subs r1, r1, #1
|
||||
bgt PLL_DELAY_loop
|
||||
/* Turn on PLL for MCU, DSP and USB */
|
||||
mov r1, #0x70
|
||||
str r1, [r0]
|
||||
/*
|
||||
* Setup MCU clock register:
|
||||
* ARMCLK = 208MHz, AHBx4CLK = 52MHz, AHBx8CLK = 104MHz
|
||||
* we have to write to the read-only part (EMICLK) as well, otherwise
|
||||
* the EMI won't work! (datasheet lies)
|
||||
*/
|
||||
ldr r0, =MTK_CONFG_MCUCLK_CON
|
||||
ldr r1, =0x7F37
|
||||
str r1, [r0]
|
||||
|
||||
/* -----------------------------
|
||||
* Initialize SDRAM controller
|
||||
* -----------------------------
|
||||
*/
|
||||
/* Reset index of SDRAM config table */
|
||||
mov r7, #0
|
||||
SDRAM_TRY_CONFIG:
|
||||
adr r1, SDRAM_CONFIG_TABLE
|
||||
/* Calculate config table offset (index * element_size) */
|
||||
lsl r2, r7, #3
|
||||
/* Calculate address of element in config table */
|
||||
add r1, r1, r2
|
||||
/* Load start address of SDRAM configuration */
|
||||
ldr r0, [r1]
|
||||
/* Check if end of SDRAM config table is reached */
|
||||
cmp r0, #0
|
||||
beq SDRAM_PASSED
|
||||
/* Load end address of SDRAM configuration */
|
||||
ldr r6, [r1, #4]
|
||||
|
||||
/* Configure SDRAM controller */
|
||||
SDRAM_REGSET_LOOP:
|
||||
ldr r1, [r0]
|
||||
ldr r2, [r0, #4]
|
||||
str r1, [r2]
|
||||
add r0, r0, #8
|
||||
mov r1, #0xFF
|
||||
SDRAM_DELAY_LOOP:
|
||||
subs r1, r1, #1
|
||||
bgt SDRAM_DELAY_LOOP
|
||||
cmp r0, r6
|
||||
blt SDRAM_REGSET_LOOP
|
||||
|
||||
/* Perform test to check if SDRAM is properly configured */
|
||||
mov r0, #0x1000
|
||||
mov r1, #0x0
|
||||
mov r2, #16384
|
||||
SDRAM_WRITE_LOOP:
|
||||
str r1, [r0]
|
||||
add r0, r0, #4
|
||||
add r1, r1, #1
|
||||
cmp r1, r2
|
||||
blt SDRAM_WRITE_LOOP
|
||||
|
||||
mov r0, #0x1000
|
||||
mov r3, #0x0
|
||||
SDRAM_VERIFY_LOOP:
|
||||
ldr r1, [r0]
|
||||
add r0, r0, #4
|
||||
cmp r1, r3
|
||||
bne SDRAM_FAILED
|
||||
add r3, r3, #1
|
||||
cmp r3, r2
|
||||
blt SDRAM_VERIFY_LOOP
|
||||
|
||||
SDRAM_PASSED:
|
||||
/* return from function */
|
||||
mov pc, lr
|
||||
|
||||
/* SDRAM configuration failed, try another one */
|
||||
SDRAM_FAILED:
|
||||
/* Increment SDRAM config table index */
|
||||
add r7, r7, #1
|
||||
b SDRAM_TRY_CONFIG
|
||||
|
||||
SDRAM_CONFIG_TABLE:
|
||||
.word SDRAM_64MB_CONFIG
|
||||
.word SDRAM_64MB_CONFIG_END
|
||||
.word SDRAM_32MB_CONFIG
|
||||
.word SDRAM_32MB_CONFIG_END
|
||||
.word 0
|
||||
|
||||
/* This configuration is for 64MB SDRAM memory */
|
||||
SDRAM_64MB_CONFIG:
|
||||
.word 0x00088E3A
|
||||
.word MTK_EMI_GENA
|
||||
.word 0x000000C0
|
||||
.word MTK_EMI_GENB
|
||||
.word 0x18C618C6
|
||||
.word MTK_EMI_GENC
|
||||
.word 0x0001000E
|
||||
.word MTK_EMI_GEND
|
||||
.word 0x00332000
|
||||
.word MTK_EMI_CONI
|
||||
.word 0x3CD24431
|
||||
.word MTK_EMI_CONJ
|
||||
.word 0x02000000
|
||||
.word MTK_EMI_CONK
|
||||
.word 0x18007505
|
||||
.word MTK_EMI_CONL
|
||||
.word 0x00002828
|
||||
.word MTK_EMI_CONM
|
||||
.word 0x1500013
|
||||
.word MTK_EMI_CONN
|
||||
.word 0x500013
|
||||
.word MTK_EMI_CONN
|
||||
.word 0x2500013
|
||||
.word MTK_EMI_CONN
|
||||
.word 0x500013
|
||||
.word MTK_EMI_CONN
|
||||
.word 0x4500013
|
||||
.word MTK_EMI_CONN
|
||||
.word 0x500013
|
||||
.word MTK_EMI_CONN
|
||||
.word 0x8500013
|
||||
.word MTK_EMI_CONN
|
||||
.word 0x500013
|
||||
.word MTK_EMI_CONN
|
||||
.word 0x80500013
|
||||
.word MTK_EMI_CONN
|
||||
.word 0x500013
|
||||
.word MTK_EMI_CONN
|
||||
SDRAM_64MB_CONFIG_END:
|
||||
|
||||
/* This configuration is for 32MB SDRAM memory */
|
||||
SDRAM_32MB_CONFIG:
|
||||
.word 0x00088a0a
|
||||
.word MTK_EMI_GENA
|
||||
.word 0x00000280
|
||||
.word MTK_EMI_GENB
|
||||
.word 0x52945294
|
||||
.word MTK_EMI_GENC
|
||||
.word 0x0001000E
|
||||
.word MTK_EMI_GEND
|
||||
.word 0x02334000
|
||||
.word MTK_EMI_CONI
|
||||
.word 0x16c12212
|
||||
.word MTK_EMI_CONJ
|
||||
.word 0x032d0000
|
||||
.word MTK_EMI_CONK
|
||||
.word 0x1c016605
|
||||
.word MTK_EMI_CONL
|
||||
.word 0x00002828
|
||||
.word MTK_EMI_CONM
|
||||
.word 0x1400013
|
||||
.word MTK_EMI_CONN
|
||||
.word 0x400013
|
||||
.word MTK_EMI_CONN
|
||||
.word 0x2400013
|
||||
.word MTK_EMI_CONN
|
||||
.word 0x400013
|
||||
.word MTK_EMI_CONN
|
||||
.word 0x4400013
|
||||
.word MTK_EMI_CONN
|
||||
.word 0x400013
|
||||
.word MTK_EMI_CONN
|
||||
.word 0x8400013
|
||||
.word MTK_EMI_CONN
|
||||
.word 0x400013
|
||||
.word MTK_EMI_CONN
|
||||
.word 0x80400013
|
||||
.word MTK_EMI_CONN
|
||||
.word 0x400013
|
||||
.word MTK_EMI_CONN
|
||||
SDRAM_32MB_CONFIG_END:
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* (C) Copyright 2002
|
||||
* Gary Jennejohn, DENX Software Engineering, <garyj@denx.de>
|
||||
*
|
||||
* (C) Copyright 2008
|
||||
* Guennadi Liakhovetki, DENX Software Engineering, <lg@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-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 = .;
|
||||
}
|
|
@ -0,0 +1,484 @@
|
|||
/*
|
||||
* (C) Copyright 2006-2008
|
||||
* Stefan Roese, DENX Software Engineering, sr@denx.de.
|
||||
*
|
||||
* Rework by Marcin Mielczarczyk <marcin.mielczarczyk@tieto.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
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <nand.h>
|
||||
#include <asm/io.h>
|
||||
#include <linux/err.h>
|
||||
|
||||
/*
|
||||
* SPL has no malloc availble and below are definitions of some temporary
|
||||
* buffers in RAM for general purpose.
|
||||
*/
|
||||
#define RAM_BUF1 (CONFIG_SYS_SDRAM_BASE + 0x1000)
|
||||
#define RAM_BUF2 (RAM_BUF1 + 0x1000)
|
||||
#define RAM_BUF3 (RAM_BUF2 + 0x1000)
|
||||
|
||||
/*
|
||||
* Macro which counts zeroes until first set bit.
|
||||
* This is used to avoid dividing, so no additional library is needed.
|
||||
* It's important as this file is compiled also in SPL and there is no need
|
||||
* to link additional library.
|
||||
*/
|
||||
#ifdef CONFIG_ARM926EJS
|
||||
#define COUNT_ZEROES(x) __builtin_ctz(x)
|
||||
#else
|
||||
#define COUNT_ZEROES(x) (ffs(x) - 1)
|
||||
#endif
|
||||
|
||||
nand_info_t nand_info[1];
|
||||
|
||||
#define CONFIG_SYS_NAND_READ_DELAY \
|
||||
{ volatile int dummy; int i; for (i=0; i<10000; i++) dummy = i; }
|
||||
|
||||
/*
|
||||
* NAND command for small page NAND devices (512)
|
||||
*/
|
||||
static void nand_command(struct mtd_info *mtd, unsigned int cmd,
|
||||
int column, int page_addr)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
int ctrl = NAND_CTRL_CLE | NAND_CTRL_CHANGE;
|
||||
|
||||
if (chip->dev_ready)
|
||||
while (!chip->dev_ready(mtd))
|
||||
;
|
||||
else
|
||||
CONFIG_SYS_NAND_READ_DELAY;
|
||||
|
||||
/* Begin command latch cycle */
|
||||
chip->cmd_ctrl(mtd, cmd, NAND_CTRL_CLE | NAND_CTRL_CHANGE);
|
||||
|
||||
ctrl = NAND_CTRL_ALE | NAND_CTRL_CHANGE;
|
||||
/* Serially input address */
|
||||
if (column != -1) {
|
||||
/* Adjust columns for 16 bit buswidth */
|
||||
if (chip->options & NAND_BUSWIDTH_16)
|
||||
column >>= 1;
|
||||
chip->cmd_ctrl(mtd, column, ctrl);
|
||||
ctrl &= ~NAND_CTRL_CHANGE;
|
||||
}
|
||||
if (page_addr != -1) {
|
||||
chip->cmd_ctrl(mtd, page_addr, ctrl);
|
||||
ctrl &= ~NAND_CTRL_CHANGE;
|
||||
chip->cmd_ctrl(mtd, page_addr >> 8, ctrl);
|
||||
/* One more address cycle for devices > 32MiB */
|
||||
if (chip->chipsize > (32 << 20))
|
||||
chip->cmd_ctrl(mtd, page_addr >> 16, ctrl);
|
||||
}
|
||||
chip->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
|
||||
|
||||
/*
|
||||
* Wait a while for the data to be ready
|
||||
*/
|
||||
if (chip->dev_ready)
|
||||
while (!chip->dev_ready(mtd))
|
||||
;
|
||||
else
|
||||
CONFIG_SYS_NAND_READ_DELAY;
|
||||
}
|
||||
|
||||
/*
|
||||
* NAND command for large page NAND devices (2k)
|
||||
*/
|
||||
static void nand_command_lp(struct mtd_info *mtd, unsigned int cmd, int column,
|
||||
int page_addr)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
|
||||
if (chip->dev_ready)
|
||||
while (!chip->dev_ready(mtd))
|
||||
;
|
||||
else
|
||||
CONFIG_SYS_NAND_READ_DELAY;
|
||||
|
||||
/* Emulate NAND_CMD_READOOB */
|
||||
if (cmd == NAND_CMD_READOOB) {
|
||||
page_addr += mtd->writesize;
|
||||
cmd = NAND_CMD_READ0;
|
||||
}
|
||||
|
||||
/* Command latch cycle */
|
||||
chip->cmd_ctrl(mtd, cmd & 0xff,
|
||||
NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE);
|
||||
|
||||
if (column != -1 || page_addr != -1) {
|
||||
int ctrl = NAND_CTRL_CHANGE | NAND_NCE | NAND_ALE;
|
||||
|
||||
/* Serially input address */
|
||||
if (column != -1) {
|
||||
/* Adjust columns for 16 bit buswidth */
|
||||
if (chip->options & NAND_BUSWIDTH_16)
|
||||
column >>= 1;
|
||||
chip->cmd_ctrl(mtd, column, ctrl);
|
||||
ctrl &= ~NAND_CTRL_CHANGE;
|
||||
chip->cmd_ctrl(mtd, column >> 8, ctrl);
|
||||
}
|
||||
if (page_addr != -1) {
|
||||
chip->cmd_ctrl(mtd, page_addr, ctrl);
|
||||
chip->cmd_ctrl(mtd, page_addr >> 8,
|
||||
NAND_NCE | NAND_ALE);
|
||||
/* One more address cycle for devices > 128MiB */
|
||||
if (chip->chipsize > (128 << 20))
|
||||
chip->cmd_ctrl(mtd, page_addr >> 16,
|
||||
NAND_NCE | NAND_ALE);
|
||||
}
|
||||
}
|
||||
chip->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
|
||||
|
||||
chip->cmd_ctrl(mtd, NAND_CMD_READSTART,
|
||||
NAND_CTRL_CLE | NAND_CTRL_CHANGE);
|
||||
chip->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
|
||||
|
||||
/*
|
||||
* Wait a while for the data to be ready
|
||||
*/
|
||||
if (chip->dev_ready)
|
||||
while (!chip->dev_ready(mtd))
|
||||
;
|
||||
else
|
||||
CONFIG_SYS_NAND_READ_DELAY;
|
||||
}
|
||||
|
||||
static int nand_is_bad_block(struct mtd_info *mtd, int page_addr)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
|
||||
if ((page_addr & (mtd->erasesize - 1)) != 0)
|
||||
/*
|
||||
* Page address is not aligned to block address,
|
||||
* in this case there is no reason to check bad block.
|
||||
*/
|
||||
return 0;
|
||||
|
||||
chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page_addr);
|
||||
chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
|
||||
|
||||
return (chip->oob_poi[5] != 0xFF) ? 1: 0;
|
||||
}
|
||||
|
||||
static int nand_read_page(struct mtd_info *mtd, int page_addr,
|
||||
unsigned char *dst)
|
||||
{
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
uint8_t *ecc_calc;
|
||||
uint8_t *ecc_code;
|
||||
int i;
|
||||
int eccsize = chip->ecc.size;
|
||||
int eccbytes = chip->ecc.bytes;
|
||||
int eccsteps = chip->ecc.steps;
|
||||
uint32_t *eccpos = chip->ecc.layout->eccpos;
|
||||
uint8_t *p = dst;
|
||||
|
||||
chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page_addr);
|
||||
|
||||
/*
|
||||
* No malloc available for now, just use some temporary locations
|
||||
* in SDRAM.
|
||||
*/
|
||||
ecc_calc = (uint8_t *)RAM_BUF2;
|
||||
ecc_code = (uint8_t *)RAM_BUF3;
|
||||
|
||||
for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
|
||||
chip->ecc.hwctl(mtd, NAND_ECC_READ);
|
||||
chip->read_buf(mtd, p, eccsize);
|
||||
chip->ecc.calculate(mtd, p, &ecc_calc[i]);
|
||||
}
|
||||
chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
|
||||
|
||||
/* Pick the ECC bytes out of the oob data */
|
||||
for (i = 0; i < chip->ecc.total; i++)
|
||||
ecc_code[i] = chip->oob_poi[eccpos[i]];
|
||||
|
||||
eccsteps = chip->ecc.steps;
|
||||
p = dst;
|
||||
|
||||
for (i = 0 ; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
|
||||
/*
|
||||
* No chance to do something with the possible error message
|
||||
* from correct_data(). We just hope that all possible errors
|
||||
* are corrected by this routine.
|
||||
*/
|
||||
chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void nand_load(struct mtd_info *mtd, unsigned int offset,
|
||||
unsigned int size, uint8_t *dst)
|
||||
{
|
||||
unsigned int page, end_page, pages_per_block;
|
||||
|
||||
/*
|
||||
* Offset should be aligned to page and block size, otherwise
|
||||
* there will be no chance to detect bad block of start offset.
|
||||
*/
|
||||
page = offset >> COUNT_ZEROES(mtd->writesize);
|
||||
end_page = page + (size >> COUNT_ZEROES(mtd->writesize));
|
||||
/* If size is not aligned to page then read one more page */
|
||||
if (size & (mtd->writesize - 1))
|
||||
end_page++;
|
||||
pages_per_block = mtd->erasesize >> COUNT_ZEROES(mtd->writesize);
|
||||
|
||||
while (page < end_page) {
|
||||
/* If this read is in new block, check for babd block*/
|
||||
if ((page & (pages_per_block - 1)) == 0) {
|
||||
if (nand_is_bad_block(mtd, page)) {
|
||||
/*
|
||||
* Bad block is detected.
|
||||
* Jump to next block and continue code loading.
|
||||
* In this case not full image will be loaded.
|
||||
*/
|
||||
page += pages_per_block;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
nand_read_page(mtd, page, dst);
|
||||
page++;
|
||||
dst += mtd->writesize;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(CONFIG_ARM)
|
||||
void board_init_f (ulong bootflag)
|
||||
{
|
||||
relocate_code (CONFIG_SYS_TEXT_BASE - TOTAL_MALLOC_LEN, NULL,
|
||||
CONFIG_SYS_TEXT_BASE);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Get the flash and manufacturer id and lookup if the type is supported
|
||||
*/
|
||||
static const struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
|
||||
struct nand_chip *chip,
|
||||
int busw, int *maf_id)
|
||||
{
|
||||
const struct nand_flash_dev *type = NULL;
|
||||
int i, dev_id, maf_idx;
|
||||
int tmp_id, tmp_manf;
|
||||
|
||||
/* Select the device */
|
||||
chip->select_chip(mtd, 0);
|
||||
|
||||
/*
|
||||
* Reset the chip, required by some chips (e.g. Micron MT29FxGxxxxx)
|
||||
* after power-up
|
||||
*/
|
||||
chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
|
||||
|
||||
/* Send the command for reading device ID */
|
||||
chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
|
||||
|
||||
/* Read manufacturer and device IDs */
|
||||
*maf_id = chip->read_byte(mtd);
|
||||
dev_id = chip->read_byte(mtd);
|
||||
|
||||
/* Try again to make sure, as some systems the bus-hold or other
|
||||
* interface concerns can cause random data which looks like a
|
||||
* possibly credible NAND flash to appear. If the two results do
|
||||
* not match, ignore the device completely.
|
||||
*/
|
||||
chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
|
||||
|
||||
/* Read manufacturer and device IDs */
|
||||
tmp_manf = chip->read_byte(mtd);
|
||||
tmp_id = chip->read_byte(mtd);
|
||||
|
||||
if (tmp_manf != *maf_id || tmp_id != dev_id)
|
||||
return ERR_PTR(-ENODEV);
|
||||
|
||||
/* Lookup the flash id */
|
||||
for (i = 0; nand_flash_ids[i].name != NULL; i++) {
|
||||
if (dev_id == nand_flash_ids[i].id) {
|
||||
type = &nand_flash_ids[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!type)
|
||||
return ERR_PTR(-ENODEV);
|
||||
|
||||
if (!mtd->name)
|
||||
mtd->name = type->name;
|
||||
|
||||
chip->chipsize = (uint64_t)type->chipsize << 20;
|
||||
|
||||
/* Newer devices have all the information in additional id bytes */
|
||||
if (!type->pagesize) {
|
||||
int extid;
|
||||
/* The 3rd id byte holds MLC / multichip data */
|
||||
chip->cellinfo = chip->read_byte(mtd);
|
||||
/* The 4th id byte is the important one */
|
||||
extid = chip->read_byte(mtd);
|
||||
/* Calc pagesize */
|
||||
mtd->writesize = 1024 << (extid & 0x3);
|
||||
extid >>= 2;
|
||||
/* Calc oobsize */
|
||||
mtd->oobsize = (8 << (extid & 0x01)) * (mtd->writesize >> 9);
|
||||
extid >>= 2;
|
||||
/* Calc blocksize. Blocksize is multiples of 64KiB */
|
||||
mtd->erasesize = (64 * 1024) << (extid & 0x03);
|
||||
extid >>= 2;
|
||||
/* Get buswidth information */
|
||||
busw = (extid & 0x01) ? NAND_BUSWIDTH_16 : 0;
|
||||
|
||||
} else {
|
||||
/*
|
||||
* Old devices have chip data hardcoded in the device id table
|
||||
*/
|
||||
mtd->erasesize = type->erasesize;
|
||||
mtd->writesize = type->pagesize;
|
||||
mtd->oobsize = mtd->writesize / 32;
|
||||
busw = type->options & NAND_BUSWIDTH_16;
|
||||
}
|
||||
|
||||
/* Try to identify manufacturer */
|
||||
for (maf_idx = 0; nand_manuf_ids[maf_idx].id != 0x0; maf_idx++) {
|
||||
if (nand_manuf_ids[maf_idx].id == *maf_id)
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check, if buswidth is correct. Hardware drivers should set
|
||||
* chip correct !
|
||||
*/
|
||||
if (busw != (chip->options & NAND_BUSWIDTH_16))
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
/* Calculate the address shift from the page size */
|
||||
chip->page_shift = ffs(mtd->writesize) - 1;
|
||||
|
||||
chip->bbt_erase_shift = chip->phys_erase_shift =
|
||||
ffs(mtd->erasesize) - 1;
|
||||
if (chip->chipsize & 0xffffffff)
|
||||
chip->chip_shift = ffs((unsigned)chip->chipsize) - 1;
|
||||
else
|
||||
chip->chip_shift = ffs((unsigned)(chip->chipsize >> 32)) + 31;
|
||||
|
||||
/* Set the bad block position */
|
||||
chip->badblockpos = mtd->writesize > 512 ?
|
||||
NAND_LARGE_BADBLOCK_POS : NAND_SMALL_BADBLOCK_POS;
|
||||
|
||||
/* Get chip options, preserve non chip based options */
|
||||
chip->options &= ~NAND_CHIPOPTIONS_MSK;
|
||||
chip->options |= type->options & NAND_CHIPOPTIONS_MSK;
|
||||
|
||||
/*
|
||||
* Set chip as a default. Board drivers can override it, if necessary
|
||||
*/
|
||||
chip->options |= NAND_NO_AUTOINCR;
|
||||
|
||||
/* Check if chip is a not a samsung device. Do not clear the
|
||||
* options for chips which are not having an extended id.
|
||||
*/
|
||||
if (*maf_id != NAND_MFR_SAMSUNG && !type->pagesize)
|
||||
chip->options &= ~NAND_SAMSUNG_LP_OPTIONS;
|
||||
|
||||
/* Do not replace user supplied command function ! */
|
||||
if (mtd->writesize > 512 && chip->cmdfunc == nand_command)
|
||||
chip->cmdfunc = nand_command_lp;
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
int nand_scan_ident(struct mtd_info *mtd, int maxchips,
|
||||
const struct nand_flash_dev *table)
|
||||
{
|
||||
int busw, nand_maf_id;
|
||||
struct nand_chip *chip = mtd->priv;
|
||||
const struct nand_flash_dev *type;
|
||||
|
||||
/* Get buswidth to select the correct functions */
|
||||
busw = chip->options & NAND_BUSWIDTH_16;
|
||||
|
||||
/* Read the flash type */
|
||||
type = nand_get_flash_type(mtd, chip, busw, &nand_maf_id);
|
||||
|
||||
if (IS_ERR(type)) {
|
||||
chip->select_chip(mtd, -1);
|
||||
return PTR_ERR(type);
|
||||
}
|
||||
|
||||
/* Store the number of chips and calc total size for mtd */
|
||||
chip->numchips = 1;
|
||||
mtd->size = chip->chipsize;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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)
|
||||
{
|
||||
struct nand_chip chip;
|
||||
nand_info_t *mtd = nand_info;
|
||||
__attribute__((noreturn)) void (*uboot)(void);
|
||||
|
||||
/*
|
||||
* Init board specific nand support
|
||||
*/
|
||||
mtd->priv = &chip;
|
||||
chip.IO_ADDR_R = (void __iomem *)CONFIG_SYS_NAND_BASE;
|
||||
chip.IO_ADDR_W = (void __iomem *)CONFIG_SYS_NAND_BASE;
|
||||
chip.dev_ready = NULL;
|
||||
chip.cmdfunc = nand_command;
|
||||
chip.options = 0;
|
||||
|
||||
board_nand_init(&chip);
|
||||
|
||||
chip.ecc.steps = mtd->writesize >> COUNT_ZEROES(chip.ecc.size);
|
||||
chip.oob_poi = (uint8_t *)RAM_BUF1;
|
||||
|
||||
if (chip.select_chip)
|
||||
chip.select_chip(mtd, 0);
|
||||
|
||||
/*
|
||||
* Load U-Boot image from NAND into RAM
|
||||
*/
|
||||
nand_load(mtd, CONFIG_SYS_NAND_U_BOOT_OFFS, CONFIG_SYS_NAND_U_BOOT_SIZE,
|
||||
(uint8_t *)CONFIG_SYS_NAND_U_BOOT_DST);
|
||||
|
||||
#ifdef CONFIG_NAND_ENV_DST
|
||||
nand_load(mtd, CONFIG_ENV_OFFSET, CONFIG_ENV_SIZE,
|
||||
(uint8_t *)CONFIG_NAND_ENV_DST);
|
||||
|
||||
#ifdef CONFIG_ENV_OFFSET_REDUND
|
||||
nand_load(mtd, CONFIG_ENV_OFFSET_REDUND, CONFIG_ENV_SIZE,
|
||||
(uint8_t *)CONFIG_NAND_ENV_DST + CONFIG_ENV_SIZE);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (chip.select_chip)
|
||||
chip.select_chip(mtd, -1);
|
||||
|
||||
/*
|
||||
* Jump to U-Boot image
|
||||
*/
|
||||
uboot = (void *)CONFIG_SYS_NAND_U_BOOT_START;
|
||||
(*uboot)();
|
||||
}
|
Loading…
Reference in New Issue