summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--board/freescale/mpc8313erdb/sdram.c2
-rw-r--r--board/freescale/mpc8349emds/mpc8349emds.c2
-rw-r--r--board/freescale/mpc8349itx/mpc8349itx.c2
-rw-r--r--board/freescale/mpc8360emds/mpc8360emds.c2
-rw-r--r--board/freescale/mpc8572ds/law.c1
-rw-r--r--board/freescale/mpc8572ds/tlb.c6
-rw-r--r--board/sbc8349/sbc8349.c2
-rw-r--r--common/cmd_nand.c2
-rw-r--r--cpu/mpc83xx/cpu.c2
-rw-r--r--doc/README.mpc8313erdb36
-rw-r--r--drivers/mtd/nand/diskonchip.c43
-rw-r--r--drivers/mtd/nand/fsl_elbc_nand.c36
-rw-r--r--drivers/mtd/nand/nand_base.c135
-rw-r--r--drivers/mtd/nand/nand_bbt.c2
-rw-r--r--drivers/mtd/nand/nand_ecc.c7
-rw-r--r--drivers/mtd/nand/nand_ids.c3
-rw-r--r--drivers/mtd/nand/nand_util.c30
-rw-r--r--drivers/mtd/onenand/onenand_base.c2
-rw-r--r--include/asm-ppc/fsl_lbc.h130
-rw-r--r--include/asm-ppc/immap_83xx.h57
-rw-r--r--include/asm-ppc/immap_85xx.h1
-rw-r--r--include/configs/MPC8572DS.h56
-rw-r--r--include/linux/mtd/blktrans.h2
-rw-r--r--include/linux/mtd/doc2000.h2
-rw-r--r--include/linux/mtd/mtd.h32
-rw-r--r--include/linux/mtd/nand.h12
-rw-r--r--include/linux/mtd/nand_ecc.h2
-rw-r--r--include/linux/mtd/nftl.h7
-rw-r--r--include/linux/mtd/onenand.h1
-rw-r--r--include/linux/mtd/onenand_regs.h6
-rw-r--r--include/mpc83xx.h85
-rw-r--r--nand_spl/nand_boot_fsl_elbc.c4
32 files changed, 473 insertions, 239 deletions
diff --git a/board/freescale/mpc8313erdb/sdram.c b/board/freescale/mpc8313erdb/sdram.c
index 99e8a43..cb13829 100644
--- a/board/freescale/mpc8313erdb/sdram.c
+++ b/board/freescale/mpc8313erdb/sdram.c
@@ -110,7 +110,7 @@ static long fixed_sdram(void)
phys_size_t initdram(int board_type)
{
volatile immap_t *im = (volatile immap_t *)CONFIG_SYS_IMMR;
- volatile lbus83xx_t *lbc = &im->lbus;
+ volatile fsl_lbus_t *lbc = &im->lbus;
u32 msize;
if ((im->sysconf.immrbar & IMMRBAR_BASE_ADDR) != (u32)im)
diff --git a/board/freescale/mpc8349emds/mpc8349emds.c b/board/freescale/mpc8349emds/mpc8349emds.c
index fa44360..06064d9 100644
--- a/board/freescale/mpc8349emds/mpc8349emds.c
+++ b/board/freescale/mpc8349emds/mpc8349emds.c
@@ -192,7 +192,7 @@ int checkboard (void)
void sdram_init(void)
{
volatile immap_t *immap = (immap_t *)CONFIG_SYS_IMMR;
- volatile lbus83xx_t *lbc= &immap->lbus;
+ volatile fsl_lbus_t *lbc = &immap->lbus;
uint *sdram_addr = (uint *)CONFIG_SYS_LBC_SDRAM_BASE;
/*
diff --git a/board/freescale/mpc8349itx/mpc8349itx.c b/board/freescale/mpc8349itx/mpc8349itx.c
index 3169536..35285b4 100644
--- a/board/freescale/mpc8349itx/mpc8349itx.c
+++ b/board/freescale/mpc8349itx/mpc8349itx.c
@@ -221,7 +221,7 @@ int misc_init_f(void)
0xfffffc00, 0xfffffc00, 0xfffffc00, 0xfffffc01
};
volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR;
- volatile lbus83xx_t *lbus = &immap->lbus;
+ volatile fsl_lbus_t *lbus = &immap->lbus;
lbus->bank[3].br = CONFIG_SYS_BR3_PRELIM;
lbus->bank[3].or = CONFIG_SYS_OR3_PRELIM;
diff --git a/board/freescale/mpc8360emds/mpc8360emds.c b/board/freescale/mpc8360emds/mpc8360emds.c
index b5cf714..85c0120 100644
--- a/board/freescale/mpc8360emds/mpc8360emds.c
+++ b/board/freescale/mpc8360emds/mpc8360emds.c
@@ -227,7 +227,7 @@ int checkboard(void)
static int sdram_init(unsigned int base)
{
volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR;
- volatile lbus83xx_t *lbc = &immap->lbus;
+ volatile fsl_lbus_t *lbc = &immap->lbus;
const int sdram_size = CONFIG_SYS_LBC_SDRAM_SIZE * 1024 * 1024;
int rem = base % sdram_size;
uint *sdram_addr;
diff --git a/board/freescale/mpc8572ds/law.c b/board/freescale/mpc8572ds/law.c
index 9f11902..83eb681 100644
--- a/board/freescale/mpc8572ds/law.c
+++ b/board/freescale/mpc8572ds/law.c
@@ -36,6 +36,7 @@ struct law_entry law_table[] = {
SET_LAW(CONFIG_SYS_PCIE3_MEM_PHYS, LAWAR_SIZE_512M, LAW_TRGT_IF_PCIE_3),
SET_LAW(CONFIG_SYS_PCIE3_IO_PHYS, LAW_SIZE_64K, LAW_TRGT_IF_PCIE_3),
SET_LAW(PIXIS_BASE, LAW_SIZE_4K, LAW_TRGT_IF_LBC),
+ SET_LAW(CONFIG_SYS_NAND_BASE_PHYS, LAW_SIZE_1M, LAW_TRGT_IF_LBC),
};
int num_law_entries = ARRAY_SIZE(law_table);
diff --git a/board/freescale/mpc8572ds/tlb.c b/board/freescale/mpc8572ds/tlb.c
index 1c5ed3f..8d1f646 100644
--- a/board/freescale/mpc8572ds/tlb.c
+++ b/board/freescale/mpc8572ds/tlb.c
@@ -80,6 +80,12 @@ struct fsl_e_tlb_entry tlb_table[] = {
SET_TLB_ENTRY(1, CONFIG_SYS_PCIE3_IO_PHYS, CONFIG_SYS_PCIE3_IO_PHYS,
MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
0, 6, BOOKE_PAGESZ_256K, 1),
+
+ /* *I*G - NAND */
+ SET_TLB_ENTRY(1, CONFIG_SYS_NAND_BASE, CONFIG_SYS_NAND_BASE_PHYS,
+ MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G,
+ 0, 7, BOOKE_PAGESZ_1M, 1),
+
};
int num_tlb_entries = ARRAY_SIZE(tlb_table);
diff --git a/board/sbc8349/sbc8349.c b/board/sbc8349/sbc8349.c
index 4154f29..e01cb03 100644
--- a/board/sbc8349/sbc8349.c
+++ b/board/sbc8349/sbc8349.c
@@ -160,7 +160,7 @@ int checkboard (void)
void sdram_init(void)
{
volatile immap_t *immap = (immap_t *)CONFIG_SYS_IMMR;
- volatile lbus83xx_t *lbc= &immap->lbus;
+ volatile fsl_lbus_t *lbc = &immap->lbus;
uint *sdram_addr = (uint *)CONFIG_SYS_LBC_SDRAM_BASE;
puts("\n SDRAM on Local Bus: ");
diff --git a/common/cmd_nand.c b/common/cmd_nand.c
index ea43f4f..0a366d3 100644
--- a/common/cmd_nand.c
+++ b/common/cmd_nand.c
@@ -469,7 +469,7 @@ usage:
}
U_BOOT_CMD(nand, 5, 1, do_nand,
- "nand - NAND sub-system\n",
+ "nand - NAND sub-system\n",
"info - show available NAND devices\n"
"nand device [dev] - show or set current device\n"
"nand read - addr off|partition size\n"
diff --git a/cpu/mpc83xx/cpu.c b/cpu/mpc83xx/cpu.c
index aa9b18d..5e885ab 100644
--- a/cpu/mpc83xx/cpu.c
+++ b/cpu/mpc83xx/cpu.c
@@ -148,7 +148,7 @@ int checkcpu(void)
void upmconfig (uint upm, uint *table, uint size)
{
volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR;
- volatile lbus83xx_t *lbus = &immap->lbus;
+ volatile fsl_lbus_t *lbus = &immap->lbus;
volatile uchar *dummy = NULL;
const u32 msel = (upm + 4) << BR_MSEL_SHIFT; /* What the MSEL field in BRn should be */
volatile u32 *mxmr = &lbus->mamr + upm; /* Pointer to mamr, mbmr, or mcmr */
diff --git a/doc/README.mpc8313erdb b/doc/README.mpc8313erdb
index 7c1af17..be7ef32 100644
--- a/doc/README.mpc8313erdb
+++ b/doc/README.mpc8313erdb
@@ -15,6 +15,18 @@ Freescale MPC8313ERDB Board
4321 4321
(where the '*' indicates the position of the tab of the switch.)
+ To boot the image at the beginning of NAND flash, use these
+ DIP switch settings for S3 S4:
+
+ +------+ +------+
+ | * | | *** |
+ | *** | | * |
+ +------+ ON +------+ ON
+ 4321 4321
+ (where the '*' indicates the position of the tab of the switch.)
+
+ When booting from NAND, use u-boot-nand.bin, not u-boot.bin.
+
2. Memory Map
The memory map looks like this:
@@ -29,6 +41,9 @@ Freescale MPC8313ERDB Board
LED Control (CS3)
0xfe00_0000 0xfe7f_ffff NOR FLASH (CS0) 8M
+ When booting from NAND, NAND flash is CS0 and NOR flash
+ is CS1.
+
3. Definitions
3.1 Explanation of NEW definitions in:
@@ -45,15 +60,20 @@ Freescale MPC8313ERDB Board
export CROSS_COMPILE=your-cross-compiler-prefix-
make distclean
- make MPC8313ERDB_33_config
- (or make MPC8313ERDB_66_config, depending on the speed of
- the oscillator on your board)
+ make MPC8313ERDB_XXX_config
+ (where XXX is:
+ 33 - 33 MHz oscillator, boot from NOR flash
+ 66 - 66 MHz oscillator, boot from NOR flash
+ NAND_33 - 33 MHz oscillator, boot from NAND flash
+ NAND_66 - 66 MHz oscillator, boot from NAND flash)
make
5. Downloading and Flashing Images
5.1 Reflash U-boot Image using U-boot
+ NOR flash:
+
=>run tftpflash
You may want to try
@@ -63,6 +83,15 @@ Freescale MPC8313ERDB Board
have an alternate means of programming the flash available
if the new u-boot doesn't boot.
+ NAND flash:
+
+ =>tftpboot $loadaddr <filename>
+ =>nand erase 0 0x80000
+ =>nand write $loadaddr 0 0x80000
+
+ ...where 0x80000 is the filesize rounded up to
+ the next 0x20000 increment.
+
5.2 Downloading and Booting Linux Kernel
Ensure that all networking-related environment variables are set
@@ -79,5 +108,4 @@ Freescale MPC8313ERDB Board
6 Notes
- Booting from NAND flash is not yet supported.
The console baudrate for MPC8313ERDB is 115200bps.
diff --git a/drivers/mtd/nand/diskonchip.c b/drivers/mtd/nand/diskonchip.c
index 4cba810..e9dc4d1 100644
--- a/drivers/mtd/nand/diskonchip.c
+++ b/drivers/mtd/nand/diskonchip.c
@@ -15,8 +15,6 @@
* converted to the generic Reed-Solomon library by Thomas Gleixner <tglx@linutronix.de>
*
* Interface to generic NAND code for M-Systems DiskOnChip devices
- *
- * $Id: diskonchip.c,v 1.55 2005/11/07 11:14:30 gleixner Exp $
*/
#include <common.h>
@@ -58,13 +56,6 @@ static unsigned long __initdata doc_locations[] = {
0xe0000, 0xe2000, 0xe4000, 0xe6000,
0xe8000, 0xea000, 0xec000, 0xee000,
#endif /* CONFIG_MTD_DOCPROBE_HIGH */
-#elif defined(__PPC__)
- 0xe4000000,
-#elif defined(CONFIG_MOMENCO_OCELOT)
- 0x2f000000,
- 0xff000000,
-#elif defined(CONFIG_MOMENCO_OCELOT_G) || defined (CONFIG_MOMENCO_OCELOT_C)
- 0xff000000,
#else
#warning Unknown architecture for DiskOnChip. No default probe locations defined
#endif
@@ -229,7 +220,7 @@ static int doc_ecc_decode(struct rs_control *rs, uint8_t *data, uint8_t *ecc)
}
}
/* If the parity is wrong, no rescue possible */
- return parity ? -1 : nerr;
+ return parity ? -EBADMSG : nerr;
}
static void DoC_Delay(struct doc_priv *doc, unsigned short cycles)
@@ -1044,7 +1035,7 @@ static int doc200x_correct_data(struct mtd_info *mtd, u_char *dat,
WriteDOC(DOC_ECC_DIS, docptr, Mplus_ECCConf);
else
WriteDOC(DOC_ECC_DIS, docptr, ECCConf);
- if (no_ecc_failures && (ret == -1)) {
+ if (no_ecc_failures && (ret == -EBADMSG)) {
printk(KERN_ERR "suppressing ECC failure\n");
ret = 0;
}
@@ -1139,9 +1130,9 @@ static inline int __init nftl_partscan(struct mtd_info *mtd, struct mtd_partitio
goto out;
mh = (struct NFTLMediaHeader *)buf;
- mh->NumEraseUnits = le16_to_cpu(mh->NumEraseUnits);
- mh->FirstPhysicalEUN = le16_to_cpu(mh->FirstPhysicalEUN);
- mh->FormattedSize = le32_to_cpu(mh->FormattedSize);
+ le16_to_cpus(&mh->NumEraseUnits);
+ le16_to_cpus(&mh->FirstPhysicalEUN);
+ le32_to_cpus(&mh->FormattedSize);
printk(KERN_INFO " DataOrgID = %s\n"
" NumEraseUnits = %d\n"
@@ -1249,12 +1240,12 @@ static inline int __init inftl_partscan(struct mtd_info *mtd, struct mtd_partiti
doc->mh1_page = doc->mh0_page + (4096 >> this->page_shift);
mh = (struct INFTLMediaHeader *)buf;
- mh->NoOfBootImageBlocks = le32_to_cpu(mh->NoOfBootImageBlocks);
- mh->NoOfBinaryPartitions = le32_to_cpu(mh->NoOfBinaryPartitions);
- mh->NoOfBDTLPartitions = le32_to_cpu(mh->NoOfBDTLPartitions);
- mh->BlockMultiplierBits = le32_to_cpu(mh->BlockMultiplierBits);
- mh->FormatFlags = le32_to_cpu(mh->FormatFlags);
- mh->PercentUsed = le32_to_cpu(mh->PercentUsed);
+ le32_to_cpus(&mh->NoOfBootImageBlocks);
+ le32_to_cpus(&mh->NoOfBinaryPartitions);
+ le32_to_cpus(&mh->NoOfBDTLPartitions);
+ le32_to_cpus(&mh->BlockMultiplierBits);
+ le32_to_cpus(&mh->FormatFlags);
+ le32_to_cpus(&mh->PercentUsed);
printk(KERN_INFO " bootRecordID = %s\n"
" NoOfBootImageBlocks = %d\n"
@@ -1291,12 +1282,12 @@ static inline int __init inftl_partscan(struct mtd_info *mtd, struct mtd_partiti
/* Scan the partitions */
for (i = 0; (i < 4); i++) {
ip = &(mh->Partitions[i]);
- ip->virtualUnits = le32_to_cpu(ip->virtualUnits);
- ip->firstUnit = le32_to_cpu(ip->firstUnit);
- ip->lastUnit = le32_to_cpu(ip->lastUnit);
- ip->flags = le32_to_cpu(ip->flags);
- ip->spareUnits = le32_to_cpu(ip->spareUnits);
- ip->Reserved0 = le32_to_cpu(ip->Reserved0);
+ le32_to_cpus(&ip->virtualUnits);
+ le32_to_cpus(&ip->firstUnit);
+ le32_to_cpus(&ip->lastUnit);
+ le32_to_cpus(&ip->flags);
+ le32_to_cpus(&ip->spareUnits);
+ le32_to_cpus(&ip->Reserved0);
printk(KERN_INFO " PARTITION[%d] ->\n"
" virtualUnits = %d\n"
diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c
index 7dda6c4..367c7d7 100644
--- a/drivers/mtd/nand/fsl_elbc_nand.c
+++ b/drivers/mtd/nand/fsl_elbc_nand.c
@@ -75,7 +75,7 @@ struct fsl_elbc_ctrl {
struct fsl_elbc_mtd *chips[MAX_BANKS];
/* device info */
- lbus83xx_t *regs;
+ fsl_lbus_t *regs;
u8 __iomem *addr; /* Address of assigned FCM buffer */
unsigned int page; /* Last page written to / read from */
unsigned int read_bytes; /* Number of bytes read during command */
@@ -171,7 +171,7 @@ static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob)
struct nand_chip *chip = mtd->priv;
struct fsl_elbc_mtd *priv = chip->priv;
struct fsl_elbc_ctrl *ctrl = priv->ctrl;
- lbus83xx_t *lbc = ctrl->regs;
+ fsl_lbus_t *lbc = ctrl->regs;
int buf_num;
ctrl->page = page_addr;
@@ -211,7 +211,7 @@ static int fsl_elbc_run_command(struct mtd_info *mtd)
struct nand_chip *chip = mtd->priv;
struct fsl_elbc_mtd *priv = chip->priv;
struct fsl_elbc_ctrl *ctrl = priv->ctrl;
- lbus83xx_t *lbc = ctrl->regs;
+ fsl_lbus_t *lbc = ctrl->regs;
long long end_tick;
u32 ltesr;
@@ -261,7 +261,7 @@ static void fsl_elbc_do_read(struct nand_chip *chip, int oob)
{
struct fsl_elbc_mtd *priv = chip->priv;
struct fsl_elbc_ctrl *ctrl = priv->ctrl;
- lbus83xx_t *lbc = ctrl->regs;
+ fsl_lbus_t *lbc = ctrl->regs;
if (priv->page_size) {
out_be32(&lbc->fir,
@@ -295,7 +295,7 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
struct nand_chip *chip = mtd->priv;
struct fsl_elbc_mtd *priv = chip->priv;
struct fsl_elbc_ctrl *ctrl = priv->ctrl;
- lbus83xx_t *lbc = ctrl->regs;
+ fsl_lbus_t *lbc = ctrl->regs;
ctrl->use_mdr = 0;
@@ -633,7 +633,7 @@ static int fsl_elbc_wait(struct mtd_info *mtd, struct nand_chip *chip)
{
struct fsl_elbc_mtd *priv = chip->priv;
struct fsl_elbc_ctrl *ctrl = priv->ctrl;
- lbus83xx_t *lbc = ctrl->regs;
+ fsl_lbus_t *lbc = ctrl->regs;
if (ctrl->status != LTESR_CC)
return NAND_STATUS_FAIL;
@@ -693,13 +693,15 @@ static struct fsl_elbc_ctrl *elbc_ctrl;
static void fsl_elbc_ctrl_init(void)
{
- immap_t *im = (immap_t *)CONFIG_SYS_IMMR;
-
elbc_ctrl = kzalloc(sizeof(*elbc_ctrl), GFP_KERNEL);
if (!elbc_ctrl)
return;
- elbc_ctrl->regs = &im->lbus;
+#ifdef CONFIG_MPC85xx
+ elbc_ctrl->regs = (void *)CONFIG_SYS_MPC85xx_LBC_ADDR;
+#else
+ elbc_ctrl->regs = &((immap_t *)CONFIG_SYS_IMMR)->lbus;
+#endif
/* clear event registers */
out_be32(&elbc_ctrl->regs->ltesr, LTESR_NAND_MASK);
@@ -775,6 +777,20 @@ int board_nand_init(struct nand_chip *nand)
nand->ecc.read_page = fsl_elbc_read_page;
nand->ecc.write_page = fsl_elbc_write_page;
+#ifdef CONFIG_FSL_ELBC_FMR
+ priv->fmr = CONFIG_FSL_ELBC_FMR;
+#else
+ priv->fmr = (15 << FMR_CWTO_SHIFT) | (2 << FMR_AL_SHIFT);
+
+ /*
+ * Hardware expects small page has ECCM0, large page has ECCM1
+ * when booting from NAND. Board config can override if not
+ * booting from NAND.
+ */
+ if (or & OR_FCM_PGS)
+ priv->fmr |= FMR_ECCM;
+#endif
+
/* If CS Base Register selects full hardware ECC then use it */
if ((br & BR_DECC) == BR_DECC_CHK_GEN) {
nand->ecc.mode = NAND_ECC_HW;
@@ -791,8 +807,6 @@ int board_nand_init(struct nand_chip *nand)
nand->ecc.mode = NAND_ECC_SOFT;
}
- priv->fmr = (15 << FMR_CWTO_SHIFT) | (2 << FMR_AL_SHIFT);
-
/* Large-page-specific setup */
if (or & OR_FCM_PGS) {
priv->page_size = 1;
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index fe34a48..ba05b76 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -7,7 +7,7 @@
* Basic support for AG-AND chips is provided.
*
* Additional technical information is available on
- * http://www.linux-mtd.infradead.org/tech/nand.html
+ * http://www.linux-mtd.infradead.org/doc/nand.html
*
* Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com)
* 2002-2006 Thomas Gleixner (tglx@linutronix.de)
@@ -24,6 +24,7 @@
* if we have HW ecc support.
* The AG-AND chips have nice features for speed improvement,
* which are not supported yet. Read / program 4 pages in one go.
+ * BBT table is not serialized, has to be fixed
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -128,7 +129,7 @@ static int nand_do_write_oob(struct mtd_info *mtd, loff_t to,
static int nand_wait(struct mtd_info *mtd, struct nand_chip *this);
/*
- * For devices which display every fart in the system on a seperate LED. Is
+ * For devices which display every fart in the system on a separate LED. Is
* compiled away when LED support is disabled.
*/
/* XXX U-BOOT XXX */
@@ -412,6 +413,7 @@ static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
/* We write two bytes, so we dont have to mess with 16 bit
* access
*/
+ nand_get_device(chip, mtd, FL_WRITING);
ofs += mtd->oobsize;
chip->ops.len = chip->ops.ooblen = 2;
chip->ops.datbuf = NULL;
@@ -419,9 +421,11 @@ static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
chip->ops.ooboffs = chip->badblockpos & ~0x01;
ret = nand_do_write_oob(mtd, ofs, &chip->ops);
+ nand_release_device(mtd);
}
if (!ret)
mtd->ecc_stats.badblocks++;
+
return ret;
}
@@ -911,7 +915,88 @@ static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
int stat;
stat = chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]);
- if (stat == -1)
+ if (stat < 0)
+ mtd->ecc_stats.failed++;
+ else
+ mtd->ecc_stats.corrected += stat;
+ }
+ return 0;
+}
+
+/**
+ * nand_read_subpage - [REPLACABLE] software ecc based sub-page read function
+ * @mtd: mtd info structure
+ * @chip: nand chip info structure
+ * @dataofs offset of requested data within the page
+ * @readlen data length
+ * @buf: buffer to store read data
+ */
+static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, uint32_t data_offs, uint32_t readlen, uint8_t *bufpoi)
+{
+ int start_step, end_step, num_steps;
+ uint32_t *eccpos = chip->ecc.layout->eccpos;
+ uint8_t *p;
+ int data_col_addr, i, gaps = 0;
+ int datafrag_len, eccfrag_len, aligned_len, aligned_pos;
+ int busw = (chip->options & NAND_BUSWIDTH_16) ? 2 : 1;
+
+ /* Column address wihin the page aligned to ECC size (256bytes). */
+ start_step = data_offs / chip->ecc.size;
+ end_step = (data_offs + readlen - 1) / chip->ecc.size;
+ num_steps = end_step - start_step + 1;
+
+ /* Data size aligned to ECC ecc.size*/
+ datafrag_len = num_steps * chip->ecc.size;
+ eccfrag_len = num_steps * chip->ecc.bytes;
+
+ data_col_addr = start_step * chip->ecc.size;
+ /* If we read not a page aligned data */
+ if (data_col_addr != 0)
+ chip->cmdfunc(mtd, NAND_CMD_RNDOUT, data_col_addr, -1);
+
+ p = bufpoi + data_col_addr;
+ chip->read_buf(mtd, p, datafrag_len);
+
+ /* Calculate ECC */
+ for (i = 0; i < eccfrag_len ; i += chip->ecc.bytes, p += chip->ecc.size)
+ chip->ecc.calculate(mtd, p, &chip->buffers->ecccalc[i]);
+
+ /* The performance is faster if to position offsets
+ according to ecc.pos. Let make sure here that
+ there are no gaps in ecc positions */
+ for (i = 0; i < eccfrag_len - 1; i++) {
+ if (eccpos[i + start_step * chip->ecc.bytes] + 1 !=
+ eccpos[i + start_step * chip->ecc.bytes + 1]) {
+ gaps = 1;
+ break;
+ }
+ }
+ if (gaps) {
+ chip->cmdfunc(mtd, NAND_CMD_RNDOUT, mtd->writesize, -1);
+ chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
+ } else {
+ /* send the command to read the particular ecc bytes */
+ /* take care about buswidth alignment in read_buf */
+ aligned_pos = eccpos[start_step * chip->ecc.bytes] & ~(busw - 1);
+ aligned_len = eccfrag_len;
+ if (eccpos[start_step * chip->ecc.bytes] & (busw - 1))
+ aligned_len++;
+ if (eccpos[(start_step + num_steps) * chip->ecc.bytes] & (busw - 1))
+ aligned_len++;
+
+ chip->cmdfunc(mtd, NAND_CMD_RNDOUT, mtd->writesize + aligned_pos, -1);
+ chip->read_buf(mtd, &chip->oob_poi[aligned_pos], aligned_len);
+ }
+
+ for (i = 0; i < eccfrag_len; i++)
+ chip->buffers->ecccode[i] = chip->oob_poi[eccpos[i + start_step * chip->ecc.bytes]];
+
+ p = bufpoi + data_col_addr;
+ for (i = 0; i < eccfrag_len ; i += chip->ecc.bytes, p += chip->ecc.size) {
+ int stat;
+
+ stat = chip->ecc.correct(mtd, p, &chip->buffers->ecccode[i], &chip->buffers->ecccalc[i]);
+ if (stat < 0)
mtd->ecc_stats.failed++;
else
mtd->ecc_stats.corrected += stat;
@@ -996,7 +1081,7 @@ static int nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip,
chip->read_buf(mtd, oob, eccbytes);
stat = chip->ecc.correct(mtd, p, oob, NULL);
- if (stat == -1)
+ if (stat < 0)
mtd->ecc_stats.failed++;
else
mtd->ecc_stats.corrected += stat;
@@ -1116,6 +1201,8 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
/* Now read the page into the buffer */
if (unlikely(ops->mode == MTD_OOB_RAW))
ret = chip->ecc.read_page_raw(mtd, chip, bufpoi);
+ else if (!aligned && NAND_SUBPAGE_READ(chip) && !oob)
+ ret = chip->ecc.read_subpage(mtd, chip, col, bytes, bufpoi);
else
ret = chip->ecc.read_page(mtd, chip, bufpoi);
if (ret < 0)
@@ -1123,7 +1210,8 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
/* Transfer not aligned data */
if (!aligned) {
- chip->pagebuf = realpage;
+ if (!NAND_SUBPAGE_READ(chip) && !oob)
+ chip->pagebuf = realpage;
memcpy(buf, chip->buffers->databuf + col, bytes);
}
@@ -2193,13 +2281,14 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
erase_exit:
ret = instr->state == MTD_ERASE_DONE ? 0 : -EIO;
- /* Do call back function */
- if (!ret)
- mtd_erase_callback(instr);
/* Deselect and wake up anyone waiting on the device */
nand_release_device(mtd);
+ /* Do call back function */
+ if (!ret)
+ mtd_erase_callback(instr);
+
/*
* If BBT requires refresh and erase was successful, rewrite any
* selected bad block tables
@@ -2356,10 +2445,17 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
{
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);
@@ -2367,6 +2463,26 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
*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) {
+ printk(KERN_INFO "%s: second ID read did not match "
+ "%02x,%02x against %02x,%02x\n", __func__,
+ *maf_id, dev_id, tmp_manf, tmp_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) {
@@ -2510,6 +2626,8 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips)
/* Check for a chip array */
for (i = 1; i < maxchips; i++) {
chip->select_chip(mtd, i);
+ /* See comment in nand_get_flash_type for reset */
+ 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 */
@@ -2630,6 +2748,7 @@ int nand_scan_tail(struct mtd_info *mtd)
chip->ecc.calculate = nand_calculate_ecc;
chip->ecc.correct = nand_correct_data;
chip->ecc.read_page = nand_read_page_swecc;
+ chip->ecc.read_subpage = nand_read_subpage;
chip->ecc.write_page = nand_write_page_swecc;
chip->ecc.read_oob = nand_read_oob_std;
chip->ecc.write_oob = nand_write_oob_std;
diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c
index b3b740d..d68a315f 100644
--- a/drivers/mtd/nand/nand_bbt.c
+++ b/drivers/mtd/nand/nand_bbt.c
@@ -6,8 +6,6 @@
*
* Copyright (C) 2004 Thomas Gleixner (tglx@linutronix.de)
*
- * $Id: nand_bbt.c,v 1.36 2005/11/07 11:14:30 gleixner Exp $
- *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
diff --git a/drivers/mtd/nand/nand_ecc.c b/drivers/mtd/nand/nand_ecc.c
index ee1f6cc..94923b9 100644
--- a/drivers/mtd/nand/nand_ecc.c
+++ b/drivers/mtd/nand/nand_ecc.c
@@ -9,8 +9,6 @@
*
* Copyright (C) 2006 Thomas Gleixner <tglx@linutronix.de>
*
- * $Id: nand_ecc.c,v 1.15 2005/11/07 11:14:30 gleixner Exp $
- *
* This file 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 or (at your option) any
@@ -47,7 +45,8 @@
#include <linux/mtd/nand_ecc.h>
#endif
-#include<linux/mtd/mtd.h>
+#include <asm/errno.h>
+#include <linux/mtd/mtd.h>
/*
* NAND-SPL has no sofware ECC for now, so don't include nand_calculate_ecc(),
@@ -206,7 +205,7 @@ int nand_correct_data(struct mtd_info *mtd, u_char *dat,
if(countbits(s0 | ((uint32_t)s1 << 8) | ((uint32_t)s2 <<16)) == 1)
return 1;
- return -1;
+ return -EBADMSG;
}
/* XXX U-BOOT XXX */
diff --git a/drivers/mtd/nand/nand_ids.c b/drivers/mtd/nand/nand_ids.c
index 2ff75c9..077c305 100644
--- a/drivers/mtd/nand/nand_ids.c
+++ b/drivers/mtd/nand/nand_ids.c
@@ -3,8 +3,6 @@
*
* Copyright (C) 2002 Thomas Gleixner (tglx@linutronix.de)
*
- * $Id: nand_ids.c,v 1.16 2005/11/07 11:14:31 gleixner Exp $
- *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
@@ -142,5 +140,6 @@ struct nand_manufacturers nand_manuf_ids[] = {
{NAND_MFR_STMICRO, "ST Micro"},
{NAND_MFR_HYNIX, "Hynix"},
{NAND_MFR_MICRON, "Micron"},
+ {NAND_MFR_AMD, "AMD"},
{0x0, "Unknown"}
};
diff --git a/drivers/mtd/nand/nand_util.c b/drivers/mtd/nand/nand_util.c
index 52b3d21..149af83 100644
--- a/drivers/mtd/nand/nand_util.c
+++ b/drivers/mtd/nand/nand_util.c
@@ -78,9 +78,7 @@ int nand_erase_opts(nand_info_t *meminfo, const nand_erase_options_t *opts)
const char *mtd_device = meminfo->name;
struct mtd_oob_ops oob_opts;
struct nand_chip *chip = meminfo->priv;
- uint8_t buf[64];
- memset(buf, 0, sizeof(buf));
memset(&erase, 0, sizeof(erase));
memset(&oob_opts, 0, sizeof(oob_opts));
@@ -89,13 +87,9 @@ int nand_erase_opts(nand_info_t *meminfo, const nand_erase_options_t *opts)
erase.addr = opts->offset;
erase_length = opts->length;
-
cleanmarker.magic = cpu_to_je16 (JFFS2_MAGIC_BITMASK);
cleanmarker.nodetype = cpu_to_je16 (JFFS2_NODETYPE_CLEANMARKER);
cleanmarker.totlen = cpu_to_je32(8);
- cleanmarker.hdr_crc = cpu_to_je32(
- crc32_no_comp(0, (unsigned char *) &cleanmarker,
- sizeof(struct jffs2_unknown_node) - 4));
/* scrub option allows to erase badblock. To prevent internal
* check from erase() method, set block check method to dummy
@@ -154,23 +148,21 @@ int nand_erase_opts(nand_info_t *meminfo, const nand_erase_options_t *opts)
}
/* format for JFFS2 ? */
- if (opts->jffs2) {
-
- chip->ops.len = chip->ops.ooblen = 64;
+ if (opts->jffs2 && chip->ecc.layout->oobavail >= 8) {
+ chip->ops.ooblen = 8;
chip->ops.datbuf = NULL;
- chip->ops.oobbuf = buf;
- chip->ops.ooboffs = chip->badblockpos & ~0x01;
+ chip->ops.oobbuf = (uint8_t *)&cleanmarker;
+ chip->ops.ooboffs = 0;
+ chip->ops.mode = MTD_OOB_AUTO;
result = meminfo->write_oob(meminfo,
- erase.addr + meminfo->oobsize,
- &chip->ops);
+ erase.addr,
+ &chip->ops);
if (result != 0) {
printf("\n%s: MTD writeoob failure: %d\n",
- mtd_device, result);
+ mtd_device, result);
continue;
}
- else
- printf("%s: MTD writeoob at 0x%08x\n",mtd_device, erase.addr + meminfo->oobsize );
}
if (!opts->quiet) {
@@ -190,11 +182,11 @@ int nand_erase_opts(nand_info_t *meminfo, const nand_erase_options_t *opts)
percent_complete = percent;
printf("\rErasing at 0x%x -- %3d%% complete.",
- erase.addr, percent);
+ erase.addr, percent);
if (opts->jffs2 && result == 0)
- printf(" Cleanmarker written at 0x%x.",
- erase.addr);
+ printf(" Cleanmarker written at 0x%x.",
+ erase.addr);
}
}
}
diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c
index c22a8a8..9b7bf3a 100644
--- a/drivers/mtd/onenand/onenand_base.c
+++ b/drivers/mtd/onenand/onenand_base.c
@@ -1428,7 +1428,7 @@ int onenand_erase(struct mtd_info *mtd, struct erase_info *instr)
MTDDEBUG (MTD_DEBUG_LEVEL3,
"onenand_erase: start = 0x%08x, len = %i\n",
- (unsigned int)instr->addr, (unsigned int)ins tr->len);
+ (unsigned int)instr->addr, (unsigned int)instr->len);
block_size = (1 << this->erase_shift);
diff --git a/include/asm-ppc/fsl_lbc.h b/include/asm-ppc/fsl_lbc.h
index ea49ddc..cac7bf6 100644
--- a/include/asm-ppc/fsl_lbc.h
+++ b/include/asm-ppc/fsl_lbc.h
@@ -307,4 +307,134 @@
#define LTEDR_RAWA 0x00400000 /* Read-after-write-atomic error checking disable */
#define LTEDR_CSD 0x00080000 /* Chip select error checking disable */
+/* FMR - Flash Mode Register
+ */
+#define FMR_CWTO 0x0000F000
+#define FMR_CWTO_SHIFT 12
+#define FMR_BOOT 0x00000800
+#define FMR_ECCM 0x00000100
+#define FMR_AL 0x00000030
+#define FMR_AL_SHIFT 4
+#define FMR_OP 0x00000003
+#define FMR_OP_SHIFT 0
+
+/* FIR - Flash Instruction Register
+ */
+#define FIR_OP0 0xF0000000
+#define FIR_OP0_SHIFT 28
+#define FIR_OP1 0x0F000000
+#define FIR_OP1_SHIFT 24
+#define FIR_OP2 0x00F00000
+#define FIR_OP2_SHIFT 20
+#define FIR_OP3 0x000F0000
+#define FIR_OP3_SHIFT 16
+#define FIR_OP4 0x0000F000
+#define FIR_OP4_SHIFT 12
+#define FIR_OP5 0x00000F00
+#define FIR_OP5_SHIFT 8
+#define FIR_OP6 0x000000F0
+#define FIR_OP6_SHIFT 4
+#define FIR_OP7 0x0000000F
+#define FIR_OP7_SHIFT 0
+#define FIR_OP_NOP 0x0 /* No operation and end of sequence */
+#define FIR_OP_CA 0x1 /* Issue current column address */
+#define FIR_OP_PA 0x2 /* Issue current block+page address */
+#define FIR_OP_UA 0x3 /* Issue user defined address */
+#define FIR_OP_CM0 0x4 /* Issue command from FCR[CMD0] */
+#define FIR_OP_CM1 0x5 /* Issue command from FCR[CMD1] */
+#define FIR_OP_CM2 0x6 /* Issue command from FCR[CMD2] */
+#define FIR_OP_CM3 0x7 /* Issue command from FCR[CMD3] */
+#define FIR_OP_WB 0x8 /* Write FBCR bytes from FCM buffer */
+#define FIR_OP_WS 0x9 /* Write 1 or 2 bytes from MDR[AS] */
+#define FIR_OP_RB 0xA /* Read FBCR bytes to FCM buffer */
+#define FIR_OP_RS 0xB /* Read 1 or 2 bytes to MDR[AS] */
+#define FIR_OP_CW0 0xC /* Wait then issue FCR[CMD0] */
+#define FIR_OP_CW1 0xD /* Wait then issue FCR[CMD1] */
+#define FIR_OP_RBW 0xE /* Wait then read FBCR bytes */
+#define FIR_OP_RSW 0xF /* Wait then read 1 or 2 bytes */
+
+/* FCR - Flash Command Register
+ */
+#define FCR_CMD0 0xFF000000
+#define FCR_CMD0_SHIFT 24
+#define FCR_CMD1 0x00FF0000
+#define FCR_CMD1_SHIFT 16
+#define FCR_CMD2 0x0000FF00
+#define FCR_CMD2_SHIFT 8
+#define FCR_CMD3 0x000000FF
+#define FCR_CMD3_SHIFT 0
+/* FBAR - Flash Block Address Register
+ */
+#define FBAR_BLK 0x00FFFFFF
+
+/* FPAR - Flash Page Address Register
+ */
+#define FPAR_SP_PI 0x00007C00
+#define FPAR_SP_PI_SHIFT 10
+#define FPAR_SP_MS 0x00000200
+#define FPAR_SP_CI 0x000001FF
+#define FPAR_SP_CI_SHIFT 0
+#define FPAR_LP_PI 0x0003F000
+#define FPAR_LP_PI_SHIFT 12
+#define FPAR_LP_MS 0x00000800
+#define FPAR_LP_CI 0x000007FF
+#define FPAR_LP_CI_SHIFT 0
+
+/* LTESR - Transfer Error Status Register
+ */
+#define LTESR_BM 0x80000000
+#define LTESR_FCT 0x40000000
+#define LTESR_PAR 0x20000000
+#define LTESR_WP 0x04000000
+#define LTESR_ATMW 0x00800000
+#define LTESR_ATMR 0x00400000
+#define LTESR_CS 0x00080000
+#define LTESR_CC 0x00000001
+
+#ifndef __ASSEMBLY__
+/*
+ * Local Bus Controller Registers.
+ */
+typedef struct lbus_bank {
+ u32 br; /* Base Register */
+ u32 or; /* Option Register */
+} lbus_bank_t;
+
+typedef struct fsl_lbus {
+ lbus_bank_t bank[8];
+ u8 res0[0x28];
+ u32 mar; /* UPM Address Register */
+ u8 res1[0x4];
+ u32 mamr; /* UPMA Mode Register */
+ u32 mbmr; /* UPMB Mode Register */
+ u32 mcmr; /* UPMC Mode Register */
+ u8 res2[0x8];
+ u32 mrtpr; /* Memory Refresh Timer Prescaler Register */
+ u32 mdr; /* UPM Data Register */
+ u8 res3[0x4];
+ u32 lsor; /* Special Operation Initiation Register */
+ u32 lsdmr; /* SDRAM Mode Register */
+ u8 res4[0x8];
+ u32 lurt; /* UPM Refresh Timer */
+ u32 lsrt; /* SDRAM Refresh Timer */
+ u8 res5[0x8];
+ u32 ltesr; /* Transfer Error Status Register */
+ u32 ltedr; /* Transfer Error Disable Register */
+ u32 lteir; /* Transfer Error Interrupt Register */
+ u32 lteatr; /* Transfer Error Attributes Register */
+ u32 ltear; /* Transfer Error Address Register */
+ u8 res6[0xC];
+ u32 lbcr; /* Configuration Register */
+ u32 lcrr; /* Clock Ratio Register */
+ u8 res7[0x8];
+ u32 fmr; /* Flash Mode Register */
+ u32 fir; /* Flash Instruction Register */
+ u32 fcr; /* Flash Command Register */
+ u32 fbar; /* Flash Block Addr Register */
+ u32 fpar; /* Flash Page Addr Register */
+ u32 fbcr; /* Flash Byte Count Register */
+ u8 res8[0xF08];
+} fsl_lbus_t;
+#endif /* __ASSEMBLY__ */
+
#endif /* __ASM_PPC_FSL_LBC_H */
diff --git a/include/asm-ppc/immap_83xx.h b/include/asm-ppc/immap_83xx.h
index ff18303..df24a6e 100644
--- a/include/asm-ppc/immap_83xx.h
+++ b/include/asm-ppc/immap_83xx.h
@@ -31,6 +31,7 @@
#include <asm/types.h>
#include <asm/fsl_i2c.h>
#include <asm/mpc8xxx_spi.h>
+#include <asm/fsl_lbc.h>
/*
* Local Access Window
@@ -343,50 +344,6 @@ typedef struct duart83xx {
} duart83xx_t;
/*
- * Local Bus Controller Registers
- */
-typedef struct lbus_bank {
- u32 br; /* Base Register */
- u32 or; /* Option Register */
-} lbus_bank_t;
-
-typedef struct lbus83xx {
- lbus_bank_t bank[8];
- u8 res0[0x28];
- u32 mar; /* UPM Address Register */
- u8 res1[0x4];
- u32 mamr; /* UPMA Mode Register */
- u32 mbmr; /* UPMB Mode Register */
- u32 mcmr; /* UPMC Mode Register */
- u8 res2[0x8];
- u32 mrtpr; /* Memory Refresh Timer Prescaler Register */
- u32 mdr; /* UPM Data Register */
- u8 res3[0x4];
- u32 lsor; /* Special Operation Initiation Register */
- u32 lsdmr; /* SDRAM Mode Register */
- u8 res4[0x8];
- u32 lurt; /* UPM Refresh Timer */
- u32 lsrt; /* SDRAM Refresh Timer */
- u8 res5[0x8];
- u32 ltesr; /* Transfer Error Status Register */
- u32 ltedr; /* Transfer Error Disable Register */
- u32 lteir; /* Transfer Error Interrupt Register */
- u32 lteatr; /* Transfer Error Attributes Register */
- u32 ltear; /* Transfer Error Address Register */
- u8 res6[0xC];
- u32 lbcr; /* Configuration Register */
- u32 lcrr; /* Clock Ratio Register */
- u8 res7[0x8];
- u32 fmr; /* Flash Mode Register */
- u32 fir; /* Flash Instruction Register */
- u32 fcr; /* Flash Command Register */
- u32 fbar; /* Flash Block Addr Register */
- u32 fpar; /* Flash Page Addr Register */
- u32 fbcr; /* Flash Byte Count Register */
- u8 res8[0xF08];
-} lbus83xx_t;
-
-/*
* DMA/Messaging Unit
*/
typedef struct dma83xx {
@@ -614,7 +571,7 @@ typedef struct immap {
u8 res2[0x1300];
duart83xx_t duart[2]; /* DUART */
u8 res3[0x900];
- lbus83xx_t lbus; /* Local Bus Controller Registers */
+ fsl_lbus_t lbus; /* Local Bus Controller Registers */
u8 res4[0x1000];
spi8xxx_t spi; /* Serial Peripheral Interface */
dma83xx_t dma; /* DMA */
@@ -648,7 +605,7 @@ typedef struct immap {
u8 res1[0x1300];
duart83xx_t duart[2]; /* DUART */
u8 res2[0x900];
- lbus83xx_t lbus; /* Local Bus Controller Registers */
+ fsl_lbus_t lbus; /* Local Bus Controller Registers */
u8 res3[0x1000];
spi8xxx_t spi; /* Serial Peripheral Interface */
dma83xx_t dma; /* DMA */
@@ -683,7 +640,7 @@ typedef struct immap {
u8 res1[0x1300];
duart83xx_t duart[2]; /* DUART */
u8 res2[0x900];
- lbus83xx_t lbus; /* Local Bus Controller Registers */
+ fsl_lbus_t lbus; /* Local Bus Controller Registers */
u8 res3[0x1000];
spi8xxx_t spi; /* Serial Peripheral Interface */
dma83xx_t dma; /* DMA */
@@ -728,7 +685,7 @@ typedef struct immap {
u8 res1[0x1300];
duart83xx_t duart[2]; /* DUART */
u8 res2[0x900];
- lbus83xx_t lbus; /* Local Bus Controller Registers */
+ fsl_lbus_t lbus; /* Local Bus Controller Registers */
u8 res3[0x1000];
spi8xxx_t spi; /* Serial Peripheral Interface */
dma83xx_t dma; /* DMA */
@@ -778,7 +735,7 @@ typedef struct immap {
u8 res4[0x1300];
duart83xx_t duart[2]; /* DUART */
u8 res5[0x900];
- lbus83xx_t lbus; /* Local Bus Controller Registers */
+ fsl_lbus_t lbus; /* Local Bus Controller Registers */
u8 res6[0x2000];
dma83xx_t dma; /* DMA */
pciconf83xx_t pci_conf[1]; /* PCI Software Configuration Registers */
@@ -817,7 +774,7 @@ typedef struct immap {
u8 res3[0x1300];
duart83xx_t duart[2]; /* DUART */
u8 res4[0x900];
- lbus83xx_t lbus; /* Local Bus Controller Registers */
+ fsl_lbus_t lbus; /* Local Bus Controller Registers */
u8 res5[0x2000];
dma83xx_t dma; /* DMA */
pciconf83xx_t pci_conf[1]; /* PCI Software Configuration Registers */
diff --git a/include/asm-ppc/immap_85xx.h b/include/asm-ppc/immap_85xx.h
index 4892d8b..75b451d 100644
--- a/include/asm-ppc/immap_85xx.h
+++ b/include/asm-ppc/immap_85xx.h
@@ -13,6 +13,7 @@
#include <asm/types.h>
#include <asm/fsl_i2c.h>
+#include <asm/fsl_lbc.h>
/*
* Local-Access Registers and ECM Registers(0x0000-0x2000)
diff --git a/include/configs/MPC8572DS.h b/include/configs/MPC8572DS.h
index eefb06c..f98e7fb 100644
--- a/include/configs/MPC8572DS.h
+++ b/include/configs/MPC8572DS.h
@@ -158,6 +158,7 @@ extern unsigned long get_board_ddr_clk(unsigned long dummy);
* Localbus non-cacheable
* 0xe000_0000 0xe80f_ffff Promjet/free 128M non-cacheable
* 0xe800_0000 0xefff_ffff FLASH 128M non-cacheable
+ * 0xffa0_0000 0xffaf_ffff NAND 1M non-cacheable
* 0xffdf_0000 0xffdf_7fff PIXIS 32K non-cacheable TLB0
* 0xffd0_0000 0xffd0_3fff L1 for stack 16K Cacheable TLB0
* 0xffe0_0000 0xffef_ffff CCSR 1M non-cacheable
@@ -260,6 +261,59 @@ extern unsigned long get_board_ddr_clk(unsigned long dummy);
#define CONFIG_SYS_MONITOR_LEN (256 * 1024) /* Reserve 256 kB for Mon */
#define CONFIG_SYS_MALLOC_LEN (1024 * 1024) /* Reserved for malloc */
+#define CONFIG_SYS_NAND_BASE 0xffa00000
+#define CONFIG_SYS_NAND_BASE_PHYS CONFIG_SYS_NAND_BASE
+#define CONFIG_SYS_NAND_BASE_LIST { CONFIG_SYS_NAND_BASE,\
+ CONFIG_SYS_NAND_BASE + 0x40000, \
+ CONFIG_SYS_NAND_BASE + 0x80000,\
+ CONFIG_SYS_NAND_BASE + 0xC0000}
+#define CONFIG_SYS_MAX_NAND_DEVICE 4
+#define NAND_MAX_CHIPS 1
+#define CONFIG_MTD_NAND_VERIFY_WRITE
+#define CONFIG_CMD_NAND 1
+#define CONFIG_NAND_FSL_ELBC 1
+#define CONFIG_SYS_NAND_BLOCK_SIZE (128 * 1024)
+
+/* NAND flash config */
+#define CONFIG_NAND_BR_PRELIM (CONFIG_SYS_NAND_BASE_PHYS \
+ | (2<<BR_DECC_SHIFT) /* Use HW ECC */ \
+ | BR_PS_8 /* Port Size = 8 bit */ \
+ | BR_MS_FCM /* MSEL = FCM */ \
+ | BR_V) /* valid */
+#define CONFIG_NAND_OR_PRELIM (0xFFFC0000 /* length 256K */ \
+ | OR_FCM_PGS /* Large Page*/ \
+ | OR_FCM_CSCT \
+ | OR_FCM_CST \
+ | OR_FCM_CHT \
+ | OR_FCM_SCY_1 \
+ | OR_FCM_TRLX \
+ | OR_FCM_EHTR)
+
+#define CONFIG_SYS_BR2_PRELIM CONFIG_NAND_BR_PRELIM /* NAND Base Address */
+#define CONFIG_SYS_OR2_PRELIM CONFIG_NAND_OR_PRELIM /* NAND Options */
+
+#define CONFIG_SYS_BR4_PRELIM ((CONFIG_SYS_NAND_BASE_PHYS + 0x40000)\
+ | (2<<BR_DECC_SHIFT) /* Use HW ECC */ \
+ | BR_PS_8 /* Port Size = 8 bit */ \
+ | BR_MS_FCM /* MSEL = FCM */ \
+ | BR_V) /* valid */
+#define CONFIG_SYS_OR4_PRELIM CONFIG_NAND_OR_PRELIM /* NAND Options */
+#define CONFIG_SYS_BR5_PRELIM ((CONFIG_SYS_NAND_BASE_PHYS + 0x80000)\
+ | (2<<BR_DECC_SHIFT) /* Use HW ECC */ \
+ | BR_PS_8 /* Port Size = 8 bit */ \
+ | BR_MS_FCM /* MSEL = FCM */ \
+ | BR_V) /* valid */
+#define CONFIG_SYS_OR5_PRELIM CONFIG_NAND_OR_PRELIM /* NAND Options */
+
+#define CONFIG_SYS_BR6_PRELIM ((CONFIG_SYS_NAND_BASE_PHYS + 0xC0000)\
+ | (2<<BR_DECC_SHIFT) /* Use HW ECC */ \
+ | BR_PS_8 /* Port Size = 8 bit */ \
+ | BR_MS_FCM /* MSEL = FCM */ \
+ | BR_V) /* valid */
+#define CONFIG_SYS_OR6_PRELIM CONFIG_NAND_OR_PRELIM /* NAND Options */
+
+
+
/* Serial Port - controlled on board with jumper J8
* open - index 2
* shorted - index 1
@@ -455,7 +509,7 @@ extern unsigned long get_board_ddr_clk(unsigned long dummy);
#if CONFIG_SYS_MONITOR_BASE > 0xfff80000
#define CONFIG_ENV_ADDR 0xfff80000
#else
-#define CONFIG_ENV_ADDR (CONFIG_SYS_MONITOR_BASE + 0x70000)
+#define CONFIG_ENV_ADDR (CONFIG_SYS_MONITOR_BASE - CONFIG_ENV_SIZE)
#endif
#define CONFIG_ENV_SIZE 0x2000
#define CONFIG_ENV_SECT_SIZE 0x20000 /* 128K (one sector) */
diff --git a/include/linux/mtd/blktrans.h b/include/linux/mtd/blktrans.h
index d1ded51..32acb6c 100644
--- a/include/linux/mtd/blktrans.h
+++ b/include/linux/mtd/blktrans.h
@@ -1,6 +1,4 @@
/*
- * $Id: blktrans.h,v 1.6 2005/11/07 11:14:54 gleixner Exp $
- *
* (C) 2003 David Woodhouse <dwmw2@infradead.org>
*
* Interface to Linux block layer for MTD 'translation layers'.
diff --git a/include/linux/mtd/doc2000.h b/include/linux/mtd/doc2000.h
index 12de284..ba29d53 100644
--- a/include/linux/mtd/doc2000.h
+++ b/include/linux/mtd/doc2000.h
@@ -6,8 +6,6 @@
* Copyright (C) 2002-2003 Greg Ungerer <gerg@snapgear.com>
* Copyright (C) 2002-2003 SnapGear Inc
*
- * $Id: doc2000.h,v 1.25 2005/11/07 11:14:54 gleixner Exp $
- *
* Released under GPL
*/
diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h
index 55d33dd..354e3a0 100644
--- a/include/linux/mtd/mtd.h
+++ b/include/linux/mtd/mtd.h
@@ -1,6 +1,4 @@
/*
- * $Id: mtd.h,v 1.61 2005/11/07 11:14:54 gleixner Exp $
- *
* Copyright (C) 1999-2003 David Woodhouse <dwmw2@infradead.org> et al.
*
* Released under GPL
@@ -132,7 +130,7 @@ struct mtd_info {
u_int32_t oobavail; /* Available OOB bytes per block */
/* Kernel-only stuff starts here. */
- char *name;
+ const char *name;
int index;
/* ecc layout structure pointer - read only ! */
@@ -144,18 +142,36 @@ struct mtd_info {
int numeraseregions;
struct mtd_erase_region_info *eraseregions;
+ /*
+ * Erase is an asynchronous operation. Device drivers are supposed
+ * to call instr->callback() whenever the operation completes, even
+ * if it completes with a failure.
+ * Callers are supposed to pass a callback function and wait for it
+ * to be called before writing to the block.
+ */
int (*erase) (struct mtd_info *mtd, struct erase_info *instr);
/* This stuff for eXecute-In-Place */
- int (*point) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char **mtdbuf);
+ /* phys is optional and may be set to NULL */
+ int (*point) (struct mtd_info *mtd, loff_t from, size_t len,
+ size_t *retlen, void **virt, phys_addr_t *phys);
/* We probably shouldn't allow XIP if the unpoint isn't a NULL */
- void (*unpoint) (struct mtd_info *mtd, u_char * addr, loff_t from, size_t len);
+ void (*unpoint) (struct mtd_info *mtd, loff_t from, size_t len);
int (*read) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
int (*write) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf);
+ /* In blackbox flight recorder like scenarios we want to make successful
+ writes in interrupt context. panic_write() is only intended to be
+ called when its known the kernel is about to panic and we need the
+ write to succeed. Since the kernel is not going to be running for much
+ longer, this function can break locks and delay to ensure the write
+ succeeds (but not sleep). */
+
+ int (*panic_write) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf);
+
int (*read_oob) (struct mtd_info *mtd, loff_t from,
struct mtd_oob_ops *ops);
int (*write_oob) (struct mtd_info *mtd, loff_t to,
@@ -274,7 +290,11 @@ static inline void mtd_erase_callback(struct erase_info *instr)
printk(KERN_INFO args); \
} while(0)
#else /* CONFIG_MTD_DEBUG */
-#define MTDDEBUG(n, args...) do { } while(0)
+#define MTDDEBUG(n, args...) \
+ do { \
+ if (0) \
+ printk(KERN_INFO args); \
+ } while(0)
#endif /* CONFIG_MTD_DEBUG */
#endif /* __MTD_MTD_H__ */
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
index 7ac72de..39f8aec 100644
--- a/include/linux/mtd/nand.h
+++ b/include/linux/mtd/nand.h
@@ -1,12 +1,10 @@
/*
* linux/include/linux/mtd/nand.h
*
- * Copyright (c) 2000 David Woodhouse <dwmw2@mvhi.com>
+ * Copyright (c) 2000 David Woodhouse <dwmw2@infradead.org>
* Steven J. Hill <sjhill@realitydiluted.com>
* Thomas Gleixner <tglx@linutronix.de>
*
- * $Id: nand.h,v 1.74 2005/09/15 13:58:50 vwool Exp $
- *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
@@ -190,6 +188,9 @@ typedef enum {
#define NAND_MUST_PAD(chip) (!(chip->options & NAND_NO_PADDING))
#define NAND_HAS_CACHEPROG(chip) ((chip->options & NAND_CACHEPRG))
#define NAND_HAS_COPYBACK(chip) ((chip->options & NAND_COPYBACK))
+/* Large page NAND with SOFT_ECC should support subpage reads */
+#define NAND_SUBPAGE_READ(chip) ((chip->ecc.mode == NAND_ECC_SOFT) \
+ && (chip->page_shift > 9))
/* Mask to zero out the chip options, which come from the id table */
#define NAND_CHIPOPTIONS_MSK (0x0000ffff & ~NAND_NO_AUTOINCR)
@@ -278,6 +279,10 @@ struct nand_ecc_ctrl {
int (*read_page)(struct mtd_info *mtd,
struct nand_chip *chip,
uint8_t *buf);
+ int (*read_subpage)(struct mtd_info *mtd,
+ struct nand_chip *chip,
+ uint32_t offs, uint32_t len,
+ uint8_t *buf);
void (*write_page)(struct mtd_info *mtd,
struct nand_chip *chip,
const uint8_t *buf);
@@ -435,6 +440,7 @@ struct nand_chip {
#define NAND_MFR_STMICRO 0x20
#define NAND_MFR_HYNIX 0xad
#define NAND_MFR_MICRON 0x2c
+#define NAND_MFR_AMD 0x01
/**
* struct nand_flash_dev - NAND Flash Device ID Structure
diff --git a/include/linux/mtd/nand_ecc.h b/include/linux/mtd/nand_ecc.h
index 12c5bc3..090da50 100644
--- a/include/linux/mtd/nand_ecc.h
+++ b/include/linux/mtd/nand_ecc.h
@@ -3,8 +3,6 @@
*
* Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com)
*
- * $Id: nand_ecc.h,v 1.4 2004/06/17 02:35:02 dbrown Exp $
- *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
diff --git a/include/linux/mtd/nftl.h b/include/linux/mtd/nftl.h
index 6731a16..fe22e0d 100644
--- a/include/linux/mtd/nftl.h
+++ b/include/linux/mtd/nftl.h
@@ -1,6 +1,4 @@
/*
- * $Id: nftl.h,v 1.16 2004/06/30 14:49:00 dbrown Exp $
- *
* (C) 1999-2003 David Woodhouse <dwmw2@infradead.org>
*/
@@ -43,6 +41,11 @@ struct NFTLrecord {
int NFTL_mount(struct NFTLrecord *s);
int NFTL_formatblock(struct NFTLrecord *s, int block);
+int nftl_read_oob(struct mtd_info *mtd, loff_t offs, size_t len,
+ size_t *retlen, uint8_t *buf);
+int nftl_write_oob(struct mtd_info *mtd, loff_t offs, size_t len,
+ size_t *retlen, uint8_t *buf);
+
#ifndef NFTL_MAJOR
#define NFTL_MAJOR 93
#endif
diff --git a/include/linux/mtd/onenand.h b/include/linux/mtd/onenand.h
index 420eb14..4467c2b 100644
--- a/include/linux/mtd/onenand.h
+++ b/include/linux/mtd/onenand.h
@@ -51,6 +51,7 @@ struct onenand_bufferram {
* @param page_shift [INTERN] number of address bits in a page
* @param ppb_shift [INTERN] number of address bits in a pages per block
* @param page_mask [INTERN] a page per block mask
+ * @param writesize [INTERN] a real page size
* @param bufferam_index [INTERN] BufferRAM index
* @param bufferam [INTERN] BufferRAM info
* @param readw [REPLACEABLE] hardware specific function for read short
diff --git a/include/linux/mtd/onenand_regs.h b/include/linux/mtd/onenand_regs.h
index 6a8aa28..a245e14 100644
--- a/include/linux/mtd/onenand_regs.h
+++ b/include/linux/mtd/onenand_regs.h
@@ -67,12 +67,16 @@
/*
* Device ID Register F001h (R)
*/
+#define ONENAND_DEVICE_DENSITY_MASK (0xf)
#define ONENAND_DEVICE_DENSITY_SHIFT (4)
#define ONENAND_DEVICE_IS_DDP (1 << 3)
#define ONENAND_DEVICE_IS_DEMUX (1 << 2)
#define ONENAND_DEVICE_VCC_MASK (0x3)
#define ONENAND_DEVICE_DENSITY_512Mb (0x002)
+#define ONENAND_DEVICE_DENSITY_1Gb (0x003)
+#define ONENAND_DEVICE_DENSITY_2Gb (0x004)
+#define ONENAND_DEVICE_DENSITY_4Gb (0x005)
/*
* Version ID Register F002h (R)
@@ -110,6 +114,8 @@
#define ONENAND_CMD_READOOB (0x13)
#define ONENAND_CMD_PROG (0x80)
#define ONENAND_CMD_PROGOOB (0x1A)
+#define ONENAND_CMD_2X_PROG (0x7D)
+#define ONENAND_CMD_2X_CACHE_PROG (0x7F)
#define ONENAND_CMD_UNLOCK (0x23)
#define ONENAND_CMD_LOCK (0x2A)
#define ONENAND_CMD_LOCK_TIGHT (0x2C)
diff --git a/include/mpc83xx.h b/include/mpc83xx.h
index ccf1077..a2c0ed9 100644
--- a/include/mpc83xx.h
+++ b/include/mpc83xx.h
@@ -1147,91 +1147,6 @@
*/
#define PMCCR1_POWER_OFF 0x00000020
-/* FMR - Flash Mode Register
- */
-#define FMR_CWTO 0x0000F000
-#define FMR_CWTO_SHIFT 12
-#define FMR_BOOT 0x00000800
-#define FMR_ECCM 0x00000100
-#define FMR_AL 0x00000030
-#define FMR_AL_SHIFT 4
-#define FMR_OP 0x00000003
-#define FMR_OP_SHIFT 0
-
-/* FIR - Flash Instruction Register
- */
-#define FIR_OP0 0xF0000000
-#define FIR_OP0_SHIFT 28
-#define FIR_OP1 0x0F000000
-#define FIR_OP1_SHIFT 24
-#define FIR_OP2 0x00F00000
-#define FIR_OP2_SHIFT 20
-#define FIR_OP3 0x000F0000
-#define FIR_OP3_SHIFT 16
-#define FIR_OP4 0x0000F000
-#define FIR_OP4_SHIFT 12
-#define FIR_OP5 0x00000F00
-#define FIR_OP5_SHIFT 8
-#define FIR_OP6 0x000000F0
-#define FIR_OP6_SHIFT 4
-#define FIR_OP7 0x0000000F
-#define FIR_OP7_SHIFT 0
-#define FIR_OP_NOP 0x0 /* No operation and end of sequence */
-#define FIR_OP_CA 0x1 /* Issue current column address */
-#define FIR_OP_PA 0x2 /* Issue current block+page address */
-#define FIR_OP_UA 0x3 /* Issue user defined address */
-#define FIR_OP_CM0 0x4 /* Issue command from FCR[CMD0] */
-#define FIR_OP_CM1 0x5 /* Issue command from FCR[CMD1] */
-#define FIR_OP_CM2 0x6 /* Issue command from FCR[CMD2] */
-#define FIR_OP_CM3 0x7 /* Issue command from FCR[CMD3] */
-#define FIR_OP_WB 0x8 /* Write FBCR bytes from FCM buffer */
-#define FIR_OP_WS 0x9 /* Write 1 or 2 bytes from MDR[AS] */
-#define FIR_OP_RB 0xA /* Read FBCR bytes to FCM buffer */
-#define FIR_OP_RS 0xB /* Read 1 or 2 bytes to MDR[AS] */
-#define FIR_OP_CW0 0xC /* Wait then issue FCR[CMD0] */
-#define FIR_OP_CW1 0xD /* Wait then issue FCR[CMD1] */
-#define FIR_OP_RBW 0xE /* Wait then read FBCR bytes */
-#define FIR_OP_RSW 0xF /* Wait then read 1 or 2 bytes */
-
-/* FCR - Flash Command Register
- */
-#define FCR_CMD0 0xFF000000
-#define FCR_CMD0_SHIFT 24
-#define FCR_CMD1 0x00FF0000
-#define FCR_CMD1_SHIFT 16
-#define FCR_CMD2 0x0000FF00
-#define FCR_CMD2_SHIFT 8
-#define FCR_CMD3 0x000000FF
-#define FCR_CMD3_SHIFT 0
-
-/* FBAR - Flash Block Address Register
- */
-#define FBAR_BLK 0x00FFFFFF
-
-/* FPAR - Flash Page Address Register
- */
-#define FPAR_SP_PI 0x00007C00
-#define FPAR_SP_PI_SHIFT 10
-#define FPAR_SP_MS 0x00000200
-#define FPAR_SP_CI 0x000001FF
-#define FPAR_SP_CI_SHIFT 0
-#define FPAR_LP_PI 0x0003F000
-#define FPAR_LP_PI_SHIFT 12
-#define FPAR_LP_MS 0x00000800
-#define FPAR_LP_CI 0x000007FF
-#define FPAR_LP_CI_SHIFT 0
-
-/* LTESR - Transfer Error Status Register
- */
-#define LTESR_BM 0x80000000
-#define LTESR_FCT 0x40000000
-#define LTESR_PAR 0x20000000
-#define LTESR_WP 0x04000000
-#define LTESR_ATMW 0x00800000
-#define LTESR_ATMR 0x00400000
-#define LTESR_CS 0x00080000
-#define LTESR_CC 0x00000001
-
/* DDRCDR - DDR Control Driver Register
*/
#define DDRCDR_DHC_EN 0x80000000
diff --git a/nand_spl/nand_boot_fsl_elbc.c b/nand_spl/nand_boot_fsl_elbc.c
index 273478f..4a961ea 100644
--- a/nand_spl/nand_boot_fsl_elbc.c
+++ b/nand_spl/nand_boot_fsl_elbc.c
@@ -33,7 +33,7 @@
static void nand_wait(void)
{
- lbus83xx_t *regs = (lbus83xx_t *)(CONFIG_SYS_IMMR + 0x5000);
+ fsl_lbus_t *regs = (fsl_lbus_t *)(CONFIG_SYS_IMMR + 0x5000);
for (;;) {
uint32_t status = in_be32(&regs->ltesr);
@@ -50,7 +50,7 @@ static void nand_wait(void)
static void nand_load(unsigned int offs, int uboot_size, uchar *dst)
{
- lbus83xx_t *regs = (lbus83xx_t *)(CONFIG_SYS_IMMR + 0x5000);
+ fsl_lbus_t *regs = (fsl_lbus_t *)(CONFIG_SYS_IMMR + 0x5000);
uchar *buf = (uchar *)CONFIG_SYS_NAND_BASE;
int large = in_be32(&regs->bank[0].or) & OR_FCM_PGS;
int block_shift = large ? 17 : 14;