Merge branch 'master' of /home/wd/git/u-boot/custodians
This commit is contained in:
commit
23bca26ab0
6
README
6
README
@ -2428,6 +2428,12 @@ to save the current settings.
|
||||
to a block boundary, and CONFIG_ENV_SIZE must be a multiple of
|
||||
the NAND devices block size.
|
||||
|
||||
- CONFIG_NAND_ENV_DST
|
||||
|
||||
Defines address in RAM to which the nand_spl code should copy the
|
||||
environment. If redundant environment is used, it will be copied to
|
||||
CONFIG_NAND_ENV_DST + CONFIG_ENV_SIZE.
|
||||
|
||||
- CONFIG_SYS_SPI_INIT_OFFSET
|
||||
|
||||
Defines offset to the initial SPI buffer area in DPRAM. The
|
||||
|
@ -32,7 +32,6 @@ LIB = $(obj)lib$(BOARD).a
|
||||
COBJS-y := $(BOARD).o cmd_bf537led.o
|
||||
COBJS-$(CONFIG_BFIN_IDE) += ide-cf.o
|
||||
COBJS-$(CONFIG_CMD_EEPROM) += spi_flash.o
|
||||
COBJS-$(CONFIG_CMD_NAND) += nand.o
|
||||
COBJS-$(CONFIG_POST) += post.o post-memory.o
|
||||
|
||||
SRCS := $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c)
|
||||
|
@ -1,100 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2007 Analog Devices 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
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
#include <nand.h>
|
||||
|
||||
#define CONCAT(a,b,c,d) a ## b ## c ## d
|
||||
#define PORT(a,b) CONCAT(pPORT,a,b,)
|
||||
|
||||
#ifndef CONFIG_NAND_GPIO_PORT
|
||||
#define CONFIG_NAND_GPIO_PORT F
|
||||
#endif
|
||||
|
||||
/*
|
||||
* hardware specific access to control-lines
|
||||
*/
|
||||
static void bfin_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
|
||||
{
|
||||
register struct nand_chip *this = mtd->priv;
|
||||
u32 IO_ADDR_W = (u32) this->IO_ADDR_W;
|
||||
|
||||
if (ctrl & NAND_CTRL_CHANGE) {
|
||||
if (ctrl & NAND_CLE)
|
||||
IO_ADDR_W = CONFIG_SYS_NAND_BASE + BFIN_NAND_CLE;
|
||||
else
|
||||
IO_ADDR_W = CONFIG_SYS_NAND_BASE;
|
||||
if (ctrl & NAND_ALE)
|
||||
IO_ADDR_W = CONFIG_SYS_NAND_BASE + BFIN_NAND_ALE;
|
||||
else
|
||||
IO_ADDR_W = CONFIG_SYS_NAND_BASE;
|
||||
this->IO_ADDR_W = (void __iomem *) IO_ADDR_W;
|
||||
}
|
||||
this->IO_ADDR_R = this->IO_ADDR_W;
|
||||
|
||||
/* Drain the writebuffer */
|
||||
SSYNC();
|
||||
|
||||
if (cmd != NAND_CMD_NONE)
|
||||
writeb(cmd, this->IO_ADDR_W);
|
||||
}
|
||||
|
||||
int bfin_device_ready(struct mtd_info *mtd)
|
||||
{
|
||||
int ret = (*PORT(CONFIG_NAND_GPIO_PORT, IO) & BFIN_NAND_READY) ? 1 : 0;
|
||||
SSYNC();
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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
|
||||
* - cmd_ctrl: 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
|
||||
* - ecc.mode: 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.
|
||||
*/
|
||||
int board_nand_init(struct nand_chip *nand)
|
||||
{
|
||||
*PORT(CONFIG_NAND_GPIO_PORT, _FER) &= ~BFIN_NAND_READY;
|
||||
*PORT(CONFIG_NAND_GPIO_PORT, IO_DIR) &= ~BFIN_NAND_READY;
|
||||
*PORT(CONFIG_NAND_GPIO_PORT, IO_INEN) |= BFIN_NAND_READY;
|
||||
|
||||
nand->cmd_ctrl = bfin_hwcontrol;
|
||||
nand->ecc.mode = NAND_ECC_SOFT;
|
||||
nand->dev_ready = bfin_device_ready;
|
||||
nand->chip_delay = 30;
|
||||
|
||||
return 0;
|
||||
}
|
@ -25,6 +25,8 @@
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <nand.h>
|
||||
#include <asm/arch/nand_defs.h>
|
||||
#include <asm/arch/hardware.h>
|
||||
#include "../common/misc.h"
|
||||
|
||||
@ -72,3 +74,29 @@ int misc_init_r(void)
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NAND_DAVINCI
|
||||
|
||||
/* Set WP on deselect, write enable on select */
|
||||
static void nand_sonata_select_chip(struct mtd_info *mtd, int chip)
|
||||
{
|
||||
#define GPIO_SET_DATA01 0x01c67018
|
||||
#define GPIO_CLR_DATA01 0x01c6701c
|
||||
#define GPIO_NAND_WP (1 << 4)
|
||||
#ifdef SONATA_BOARD_GPIOWP
|
||||
if (chip < 0) {
|
||||
REG(GPIO_CLR_DATA01) |= GPIO_NAND_WP;
|
||||
} else {
|
||||
REG(GPIO_SET_DATA01) |= GPIO_NAND_WP;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int board_nand_init(struct nand_chip *nand)
|
||||
{
|
||||
davinci_nand_init(nand);
|
||||
nand->select_chip = nand_sonata_select_chip;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_NAND_DAVINCI */
|
||||
|
@ -414,18 +414,29 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
|
||||
}
|
||||
|
||||
if (strcmp(cmd, "markbad") == 0) {
|
||||
addr = (ulong)simple_strtoul(argv[2], NULL, 16);
|
||||
argc -= 2;
|
||||
argv += 2;
|
||||
|
||||
int ret = nand->block_markbad(nand, addr);
|
||||
if (ret == 0) {
|
||||
printf("block 0x%08lx successfully marked as bad\n",
|
||||
(ulong) addr);
|
||||
return 0;
|
||||
} else {
|
||||
printf("block 0x%08lx NOT marked as bad! ERROR %d\n",
|
||||
(ulong) addr, ret);
|
||||
if (argc <= 0)
|
||||
goto usage;
|
||||
|
||||
while (argc > 0) {
|
||||
addr = simple_strtoul(*argv, NULL, 16);
|
||||
|
||||
if (nand->block_markbad(nand, addr)) {
|
||||
printf("block 0x%08lx NOT marked "
|
||||
"as bad! ERROR %d\n",
|
||||
addr, ret);
|
||||
ret = 1;
|
||||
} else {
|
||||
printf("block 0x%08lx successfully "
|
||||
"marked as bad\n",
|
||||
addr);
|
||||
}
|
||||
--argc;
|
||||
++argv;
|
||||
}
|
||||
return 1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (strcmp(cmd, "biterr") == 0) {
|
||||
|
@ -340,7 +340,7 @@ int do_onenand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
|
||||
int blocksize;
|
||||
ulong addr, ofs;
|
||||
size_t len, retlen = 0;
|
||||
int ret;
|
||||
int ret = 0;
|
||||
char *cmd, *s;
|
||||
|
||||
mtd = &onenand_mtd;
|
||||
@ -434,18 +434,29 @@ int do_onenand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
|
||||
}
|
||||
|
||||
if (strcmp(cmd, "markbad") == 0) {
|
||||
addr = (ulong)simple_strtoul(argv[2], NULL, 16);
|
||||
argc -= 2;
|
||||
argv += 2;
|
||||
|
||||
int ret = mtd->block_markbad(mtd, addr);
|
||||
if (ret == 0) {
|
||||
printf("block 0x%08lx successfully marked as bad\n",
|
||||
(ulong) addr);
|
||||
return 0;
|
||||
} else {
|
||||
printf("block 0x%08lx NOT marked as bad! ERROR %d\n",
|
||||
(ulong) addr, ret);
|
||||
if (argc <= 0)
|
||||
goto usage;
|
||||
|
||||
while (argc > 0) {
|
||||
addr = simple_strtoul(*argv, NULL, 16);
|
||||
|
||||
if (mtd->block_markbad(mtd, addr)) {
|
||||
printf("block 0x%08lx NOT marked "
|
||||
"as bad! ERROR %d\n",
|
||||
addr, ret);
|
||||
ret = 1;
|
||||
} else {
|
||||
printf("block 0x%08lx successfully "
|
||||
"marked as bad\n",
|
||||
addr);
|
||||
}
|
||||
--argc;
|
||||
++argv;
|
||||
}
|
||||
return 1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (strncmp(cmd, "dump", 4) == 0) {
|
||||
@ -474,7 +485,7 @@ usage:
|
||||
}
|
||||
|
||||
U_BOOT_CMD(
|
||||
onenand, 6, 1, do_onenand,
|
||||
onenand, CONFIG_SYS_MAXARGS, 1, do_onenand,
|
||||
"OneNAND sub-system",
|
||||
"info - show available OneNAND devices\n"
|
||||
"onenand bad - show bad blocks\n"
|
||||
|
@ -68,9 +68,11 @@ extern int default_environment_size;
|
||||
char * env_name_spec = "NAND";
|
||||
|
||||
|
||||
#ifdef ENV_IS_EMBEDDED
|
||||
#if defined(ENV_IS_EMBEDDED)
|
||||
extern uchar environment[];
|
||||
env_t *env_ptr = (env_t *)(&environment[0]);
|
||||
#elif defined(CONFIG_NAND_ENV_DST)
|
||||
env_t *env_ptr = (env_t *)CONFIG_NAND_ENV_DST;
|
||||
#else /* ! ENV_IS_EMBEDDED */
|
||||
env_t *env_ptr = 0;
|
||||
#endif /* ENV_IS_EMBEDDED */
|
||||
@ -102,26 +104,33 @@ uchar env_get_char_spec (int index)
|
||||
*/
|
||||
int env_init(void)
|
||||
{
|
||||
#if defined(ENV_IS_EMBEDDED)
|
||||
size_t total;
|
||||
#if defined(ENV_IS_EMBEDDED) || defined(CONFIG_NAND_ENV_DST)
|
||||
int crc1_ok = 0, crc2_ok = 0;
|
||||
env_t *tmp_env1, *tmp_env2;
|
||||
env_t *tmp_env1;
|
||||
|
||||
total = CONFIG_ENV_SIZE;
|
||||
#ifdef CONFIG_ENV_OFFSET_REDUND
|
||||
env_t *tmp_env2;
|
||||
|
||||
tmp_env2 = (env_t *)((ulong)env_ptr + CONFIG_ENV_SIZE);
|
||||
crc2_ok = (crc32(0, tmp_env2->data, ENV_SIZE) == tmp_env2->crc);
|
||||
#endif
|
||||
|
||||
tmp_env1 = env_ptr;
|
||||
tmp_env2 = (env_t *)((ulong)env_ptr + CONFIG_ENV_SIZE);
|
||||
|
||||
crc1_ok = (crc32(0, tmp_env1->data, ENV_SIZE) == tmp_env1->crc);
|
||||
crc2_ok = (crc32(0, tmp_env2->data, ENV_SIZE) == tmp_env2->crc);
|
||||
|
||||
if (!crc1_ok && !crc2_ok)
|
||||
if (!crc1_ok && !crc2_ok) {
|
||||
gd->env_addr = 0;
|
||||
gd->env_valid = 0;
|
||||
else if(crc1_ok && !crc2_ok)
|
||||
|
||||
return 0;
|
||||
} else if (crc1_ok && !crc2_ok) {
|
||||
gd->env_valid = 1;
|
||||
else if(!crc1_ok && crc2_ok)
|
||||
}
|
||||
#ifdef CONFIG_ENV_OFFSET_REDUND
|
||||
else if (!crc1_ok && crc2_ok) {
|
||||
gd->env_valid = 2;
|
||||
else {
|
||||
} else {
|
||||
/* both ok - check serial */
|
||||
if(tmp_env1->flags == 255 && tmp_env2->flags == 0)
|
||||
gd->env_valid = 2;
|
||||
@ -135,14 +144,19 @@ int env_init(void)
|
||||
gd->env_valid = 1;
|
||||
}
|
||||
|
||||
if (gd->env_valid == 2)
|
||||
env_ptr = tmp_env2;
|
||||
else
|
||||
#endif
|
||||
if (gd->env_valid == 1)
|
||||
env_ptr = tmp_env1;
|
||||
else if (gd->env_valid == 2)
|
||||
env_ptr = tmp_env2;
|
||||
#else /* ENV_IS_EMBEDDED */
|
||||
|
||||
gd->env_addr = (ulong)env_ptr->data;
|
||||
|
||||
#else /* ENV_IS_EMBEDDED || CONFIG_NAND_ENV_DST */
|
||||
gd->env_addr = (ulong)&default_environment[0];
|
||||
gd->env_valid = 1;
|
||||
#endif /* ENV_IS_EMBEDDED */
|
||||
#endif /* ENV_IS_EMBEDDED || CONFIG_NAND_ENV_DST */
|
||||
|
||||
return (0);
|
||||
}
|
||||
@ -183,12 +197,10 @@ int writeenv(size_t offset, u_char *buf)
|
||||
#ifdef CONFIG_ENV_OFFSET_REDUND
|
||||
int saveenv(void)
|
||||
{
|
||||
size_t total;
|
||||
int ret = 0;
|
||||
nand_erase_options_t nand_erase_options;
|
||||
|
||||
env_ptr->flags++;
|
||||
total = CONFIG_ENV_SIZE;
|
||||
|
||||
nand_erase_options.length = CONFIG_ENV_RANGE;
|
||||
nand_erase_options.quiet = 0;
|
||||
@ -226,7 +238,6 @@ int saveenv(void)
|
||||
#else /* ! CONFIG_ENV_OFFSET_REDUND */
|
||||
int saveenv(void)
|
||||
{
|
||||
size_t total;
|
||||
int ret = 0;
|
||||
nand_erase_options_t nand_erase_options;
|
||||
|
||||
@ -243,7 +254,6 @@ int saveenv(void)
|
||||
return 1;
|
||||
|
||||
puts ("Writing to Nand... ");
|
||||
total = CONFIG_ENV_SIZE;
|
||||
if (writeenv(CONFIG_ENV_OFFSET, (u_char *) env_ptr)) {
|
||||
puts("FAILED!\n");
|
||||
return 1;
|
||||
@ -287,12 +297,9 @@ int readenv (size_t offset, u_char * buf)
|
||||
void env_relocate_spec (void)
|
||||
{
|
||||
#if !defined(ENV_IS_EMBEDDED)
|
||||
size_t total;
|
||||
int crc1_ok = 0, crc2_ok = 0;
|
||||
env_t *tmp_env1, *tmp_env2;
|
||||
|
||||
total = CONFIG_ENV_SIZE;
|
||||
|
||||
tmp_env1 = (env_t *) malloc(CONFIG_ENV_SIZE);
|
||||
tmp_env2 = (env_t *) malloc(CONFIG_ENV_SIZE);
|
||||
|
||||
|
@ -58,7 +58,7 @@ uchar env_get_char_spec(int index)
|
||||
|
||||
void env_relocate_spec(void)
|
||||
{
|
||||
unsigned long env_addr;
|
||||
loff_t env_addr;
|
||||
int use_default = 0;
|
||||
size_t retlen;
|
||||
|
||||
|
@ -101,15 +101,6 @@ Configuration Options:
|
||||
CONFIG_SYS_NAND_MAX_CHIPS
|
||||
The maximum number of NAND chips per device to be supported.
|
||||
|
||||
CONFIG_SYS_DAVINCI_BROKEN_ECC
|
||||
Versions of U-Boot <= 1.3.3 and Montavista Linux kernels
|
||||
generated bogus ECCs on large-page NAND. Both large and small page
|
||||
NAND ECCs were incompatible with the Linux davinci git tree (since
|
||||
NAND was integrated in 2.6.24).
|
||||
Turn this ON if you want backwards compatibility.
|
||||
Turn this OFF if you want U-Boot and the Linux davinci git kernel
|
||||
to use the same ECC format.
|
||||
|
||||
NOTE:
|
||||
=====
|
||||
|
||||
|
@ -42,9 +42,10 @@ COBJS-$(CONFIG_NAND_FSL_ELBC) += fsl_elbc_nand.o
|
||||
COBJS-$(CONFIG_NAND_FSL_UPM) += fsl_upm.o
|
||||
COBJS-$(CONFIG_NAND_MPC5121_NFC) += mpc5121_nfc.o
|
||||
COBJS-$(CONFIG_NAND_NOMADIK) += nomadik.o
|
||||
COBJS-$(CONFIG_NAND_S3C2410) += s3c2410_nand.c
|
||||
COBJS-$(CONFIG_NAND_S3C2410) += s3c2410_nand.o
|
||||
COBJS-$(CONFIG_NAND_S3C64XX) += s3c64xx.o
|
||||
COBJS-$(CONFIG_NAND_OMAP_GPMC) += omap_gpmc.o
|
||||
COBJS-$(CONFIG_NAND_PLAT) += nand_plat.o
|
||||
endif
|
||||
|
||||
COBJS := $(COBJS-y)
|
||||
|
@ -47,7 +47,7 @@
|
||||
#include <asm/arch/nand_defs.h>
|
||||
#include <asm/arch/emif_defs.h>
|
||||
|
||||
extern struct nand_chip nand_dev_desc[CONFIG_SYS_MAX_NAND_DEVICE];
|
||||
static emif_registers *const emif_regs = (void *) DAVINCI_ASYNC_EMIF_CNTRL_BASE;
|
||||
|
||||
static void nand_davinci_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
|
||||
{
|
||||
@ -68,81 +68,30 @@ static void nand_davinci_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int c
|
||||
writeb(cmd, this->IO_ADDR_W);
|
||||
}
|
||||
|
||||
/* Set WP on deselect, write enable on select */
|
||||
static void nand_davinci_select_chip(struct mtd_info *mtd, int chip)
|
||||
{
|
||||
#define GPIO_SET_DATA01 0x01c67018
|
||||
#define GPIO_CLR_DATA01 0x01c6701c
|
||||
#define GPIO_NAND_WP (1 << 4)
|
||||
#ifdef SONATA_BOARD_GPIOWP
|
||||
if (chip < 0) {
|
||||
REG(GPIO_CLR_DATA01) |= GPIO_NAND_WP;
|
||||
} else {
|
||||
REG(GPIO_SET_DATA01) |= GPIO_NAND_WP;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SYS_NAND_HW_ECC
|
||||
#ifdef CONFIG_SYS_DAVINCI_BROKEN_ECC
|
||||
/* Linux-compatible ECC uses MTD defaults. */
|
||||
/* These layouts are not compatible with Linux or RBL/UBL. */
|
||||
#ifdef CONFIG_SYS_NAND_LARGEPAGE
|
||||
static struct nand_ecclayout davinci_nand_ecclayout = {
|
||||
.eccbytes = 12,
|
||||
.eccpos = {8, 9, 10, 24, 25, 26, 40, 41, 42, 56, 57, 58},
|
||||
.oobfree = {
|
||||
{.offset = 2, .length = 6},
|
||||
{.offset = 12, .length = 12},
|
||||
{.offset = 28, .length = 12},
|
||||
{.offset = 44, .length = 12},
|
||||
{.offset = 60, .length = 4}
|
||||
}
|
||||
};
|
||||
#elif defined(CONFIG_SYS_NAND_SMALLPAGE)
|
||||
static struct nand_ecclayout davinci_nand_ecclayout = {
|
||||
.eccbytes = 3,
|
||||
.eccpos = {0, 1, 2},
|
||||
.oobfree = {
|
||||
{.offset = 6, .length = 2},
|
||||
{.offset = 8, .length = 8}
|
||||
}
|
||||
};
|
||||
#else
|
||||
#error "Either CONFIG_SYS_NAND_LARGEPAGE or CONFIG_SYS_NAND_SMALLPAGE must be defined!"
|
||||
#endif
|
||||
#endif /* CONFIG_SYS_DAVINCI_BROKEN_ECC */
|
||||
|
||||
static void nand_davinci_enable_hwecc(struct mtd_info *mtd, int mode)
|
||||
{
|
||||
emifregs emif_addr;
|
||||
int dummy;
|
||||
|
||||
emif_addr = (emifregs)DAVINCI_ASYNC_EMIF_CNTRL_BASE;
|
||||
dummy = emif_regs->NANDF1ECC;
|
||||
|
||||
dummy = emif_addr->NANDF1ECC;
|
||||
dummy = emif_addr->NANDF2ECC;
|
||||
dummy = emif_addr->NANDF3ECC;
|
||||
dummy = emif_addr->NANDF4ECC;
|
||||
|
||||
emif_addr->NANDFCR |= (1 << 8);
|
||||
/* FIXME: only chipselect 0 is supported for now */
|
||||
emif_regs->NANDFCR |= 1 << 8;
|
||||
}
|
||||
|
||||
static u_int32_t nand_davinci_readecc(struct mtd_info *mtd, u_int32_t region)
|
||||
{
|
||||
u_int32_t ecc = 0;
|
||||
emifregs emif_base_addr;
|
||||
|
||||
emif_base_addr = (emifregs)DAVINCI_ASYNC_EMIF_CNTRL_BASE;
|
||||
|
||||
if (region == 1)
|
||||
ecc = emif_base_addr->NANDF1ECC;
|
||||
ecc = emif_regs->NANDF1ECC;
|
||||
else if (region == 2)
|
||||
ecc = emif_base_addr->NANDF2ECC;
|
||||
ecc = emif_regs->NANDF2ECC;
|
||||
else if (region == 3)
|
||||
ecc = emif_base_addr->NANDF3ECC;
|
||||
ecc = emif_regs->NANDF3ECC;
|
||||
else if (region == 4)
|
||||
ecc = emif_base_addr->NANDF4ECC;
|
||||
ecc = emif_regs->NANDF4ECC;
|
||||
|
||||
return(ecc);
|
||||
}
|
||||
@ -150,29 +99,6 @@ static u_int32_t nand_davinci_readecc(struct mtd_info *mtd, u_int32_t region)
|
||||
static int nand_davinci_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code)
|
||||
{
|
||||
u_int32_t tmp;
|
||||
#ifdef CONFIG_SYS_DAVINCI_BROKEN_ECC
|
||||
/*
|
||||
* This is not how you should read ECCs on large page Davinci devices.
|
||||
* The region parameter gets you ECCs for flash chips on different chip
|
||||
* selects, not the 4x512 byte pages in a 2048 byte page.
|
||||
*
|
||||
* Preserved for backwards compatibility though.
|
||||
*/
|
||||
|
||||
int region, n;
|
||||
struct nand_chip *this = mtd->priv;
|
||||
|
||||
n = (this->ecc.size/512);
|
||||
|
||||
region = 1;
|
||||
while (n--) {
|
||||
tmp = nand_davinci_readecc(mtd, region);
|
||||
*ecc_code++ = tmp;
|
||||
*ecc_code++ = tmp >> 16;
|
||||
*ecc_code++ = ((tmp >> 8) & 0x0f) | ((tmp >> 20) & 0xf0);
|
||||
region++;
|
||||
}
|
||||
#else
|
||||
const int region = 1;
|
||||
|
||||
tmp = nand_davinci_readecc(mtd, region);
|
||||
@ -187,148 +113,26 @@ static int nand_davinci_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u
|
||||
*ecc_code++ = tmp;
|
||||
*ecc_code++ = tmp >> 8;
|
||||
*ecc_code++ = tmp >> 16;
|
||||
#endif /* CONFIG_SYS_DAVINCI_BROKEN_ECC */
|
||||
return(0);
|
||||
|
||||
/* NOTE: the above code matches mainline Linux:
|
||||
* .PQR.stu ==> ~PQRstu
|
||||
*
|
||||
* MontaVista/TI kernels encode those bytes differently, use
|
||||
* complicated (and allegedly sometimes-wrong) correction code,
|
||||
* and usually shipped with U-Boot that uses software ECC:
|
||||
* .PQR.stu ==> PsQRtu
|
||||
*
|
||||
* If you need MV/TI compatible NAND I/O in U-Boot, it should
|
||||
* be possible to (a) change the mangling above, (b) reverse
|
||||
* that mangling in nand_davinci_correct_data() below.
|
||||
*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SYS_DAVINCI_BROKEN_ECC
|
||||
static void nand_davinci_gen_true_ecc(u_int8_t *ecc_buf)
|
||||
{
|
||||
u_int32_t tmp = ecc_buf[0] | (ecc_buf[1] << 16) | ((ecc_buf[2] & 0xf0) << 20) | ((ecc_buf[2] & 0x0f) << 8);
|
||||
|
||||
ecc_buf[0] = ~(P64o(tmp) | P64e(tmp) | P32o(tmp) | P32e(tmp) | P16o(tmp) | P16e(tmp) | P8o(tmp) | P8e(tmp));
|
||||
ecc_buf[1] = ~(P1024o(tmp) | P1024e(tmp) | P512o(tmp) | P512e(tmp) | P256o(tmp) | P256e(tmp) | P128o(tmp) | P128e(tmp));
|
||||
ecc_buf[2] = ~( P4o(tmp) | P4e(tmp) | P2o(tmp) | P2e(tmp) | P1o(tmp) | P1e(tmp) | P2048o(tmp) | P2048e(tmp));
|
||||
}
|
||||
|
||||
static int nand_davinci_compare_ecc(u_int8_t *ecc_nand, u_int8_t *ecc_calc, u_int8_t *page_data)
|
||||
{
|
||||
u_int32_t i;
|
||||
u_int8_t tmp0_bit[8], tmp1_bit[8], tmp2_bit[8];
|
||||
u_int8_t comp0_bit[8], comp1_bit[8], comp2_bit[8];
|
||||
u_int8_t ecc_bit[24];
|
||||
u_int8_t ecc_sum = 0;
|
||||
u_int8_t find_bit = 0;
|
||||
u_int32_t find_byte = 0;
|
||||
int is_ecc_ff;
|
||||
|
||||
is_ecc_ff = ((*ecc_nand == 0xff) && (*(ecc_nand + 1) == 0xff) && (*(ecc_nand + 2) == 0xff));
|
||||
|
||||
nand_davinci_gen_true_ecc(ecc_nand);
|
||||
nand_davinci_gen_true_ecc(ecc_calc);
|
||||
|
||||
for (i = 0; i <= 2; i++) {
|
||||
*(ecc_nand + i) = ~(*(ecc_nand + i));
|
||||
*(ecc_calc + i) = ~(*(ecc_calc + i));
|
||||
}
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
tmp0_bit[i] = *ecc_nand % 2;
|
||||
*ecc_nand = *ecc_nand / 2;
|
||||
}
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
tmp1_bit[i] = *(ecc_nand + 1) % 2;
|
||||
*(ecc_nand + 1) = *(ecc_nand + 1) / 2;
|
||||
}
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
tmp2_bit[i] = *(ecc_nand + 2) % 2;
|
||||
*(ecc_nand + 2) = *(ecc_nand + 2) / 2;
|
||||
}
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
comp0_bit[i] = *ecc_calc % 2;
|
||||
*ecc_calc = *ecc_calc / 2;
|
||||
}
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
comp1_bit[i] = *(ecc_calc + 1) % 2;
|
||||
*(ecc_calc + 1) = *(ecc_calc + 1) / 2;
|
||||
}
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
comp2_bit[i] = *(ecc_calc + 2) % 2;
|
||||
*(ecc_calc + 2) = *(ecc_calc + 2) / 2;
|
||||
}
|
||||
|
||||
for (i = 0; i< 6; i++)
|
||||
ecc_bit[i] = tmp2_bit[i + 2] ^ comp2_bit[i + 2];
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
ecc_bit[i + 6] = tmp0_bit[i] ^ comp0_bit[i];
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
ecc_bit[i + 14] = tmp1_bit[i] ^ comp1_bit[i];
|
||||
|
||||
ecc_bit[22] = tmp2_bit[0] ^ comp2_bit[0];
|
||||
ecc_bit[23] = tmp2_bit[1] ^ comp2_bit[1];
|
||||
|
||||
for (i = 0; i < 24; i++)
|
||||
ecc_sum += ecc_bit[i];
|
||||
|
||||
switch (ecc_sum) {
|
||||
case 0:
|
||||
/* Not reached because this function is not called if
|
||||
ECC values are equal */
|
||||
return 0;
|
||||
case 1:
|
||||
/* Uncorrectable error */
|
||||
MTDDEBUG (MTD_DEBUG_LEVEL0,
|
||||
"ECC UNCORRECTED_ERROR 1\n");
|
||||
return(-1);
|
||||
case 12:
|
||||
/* Correctable error */
|
||||
find_byte = (ecc_bit[23] << 8) +
|
||||
(ecc_bit[21] << 7) +
|
||||
(ecc_bit[19] << 6) +
|
||||
(ecc_bit[17] << 5) +
|
||||
(ecc_bit[15] << 4) +
|
||||
(ecc_bit[13] << 3) +
|
||||
(ecc_bit[11] << 2) +
|
||||
(ecc_bit[9] << 1) +
|
||||
ecc_bit[7];
|
||||
|
||||
find_bit = (ecc_bit[5] << 2) + (ecc_bit[3] << 1) + ecc_bit[1];
|
||||
|
||||
MTDDEBUG (MTD_DEBUG_LEVEL0, "Correcting single bit ECC "
|
||||
"error at offset: %d, bit: %d\n",
|
||||
find_byte, find_bit);
|
||||
|
||||
page_data[find_byte] ^= (1 << find_bit);
|
||||
|
||||
return(0);
|
||||
default:
|
||||
if (is_ecc_ff) {
|
||||
if (ecc_calc[0] == 0 && ecc_calc[1] == 0 && ecc_calc[2] == 0)
|
||||
return(0);
|
||||
}
|
||||
MTDDEBUG (MTD_DEBUG_LEVEL0,
|
||||
"UNCORRECTED_ERROR default\n");
|
||||
return(-1);
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_SYS_DAVINCI_BROKEN_ECC */
|
||||
|
||||
static int nand_davinci_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
#ifdef CONFIG_SYS_DAVINCI_BROKEN_ECC
|
||||
int block_count = 0, i, rc;
|
||||
|
||||
block_count = (this->ecc.size/512);
|
||||
for (i = 0; i < block_count; i++) {
|
||||
if (memcmp(read_ecc, calc_ecc, 3) != 0) {
|
||||
rc = nand_davinci_compare_ecc(read_ecc, calc_ecc, dat);
|
||||
if (rc < 0) {
|
||||
return(rc);
|
||||
}
|
||||
}
|
||||
read_ecc += 3;
|
||||
calc_ecc += 3;
|
||||
dat += 512;
|
||||
}
|
||||
#else
|
||||
u_int32_t ecc_nand = read_ecc[0] | (read_ecc[1] << 8) |
|
||||
(read_ecc[2] << 16);
|
||||
u_int32_t ecc_calc = calc_ecc[0] | (calc_ecc[1] << 8) |
|
||||
@ -362,31 +166,24 @@ static int nand_davinci_correct_data(struct mtd_info *mtd, u_char *dat, u_char *
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_SYS_DAVINCI_BROKEN_ECC */
|
||||
return(0);
|
||||
}
|
||||
#endif /* CONFIG_SYS_NAND_HW_ECC */
|
||||
|
||||
static int nand_davinci_dev_ready(struct mtd_info *mtd)
|
||||
{
|
||||
emifregs emif_addr;
|
||||
|
||||
emif_addr = (emifregs)DAVINCI_ASYNC_EMIF_CNTRL_BASE;
|
||||
|
||||
return(emif_addr->NANDFSR & 0x1);
|
||||
}
|
||||
|
||||
static int nand_davinci_waitfunc(struct mtd_info *mtd, struct nand_chip *this)
|
||||
{
|
||||
while(!nand_davinci_dev_ready(mtd)) {;}
|
||||
*NAND_CE0CLE = NAND_STATUS;
|
||||
return(*NAND_CE0DATA);
|
||||
return emif_regs->NANDFSR & 0x1;
|
||||
}
|
||||
|
||||
static void nand_flash_init(void)
|
||||
{
|
||||
/* This is for DM6446 EVM and *very* similar. DO NOT GROW THIS!
|
||||
* Instead, have your board_init() set EMIF timings, based on its
|
||||
* knowledge of the clocks and what devices are hooked up ... and
|
||||
* don't even do that unless no UBL handled it.
|
||||
*/
|
||||
#ifdef CONFIG_SOC_DM6446
|
||||
u_int32_t acfg1 = 0x3ffffffc;
|
||||
emifregs emif_regs;
|
||||
|
||||
/*------------------------------------------------------------------*
|
||||
* NAND FLASH CHIP TIMEOUT @ 459 MHz *
|
||||
@ -408,39 +205,22 @@ static void nand_flash_init(void)
|
||||
| (0 << 0 ) /* asyncSize 8-bit bus */
|
||||
;
|
||||
|
||||
emif_regs = (emifregs)DAVINCI_ASYNC_EMIF_CNTRL_BASE;
|
||||
|
||||
emif_regs->AB1CR = acfg1; /* CS2 */
|
||||
|
||||
emif_regs->NANDFCR = 0x00000101; /* NAND flash on CS2 */
|
||||
#endif
|
||||
}
|
||||
|
||||
int board_nand_init(struct nand_chip *nand)
|
||||
void davinci_nand_init(struct nand_chip *nand)
|
||||
{
|
||||
nand->IO_ADDR_R = (void __iomem *)NAND_CE0DATA;
|
||||
nand->IO_ADDR_W = (void __iomem *)NAND_CE0DATA;
|
||||
nand->chip_delay = 0;
|
||||
nand->select_chip = nand_davinci_select_chip;
|
||||
#ifdef CONFIG_SYS_NAND_USE_FLASH_BBT
|
||||
nand->options = NAND_USE_FLASH_BBT;
|
||||
#endif
|
||||
#ifdef CONFIG_SYS_NAND_HW_ECC
|
||||
nand->ecc.mode = NAND_ECC_HW;
|
||||
#ifdef CONFIG_SYS_DAVINCI_BROKEN_ECC
|
||||
nand->ecc.layout = &davinci_nand_ecclayout;
|
||||
#ifdef CONFIG_SYS_NAND_LARGEPAGE
|
||||
nand->ecc.size = 2048;
|
||||
nand->ecc.bytes = 12;
|
||||
#elif defined(CONFIG_SYS_NAND_SMALLPAGE)
|
||||
nand->ecc.size = 512;
|
||||
nand->ecc.bytes = 3;
|
||||
#else
|
||||
#error "Either CONFIG_SYS_NAND_LARGEPAGE or CONFIG_SYS_NAND_SMALLPAGE must be defined!"
|
||||
#endif
|
||||
#else
|
||||
nand->ecc.size = 512;
|
||||
nand->ecc.bytes = 3;
|
||||
#endif /* CONFIG_SYS_DAVINCI_BROKEN_ECC */
|
||||
nand->ecc.calculate = nand_davinci_calculate_ecc;
|
||||
nand->ecc.correct = nand_davinci_correct_data;
|
||||
nand->ecc.hwctl = nand_davinci_enable_hwecc;
|
||||
@ -452,9 +232,14 @@ int board_nand_init(struct nand_chip *nand)
|
||||
nand->cmd_ctrl = nand_davinci_hwcontrol;
|
||||
|
||||
nand->dev_ready = nand_davinci_dev_ready;
|
||||
nand->waitfunc = nand_davinci_waitfunc;
|
||||
|
||||
nand_flash_init();
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
int board_nand_init(struct nand_chip *chip) __attribute__((weak));
|
||||
|
||||
int board_nand_init(struct nand_chip *chip)
|
||||
{
|
||||
davinci_nand_init(chip);
|
||||
return 0;
|
||||
}
|
||||
|
@ -766,6 +766,9 @@ int board_nand_init(struct nand_chip *nand)
|
||||
nand->waitfunc = fsl_elbc_wait;
|
||||
|
||||
/* set up nand options */
|
||||
/* redirect the pointer of bbt pattern to RAM */
|
||||
bbt_main_descr.pattern = bbt_pattern;
|
||||
bbt_mirror_descr.pattern = mirror_pattern;
|
||||
nand->bbt_td = &bbt_main_descr;
|
||||
nand->bbt_md = &bbt_mirror_descr;
|
||||
|
||||
@ -812,6 +815,7 @@ int board_nand_init(struct nand_chip *nand)
|
||||
/* Large-page-specific setup */
|
||||
if (or & OR_FCM_PGS) {
|
||||
priv->page_size = 1;
|
||||
largepage_memorybased.pattern = scan_ff_pattern;
|
||||
nand->badblock_pattern = &largepage_memorybased;
|
||||
|
||||
/* adjust ecc setup if needed */
|
||||
|
53
drivers/mtd/nand/nand_plat.c
Normal file
53
drivers/mtd/nand/nand_plat.c
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Genericish driver for memory mapped NAND devices
|
||||
*
|
||||
* Copyright (c) 2006-2009 Analog Devices Inc.
|
||||
* Licensed under the GPL-2 or later.
|
||||
*/
|
||||
|
||||
/* Your board must implement the following macros:
|
||||
* NAND_PLAT_WRITE_CMD(chip, cmd)
|
||||
* NAND_PLAT_WRITE_ADR(chip, cmd)
|
||||
* NAND_PLAT_INIT()
|
||||
*
|
||||
* It may also implement the following:
|
||||
* NAND_PLAT_DEV_READY(chip)
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
#include <nand.h>
|
||||
|
||||
static void plat_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
|
||||
if (cmd == NAND_CMD_NONE)
|
||||
return;
|
||||
|
||||
if (ctrl & NAND_CLE)
|
||||
NAND_PLAT_WRITE_CMD(this, cmd);
|
||||
else
|
||||
NAND_PLAT_WRITE_ADR(this, cmd);
|
||||
}
|
||||
|
||||
#ifdef NAND_PLAT_DEV_READY
|
||||
static int plat_dev_ready(struct mtd_info *mtd)
|
||||
{
|
||||
return NAND_PLAT_DEV_READY((struct nand_chip *)mtd->priv);
|
||||
}
|
||||
#else
|
||||
# define plat_dev_ready NULL
|
||||
#endif
|
||||
|
||||
int board_nand_init(struct nand_chip *nand)
|
||||
{
|
||||
NAND_PLAT_INIT();
|
||||
|
||||
nand->cmd_ctrl = plat_cmd_ctrl;
|
||||
nand->dev_ready = plat_dev_ready;
|
||||
nand->ecc.mode = NAND_ECC_SOFT;
|
||||
|
||||
return 0;
|
||||
}
|
@ -315,7 +315,7 @@ int nand_lock(struct mtd_info *mtd, int tight)
|
||||
* NAND_LOCK_STATUS_UNLOCK: page unlocked
|
||||
*
|
||||
*/
|
||||
int nand_get_lock_status(struct mtd_info *mtd, ulong offset)
|
||||
int nand_get_lock_status(struct mtd_info *mtd, loff_t offset)
|
||||
{
|
||||
int ret = 0;
|
||||
int chipnr;
|
||||
@ -436,7 +436,7 @@ int nand_unlock(struct mtd_info *mtd, ulong start, ulong length)
|
||||
* @param length image length
|
||||
* @return image length including bad blocks
|
||||
*/
|
||||
static size_t get_len_incl_bad (nand_info_t *nand, size_t offset,
|
||||
static size_t get_len_incl_bad (nand_info_t *nand, loff_t offset,
|
||||
const size_t length)
|
||||
{
|
||||
size_t len_incl_bad = 0;
|
||||
@ -473,7 +473,7 @@ static size_t get_len_incl_bad (nand_info_t *nand, size_t offset,
|
||||
* @param buf buffer to read from
|
||||
* @return 0 in case of success
|
||||
*/
|
||||
int nand_write_skip_bad(nand_info_t *nand, size_t offset, size_t *length,
|
||||
int nand_write_skip_bad(nand_info_t *nand, loff_t offset, size_t *length,
|
||||
u_char *buffer)
|
||||
{
|
||||
int rval;
|
||||
@ -498,7 +498,7 @@ int nand_write_skip_bad(nand_info_t *nand, size_t offset, size_t *length,
|
||||
if (len_incl_bad == *length) {
|
||||
rval = nand_write (nand, offset, length, buffer);
|
||||
if (rval != 0)
|
||||
printf ("NAND write to offset %zx failed %d\n",
|
||||
printf ("NAND write to offset %llx failed %d\n",
|
||||
offset, rval);
|
||||
|
||||
return rval;
|
||||
@ -509,7 +509,7 @@ int nand_write_skip_bad(nand_info_t *nand, size_t offset, size_t *length,
|
||||
size_t write_size;
|
||||
|
||||
if (nand_block_isbad (nand, offset & ~(nand->erasesize - 1))) {
|
||||
printf ("Skip bad block 0x%08zx\n",
|
||||
printf ("Skip bad block 0x%08llx\n",
|
||||
offset & ~(nand->erasesize - 1));
|
||||
offset += nand->erasesize - block_offset;
|
||||
continue;
|
||||
@ -522,7 +522,7 @@ int nand_write_skip_bad(nand_info_t *nand, size_t offset, size_t *length,
|
||||
|
||||
rval = nand_write (nand, offset, &write_size, p_buffer);
|
||||
if (rval != 0) {
|
||||
printf ("NAND write to offset %zx failed %d\n",
|
||||
printf ("NAND write to offset %llx failed %d\n",
|
||||
offset, rval);
|
||||
*length -= left_to_write;
|
||||
return rval;
|
||||
@ -550,7 +550,7 @@ int nand_write_skip_bad(nand_info_t *nand, size_t offset, size_t *length,
|
||||
* @param buffer buffer to write to
|
||||
* @return 0 in case of success
|
||||
*/
|
||||
int nand_read_skip_bad(nand_info_t *nand, size_t offset, size_t *length,
|
||||
int nand_read_skip_bad(nand_info_t *nand, loff_t offset, size_t *length,
|
||||
u_char *buffer)
|
||||
{
|
||||
int rval;
|
||||
@ -568,7 +568,7 @@ int nand_read_skip_bad(nand_info_t *nand, size_t offset, size_t *length,
|
||||
if (len_incl_bad == *length) {
|
||||
rval = nand_read (nand, offset, length, buffer);
|
||||
if (rval != 0)
|
||||
printf ("NAND read from offset %zx failed %d\n",
|
||||
printf ("NAND read from offset %llx failed %d\n",
|
||||
offset, rval);
|
||||
|
||||
return rval;
|
||||
@ -579,7 +579,7 @@ int nand_read_skip_bad(nand_info_t *nand, size_t offset, size_t *length,
|
||||
size_t read_length;
|
||||
|
||||
if (nand_block_isbad (nand, offset & ~(nand->erasesize - 1))) {
|
||||
printf ("Skipping bad block 0x%08zx\n",
|
||||
printf ("Skipping bad block 0x%08llx\n",
|
||||
offset & ~(nand->erasesize - 1));
|
||||
offset += nand->erasesize - block_offset;
|
||||
continue;
|
||||
@ -592,7 +592,7 @@ int nand_read_skip_bad(nand_info_t *nand, size_t offset, size_t *length,
|
||||
|
||||
rval = nand_read (nand, offset, &read_length, p_buffer);
|
||||
if (rval != 0) {
|
||||
printf ("NAND read from offset %zx failed %d\n",
|
||||
printf ("NAND read from offset %llx failed %d\n",
|
||||
offset, rval);
|
||||
*length -= left_to_read;
|
||||
return rval;
|
||||
|
@ -28,134 +28,18 @@
|
||||
|
||||
#include <asm/arch/hardware.h>
|
||||
|
||||
#ifdef CONFIG_SOC_DM646x
|
||||
#define MASK_CLE 0x80000
|
||||
#define MASK_ALE 0x40000
|
||||
#else
|
||||
#define MASK_CLE 0x10
|
||||
#define MASK_ALE 0x0a
|
||||
|
||||
#define NAND_CE0CLE ((volatile u_int8_t *)(CONFIG_SYS_NAND_BASE + 0x10))
|
||||
#define NAND_CE0ALE ((volatile u_int8_t *)(CONFIG_SYS_NAND_BASE + 0x0a))
|
||||
#define NAND_CE0DATA ((volatile u_int8_t *)CONFIG_SYS_NAND_BASE)
|
||||
|
||||
typedef struct {
|
||||
u_int32_t NRCSR;
|
||||
u_int32_t AWCCR;
|
||||
u_int8_t RSVD0[8];
|
||||
u_int32_t AB1CR;
|
||||
u_int32_t AB2CR;
|
||||
u_int32_t AB3CR;
|
||||
u_int32_t AB4CR;
|
||||
u_int8_t RSVD1[32];
|
||||
u_int32_t NIRR;
|
||||
u_int32_t NIMR;
|
||||
u_int32_t NIMSR;
|
||||
u_int32_t NIMCR;
|
||||
u_int8_t RSVD2[16];
|
||||
u_int32_t NANDFCR;
|
||||
u_int32_t NANDFSR;
|
||||
u_int8_t RSVD3[8];
|
||||
u_int32_t NANDF1ECC;
|
||||
u_int32_t NANDF2ECC;
|
||||
u_int32_t NANDF3ECC;
|
||||
u_int32_t NANDF4ECC;
|
||||
u_int8_t RSVD4[4];
|
||||
u_int32_t IODFTECR;
|
||||
u_int32_t IODFTGCR;
|
||||
u_int8_t RSVD5[4];
|
||||
u_int32_t IODFTMRLR;
|
||||
u_int32_t IODFTMRMR;
|
||||
u_int32_t IODFTMRMSBR;
|
||||
u_int8_t RSVD6[20];
|
||||
u_int32_t MODRNR;
|
||||
u_int8_t RSVD7[76];
|
||||
u_int32_t CE0DATA;
|
||||
u_int32_t CE0ALE;
|
||||
u_int32_t CE0CLE;
|
||||
u_int8_t RSVD8[4];
|
||||
u_int32_t CE1DATA;
|
||||
u_int32_t CE1ALE;
|
||||
u_int32_t CE1CLE;
|
||||
u_int8_t RSVD9[4];
|
||||
u_int32_t CE2DATA;
|
||||
u_int32_t CE2ALE;
|
||||
u_int32_t CE2CLE;
|
||||
u_int8_t RSVD10[4];
|
||||
u_int32_t CE3DATA;
|
||||
u_int32_t CE3ALE;
|
||||
u_int32_t CE3CLE;
|
||||
} nand_registers;
|
||||
|
||||
typedef volatile nand_registers *nandregs;
|
||||
#define MASK_ALE 0x08
|
||||
#endif
|
||||
|
||||
#define NAND_READ_START 0x00
|
||||
#define NAND_READ_END 0x30
|
||||
#define NAND_STATUS 0x70
|
||||
|
||||
#ifdef CONFIG_SYS_NAND_HW_ECC
|
||||
#define NAND_Ecc_P1e (1 << 0)
|
||||
#define NAND_Ecc_P2e (1 << 1)
|
||||
#define NAND_Ecc_P4e (1 << 2)
|
||||
#define NAND_Ecc_P8e (1 << 3)
|
||||
#define NAND_Ecc_P16e (1 << 4)
|
||||
#define NAND_Ecc_P32e (1 << 5)
|
||||
#define NAND_Ecc_P64e (1 << 6)
|
||||
#define NAND_Ecc_P128e (1 << 7)
|
||||
#define NAND_Ecc_P256e (1 << 8)
|
||||
#define NAND_Ecc_P512e (1 << 9)
|
||||
#define NAND_Ecc_P1024e (1 << 10)
|
||||
#define NAND_Ecc_P2048e (1 << 11)
|
||||
|
||||
#define NAND_Ecc_P1o (1 << 16)
|
||||
#define NAND_Ecc_P2o (1 << 17)
|
||||
#define NAND_Ecc_P4o (1 << 18)
|
||||
#define NAND_Ecc_P8o (1 << 19)
|
||||
#define NAND_Ecc_P16o (1 << 20)
|
||||
#define NAND_Ecc_P32o (1 << 21)
|
||||
#define NAND_Ecc_P64o (1 << 22)
|
||||
#define NAND_Ecc_P128o (1 << 23)
|
||||
#define NAND_Ecc_P256o (1 << 24)
|
||||
#define NAND_Ecc_P512o (1 << 25)
|
||||
#define NAND_Ecc_P1024o (1 << 26)
|
||||
#define NAND_Ecc_P2048o (1 << 27)
|
||||
|
||||
#define TF(v) (v ? 1 : 0)
|
||||
|
||||
#define P2048e(a) (TF(a & NAND_Ecc_P2048e) << 0)
|
||||
#define P2048o(a) (TF(a & NAND_Ecc_P2048o) << 1)
|
||||
#define P1e(a) (TF(a & NAND_Ecc_P1e) << 2)
|
||||
#define P1o(a) (TF(a & NAND_Ecc_P1o) << 3)
|
||||
#define P2e(a) (TF(a & NAND_Ecc_P2e) << 4)
|
||||
#define P2o(a) (TF(a & NAND_Ecc_P2o) << 5)
|
||||
#define P4e(a) (TF(a & NAND_Ecc_P4e) << 6)
|
||||
#define P4o(a) (TF(a & NAND_Ecc_P4o) << 7)
|
||||
|
||||
#define P8e(a) (TF(a & NAND_Ecc_P8e) << 0)
|
||||
#define P8o(a) (TF(a & NAND_Ecc_P8o) << 1)
|
||||
#define P16e(a) (TF(a & NAND_Ecc_P16e) << 2)
|
||||
#define P16o(a) (TF(a & NAND_Ecc_P16o) << 3)
|
||||
#define P32e(a) (TF(a & NAND_Ecc_P32e) << 4)
|
||||
#define P32o(a) (TF(a & NAND_Ecc_P32o) << 5)
|
||||
#define P64e(a) (TF(a & NAND_Ecc_P64e) << 6)
|
||||
#define P64o(a) (TF(a & NAND_Ecc_P64o) << 7)
|
||||
|
||||
#define P128e(a) (TF(a & NAND_Ecc_P128e) << 0)
|
||||
#define P128o(a) (TF(a & NAND_Ecc_P128o) << 1)
|
||||
#define P256e(a) (TF(a & NAND_Ecc_P256e) << 2)
|
||||
#define P256o(a) (TF(a & NAND_Ecc_P256o) << 3)
|
||||
#define P512e(a) (TF(a & NAND_Ecc_P512e) << 4)
|
||||
#define P512o(a) (TF(a & NAND_Ecc_P512o) << 5)
|
||||
#define P1024e(a) (TF(a & NAND_Ecc_P1024e) << 6)
|
||||
#define P1024o(a) (TF(a & NAND_Ecc_P1024o) << 7)
|
||||
|
||||
#define P8e_s(a) (TF(a & NAND_Ecc_P8e) << 0)
|
||||
#define P8o_s(a) (TF(a & NAND_Ecc_P8o) << 1)
|
||||
#define P16e_s(a) (TF(a & NAND_Ecc_P16e) << 2)
|
||||
#define P16o_s(a) (TF(a & NAND_Ecc_P16o) << 3)
|
||||
#define P1e_s(a) (TF(a & NAND_Ecc_P1e) << 4)
|
||||
#define P1o_s(a) (TF(a & NAND_Ecc_P1o) << 5)
|
||||
#define P2e_s(a) (TF(a & NAND_Ecc_P2e) << 6)
|
||||
#define P2o_s(a) (TF(a & NAND_Ecc_P2o) << 7)
|
||||
|
||||
#define P4e_s(a) (TF(a & NAND_Ecc_P4e) << 0)
|
||||
#define P4o_s(a) (TF(a & NAND_Ecc_P4o) << 1)
|
||||
#endif
|
||||
extern void davinci_nand_init(struct nand_chip *nand);
|
||||
|
||||
#endif
|
||||
|
@ -151,36 +151,28 @@
|
||||
/*
|
||||
* NAND Settings
|
||||
*/
|
||||
/* #define CONFIG_BF537_NAND */
|
||||
#ifdef CONFIG_BF537_NAND
|
||||
# define CONFIG_CMD_NAND
|
||||
#endif
|
||||
|
||||
#define CONFIG_SYS_NAND_ADDR 0x20212000
|
||||
#define CONFIG_SYS_NAND_BASE CONFIG_SYS_NAND_ADDR
|
||||
/* #define CONFIG_NAND_PLAT */
|
||||
#define CONFIG_SYS_NAND_BASE 0x20212000
|
||||
#define CONFIG_SYS_MAX_NAND_DEVICE 1
|
||||
#define SECTORSIZE 512
|
||||
#define ADDR_COLUMN 1
|
||||
#define ADDR_PAGE 2
|
||||
#define ADDR_COLUMN_PAGE 3
|
||||
#define NAND_ChipID_UNKNOWN 0x00
|
||||
#define NAND_MAX_FLOORS 1
|
||||
#define BFIN_NAND_READY PF3
|
||||
|
||||
#define NAND_WAIT_READY(nand) \
|
||||
#define BFIN_NAND_CLE(chip) ((unsigned long)(chip)->IO_ADDR_W | (1 << 2))
|
||||
#define BFIN_NAND_ALE(chip) ((unsigned long)(chip)->IO_ADDR_W | (1 << 1))
|
||||
#define BFIN_NAND_READY PF3
|
||||
#define BFIN_NAND_WRITE(addr, cmd) \
|
||||
do { \
|
||||
int timeout = 0; \
|
||||
while (!(*pPORTFIO & PF3)) \
|
||||
if (timeout++ > 100000) \
|
||||
break; \
|
||||
bfin_write8(addr, cmd); \
|
||||
SSYNC(); \
|
||||
} while (0)
|
||||
|
||||
#define BFIN_NAND_CLE (1 << 2) /* A2 -> Command Enable */
|
||||
#define BFIN_NAND_ALE (1 << 1) /* A1 -> Address Enable */
|
||||
#define WRITE_NAND_COMMAND(d, adr) bfin_write8(adr | BFIN_NAND_CLE, d)
|
||||
#define WRITE_NAND_ADDRESS(d, adr) bfin_write8(adr | BFIN_NAND_ALE, d)
|
||||
#define WRITE_NAND(d, adr) bfin_write8(adr, d)
|
||||
#define READ_NAND(adr) bfin_read8(adr)
|
||||
#define NAND_PLAT_WRITE_CMD(chip, cmd) BFIN_NAND_WRITE(BFIN_NAND_CLE(chip), cmd)
|
||||
#define NAND_PLAT_WRITE_ADR(chip, cmd) BFIN_NAND_WRITE(BFIN_NAND_ALE(chip), cmd)
|
||||
#define NAND_PLAT_DEV_READY(chip) (bfin_read_PORTFIO() & BFIN_NAND_READY)
|
||||
#define NAND_PLAT_INIT() \
|
||||
do { \
|
||||
bfin_write_PORTF_FER(bfin_read_PORTF_FER() & ~BFIN_NAND_READY); \
|
||||
bfin_write_PORTFIO_DIR(bfin_read_PORTFIO_DIR() & ~BFIN_NAND_READY); \
|
||||
bfin_write_PORTFIO_INEN(bfin_read_PORTFIO_INEN() | BFIN_NAND_READY); \
|
||||
} while (0)
|
||||
|
||||
|
||||
/*
|
||||
|
@ -38,6 +38,9 @@
|
||||
# define CONFIG_CMD_USB_STORAGE
|
||||
# define CONFIG_DOS_PARTITION
|
||||
# endif
|
||||
# ifdef CONFIG_NAND_PLAT
|
||||
# define CONFIG_CMD_NAND
|
||||
# endif
|
||||
# ifdef CONFIG_POST
|
||||
# define CONFIG_CMD_DIAG
|
||||
# endif
|
||||
|
@ -209,6 +209,9 @@
|
||||
/* total memory available to uboot */
|
||||
#define CONFIG_SYS_UBOOT_SIZE (1024 * 1024)
|
||||
|
||||
/* Put environment copies after the end of U-Boot owned RAM */
|
||||
#define CONFIG_NAND_ENV_DST (CONFIG_SYS_UBOOT_BASE + CONFIG_SYS_UBOOT_SIZE)
|
||||
|
||||
#ifdef CONFIG_ENABLE_MMU
|
||||
#define CONFIG_SYS_MAPPED_RAM_BASE 0xc0000000
|
||||
#define CONFIG_BOOTCOMMAND "nand read 0xc0018000 0x60000 0x1c0000;" \
|
||||
|
@ -38,22 +38,22 @@ typedef struct mtd_info nand_info_t;
|
||||
extern int nand_curr_device;
|
||||
extern nand_info_t nand_info[];
|
||||
|
||||
static inline int nand_read(nand_info_t *info, off_t ofs, size_t *len, u_char *buf)
|
||||
static inline int nand_read(nand_info_t *info, loff_t ofs, size_t *len, u_char *buf)
|
||||
{
|
||||
return info->read(info, ofs, *len, (size_t *)len, buf);
|
||||
}
|
||||
|
||||
static inline int nand_write(nand_info_t *info, off_t ofs, size_t *len, u_char *buf)
|
||||
static inline int nand_write(nand_info_t *info, loff_t ofs, size_t *len, u_char *buf)
|
||||
{
|
||||
return info->write(info, ofs, *len, (size_t *)len, buf);
|
||||
}
|
||||
|
||||
static inline int nand_block_isbad(nand_info_t *info, off_t ofs)
|
||||
static inline int nand_block_isbad(nand_info_t *info, loff_t ofs)
|
||||
{
|
||||
return info->block_isbad(info, ofs);
|
||||
}
|
||||
|
||||
static inline int nand_erase(nand_info_t *info, off_t off, size_t size)
|
||||
static inline int nand_erase(nand_info_t *info, loff_t off, size_t size)
|
||||
{
|
||||
struct erase_info instr;
|
||||
|
||||
@ -110,9 +110,9 @@ struct nand_erase_options {
|
||||
|
||||
typedef struct nand_erase_options nand_erase_options_t;
|
||||
|
||||
int nand_read_skip_bad(nand_info_t *nand, size_t offset, size_t *length,
|
||||
int nand_read_skip_bad(nand_info_t *nand, loff_t offset, size_t *length,
|
||||
u_char *buffer);
|
||||
int nand_write_skip_bad(nand_info_t *nand, size_t offset, size_t *length,
|
||||
int nand_write_skip_bad(nand_info_t *nand, loff_t offset, size_t *length,
|
||||
u_char *buffer);
|
||||
int nand_erase_opts(nand_info_t *meminfo, const nand_erase_options_t *opts);
|
||||
|
||||
@ -122,7 +122,7 @@ int nand_erase_opts(nand_info_t *meminfo, const nand_erase_options_t *opts);
|
||||
|
||||
int nand_lock( nand_info_t *meminfo, int tight );
|
||||
int nand_unlock( nand_info_t *meminfo, ulong start, ulong length );
|
||||
int nand_get_lock_status(nand_info_t *meminfo, ulong offset);
|
||||
int nand_get_lock_status(nand_info_t *meminfo, loff_t offset);
|
||||
|
||||
#ifdef CONFIG_SYS_NAND_SELECT_DEVICE
|
||||
void board_nand_select_device(struct nand_chip *nand, int chip);
|
||||
|
@ -47,11 +47,13 @@ static int nand_command(struct mtd_info *mtd, int block, int page, int offs, u8
|
||||
/* Set ALE and clear CLE to start address cycle */
|
||||
/* Column address */
|
||||
this->cmd_ctrl(mtd, offs, NAND_CTRL_ALE | NAND_CTRL_CHANGE);
|
||||
this->cmd_ctrl(mtd, page_addr & 0xff, 0); /* A[16:9] */
|
||||
this->cmd_ctrl(mtd, (page_addr >> 8) & 0xff, 0); /* A[24:17] */
|
||||
this->cmd_ctrl(mtd, page_addr & 0xff, NAND_CTRL_ALE); /* A[16:9] */
|
||||
this->cmd_ctrl(mtd, (page_addr >> 8) & 0xff,
|
||||
NAND_CTRL_ALE); /* A[24:17] */
|
||||
#ifdef CONFIG_SYS_NAND_4_ADDR_CYCLE
|
||||
/* One more address cycle for devices > 32MiB */
|
||||
this->cmd_ctrl(mtd, (page_addr >> 16) & 0x0f, 0); /* A[28:25] */
|
||||
this->cmd_ctrl(mtd, (page_addr >> 16) & 0x0f,
|
||||
NAND_CTRL_ALE); /* A[28:25] */
|
||||
#endif
|
||||
/* Latch in address */
|
||||
this->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
|
||||
@ -94,13 +96,15 @@ static int nand_command(struct mtd_info *mtd, int block, int page, int offs, u8
|
||||
/* Column address */
|
||||
this->cmd_ctrl(mtd, offs & 0xff,
|
||||
NAND_CTRL_ALE | NAND_CTRL_CHANGE); /* A[7:0] */
|
||||
this->cmd_ctrl(mtd, (offs >> 8) & 0xff, 0); /* A[11:9] */
|
||||
this->cmd_ctrl(mtd, (offs >> 8) & 0xff, NAND_CTRL_ALE); /* A[11:9] */
|
||||
/* Row address */
|
||||
this->cmd_ctrl(mtd, (page_addr & 0xff), 0); /* A[19:12] */
|
||||
this->cmd_ctrl(mtd, ((page_addr >> 8) & 0xff), 0); /* A[27:20] */
|
||||
this->cmd_ctrl(mtd, (page_addr & 0xff), NAND_CTRL_ALE); /* A[19:12] */
|
||||
this->cmd_ctrl(mtd, ((page_addr >> 8) & 0xff),
|
||||
NAND_CTRL_ALE); /* A[27:20] */
|
||||
#ifdef CONFIG_SYS_NAND_5_ADDR_CYCLE
|
||||
/* One more address cycle for devices > 128MiB */
|
||||
this->cmd_ctrl(mtd, (page_addr >> 16) & 0x0f, 0); /* A[31:28] */
|
||||
this->cmd_ctrl(mtd, (page_addr >> 16) & 0x0f,
|
||||
NAND_CTRL_ALE); /* A[31:28] */
|
||||
#endif
|
||||
/* Latch in address */
|
||||
this->cmd_ctrl(mtd, NAND_CMD_READSTART,
|
||||
@ -246,6 +250,16 @@ void nand_boot(void)
|
||||
ret = nand_load(&nand_info, CONFIG_SYS_NAND_U_BOOT_OFFS, CONFIG_SYS_NAND_U_BOOT_SIZE,
|
||||
(uchar *)CONFIG_SYS_NAND_U_BOOT_DST);
|
||||
|
||||
#ifdef CONFIG_NAND_ENV_DST
|
||||
nand_load(&nand_info, CONFIG_ENV_OFFSET, CONFIG_ENV_SIZE,
|
||||
(uchar *)CONFIG_NAND_ENV_DST);
|
||||
|
||||
#ifdef CONFIG_ENV_OFFSET_REDUND
|
||||
nand_load(&nand_info, CONFIG_ENV_OFFSET_REDUND, CONFIG_ENV_SIZE,
|
||||
(uchar *)CONFIG_NAND_ENV_DST + CONFIG_ENV_SIZE);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (nand_chip.select_chip)
|
||||
nand_chip.select_chip(&nand_info, -1);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user