summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTom Rini <trini@konsulko.com>2016-06-04 08:49:47 -0400
committerTom Rini <trini@konsulko.com>2016-06-04 08:49:47 -0400
commit715b3a9b2486e8d7a32365d817c77209b35ee796 (patch)
tree5daa126a15d2e0d60156664d19adbf451324d098
parentc41c649c2fdec7bf6ef84173597cc3feabdb7828 (diff)
parent667067faa18334f1e28c01b47530b5cce1b6182f (diff)
downloadblackbird-obmc-uboot-715b3a9b2486e8d7a32365d817c77209b35ee796.tar.gz
blackbird-obmc-uboot-715b3a9b2486e8d7a32365d817c77209b35ee796.zip
Merge git://git.denx.de/u-boot-nand-flash
-rw-r--r--board/BuR/common/common.c2
-rw-r--r--board/atmel/at91sam9261ek/at91sam9261ek.c2
-rw-r--r--board/atmel/at91sam9263ek/at91sam9263ek.c2
-rw-r--r--board/atmel/at91sam9m10g45ek/at91sam9m10g45ek.c2
-rw-r--r--board/atmel/at91sam9n12ek/at91sam9n12ek.c2
-rw-r--r--board/atmel/at91sam9rlek/at91sam9rlek.c2
-rw-r--r--board/atmel/at91sam9x5ek/at91sam9x5ek.c2
-rw-r--r--board/atmel/sama5d3xek/sama5d3xek.c2
-rw-r--r--board/atmel/sama5d4_xplained/sama5d4_xplained.c2
-rw-r--r--board/atmel/sama5d4ek/sama5d4ek.c2
-rw-r--r--board/esd/common/esd405ep_nand.c2
-rw-r--r--board/freescale/m5329evb/nand.c2
-rw-r--r--board/freescale/m5373evb/nand.c2
-rw-r--r--board/ronetix/pm9261/pm9261.c2
-rw-r--r--board/ronetix/pm9263/pm9263.c2
-rw-r--r--board/socrates/nand.c6
-rw-r--r--board/xes/common/actl_nand.c2
-rw-r--r--cmd/bootm.c30
-rw-r--r--cmd/jffs2.c8
-rw-r--r--cmd/nand.c189
-rw-r--r--common/env_nand.c24
-rw-r--r--common/fb_nand.c32
-rw-r--r--common/splash_source.c4
-rw-r--r--doc/README.nand15
-rw-r--r--drivers/dfu/dfu_nand.c24
-rw-r--r--drivers/mtd/nand/Makefile3
-rw-r--r--drivers/mtd/nand/am335x_spl_bch.c54
-rw-r--r--drivers/mtd/nand/arasan_nfc.c42
-rw-r--r--drivers/mtd/nand/atmel_nand.c126
-rw-r--r--drivers/mtd/nand/davinci_nand.c25
-rw-r--r--drivers/mtd/nand/denali.c37
-rw-r--r--drivers/mtd/nand/denali.h1
-rw-r--r--drivers/mtd/nand/denali_spl.c2
-rw-r--r--drivers/mtd/nand/docg4.c1030
-rw-r--r--drivers/mtd/nand/docg4_spl.c219
-rw-r--r--drivers/mtd/nand/fsl_elbc_nand.c41
-rw-r--r--drivers/mtd/nand/fsl_ifc_nand.c48
-rw-r--r--drivers/mtd/nand/fsl_upm.c22
-rw-r--r--drivers/mtd/nand/fsmc_nand.c15
-rw-r--r--drivers/mtd/nand/jz4740_nand.c258
-rw-r--r--drivers/mtd/nand/kb9202_nand.c2
-rw-r--r--drivers/mtd/nand/kirkwood_nand.c2
-rw-r--r--drivers/mtd/nand/lpc32xx_nand_mlc.c14
-rw-r--r--drivers/mtd/nand/lpc32xx_nand_slc.c5
-rw-r--r--drivers/mtd/nand/mpc5121_nfc.c31
-rw-r--r--drivers/mtd/nand/mxc_nand.c62
-rw-r--r--drivers/mtd/nand/mxc_nand_spl.c2
-rw-r--r--drivers/mtd/nand/mxs_nand.c50
-rw-r--r--drivers/mtd/nand/mxs_nand_spl.c40
-rw-r--r--drivers/mtd/nand/nand.c28
-rw-r--r--drivers/mtd/nand/nand_base.c420
-rw-r--r--drivers/mtd/nand/nand_bbt.c62
-rw-r--r--drivers/mtd/nand/nand_bch.c33
-rw-r--r--drivers/mtd/nand/nand_ids.c10
-rw-r--r--drivers/mtd/nand/nand_plat.c4
-rw-r--r--drivers/mtd/nand/nand_spl_simple.c84
-rw-r--r--drivers/mtd/nand/nand_util.c176
-rw-r--r--drivers/mtd/nand/ndfc.c16
-rw-r--r--drivers/mtd/nand/omap_gpmc.c46
-rw-r--r--drivers/mtd/nand/pxa3xx_nand.c45
-rw-r--r--drivers/mtd/nand/s3c2410_nand.c6
-rw-r--r--drivers/mtd/nand/tegra_nand.c48
-rw-r--r--drivers/mtd/nand/vf610_nfc.c14
-rw-r--r--drivers/net/fm/fm.c2
-rw-r--r--drivers/net/phy/cortina.c4
-rw-r--r--fs/jffs2/jffs2_1pass.c2
-rw-r--r--fs/jffs2/jffs2_nand_1pass.c24
-rw-r--r--fs/yaffs2/yaffs_uboot_glue.c10
-rw-r--r--include/linux/mtd/docg4.h132
-rw-r--r--include/linux/mtd/mtd.h5
-rw-r--r--include/linux/mtd/nand.h92
-rw-r--r--include/linux/mtd/nand_bch.h10
-rw-r--r--include/nand.h43
-rw-r--r--tools/palmtreo680/flash_u-boot.c177
74 files changed, 1172 insertions, 2816 deletions
diff --git a/board/BuR/common/common.c b/board/BuR/common/common.c
index ce4acc13e0..e947e54c39 100644
--- a/board/BuR/common/common.c
+++ b/board/BuR/common/common.c
@@ -259,7 +259,7 @@ static int load_devicetree(void)
}
#ifdef CONFIG_NAND
dtbsize = 0x20000;
- rc = nand_read_skip_bad(&nand_info[0], 0x40000, (size_t *)&dtbsize,
+ rc = nand_read_skip_bad(nand_info[0], 0x40000, (size_t *)&dtbsize,
NULL, 0x20000, (u_char *)dtbaddr);
#else
char *dtbname = getenv("dtb");
diff --git a/board/atmel/at91sam9261ek/at91sam9261ek.c b/board/atmel/at91sam9261ek/at91sam9261ek.c
index 7b7cd2c426..6398bcbc9e 100644
--- a/board/atmel/at91sam9261ek/at91sam9261ek.c
+++ b/board/atmel/at91sam9261ek/at91sam9261ek.c
@@ -212,7 +212,7 @@ void lcd_show_board_info(void)
dram_size += gd->bd->bi_dram[i].size;
nand_size = 0;
for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++)
- nand_size += nand_info[i].size;
+ nand_size += nand_info[i]->size;
lcd_printf (" %ld MB SDRAM, %ld MB NAND\n",
dram_size >> 20,
nand_size >> 20 );
diff --git a/board/atmel/at91sam9263ek/at91sam9263ek.c b/board/atmel/at91sam9263ek/at91sam9263ek.c
index af68e10390..04e5812db3 100644
--- a/board/atmel/at91sam9263ek/at91sam9263ek.c
+++ b/board/atmel/at91sam9263ek/at91sam9263ek.c
@@ -191,7 +191,7 @@ void lcd_show_board_info(void)
dram_size += gd->bd->bi_dram[i].size;
nand_size = 0;
for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++)
- nand_size += nand_info[i].size;
+ nand_size += nand_info[i]->size;
#ifndef CONFIG_SYS_NO_FLASH
flash_size = 0;
for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; i++)
diff --git a/board/atmel/at91sam9m10g45ek/at91sam9m10g45ek.c b/board/atmel/at91sam9m10g45ek/at91sam9m10g45ek.c
index 4c6431266f..6871916865 100644
--- a/board/atmel/at91sam9m10g45ek/at91sam9m10g45ek.c
+++ b/board/atmel/at91sam9m10g45ek/at91sam9m10g45ek.c
@@ -272,7 +272,7 @@ void lcd_show_board_info(void)
dram_size += gd->bd->bi_dram[i].size;
nand_size = 0;
for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++)
- nand_size += nand_info[i].size;
+ nand_size += nand_info[i]->size;
lcd_printf (" %ld MB SDRAM, %ld MB NAND\n",
dram_size >> 20,
nand_size >> 20 );
diff --git a/board/atmel/at91sam9n12ek/at91sam9n12ek.c b/board/atmel/at91sam9n12ek/at91sam9n12ek.c
index d3555bbdf6..fc4f50d219 100644
--- a/board/atmel/at91sam9n12ek/at91sam9n12ek.c
+++ b/board/atmel/at91sam9n12ek/at91sam9n12ek.c
@@ -124,7 +124,7 @@ void lcd_show_board_info(void)
dram_size += gd->bd->bi_dram[i].size;
nand_size = 0;
for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++)
- nand_size += nand_info[i].size;
+ nand_size += nand_info[i]->size;
lcd_printf(" %ld MB SDRAM, %ld MB NAND\n",
dram_size >> 20,
nand_size >> 20);
diff --git a/board/atmel/at91sam9rlek/at91sam9rlek.c b/board/atmel/at91sam9rlek/at91sam9rlek.c
index 9ef2864bb1..994f246078 100644
--- a/board/atmel/at91sam9rlek/at91sam9rlek.c
+++ b/board/atmel/at91sam9rlek/at91sam9rlek.c
@@ -151,7 +151,7 @@ void lcd_show_board_info(void)
dram_size += gd->bd->bi_dram[i].size;
nand_size = 0;
for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++)
- nand_size += nand_info[i].size;
+ nand_size += nand_info[i]->size;
lcd_printf (" %ld MB SDRAM, %ld MB NAND\n",
dram_size >> 20,
nand_size >> 20 );
diff --git a/board/atmel/at91sam9x5ek/at91sam9x5ek.c b/board/atmel/at91sam9x5ek/at91sam9x5ek.c
index c14df303b2..b0d440d728 100644
--- a/board/atmel/at91sam9x5ek/at91sam9x5ek.c
+++ b/board/atmel/at91sam9x5ek/at91sam9x5ek.c
@@ -196,7 +196,7 @@ void lcd_show_board_info(void)
dram_size += gd->bd->bi_dram[i].size;
nand_size = 0;
for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++)
- nand_size += nand_info[i].size;
+ nand_size += nand_info[i]->size;
lcd_printf(" %ld MB SDRAM, %ld MB NAND\n",
dram_size >> 20,
nand_size >> 20);
diff --git a/board/atmel/sama5d3xek/sama5d3xek.c b/board/atmel/sama5d3xek/sama5d3xek.c
index e8ee612036..fa90270b86 100644
--- a/board/atmel/sama5d3xek/sama5d3xek.c
+++ b/board/atmel/sama5d3xek/sama5d3xek.c
@@ -207,7 +207,7 @@ void lcd_show_board_info(void)
nand_size = 0;
#ifdef CONFIG_NAND_ATMEL
for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++)
- nand_size += nand_info[i].size;
+ nand_size += nand_info[i]->size;
#endif
lcd_printf("%ld MB SDRAM, %lld MB NAND\n",
dram_size >> 20, nand_size >> 20);
diff --git a/board/atmel/sama5d4_xplained/sama5d4_xplained.c b/board/atmel/sama5d4_xplained/sama5d4_xplained.c
index f4eef9609f..23ec274468 100644
--- a/board/atmel/sama5d4_xplained/sama5d4_xplained.c
+++ b/board/atmel/sama5d4_xplained/sama5d4_xplained.c
@@ -191,7 +191,7 @@ void lcd_show_board_info(void)
nand_size = 0;
#ifdef CONFIG_NAND_ATMEL
for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++)
- nand_size += nand_info[i].size;
+ nand_size += nand_info[i]->size;
#endif
lcd_printf("%ld MB SDRAM, %ld MB NAND\n",
dram_size >> 20, nand_size >> 20);
diff --git a/board/atmel/sama5d4ek/sama5d4ek.c b/board/atmel/sama5d4ek/sama5d4ek.c
index aee621789e..72bad23087 100644
--- a/board/atmel/sama5d4ek/sama5d4ek.c
+++ b/board/atmel/sama5d4ek/sama5d4ek.c
@@ -187,7 +187,7 @@ void lcd_show_board_info(void)
nand_size = 0;
#ifdef CONFIG_NAND_ATMEL
for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++)
- nand_size += nand_info[i].size;
+ nand_size += nand_info[i]->size;
#endif
lcd_printf("%ld MB SDRAM, %ld MB NAND\n",
dram_size >> 20, nand_size >> 20);
diff --git a/board/esd/common/esd405ep_nand.c b/board/esd/common/esd405ep_nand.c
index f46936ca36..51ac10c8c0 100644
--- a/board/esd/common/esd405ep_nand.c
+++ b/board/esd/common/esd405ep_nand.c
@@ -16,7 +16,7 @@
*/
static void esd405ep_nand_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
{
- struct nand_chip *this = mtd->priv;
+ struct nand_chip *this = mtd_to_nand(mtd);
if (ctrl & NAND_CTRL_CHANGE) {
if ( ctrl & NAND_CLE )
out_be32((void *)GPIO0_OR, in_be32((void *)GPIO0_OR) | CONFIG_SYS_NAND_CLE);
diff --git a/board/freescale/m5329evb/nand.c b/board/freescale/m5329evb/nand.c
index 8d88bc03c0..88496812bf 100644
--- a/board/freescale/m5329evb/nand.c
+++ b/board/freescale/m5329evb/nand.c
@@ -24,7 +24,7 @@ DECLARE_GLOBAL_DATA_PTR;
static void nand_hwcontrol(struct mtd_info *mtdinfo, int cmd, unsigned int ctrl)
{
- struct nand_chip *this = mtdinfo->priv;
+ struct nand_chip *this = mtd_to_nand(mtdinfo);
volatile u16 *nCE = (u16 *) CONFIG_SYS_LATCH_ADDR;
if (ctrl & NAND_CTRL_CHANGE) {
diff --git a/board/freescale/m5373evb/nand.c b/board/freescale/m5373evb/nand.c
index 92cef2a97d..a96a59991f 100644
--- a/board/freescale/m5373evb/nand.c
+++ b/board/freescale/m5373evb/nand.c
@@ -24,7 +24,7 @@ DECLARE_GLOBAL_DATA_PTR;
static void nand_hwcontrol(struct mtd_info *mtdinfo, int cmd, unsigned int ctrl)
{
- struct nand_chip *this = mtdinfo->priv;
+ struct nand_chip *this = mtd_to_nand(mtdinfo);
volatile u16 *nCE = (u16 *) CONFIG_SYS_LATCH_ADDR;
if (ctrl & NAND_CTRL_CHANGE) {
diff --git a/board/ronetix/pm9261/pm9261.c b/board/ronetix/pm9261/pm9261.c
index 3cc01cb687..e2cb94ee13 100644
--- a/board/ronetix/pm9261/pm9261.c
+++ b/board/ronetix/pm9261/pm9261.c
@@ -194,7 +194,7 @@ void lcd_show_board_info(void)
nand_size = 0;
for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++)
- nand_size += nand_info[i].size;
+ nand_size += nand_info[i]->size;
flash_size = 0;
for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; i++)
diff --git a/board/ronetix/pm9263/pm9263.c b/board/ronetix/pm9263/pm9263.c
index 276ff80943..e9f9b67b77 100644
--- a/board/ronetix/pm9263/pm9263.c
+++ b/board/ronetix/pm9263/pm9263.c
@@ -293,7 +293,7 @@ void lcd_show_board_info(void)
nand_size = 0;
for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++)
- nand_size += nand_info[i].size;
+ nand_size += nand_info[i]->size;
flash_size = 0;
for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; i++)
diff --git a/board/socrates/nand.c b/board/socrates/nand.c
index 15e6ea6944..a67d812c81 100644
--- a/board/socrates/nand.c
+++ b/board/socrates/nand.c
@@ -48,7 +48,7 @@ static void sc_nand_write_byte(struct mtd_info *mtd, u_char byte)
static void sc_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
{
int i;
- struct nand_chip *this = mtd->priv;
+ struct nand_chip *this = mtd_to_nand(mtd);
for (i = 0; i < len; i++) {
out_be32(this->IO_ADDR_W,
@@ -88,7 +88,7 @@ static u16 sc_nand_read_word(struct mtd_info *mtd)
static void sc_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
{
int i;
- struct nand_chip *this = mtd->priv;
+ struct nand_chip *this = mtd_to_nand(mtd);
int val;
val = (state & FPGA_NAND_ENABLE) | FPGA_NAND_CMD_READ;
@@ -105,7 +105,7 @@ static void sc_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
*/
static int sc_nand_device_ready(struct mtd_info *mtdinfo)
{
- struct nand_chip *this = mtdinfo->priv;
+ struct nand_chip *this = mtd_to_nand(mtdinfo);
if (in_be32(this->IO_ADDR_W) & FPGA_NAND_BUSY)
return 0; /* busy */
diff --git a/board/xes/common/actl_nand.c b/board/xes/common/actl_nand.c
index bf896fe0ce..d1f3668bcb 100644
--- a/board/xes/common/actl_nand.c
+++ b/board/xes/common/actl_nand.c
@@ -16,7 +16,7 @@
*/
static void nand_addr_hwcontrol(struct mtd_info *mtd, int cmd, uint ctrl)
{
- struct nand_chip *this = mtd->priv;
+ struct nand_chip *this = mtd_to_nand(mtd);
ulong IO_ADDR_W;
if (ctrl & NAND_CTRL_CHANGE) {
diff --git a/cmd/bootm.c b/cmd/bootm.c
index ee3b460adb..f5e91f40a9 100644
--- a/cmd/bootm.c
+++ b/cmd/bootm.c
@@ -372,8 +372,8 @@ next_bank: ;
#endif
#if defined(CONFIG_CMD_IMLS_NAND)
-static int nand_imls_legacyimage(nand_info_t *nand, int nand_dev, loff_t off,
- size_t len)
+static int nand_imls_legacyimage(struct mtd_info *mtd, int nand_dev,
+ loff_t off, size_t len)
{
void *imgdata;
int ret;
@@ -386,8 +386,7 @@ static int nand_imls_legacyimage(nand_info_t *nand, int nand_dev, loff_t off,
return -ENOMEM;
}
- ret = nand_read_skip_bad(nand, off, &len,
- imgdata);
+ ret = nand_read_skip_bad(mtd, off, &len, imgdata);
if (ret < 0 && ret != -EUCLEAN) {
free(imgdata);
return ret;
@@ -413,8 +412,8 @@ static int nand_imls_legacyimage(nand_info_t *nand, int nand_dev, loff_t off,
return 0;
}
-static int nand_imls_fitimage(nand_info_t *nand, int nand_dev, loff_t off,
- size_t len)
+static int nand_imls_fitimage(struct mtd_info *mtd, int nand_dev, loff_t off,
+ size_t len)
{
void *imgdata;
int ret;
@@ -427,8 +426,7 @@ static int nand_imls_fitimage(nand_info_t *nand, int nand_dev, loff_t off,
return -ENOMEM;
}
- ret = nand_read_skip_bad(nand, off, &len,
- imgdata);
+ ret = nand_read_skip_bad(mtd, off, &len, imgdata);
if (ret < 0 && ret != -EUCLEAN) {
free(imgdata);
return ret;
@@ -449,7 +447,7 @@ static int nand_imls_fitimage(nand_info_t *nand, int nand_dev, loff_t off,
static int do_imls_nand(void)
{
- nand_info_t *nand;
+ struct mtd_info *mtd;
int nand_dev = nand_curr_device;
size_t len;
loff_t off;
@@ -463,20 +461,20 @@ static int do_imls_nand(void)
printf("\n");
for (nand_dev = 0; nand_dev < CONFIG_SYS_MAX_NAND_DEVICE; nand_dev++) {
- nand = &nand_info[nand_dev];
- if (!nand->name || !nand->size)
+ mtd = nand_info[nand_dev];
+ if (!mtd->name || !mtd->size)
continue;
- for (off = 0; off < nand->size; off += nand->erasesize) {
+ for (off = 0; off < mtd->size; off += mtd->erasesize) {
const image_header_t *header;
int ret;
- if (nand_block_isbad(nand, off))
+ if (nand_block_isbad(mtd, off))
continue;
len = sizeof(buffer);
- ret = nand_read(nand, off, &len, (u8 *)buffer);
+ ret = nand_read(mtd, off, &len, (u8 *)buffer);
if (ret < 0 && ret != -EUCLEAN) {
printf("NAND read error %d at offset %08llX\n",
ret, off);
@@ -489,13 +487,13 @@ static int do_imls_nand(void)
header = (const image_header_t *)buffer;
len = image_get_image_size(header);
- nand_imls_legacyimage(nand, nand_dev, off, len);
+ nand_imls_legacyimage(mtd, nand_dev, off, len);
break;
#endif
#if defined(CONFIG_FIT)
case IMAGE_FORMAT_FIT:
len = fit_get_size(buffer);
- nand_imls_fitimage(nand, nand_dev, off, len);
+ nand_imls_fitimage(mtd, nand_dev, off, len);
break;
#endif
}
diff --git a/cmd/jffs2.c b/cmd/jffs2.c
index 0b2eefa195..f00d53a6c8 100644
--- a/cmd/jffs2.c
+++ b/cmd/jffs2.c
@@ -167,7 +167,7 @@ static int mtd_device_validate(u8 type, u8 num, u32 *size)
} else if (type == MTD_DEV_TYPE_NAND) {
#if defined(CONFIG_JFFS2_NAND) && defined(CONFIG_CMD_NAND)
if (num < CONFIG_SYS_MAX_NAND_DEVICE) {
- *size = nand_info[num].size;
+ *size = nand_info[num]->size;
return 0;
}
@@ -242,11 +242,11 @@ static int mtd_id_parse(const char *id, const char **ret_id, u8 *dev_type, u8 *d
static inline u32 get_part_sector_size_nand(struct mtdids *id)
{
#if defined(CONFIG_JFFS2_NAND) && defined(CONFIG_CMD_NAND)
- nand_info_t *nand;
+ struct mtd_info *mtd;
- nand = &nand_info[id->num];
+ mtd = nand_info[id->num];
- return nand->erasesize;
+ return mtd->erasesize;
#else
BUG();
return 0;
diff --git a/cmd/nand.c b/cmd/nand.c
index a6b67e29f1..583a18f341 100644
--- a/cmd/nand.c
+++ b/cmd/nand.c
@@ -38,7 +38,8 @@ int find_dev_and_part(const char *id, struct mtd_device **dev,
u8 *part_num, struct part_info **part);
#endif
-static int nand_dump(nand_info_t *nand, ulong off, int only_oob, int repeat)
+static int nand_dump(struct mtd_info *mtd, ulong off, int only_oob,
+ int repeat)
{
int i;
u_char *datbuf, *oobbuf, *p;
@@ -46,32 +47,32 @@ static int nand_dump(nand_info_t *nand, ulong off, int only_oob, int repeat)
int ret = 0;
if (repeat)
- off = last + nand->writesize;
+ off = last + mtd->writesize;
last = off;
- datbuf = memalign(ARCH_DMA_MINALIGN, nand->writesize);
+ datbuf = memalign(ARCH_DMA_MINALIGN, mtd->writesize);
if (!datbuf) {
puts("No memory for page buffer\n");
return 1;
}
- oobbuf = memalign(ARCH_DMA_MINALIGN, nand->oobsize);
+ oobbuf = memalign(ARCH_DMA_MINALIGN, mtd->oobsize);
if (!oobbuf) {
puts("No memory for page buffer\n");
ret = 1;
goto free_dat;
}
- off &= ~(nand->writesize - 1);
+ off &= ~(mtd->writesize - 1);
loff_t addr = (loff_t) off;
struct mtd_oob_ops ops;
memset(&ops, 0, sizeof(ops));
ops.datbuf = datbuf;
ops.oobbuf = oobbuf;
- ops.len = nand->writesize;
- ops.ooblen = nand->oobsize;
+ ops.len = mtd->writesize;
+ ops.ooblen = mtd->oobsize;
ops.mode = MTD_OPS_RAW;
- i = mtd_read_oob(nand, addr, &ops);
+ i = mtd_read_oob(mtd, addr, &ops);
if (i < 0) {
printf("Error (%d) reading page %08lx\n", i, off);
ret = 1;
@@ -80,7 +81,7 @@ static int nand_dump(nand_info_t *nand, ulong off, int only_oob, int repeat)
printf("Page %08lx dump:\n", off);
if (!only_oob) {
- i = nand->writesize >> 4;
+ i = mtd->writesize >> 4;
p = datbuf;
while (i--) {
@@ -94,7 +95,7 @@ static int nand_dump(nand_info_t *nand, ulong off, int only_oob, int repeat)
}
puts("OOB:\n");
- i = nand->oobsize >> 3;
+ i = mtd->oobsize >> 3;
p = oobbuf;
while (i--) {
printf("\t%02x %02x %02x %02x %02x %02x %02x %02x\n",
@@ -115,7 +116,7 @@ free_dat:
static int set_dev(int dev)
{
if (dev < 0 || dev >= CONFIG_SYS_MAX_NAND_DEVICE ||
- !nand_info[dev].name) {
+ !nand_info[dev]->name) {
puts("No such device\n");
return -1;
}
@@ -123,12 +124,12 @@ static int set_dev(int dev)
if (nand_curr_device == dev)
return 0;
- printf("Device %d: %s", dev, nand_info[dev].name);
+ printf("Device %d: %s", dev, nand_info[dev]->name);
puts("... is now current device\n");
nand_curr_device = dev;
#ifdef CONFIG_SYS_NAND_SELECT_DEVICE
- board_nand_select_device(nand_info[dev].priv, dev);
+ board_nand_select_device(nand_info[dev]->priv, dev);
#endif
return 0;
@@ -152,32 +153,32 @@ static void print_status(ulong start, ulong end, ulong erasesize, int status)
((status & NAND_LOCK_STATUS_UNLOCK) ? "UNLOCK " : ""));
}
-static void do_nand_status(nand_info_t *nand)
+static void do_nand_status(struct mtd_info *mtd)
{
ulong block_start = 0;
ulong off;
int last_status = -1;
- struct nand_chip *nand_chip = nand->priv;
+ struct nand_chip *nand_chip = mtd_to_nand(mtd);
/* check the WP bit */
- nand_chip->cmdfunc(nand, NAND_CMD_STATUS, -1, -1);
+ nand_chip->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1);
printf("device is %swrite protected\n",
- (nand_chip->read_byte(nand) & 0x80 ?
- "NOT " : ""));
+ (nand_chip->read_byte(mtd) & 0x80 ?
+ "NOT " : ""));
- for (off = 0; off < nand->size; off += nand->erasesize) {
- int s = nand_get_lock_status(nand, off);
+ for (off = 0; off < mtd->size; off += mtd->erasesize) {
+ int s = nand_get_lock_status(mtd, off);
/* print message only if status has changed */
if (s != last_status && off != 0) {
- print_status(block_start, off, nand->erasesize,
+ print_status(block_start, off, mtd->erasesize,
last_status);
block_start = off;
}
last_status = s;
}
/* Print the last block info */
- print_status(block_start, off, nand->erasesize, last_status);
+ print_status(block_start, off, mtd->erasesize, last_status);
}
#endif
@@ -188,10 +189,10 @@ int do_nand_env_oob(cmd_tbl_t *cmdtp, int argc, char *const argv[])
{
int ret;
uint32_t oob_buf[ENV_OFFSET_SIZE/sizeof(uint32_t)];
- nand_info_t *nand = &nand_info[0];
+ struct mtd_info *mtd = nand_info[0];
char *cmd = argv[1];
- if (CONFIG_SYS_MAX_NAND_DEVICE == 0 || !nand->name) {
+ if (CONFIG_SYS_MAX_NAND_DEVICE == 0 || !mtd->name) {
puts("no devices available\n");
return 1;
}
@@ -199,7 +200,7 @@ int do_nand_env_oob(cmd_tbl_t *cmdtp, int argc, char *const argv[])
set_dev(0);
if (!strcmp(cmd, "get")) {
- ret = get_nand_env_oob(nand, &nand_env_oob_offset);
+ ret = get_nand_env_oob(mtd, &nand_env_oob_offset);
if (ret)
return 1;
@@ -215,7 +216,7 @@ int do_nand_env_oob(cmd_tbl_t *cmdtp, int argc, char *const argv[])
/* We don't care about size, or maxsize. */
if (mtd_arg_off(argv[2], &idx, &addr, &maxsize, &maxsize,
- MTD_DEV_TYPE_NAND, nand_info[idx].size)) {
+ MTD_DEV_TYPE_NAND, nand_info[idx]->size)) {
puts("Offset or partition name expected\n");
return 1;
}
@@ -229,15 +230,15 @@ int do_nand_env_oob(cmd_tbl_t *cmdtp, int argc, char *const argv[])
return 1;
}
- if (nand->oobavail < ENV_OFFSET_SIZE) {
+ if (mtd->oobavail < ENV_OFFSET_SIZE) {
printf("Insufficient available OOB bytes:\n"
"%d OOB bytes available but %d required for "
"env.oob support\n",
- nand->oobavail, ENV_OFFSET_SIZE);
+ mtd->oobavail, ENV_OFFSET_SIZE);
return 1;
}
- if ((addr & (nand->erasesize - 1)) != 0) {
+ if ((addr & (mtd->erasesize - 1)) != 0) {
printf("Environment offset must be block-aligned\n");
return 1;
}
@@ -249,15 +250,15 @@ int do_nand_env_oob(cmd_tbl_t *cmdtp, int argc, char *const argv[])
ops.oobbuf = (void *) oob_buf;
oob_buf[0] = ENV_OOB_MARKER;
- oob_buf[1] = addr / nand->erasesize;
+ oob_buf[1] = addr / mtd->erasesize;
- ret = nand->write_oob(nand, ENV_OFFSET_SIZE, &ops);
+ ret = mtd->write_oob(mtd, ENV_OFFSET_SIZE, &ops);
if (ret) {
printf("Error writing OOB block 0\n");
return ret;
}
- ret = get_nand_env_oob(nand, &nand_env_oob_offset);
+ ret = get_nand_env_oob(mtd, &nand_env_oob_offset);
if (ret) {
printf("Error reading env offset in OOB\n");
return ret;
@@ -283,29 +284,29 @@ usage:
static void nand_print_and_set_info(int idx)
{
- nand_info_t *nand = &nand_info[idx];
- struct nand_chip *chip = nand->priv;
+ struct mtd_info *mtd = nand_info[idx];
+ struct nand_chip *chip = mtd_to_nand(mtd);
printf("Device %d: ", idx);
if (chip->numchips > 1)
printf("%dx ", chip->numchips);
printf("%s, sector size %u KiB\n",
- nand->name, nand->erasesize >> 10);
- printf(" Page size %8d b\n", nand->writesize);
- printf(" OOB size %8d b\n", nand->oobsize);
- printf(" Erase size %8d b\n", nand->erasesize);
+ mtd->name, mtd->erasesize >> 10);
+ printf(" Page size %8d b\n", mtd->writesize);
+ printf(" OOB size %8d b\n", mtd->oobsize);
+ printf(" Erase size %8d b\n", mtd->erasesize);
printf(" subpagesize %8d b\n", chip->subpagesize);
printf(" options 0x%8x\n", chip->options);
printf(" bbt options 0x%8x\n", chip->bbt_options);
/* Set geometry info */
- setenv_hex("nand_writesize", nand->writesize);
- setenv_hex("nand_oobsize", nand->oobsize);
- setenv_hex("nand_erasesize", nand->erasesize);
+ setenv_hex("nand_writesize", mtd->writesize);
+ setenv_hex("nand_oobsize", mtd->oobsize);
+ setenv_hex("nand_erasesize", mtd->erasesize);
}
-static int raw_access(nand_info_t *nand, ulong addr, loff_t off, ulong count,
- int read)
+static int raw_access(struct mtd_info *mtd, ulong addr, loff_t off,
+ ulong count, int read)
{
int ret = 0;
@@ -313,18 +314,18 @@ static int raw_access(nand_info_t *nand, ulong addr, loff_t off, ulong count,
/* Raw access */
mtd_oob_ops_t ops = {
.datbuf = (u8 *)addr,
- .oobbuf = ((u8 *)addr) + nand->writesize,
- .len = nand->writesize,
- .ooblen = nand->oobsize,
+ .oobbuf = ((u8 *)addr) + mtd->writesize,
+ .len = mtd->writesize,
+ .ooblen = mtd->oobsize,
.mode = MTD_OPS_RAW
};
if (read) {
- ret = mtd_read_oob(nand, off, &ops);
+ ret = mtd_read_oob(mtd, off, &ops);
} else {
- ret = mtd_write_oob(nand, off, &ops);
+ ret = mtd_write_oob(mtd, off, &ops);
if (!ret)
- ret = nand_verify_page_oob(nand, &ops, off);
+ ret = nand_verify_page_oob(mtd, &ops, off);
}
if (ret) {
@@ -333,8 +334,8 @@ static int raw_access(nand_info_t *nand, ulong addr, loff_t off, ulong count,
break;
}
- addr += nand->writesize + nand->oobsize;
- off += nand->writesize;
+ addr += mtd->writesize + mtd->oobsize;
+ off += mtd->writesize;
}
return ret;
@@ -348,18 +349,18 @@ static void adjust_size_for_badblocks(loff_t *size, loff_t offset, int dev)
/* We grab the nand info object here fresh because this is usually
* called after arg_off_size() which can change the value of dev.
*/
- nand_info_t *nand = &nand_info[dev];
+ struct mtd_info *mtd = nand_info[dev];
loff_t maxoffset = offset + *size;
int badblocks = 0;
/* count badblocks in NAND from offset to offset + size */
- for (; offset < maxoffset; offset += nand->erasesize) {
- if (nand_block_isbad(nand, offset))
+ for (; offset < maxoffset; offset += mtd->erasesize) {
+ if (nand_block_isbad(mtd, offset))
badblocks++;
}
/* adjust size if any bad blocks found */
if (badblocks) {
- *size -= badblocks * nand->erasesize;
+ *size -= badblocks * mtd->erasesize;
printf("size adjusted to 0x%llx (%d bad blocks)\n",
(unsigned long long)*size, badblocks);
}
@@ -371,7 +372,7 @@ static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
ulong addr;
loff_t off, size, maxsize;
char *cmd, *s;
- nand_info_t *nand;
+ struct mtd_info *mtd;
#ifdef CONFIG_SYS_NAND_QUIET
int quiet = CONFIG_SYS_NAND_QUIET;
#else
@@ -398,7 +399,7 @@ static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
putc('\n');
for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++) {
- if (nand_info[i].name)
+ if (nand_info[i]->name)
nand_print_and_set_info(i);
}
return 0;
@@ -433,16 +434,16 @@ static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
* for another device is to be used.
*/
if (dev < 0 || dev >= CONFIG_SYS_MAX_NAND_DEVICE ||
- !nand_info[dev].name) {
+ !nand_info[dev]->name) {
puts("\nno devices available\n");
return 1;
}
- nand = &nand_info[dev];
+ mtd = nand_info[dev];
if (strcmp(cmd, "bad") == 0) {
printf("\nDevice %d bad blocks:\n", dev);
- for (off = 0; off < nand->size; off += nand->erasesize)
- if (nand_block_isbad(nand, off))
+ for (off = 0; off < mtd->size; off += mtd->erasesize)
+ if (nand_block_isbad(mtd, off))
printf(" %08llx\n", (unsigned long long)off);
return 0;
}
@@ -496,13 +497,13 @@ static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
/* skip first two or three arguments, look for offset and size */
if (mtd_arg_off_size(argc - o, argv + o, &dev, &off, &size,
&maxsize, MTD_DEV_TYPE_NAND,
- nand_info[dev].size) != 0)
+ nand_info[dev]->size) != 0)
return 1;
if (set_dev(dev))
return 1;
- nand = &nand_info[dev];
+ mtd = nand_info[dev];
memset(&opts, 0, sizeof(opts));
opts.offset = off;
@@ -524,7 +525,7 @@ static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
}
}
}
- ret = nand_erase_opts(nand, &opts);
+ ret = nand_erase_opts(mtd, &opts);
printf("%s\n", ret ? "ERROR" : "OK");
return ret == 0 ? 0 : 1;
@@ -535,7 +536,7 @@ static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
goto usage;
off = (int)simple_strtoul(argv[2], NULL, 16);
- ret = nand_dump(nand, off, !strcmp(&cmd[4], ".oob"), repeat);
+ ret = nand_dump(mtd, off, !strcmp(&cmd[4], ".oob"), repeat);
return ret == 0 ? 1 : 0;
}
@@ -561,30 +562,30 @@ static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
if (mtd_arg_off(argv[3], &dev, &off, &size, &maxsize,
MTD_DEV_TYPE_NAND,
- nand_info[dev].size))
+ nand_info[dev]->size))
return 1;
if (set_dev(dev))
return 1;
- nand = &nand_info[dev];
+ mtd = nand_info[dev];
if (argc > 4 && !str2long(argv[4], &pagecount)) {
printf("'%s' is not a number\n", argv[4]);
return 1;
}
- if (pagecount * nand->writesize > size) {
+ if (pagecount * mtd->writesize > size) {
puts("Size exceeds partition or device limit\n");
return -1;
}
- rwsize = pagecount * (nand->writesize + nand->oobsize);
+ rwsize = pagecount * (mtd->writesize + mtd->oobsize);
} else {
if (mtd_arg_off_size(argc - 3, argv + 3, &dev, &off,
&size, &maxsize,
MTD_DEV_TYPE_NAND,
- nand_info[dev].size) != 0)
+ nand_info[dev]->size) != 0)
return 1;
if (set_dev(dev))
@@ -596,16 +597,16 @@ static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
rwsize = size;
}
- nand = &nand_info[dev];
+ mtd = nand_info[dev];
if (!s || !strcmp(s, ".jffs2") ||
!strcmp(s, ".e") || !strcmp(s, ".i")) {
if (read)
- ret = nand_read_skip_bad(nand, off, &rwsize,
+ ret = nand_read_skip_bad(mtd, off, &rwsize,
NULL, maxsize,
(u_char *)addr);
else
- ret = nand_write_skip_bad(nand, off, &rwsize,
+ ret = nand_write_skip_bad(mtd, off, &rwsize,
NULL, maxsize,
(u_char *)addr,
WITH_WR_VERIFY);
@@ -615,7 +616,7 @@ static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
printf("Unknown nand command suffix '%s'\n", s);
return 1;
}
- ret = nand_write_skip_bad(nand, off, &rwsize, NULL,
+ ret = nand_write_skip_bad(mtd, off, &rwsize, NULL,
maxsize, (u_char *)addr,
WITH_DROP_FFS | WITH_WR_VERIFY);
#endif
@@ -628,11 +629,11 @@ static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
};
if (read)
- ret = mtd_read_oob(nand, off, &ops);
+ ret = mtd_read_oob(mtd, off, &ops);
else
- ret = mtd_write_oob(nand, off, &ops);
+ ret = mtd_write_oob(mtd, off, &ops);
} else if (raw) {
- ret = raw_access(nand, addr, off, pagecount, read);
+ ret = raw_access(mtd, addr, off, pagecount, read);
} else {
printf("Unknown nand command suffix '%s'.\n", s);
return 1;
@@ -655,8 +656,8 @@ static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
}
printf("\nNAND torture: device %d offset 0x%llx size 0x%x\n",
- dev, off, nand->erasesize);
- ret = nand_torture(nand, off);
+ dev, off, mtd->erasesize);
+ ret = nand_torture(mtd, off);
printf(" %s\n", ret ? "Failed" : "Passed");
return ret == 0 ? 0 : 1;
@@ -673,7 +674,7 @@ static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
while (argc > 0) {
addr = simple_strtoul(*argv, NULL, 16);
- if (mtd_block_markbad(nand, addr)) {
+ if (mtd_block_markbad(mtd, addr)) {
printf("block 0x%08lx NOT marked "
"as bad! ERROR %d\n",
addr, ret);
@@ -705,9 +706,9 @@ static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
status = 1;
}
if (status) {
- do_nand_status(nand);
+ do_nand_status(mtd);
} else {
- if (!nand_lock(nand, tight)) {
+ if (!nand_lock(mtd, tight)) {
puts("NAND flash successfully locked\n");
} else {
puts("Error locking NAND flash\n");
@@ -727,13 +728,13 @@ static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
if (mtd_arg_off_size(argc - 2, argv + 2, &dev, &off, &size,
&maxsize, MTD_DEV_TYPE_NAND,
- nand_info[dev].size) < 0)
+ nand_info[dev]->size) < 0)
return 1;
if (set_dev(dev))
return 1;
- if (!nand_unlock(&nand_info[dev], off, size, allexcept)) {
+ if (!nand_unlock(nand_info[dev], off, size, allexcept)) {
puts("NAND flash successfully unlocked\n");
} else {
puts("Error unlocking NAND flash, "
@@ -801,7 +802,7 @@ U_BOOT_CMD(
"NAND sub-system", nand_help_text
);
-static int nand_load_image(cmd_tbl_t *cmdtp, nand_info_t *nand,
+static int nand_load_image(cmd_tbl_t *cmdtp, struct mtd_info *mtd,
ulong offset, ulong addr, char *cmd)
{
int r;
@@ -822,11 +823,11 @@ static int nand_load_image(cmd_tbl_t *cmdtp, nand_info_t *nand,
return 1;
}
- printf("\nLoading from %s, offset 0x%lx\n", nand->name, offset);
+ printf("\nLoading from %s, offset 0x%lx\n", mtd->name, offset);
- cnt = nand->writesize;
- r = nand_read_skip_bad(nand, offset, &cnt, NULL, nand->size,
- (u_char *)addr);
+ cnt = mtd->writesize;
+ r = nand_read_skip_bad(mtd, offset, &cnt, NULL, mtd->size,
+ (u_char *)addr);
if (r) {
puts("** Read error\n");
bootstage_error(BOOTSTAGE_ID_NAND_HDR_READ);
@@ -860,8 +861,8 @@ static int nand_load_image(cmd_tbl_t *cmdtp, nand_info_t *nand,
}
bootstage_mark(BOOTSTAGE_ID_NAND_TYPE);
- r = nand_read_skip_bad(nand, offset, &cnt, NULL, nand->size,
- (u_char *)addr);
+ r = nand_read_skip_bad(mtd, offset, &cnt, NULL, mtd->size,
+ (u_char *)addr);
if (r) {
puts("** Read error\n");
bootstage_error(BOOTSTAGE_ID_NAND_READ);
@@ -914,7 +915,7 @@ static int do_nandboot(cmd_tbl_t *cmdtp, int flag, int argc,
addr = simple_strtoul(argv[1], NULL, 16);
else
addr = CONFIG_SYS_LOAD_ADDR;
- return nand_load_image(cmdtp, &nand_info[dev->id->num],
+ return nand_load_image(cmdtp, nand_info[dev->id->num],
part->offset, addr, argv[0]);
}
}
@@ -957,14 +958,14 @@ usage:
idx = simple_strtoul(boot_device, NULL, 16);
- if (idx < 0 || idx >= CONFIG_SYS_MAX_NAND_DEVICE || !nand_info[idx].name) {
+ if (idx < 0 || idx >= CONFIG_SYS_MAX_NAND_DEVICE || !nand_info[idx]->name) {
printf("\n** Device %d not available\n", idx);
bootstage_error(BOOTSTAGE_ID_NAND_AVAILABLE);
return 1;
}
bootstage_mark(BOOTSTAGE_ID_NAND_AVAILABLE);
- return nand_load_image(cmdtp, &nand_info[idx], offset, addr, argv[0]);
+ return nand_load_image(cmdtp, nand_info[idx], offset, addr, argv[0]);
}
U_BOOT_CMD(nboot, 4, 1, do_nandboot,
diff --git a/common/env_nand.c b/common/env_nand.c
index b32eeac9d7..fc99a5e3fc 100644
--- a/common/env_nand.c
+++ b/common/env_nand.c
@@ -132,15 +132,15 @@ static int writeenv(size_t offset, u_char *buf)
size_t blocksize, len;
u_char *char_ptr;
- blocksize = nand_info[0].erasesize;
+ blocksize = nand_info[0]->erasesize;
len = min(blocksize, (size_t)CONFIG_ENV_SIZE);
while (amount_saved < CONFIG_ENV_SIZE && offset < end) {
- if (nand_block_isbad(&nand_info[0], offset)) {
+ if (nand_block_isbad(nand_info[0], offset)) {
offset += blocksize;
} else {
char_ptr = &buf[amount_saved];
- if (nand_write(&nand_info[0], offset, &len, char_ptr))
+ if (nand_write(nand_info[0], offset, &len, char_ptr))
return 1;
offset += blocksize;
@@ -164,7 +164,7 @@ static int erase_and_write_env(const struct env_location *location,
int ret = 0;
printf("Erasing %s...\n", location->name);
- if (nand_erase_opts(&nand_info[0], &location->erase_opts))
+ if (nand_erase_opts(nand_info[0], &location->erase_opts))
return 1;
printf("Writing to %s... ", location->name);
@@ -247,20 +247,20 @@ static int readenv(size_t offset, u_char *buf)
size_t blocksize, len;
u_char *char_ptr;
- blocksize = nand_info[0].erasesize;
+ blocksize = nand_info[0]->erasesize;
if (!blocksize)
return 1;
len = min(blocksize, (size_t)CONFIG_ENV_SIZE);
while (amount_loaded < CONFIG_ENV_SIZE && offset < end) {
- if (nand_block_isbad(&nand_info[0], offset)) {
+ if (nand_block_isbad(nand_info[0], offset)) {
offset += blocksize;
} else {
char_ptr = &buf[amount_loaded];
- if (nand_read_skip_bad(&nand_info[0], offset,
+ if (nand_read_skip_bad(nand_info[0], offset,
&len, NULL,
- nand_info[0].size, char_ptr))
+ nand_info[0]->size, char_ptr))
return 1;
offset += blocksize;
@@ -276,7 +276,7 @@ static int readenv(size_t offset, u_char *buf)
#endif /* #if defined(CONFIG_SPL_BUILD) */
#ifdef CONFIG_ENV_OFFSET_OOB
-int get_nand_env_oob(nand_info_t *nand, unsigned long *result)
+int get_nand_env_oob(struct mtd_info *mtd, unsigned long *result)
{
struct mtd_oob_ops ops;
uint32_t oob_buf[ENV_OFFSET_SIZE / sizeof(uint32_t)];
@@ -288,14 +288,14 @@ int get_nand_env_oob(nand_info_t *nand, unsigned long *result)
ops.ooblen = ENV_OFFSET_SIZE;
ops.oobbuf = (void *)oob_buf;
- ret = nand->read_oob(nand, ENV_OFFSET_SIZE, &ops);
+ ret = mtd->read_oob(mtd, ENV_OFFSET_SIZE, &ops);
if (ret) {
printf("error reading OOB block 0\n");
return ret;
}
if (oob_buf[0] == ENV_OOB_MARKER) {
- *result = oob_buf[1] * nand->erasesize;
+ *result = oob_buf[1] * mtd->erasesize;
} else if (oob_buf[0] == ENV_OOB_MARKER_OLD) {
*result = oob_buf[1];
} else {
@@ -387,7 +387,7 @@ void env_relocate_spec(void)
ALLOC_CACHE_ALIGN_BUFFER(char, buf, CONFIG_ENV_SIZE);
#if defined(CONFIG_ENV_OFFSET_OOB)
- ret = get_nand_env_oob(&nand_info[0], &nand_env_oob_offset);
+ ret = get_nand_env_oob(nand_info[0], &nand_env_oob_offset);
/*
* If unable to read environment offset from NAND OOB then fall through
* to the normal environment reading code below
diff --git a/common/fb_nand.c b/common/fb_nand.c
index 9ca8602a73..e55ea3872f 100644
--- a/common/fb_nand.c
+++ b/common/fb_nand.c
@@ -19,7 +19,7 @@
static char *response_str;
struct fb_nand_sparse {
- nand_info_t *nand;
+ struct mtd_info *nand;
struct part_info *part;
};
@@ -34,7 +34,7 @@ __weak int board_fastboot_write_partition_setup(char *name)
}
static int fb_nand_lookup(const char *partname, char *response,
- nand_info_t **nand,
+ struct mtd_info **nand,
struct part_info **part)
{
struct mtd_device *dev;
@@ -62,12 +62,12 @@ static int fb_nand_lookup(const char *partname, char *response,
return -EINVAL;
}
- *nand = &nand_info[dev->id->num];
+ *mtd = nand_info[dev->id->num];
return 0;
}
-static int _fb_nand_erase(nand_info_t *nand, struct part_info *part)
+static int _fb_nand_erase(struct mtd_info *mtd, struct part_info *part)
{
nand_erase_options_t opts;
int ret;
@@ -80,7 +80,7 @@ static int _fb_nand_erase(nand_info_t *nand, struct part_info *part)
printf("Erasing blocks 0x%llx to 0x%llx\n",
part->offset, part->offset + part->size);
- ret = nand_erase_opts(nand, &opts);
+ ret = nand_erase_opts(mtd, &opts);
if (ret)
return ret;
@@ -90,7 +90,7 @@ static int _fb_nand_erase(nand_info_t *nand, struct part_info *part)
return 0;
}
-static int _fb_nand_write(nand_info_t *nand, struct part_info *part,
+static int _fb_nand_write(struct mtd_info *mtd, struct part_info *part,
void *buffer, unsigned int offset,
unsigned int length, size_t *written)
{
@@ -100,7 +100,7 @@ static int _fb_nand_write(nand_info_t *nand, struct part_info *part,
flags |= WITH_DROP_FFS;
#endif
- return nand_write_skip_bad(nand, offset, &length, written,
+ return nand_write_skip_bad(mtd, offset, &length, written,
part->size - (offset - part->offset),
buffer, flags);
}
@@ -131,13 +131,13 @@ void fb_nand_flash_write(const char *partname, unsigned int session_id,
char *response)
{
struct part_info *part;
- nand_info_t *nand = NULL;
+ struct mtd_info *mtd = NULL;
int ret;
/* initialize the response buffer */
response_str = response;
- ret = fb_nand_lookup(partname, response, &nand, &part);
+ ret = fb_nand_lookup(partname, response, &mtd, &part);
if (ret) {
error("invalid NAND device");
fastboot_fail(response_str, "invalid NAND device");
@@ -152,10 +152,10 @@ void fb_nand_flash_write(const char *partname, unsigned int session_id,
struct fb_nand_sparse sparse_priv;
sparse_storage_t sparse;
- sparse_priv.nand = nand;
+ sparse_priv.nand = mtd;
sparse_priv.part = part;
- sparse.block_sz = nand->writesize;
+ sparse.block_sz = mtd->writesize;
sparse.start = part->offset / sparse.block_sz;
sparse.size = part->size / sparse.block_sz;
sparse.name = part->name;
@@ -167,7 +167,7 @@ void fb_nand_flash_write(const char *partname, unsigned int session_id,
printf("Flashing raw image at offset 0x%llx\n",
part->offset);
- ret = _fb_nand_write(nand, part, download_buffer, part->offset,
+ ret = _fb_nand_write(mtd, part, download_buffer, part->offset,
download_bytes, NULL);
printf("........ wrote %u bytes to '%s'\n",
@@ -185,13 +185,13 @@ void fb_nand_flash_write(const char *partname, unsigned int session_id,
void fb_nand_erase(const char *partname, char *response)
{
struct part_info *part;
- nand_info_t *nand = NULL;
+ struct mtd_info *mtd = NULL;
int ret;
/* initialize the response buffer */
response_str = response;
- ret = fb_nand_lookup(partname, response, &nand, &part);
+ ret = fb_nand_lookup(partname, response, &mtd, &part);
if (ret) {
error("invalid NAND device");
fastboot_fail(response_str, "invalid NAND device");
@@ -202,9 +202,9 @@ void fb_nand_erase(const char *partname, char *response)
if (ret)
return;
- ret = _fb_nand_erase(nand, part);
+ ret = _fb_nand_erase(mtd, part);
if (ret) {
- error("failed erasing from device %s", nand->name);
+ error("failed erasing from device %s", mtd->name);
fastboot_fail(response_str, "failed erasing from device");
return;
}
diff --git a/common/splash_source.c b/common/splash_source.c
index a09dd4b46e..f86a78a436 100644
--- a/common/splash_source.c
+++ b/common/splash_source.c
@@ -45,9 +45,9 @@ static int splash_sf_read_raw(u32 bmp_load_addr, int offset, size_t read_size)
#ifdef CONFIG_CMD_NAND
static int splash_nand_read_raw(u32 bmp_load_addr, int offset, size_t read_size)
{
- return nand_read_skip_bad(&nand_info[nand_curr_device], offset,
+ return nand_read_skip_bad(nand_info[nand_curr_device], offset,
&read_size, NULL,
- nand_info[nand_curr_device].size,
+ nand_info[nand_curr_device]->size,
(u_char *)bmp_load_addr);
}
#else
diff --git a/doc/README.nand b/doc/README.nand
index 545d88ca68..96ffc48940 100644
--- a/doc/README.nand
+++ b/doc/README.nand
@@ -136,15 +136,8 @@ Configuration Options:
Example of new init to be added to the end of an existing driver
init:
- /*
- * devnum is the device number to be used in nand commands
- * and in mtd->name. Must be less than
- * CONFIG_SYS_NAND_MAX_DEVICE.
- */
- mtd = &nand_info[devnum];
-
/* chip is struct nand_chip, and is now provided by the driver. */
- mtd->priv = &chip;
+ mtd = &chip.mtd;
/*
* Fill in appropriate values if this driver uses these fields,
@@ -165,7 +158,11 @@ Configuration Options:
if (nand_scan_tail(mtd))
error out
- if (nand_register(devnum))
+ /*
+ * devnum is the device number to be used in nand commands
+ * and in mtd->name. Must be less than CONFIG_SYS_NAND_MAX_DEVICE.
+ */
+ if (nand_register(devnum, mtd))
error out
In addition to providing more flexibility to the driver, it reduces
diff --git a/drivers/dfu/dfu_nand.c b/drivers/dfu/dfu_nand.c
index a9754922e8..ab782bead4 100644
--- a/drivers/dfu/dfu_nand.c
+++ b/drivers/dfu/dfu_nand.c
@@ -25,7 +25,7 @@ static int nand_block_op(enum dfu_op op, struct dfu_entity *dfu,
loff_t start, lim;
size_t count, actual;
int ret;
- nand_info_t *nand;
+ struct mtd_info *mtd;
/* if buf == NULL return total size of the area */
if (buf == NULL) {
@@ -39,16 +39,16 @@ static int nand_block_op(enum dfu_op op, struct dfu_entity *dfu,
if (nand_curr_device < 0 ||
nand_curr_device >= CONFIG_SYS_MAX_NAND_DEVICE ||
- !nand_info[nand_curr_device].name) {
+ !nand_info[nand_curr_device]->name) {
printf("%s: invalid nand device\n", __func__);
return -1;
}
- nand = &nand_info[nand_curr_device];
+ mtd = nand_info[nand_curr_device];
if (op == DFU_OP_READ) {
- ret = nand_read_skip_bad(nand, start, &count, &actual,
- lim, buf);
+ ret = nand_read_skip_bad(mtd, start, &count, &actual,
+ lim, buf);
} else {
nand_erase_options_t opts;
@@ -59,12 +59,12 @@ static int nand_block_op(enum dfu_op op, struct dfu_entity *dfu,
opts.quiet = 1;
opts.lim = lim;
/* first erase */
- ret = nand_erase_opts(nand, &opts);
+ ret = nand_erase_opts(mtd, &opts);
if (ret)
return ret;
/* then write */
- ret = nand_write_skip_bad(nand, start, &count, &actual,
- lim, buf, WITH_WR_VERIFY);
+ ret = nand_write_skip_bad(mtd, start, &count, &actual,
+ lim, buf, WITH_WR_VERIFY);
}
if (ret != 0) {
@@ -142,24 +142,24 @@ static int dfu_flush_medium_nand(struct dfu_entity *dfu)
/* in case of ubi partition, erase rest of the partition */
if (dfu->data.nand.ubi) {
- nand_info_t *nand;
+ struct mtd_info *mtd;
nand_erase_options_t opts;
if (nand_curr_device < 0 ||
nand_curr_device >= CONFIG_SYS_MAX_NAND_DEVICE ||
- !nand_info[nand_curr_device].name) {
+ !nand_info[nand_curr_device]->name) {
printf("%s: invalid nand device\n", __func__);
return -1;
}
- nand = &nand_info[nand_curr_device];
+ mtd = nand_info[nand_curr_device];
memset(&opts, 0, sizeof(opts));
opts.offset = dfu->data.nand.start + dfu->offset +
dfu->bad_skip;
opts.length = dfu->data.nand.start +
dfu->data.nand.size - opts.offset;
- ret = nand_erase_opts(nand, &opts);
+ ret = nand_erase_opts(mtd, &opts);
if (ret != 0)
printf("Failure erase: %d\n", ret);
}
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index 6fb37182d5..837d397bda 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -13,7 +13,6 @@ endif
obj-$(CONFIG_SPL_NAND_AM33XX_BCH) += am335x_spl_bch.o
obj-$(CONFIG_SPL_NAND_DENALI) += denali_spl.o
-obj-$(CONFIG_SPL_NAND_DOCG4) += docg4_spl.o
obj-$(CONFIG_SPL_NAND_SIMPLE) += nand_spl_simple.o
obj-$(CONFIG_SPL_NAND_LOAD) += nand_spl_load.o
obj-$(CONFIG_SPL_NAND_ECC) += nand_ecc.o
@@ -50,7 +49,6 @@ obj-$(CONFIG_NAND_FSL_ELBC) += fsl_elbc_nand.o
obj-$(CONFIG_NAND_FSL_IFC) += fsl_ifc_nand.o
obj-$(CONFIG_NAND_FSL_UPM) += fsl_upm.o
obj-$(CONFIG_NAND_FSMC) += fsmc_nand.o
-obj-$(CONFIG_NAND_JZ4740) += jz4740_nand.o
obj-$(CONFIG_NAND_KB9202) += kb9202_nand.o
obj-$(CONFIG_NAND_KIRKWOOD) += kirkwood_nand.o
obj-$(CONFIG_NAND_KMETER1) += kmeter1_nand.o
@@ -68,7 +66,6 @@ obj-$(CONFIG_TEGRA_NAND) += tegra_nand.o
obj-$(CONFIG_NAND_OMAP_GPMC) += omap_gpmc.o
obj-$(CONFIG_NAND_OMAP_ELM) += omap_elm.o
obj-$(CONFIG_NAND_PLAT) += nand_plat.o
-obj-$(CONFIG_NAND_DOCG4) += docg4.o
else # minimal SPL drivers
diff --git a/drivers/mtd/nand/am335x_spl_bch.c b/drivers/mtd/nand/am335x_spl_bch.c
index 31c78258b9..f8770e0ad8 100644
--- a/drivers/mtd/nand/am335x_spl_bch.c
+++ b/drivers/mtd/nand/am335x_spl_bch.c
@@ -16,7 +16,7 @@
#include <linux/mtd/nand_ecc.h>
static int nand_ecc_pos[] = CONFIG_SYS_NAND_ECCPOS;
-nand_info_t nand_info[1];
+static struct mtd_info *mtd;
static struct nand_chip nand_chip;
#define ECCSTEPS (CONFIG_SYS_NAND_PAGE_SIZE / \
@@ -30,12 +30,12 @@ static struct nand_chip nand_chip;
static int nand_command(int block, int page, uint32_t offs,
u8 cmd)
{
- struct nand_chip *this = nand_info[0].priv;
+ struct nand_chip *this = mtd_to_nand(mtd);
int page_addr = page + block * CONFIG_SYS_NAND_PAGE_COUNT;
void (*hwctrl)(struct mtd_info *mtd, int cmd,
unsigned int ctrl) = this->cmd_ctrl;
- while (!this->dev_ready(&nand_info[0]))
+ while (!this->dev_ready(mtd))
;
/* Emulate NAND_CMD_READOOB */
@@ -45,11 +45,11 @@ static int nand_command(int block, int page, uint32_t offs,
}
/* Begin command latch cycle */
- hwctrl(&nand_info[0], cmd, NAND_CTRL_CLE | NAND_CTRL_CHANGE);
+ hwctrl(mtd, cmd, NAND_CTRL_CLE | NAND_CTRL_CHANGE);
if (cmd == NAND_CMD_RESET) {
- hwctrl(&nand_info[0], NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
- while (!this->dev_ready(&nand_info[0]))
+ hwctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
+ while (!this->dev_ready(mtd))
;
return 0;
}
@@ -60,39 +60,39 @@ static int nand_command(int block, int page, uint32_t offs,
/* Set ALE and clear CLE to start address cycle */
/* Column address */
- hwctrl(&nand_info[0], offs & 0xff,
+ hwctrl(mtd, offs & 0xff,
NAND_CTRL_ALE | NAND_CTRL_CHANGE); /* A[7:0] */
- hwctrl(&nand_info[0], (offs >> 8) & 0xff, NAND_CTRL_ALE); /* A[11:9] */
+ hwctrl(mtd, (offs >> 8) & 0xff, NAND_CTRL_ALE); /* A[11:9] */
/* Row address */
if (cmd != NAND_CMD_RNDOUT) {
- hwctrl(&nand_info[0], (page_addr & 0xff),
+ hwctrl(mtd, (page_addr & 0xff),
NAND_CTRL_ALE); /* A[19:12] */
- hwctrl(&nand_info[0], ((page_addr >> 8) & 0xff),
+ hwctrl(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 */
- hwctrl(&nand_info[0], (page_addr >> 16) & 0x0f,
+ hwctrl(mtd, (page_addr >> 16) & 0x0f,
NAND_CTRL_ALE); /* A[31:28] */
#endif
}
- hwctrl(&nand_info[0], NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
+ hwctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
if (cmd == NAND_CMD_READ0) {
/* Latch in address */
- hwctrl(&nand_info[0], NAND_CMD_READSTART,
+ hwctrl(mtd, NAND_CMD_READSTART,
NAND_CTRL_CLE | NAND_CTRL_CHANGE);
- hwctrl(&nand_info[0], NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
+ hwctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
/*
* Wait a while for the data to be ready
*/
- while (!this->dev_ready(&nand_info[0]))
+ while (!this->dev_ready(mtd))
;
} else if (cmd == NAND_CMD_RNDOUT) {
- hwctrl(&nand_info[0], NAND_CMD_RNDOUTSTART, NAND_CTRL_CLE |
+ hwctrl(mtd, NAND_CMD_RNDOUTSTART, NAND_CTRL_CLE |
NAND_CTRL_CHANGE);
- hwctrl(&nand_info[0], NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
+ hwctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
}
return 0;
@@ -100,7 +100,7 @@ static int nand_command(int block, int page, uint32_t offs,
static int nand_is_bad_block(int block)
{
- struct nand_chip *this = nand_info[0].priv;
+ struct nand_chip *this = mtd_to_nand(mtd);
nand_command(block, 0, CONFIG_SYS_NAND_BAD_BLOCK_POS,
NAND_CMD_READOOB);
@@ -121,7 +121,7 @@ static int nand_is_bad_block(int block)
static int nand_read_page(int block, int page, void *dst)
{
- struct nand_chip *this = nand_info[0].priv;
+ struct nand_chip *this = mtd_to_nand(mtd);
u_char ecc_calc[ECCTOTAL];
u_char ecc_code[ECCTOTAL];
u_char oob_data[CONFIG_SYS_NAND_OOBSIZE];
@@ -137,15 +137,15 @@ static int nand_read_page(int block, int page, void *dst)
nand_command(block, page, 0, NAND_CMD_READ0);
for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
- this->ecc.hwctl(&nand_info[0], NAND_ECC_READ);
+ this->ecc.hwctl(mtd, NAND_ECC_READ);
nand_command(block, page, data_pos, NAND_CMD_RNDOUT);
- this->read_buf(&nand_info[0], p, eccsize);
+ this->read_buf(mtd, p, eccsize);
nand_command(block, page, oob_pos, NAND_CMD_RNDOUT);
- this->read_buf(&nand_info[0], oob, eccbytes);
- this->ecc.calculate(&nand_info[0], p, &ecc_calc[i]);
+ this->read_buf(mtd, oob, eccbytes);
+ this->ecc.calculate(mtd, p, &ecc_calc[i]);
data_pos += eccsize;
oob_pos += eccbytes;
@@ -164,7 +164,7 @@ static int nand_read_page(int block, int page, void *dst)
* from correct_data(). We just hope that all possible errors
* are corrected by this routine.
*/
- this->ecc.correct(&nand_info[0], p, &ecc_code[i], &ecc_calc[i]);
+ this->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]);
}
return 0;
@@ -223,13 +223,13 @@ void nand_init(void)
/*
* Init board specific nand support
*/
- nand_info[0].priv = &nand_chip;
+ mtd = &nand_chip.mtd;
nand_chip.IO_ADDR_R = nand_chip.IO_ADDR_W =
(void __iomem *)CONFIG_SYS_NAND_BASE;
board_nand_init(&nand_chip);
if (nand_chip.select_chip)
- nand_chip.select_chip(&nand_info[0], 0);
+ nand_chip.select_chip(mtd, 0);
/* NAND chip may require reset after power-on */
nand_command(0, 0, 0, NAND_CMD_RESET);
@@ -239,5 +239,5 @@ void nand_init(void)
void nand_deselect(void)
{
if (nand_chip.select_chip)
- nand_chip.select_chip(&nand_info[0], -1);
+ nand_chip.select_chip(mtd, -1);
}
diff --git a/drivers/mtd/nand/arasan_nfc.c b/drivers/mtd/nand/arasan_nfc.c
index 2d73a05e75..320cbaa859 100644
--- a/drivers/mtd/nand/arasan_nfc.c
+++ b/drivers/mtd/nand/arasan_nfc.c
@@ -230,7 +230,7 @@ static void arasan_nand_enable_ecc(void)
static u8 arasan_nand_get_addrcycle(struct mtd_info *mtd)
{
u8 addrcycles;
- struct nand_chip *chip = mtd->priv;
+ struct nand_chip *chip = mtd_to_nand(mtd);
switch (curr_cmd->addr_cycles) {
case NAND_ADDR_CYCL_NONE:
@@ -264,7 +264,7 @@ static u8 arasan_nand_get_addrcycle(struct mtd_info *mtd)
static int arasan_nand_read_page(struct mtd_info *mtd, u8 *buf, u32 size)
{
- struct nand_chip *chip = mtd->priv;
+ struct nand_chip *chip = mtd_to_nand(mtd);
u32 reg_val, i, pktsize, pktnum;
u32 *bufptr = (u32 *)buf;
u32 timeout;
@@ -433,7 +433,8 @@ static void arasan_nand_fill_tx(const u8 *buf, int len)
}
static int arasan_nand_write_page_hwecc(struct mtd_info *mtd,
- struct nand_chip *chip, const u8 *buf, int oob_required)
+ struct nand_chip *chip, const u8 *buf, int oob_required,
+ int page)
{
u32 reg_val, i, pktsize, pktnum;
const u32 *bufptr = (const u32 *)buf;
@@ -441,7 +442,7 @@ static int arasan_nand_write_page_hwecc(struct mtd_info *mtd,
u32 size = mtd->writesize;
u32 rdcount = 0;
u8 column_addr_cycles;
- struct arasan_nand_info *nand = chip->priv;
+ struct arasan_nand_info *nand = nand_get_controller_data(chip);
if (chip->ecc_step_ds >= ARASAN_NAND_PKTSIZE_1K)
pktsize = ARASAN_NAND_PKTSIZE_1K;
@@ -944,7 +945,7 @@ static void arasan_nand_read_buf(struct mtd_info *mtd, u8 *buf, int size)
static u8 arasan_nand_read_byte(struct mtd_info *mtd)
{
- struct nand_chip *chip = mtd->priv;
+ struct nand_chip *chip = mtd_to_nand(mtd);
u32 size;
u8 val;
struct nand_onfi_params *p;
@@ -976,8 +977,8 @@ static void arasan_nand_cmd_function(struct mtd_info *mtd, unsigned int command,
int column, int page_addr)
{
u32 i, ret = 0;
- struct nand_chip *chip = mtd->priv;
- struct arasan_nand_info *nand = chip->priv;
+ struct nand_chip *chip = mtd_to_nand(mtd);
+ struct arasan_nand_info *nand = nand_get_controller_data(chip);
curr_cmd = NULL;
writel(ARASAN_NAND_INT_STS_XFR_CMPLT_MASK,
@@ -1033,7 +1034,7 @@ static int arasan_nand_ecc_init(struct mtd_info *mtd)
{
int found = -1;
u32 regval, eccpos_start, i;
- struct nand_chip *nand_chip = mtd->priv;
+ struct nand_chip *nand_chip = mtd_to_nand(mtd);
nand_chip->ecc.mode = NAND_ECC_HW;
nand_chip->ecc.hwctl = NULL;
@@ -1058,20 +1059,20 @@ static int arasan_nand_ecc_init(struct mtd_info *mtd)
if (found < 0)
return 1;
- regval = ecc_matrix[i].eccaddr |
- (ecc_matrix[i].eccsize << ARASAN_NAND_ECC_SIZE_SHIFT) |
- (ecc_matrix[i].bch << ARASAN_NAND_ECC_BCH_SHIFT);
+ regval = ecc_matrix[found].eccaddr |
+ (ecc_matrix[found].eccsize << ARASAN_NAND_ECC_SIZE_SHIFT) |
+ (ecc_matrix[found].bch << ARASAN_NAND_ECC_BCH_SHIFT);
writel(regval, &arasan_nand_base->ecc_reg);
- if (ecc_matrix[i].bch) {
+ if (ecc_matrix[found].bch) {
regval = readl(&arasan_nand_base->memadr_reg2);
regval &= ~ARASAN_NAND_MEM_ADDR2_BCH_MASK;
- regval |= (ecc_matrix[i].bchval <<
+ regval |= (ecc_matrix[found].bchval <<
ARASAN_NAND_MEM_ADDR2_BCH_SHIFT);
writel(regval, &arasan_nand_base->memadr_reg2);
}
- nand_oob.eccbytes = ecc_matrix[i].eccsize;
+ nand_oob.eccbytes = ecc_matrix[found].eccsize;
eccpos_start = mtd->oobsize - nand_oob.eccbytes;
for (i = 0; i < nand_oob.eccbytes; i++)
@@ -1080,9 +1081,9 @@ static int arasan_nand_ecc_init(struct mtd_info *mtd)
nand_oob.oobfree[0].offset = 2;
nand_oob.oobfree[0].length = eccpos_start - 2;
- nand_chip->ecc.size = ecc_matrix[i].ecc_codeword_size;
- nand_chip->ecc.strength = ecc_matrix[i].eccbits;
- nand_chip->ecc.bytes = ecc_matrix[i].eccsize;
+ nand_chip->ecc.size = ecc_matrix[found].ecc_codeword_size;
+ nand_chip->ecc.strength = ecc_matrix[found].eccbits;
+ nand_chip->ecc.bytes = ecc_matrix[found].eccsize;
nand_chip->ecc.layout = &nand_oob;
return 0;
@@ -1101,9 +1102,8 @@ static int arasan_nand_init(struct nand_chip *nand_chip, int devnum)
}
nand->nand_base = arasan_nand_base;
- mtd = &nand_info[0];
- nand_chip->priv = nand;
- mtd->priv = nand_chip;
+ mtd = nand_to_mtd(nand_chip);
+ nand_set_controller_data(nand_chip, nand);
/* Set the driver entry points for MTD */
nand_chip->cmdfunc = arasan_nand_cmd_function;
@@ -1134,7 +1134,7 @@ static int arasan_nand_init(struct nand_chip *nand_chip, int devnum)
goto fail;
}
- if (nand_register(devnum)) {
+ if (nand_register(devnum, mtd)) {
printf("Nand Register Fail\n");
goto fail;
}
diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c
index 7cc1de0313..75e830724c 100644
--- a/drivers/mtd/nand/atmel_nand.c
+++ b/drivers/mtd/nand/atmel_nand.c
@@ -160,8 +160,8 @@ static int pmecc_data_alloc(struct atmel_nand_host *host)
static void pmecc_gen_syndrome(struct mtd_info *mtd, int sector)
{
- struct nand_chip *nand_chip = mtd->priv;
- struct atmel_nand_host *host = nand_chip->priv;
+ struct nand_chip *nand_chip = mtd_to_nand(mtd);
+ struct atmel_nand_host *host = nand_get_controller_data(nand_chip);
int i;
uint32_t value;
@@ -177,8 +177,8 @@ static void pmecc_gen_syndrome(struct mtd_info *mtd, int sector)
static void pmecc_substitute(struct mtd_info *mtd)
{
- struct nand_chip *nand_chip = mtd->priv;
- struct atmel_nand_host *host = nand_chip->priv;
+ struct nand_chip *nand_chip = mtd_to_nand(mtd);
+ struct atmel_nand_host *host = nand_get_controller_data(nand_chip);
int16_t __iomem *alpha_to = host->pmecc_alpha_to;
int16_t __iomem *index_of = host->pmecc_index_of;
int16_t *partial_syn = host->pmecc_partial_syn;
@@ -227,8 +227,8 @@ static void pmecc_substitute(struct mtd_info *mtd)
*/
static void pmecc_get_sigma(struct mtd_info *mtd)
{
- struct nand_chip *nand_chip = mtd->priv;
- struct atmel_nand_host *host = nand_chip->priv;
+ struct nand_chip *nand_chip = mtd_to_nand(mtd);
+ struct atmel_nand_host *host = nand_get_controller_data(nand_chip);
int16_t *lmu = host->pmecc_lmu;
int16_t *si = host->pmecc_si;
@@ -383,8 +383,8 @@ static void pmecc_get_sigma(struct mtd_info *mtd)
static int pmecc_err_location(struct mtd_info *mtd)
{
- struct nand_chip *nand_chip = mtd->priv;
- struct atmel_nand_host *host = nand_chip->priv;
+ struct nand_chip *nand_chip = mtd_to_nand(mtd);
+ struct atmel_nand_host *host = nand_get_controller_data(nand_chip);
const int cap = host->pmecc_corr_cap;
const int num = 2 * cap + 1;
int sector_size = host->pmecc_sector_size;
@@ -437,8 +437,8 @@ static int pmecc_err_location(struct mtd_info *mtd)
static void pmecc_correct_data(struct mtd_info *mtd, uint8_t *buf, uint8_t *ecc,
int sector_num, int extra_bytes, int err_nbr)
{
- struct nand_chip *nand_chip = mtd->priv;
- struct atmel_nand_host *host = nand_chip->priv;
+ struct nand_chip *nand_chip = mtd_to_nand(mtd);
+ struct atmel_nand_host *host = nand_get_controller_data(nand_chip);
int i = 0;
int byte_pos, bit_pos, sector_size, pos;
uint32_t tmp;
@@ -483,8 +483,8 @@ static void pmecc_correct_data(struct mtd_info *mtd, uint8_t *buf, uint8_t *ecc,
static int pmecc_correction(struct mtd_info *mtd, u32 pmecc_stat, uint8_t *buf,
u8 *ecc)
{
- struct nand_chip *nand_chip = mtd->priv;
- struct atmel_nand_host *host = nand_chip->priv;
+ struct nand_chip *nand_chip = mtd_to_nand(mtd);
+ struct atmel_nand_host *host = nand_get_controller_data(nand_chip);
int i, err_nbr, eccbytes;
uint8_t *buf_pos;
@@ -513,7 +513,7 @@ normal_check:
if (err_nbr == -1) {
dev_err(host->dev, "PMECC: Too many errors\n");
mtd->ecc_stats.failed++;
- return -EIO;
+ return -EBADMSG;
} else {
pmecc_correct_data(mtd, buf_pos, ecc, i,
host->pmecc_bytes_per_sector, err_nbr);
@@ -529,7 +529,7 @@ normal_check:
static int atmel_nand_pmecc_read_page(struct mtd_info *mtd,
struct nand_chip *chip, uint8_t *buf, int oob_required, int page)
{
- struct atmel_nand_host *host = chip->priv;
+ struct atmel_nand_host *host = nand_get_controller_data(chip);
int eccsize = chip->ecc.size;
uint8_t *oob = chip->oob_poi;
uint32_t *eccpos = chip->ecc.layout->eccpos;
@@ -562,16 +562,16 @@ static int atmel_nand_pmecc_read_page(struct mtd_info *mtd,
stat = pmecc_readl(host->pmecc, isr);
if (stat != 0)
if (pmecc_correction(mtd, stat, buf, &oob[eccpos[0]]) != 0)
- return -EIO;
+ return -EBADMSG;
return 0;
}
static int atmel_nand_pmecc_write_page(struct mtd_info *mtd,
struct nand_chip *chip, const uint8_t *buf,
- int oob_required)
+ int oob_required, int page)
{
- struct atmel_nand_host *host = chip->priv;
+ struct atmel_nand_host *host = nand_get_controller_data(chip);
uint32_t *eccpos = chip->ecc.layout->eccpos;
int i, j;
int timeout = PMECC_MAX_TIMEOUT_US;
@@ -615,8 +615,8 @@ out:
static void atmel_pmecc_core_init(struct mtd_info *mtd)
{
- struct nand_chip *nand_chip = mtd->priv;
- struct atmel_nand_host *host = nand_chip->priv;
+ struct nand_chip *nand_chip = mtd_to_nand(mtd);
+ struct atmel_nand_host *host = nand_get_controller_data(nand_chip);
uint32_t val = 0;
struct nand_ecclayout *ecc_layout;
@@ -808,7 +808,8 @@ static int atmel_pmecc_nand_init_params(struct nand_chip *nand,
struct atmel_nand_host *host;
int cap, sector_size;
- host = nand->priv = &pmecc_host;
+ host = &pmecc_host;
+ nand_set_controller_data(nand, host);
nand->ecc.mode = NAND_ECC_HW;
nand->ecc.calculate = NULL;
@@ -1080,7 +1081,7 @@ static int atmel_nand_read_page(struct mtd_info *mtd, struct nand_chip *chip,
static int atmel_nand_correct(struct mtd_info *mtd, u_char *dat,
u_char *read_ecc, u_char *isnull)
{
- struct nand_chip *nand_chip = mtd->priv;
+ struct nand_chip *nand_chip = mtd_to_nand(mtd);
unsigned int ecc_status;
unsigned int ecc_word, ecc_bit;
@@ -1111,7 +1112,7 @@ static int atmel_nand_correct(struct mtd_info *mtd, u_char *dat,
* We can't correct so many errors */
dev_warn(host->dev, "atmel_nand : multiple errors detected."
" Unable to correct.\n");
- return -EIO;
+ return -EBADMSG;
}
/* if there's a single bit error : we can correct it */
@@ -1207,7 +1208,7 @@ int atmel_hwecc_nand_init_param(struct nand_chip *nand, struct mtd_info *mtd)
static void at91_nand_hwcontrol(struct mtd_info *mtd,
int cmd, unsigned int ctrl)
{
- struct nand_chip *this = mtd->priv;
+ struct nand_chip *this = mtd_to_nand(mtd);
if (ctrl & NAND_CTRL_CHANGE) {
ulong IO_ADDR_W = (ulong) this->IO_ADDR_W;
@@ -1238,17 +1239,17 @@ static int at91_nand_ready(struct mtd_info *mtd)
#ifdef CONFIG_SPL_BUILD
/* The following code is for SPL */
-static nand_info_t mtd;
+static struct mtd_info *mtd;
static struct nand_chip nand_chip;
static int nand_command(int block, int page, uint32_t offs, u8 cmd)
{
- struct nand_chip *this = mtd.priv;
+ struct nand_chip *this = mtd_to_nand(mtd);
int page_addr = page + block * CONFIG_SYS_NAND_PAGE_COUNT;
void (*hwctrl)(struct mtd_info *mtd, int cmd,
unsigned int ctrl) = this->cmd_ctrl;
- while (!this->dev_ready(&mtd))
+ while (!this->dev_ready(mtd))
;
if (cmd == NAND_CMD_READOOB) {
@@ -1256,24 +1257,24 @@ static int nand_command(int block, int page, uint32_t offs, u8 cmd)
cmd = NAND_CMD_READ0;
}
- hwctrl(&mtd, cmd, NAND_CTRL_CLE | NAND_CTRL_CHANGE);
+ hwctrl(mtd, cmd, NAND_CTRL_CLE | NAND_CTRL_CHANGE);
if ((this->options & NAND_BUSWIDTH_16) && !nand_opcode_8bits(cmd))
offs >>= 1;
- hwctrl(&mtd, offs & 0xff, NAND_CTRL_ALE | NAND_CTRL_CHANGE);
- hwctrl(&mtd, (offs >> 8) & 0xff, NAND_CTRL_ALE);
- hwctrl(&mtd, (page_addr & 0xff), NAND_CTRL_ALE);
- hwctrl(&mtd, ((page_addr >> 8) & 0xff), NAND_CTRL_ALE);
+ hwctrl(mtd, offs & 0xff, NAND_CTRL_ALE | NAND_CTRL_CHANGE);
+ hwctrl(mtd, (offs >> 8) & 0xff, NAND_CTRL_ALE);
+ hwctrl(mtd, (page_addr & 0xff), NAND_CTRL_ALE);
+ hwctrl(mtd, ((page_addr >> 8) & 0xff), NAND_CTRL_ALE);
#ifdef CONFIG_SYS_NAND_5_ADDR_CYCLE
- hwctrl(&mtd, (page_addr >> 16) & 0x0f, NAND_CTRL_ALE);
+ hwctrl(mtd, (page_addr >> 16) & 0x0f, NAND_CTRL_ALE);
#endif
- hwctrl(&mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
+ hwctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
- hwctrl(&mtd, NAND_CMD_READSTART, NAND_CTRL_CLE | NAND_CTRL_CHANGE);
- hwctrl(&mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
+ hwctrl(mtd, NAND_CMD_READSTART, NAND_CTRL_CLE | NAND_CTRL_CHANGE);
+ hwctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
- while (!this->dev_ready(&mtd))
+ while (!this->dev_ready(mtd))
;
return 0;
@@ -1281,7 +1282,7 @@ static int nand_command(int block, int page, uint32_t offs, u8 cmd)
static int nand_is_bad_block(int block)
{
- struct nand_chip *this = mtd.priv;
+ struct nand_chip *this = mtd_to_nand(mtd);
nand_command(block, 0, CONFIG_SYS_NAND_BAD_BLOCK_POS, NAND_CMD_READOOB);
@@ -1304,7 +1305,7 @@ static int nand_ecc_pos[] = CONFIG_SYS_NAND_ECCPOS;
static int nand_read_page(int block, int page, void *dst)
{
- struct nand_chip *this = mtd.priv;
+ struct nand_chip *this = mtd_to_nand(mtd);
u_char ecc_calc[ECCTOTAL];
u_char ecc_code[ECCTOTAL];
u_char oob_data[CONFIG_SYS_NAND_OOBSIZE];
@@ -1317,11 +1318,11 @@ static int nand_read_page(int block, int page, void *dst)
for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
if (this->ecc.mode != NAND_ECC_SOFT)
- this->ecc.hwctl(&mtd, NAND_ECC_READ);
- this->read_buf(&mtd, p, eccsize);
- this->ecc.calculate(&mtd, p, &ecc_calc[i]);
+ this->ecc.hwctl(mtd, NAND_ECC_READ);
+ this->read_buf(mtd, p, eccsize);
+ this->ecc.calculate(mtd, p, &ecc_calc[i]);
}
- this->read_buf(&mtd, oob_data, CONFIG_SYS_NAND_OOBSIZE);
+ this->read_buf(mtd, oob_data, CONFIG_SYS_NAND_OOBSIZE);
for (i = 0; i < ECCTOTAL; i++)
ecc_code[i] = oob_data[nand_ecc_pos[i]];
@@ -1330,35 +1331,35 @@ static int nand_read_page(int block, int page, void *dst)
p = dst;
for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize)
- this->ecc.correct(&mtd, p, &ecc_code[i], &ecc_calc[i]);
+ this->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]);
return 0;
}
int spl_nand_erase_one(int block, int page)
{
- struct nand_chip *this = mtd.priv;
+ struct nand_chip *this = mtd_to_nand(mtd);
void (*hwctrl)(struct mtd_info *mtd, int cmd,
unsigned int ctrl) = this->cmd_ctrl;
int page_addr;
if (nand_chip.select_chip)
- nand_chip.select_chip(&mtd, 0);
+ nand_chip.select_chip(mtd, 0);
page_addr = page + block * CONFIG_SYS_NAND_PAGE_COUNT;
- hwctrl(&mtd, NAND_CMD_ERASE1, NAND_CTRL_CLE | NAND_CTRL_CHANGE);
+ hwctrl(mtd, NAND_CMD_ERASE1, NAND_CTRL_CLE | NAND_CTRL_CHANGE);
/* Row address */
- hwctrl(&mtd, (page_addr & 0xff), NAND_CTRL_ALE | NAND_CTRL_CHANGE);
- hwctrl(&mtd, ((page_addr >> 8) & 0xff),
+ hwctrl(mtd, (page_addr & 0xff), NAND_CTRL_ALE | NAND_CTRL_CHANGE);
+ hwctrl(mtd, ((page_addr >> 8) & 0xff),
NAND_CTRL_ALE | NAND_CTRL_CHANGE);
#ifdef CONFIG_SYS_NAND_5_ADDR_CYCLE
/* One more address cycle for devices > 128MiB */
- hwctrl(&mtd, (page_addr >> 16) & 0x0f,
+ hwctrl(mtd, (page_addr >> 16) & 0x0f,
NAND_CTRL_ALE | NAND_CTRL_CHANGE);
#endif
- hwctrl(&mtd, NAND_CMD_ERASE2, NAND_CTRL_CLE | NAND_CTRL_CHANGE);
+ hwctrl(mtd, NAND_CMD_ERASE2, NAND_CTRL_CLE | NAND_CTRL_CHANGE);
- while (!this->dev_ready(&mtd))
+ while (!this->dev_ready(mtd))
;
nand_deselect();
@@ -1368,10 +1369,10 @@ int spl_nand_erase_one(int block, int page)
#else
static int nand_read_page(int block, int page, void *dst)
{
- struct nand_chip *this = mtd.priv;
+ struct nand_chip *this = mtd_to_nand(mtd);
nand_command(block, page, 0, NAND_CMD_READ0);
- atmel_nand_pmecc_read_page(&mtd, this, dst, 0, page);
+ atmel_nand_pmecc_read_page(mtd, this, dst, 0, page);
return 0;
}
@@ -1407,7 +1408,7 @@ int nand_spl_load_image(uint32_t offs, unsigned int size, void *dst)
int at91_nand_wait_ready(struct mtd_info *mtd)
{
- struct nand_chip *this = mtd->priv;
+ struct nand_chip *this = mtd_to_nand(mtd);
udelay(this->chip_delay);
@@ -1438,7 +1439,7 @@ int board_nand_init(struct nand_chip *nand)
#ifdef CONFIG_ATMEL_NAND_HWECC
#ifdef CONFIG_ATMEL_NAND_HW_PMECC
- ret = atmel_pmecc_nand_init_params(nand, &mtd);
+ ret = atmel_pmecc_nand_init_params(nand, mtd);
#endif
#endif
@@ -1447,9 +1448,9 @@ int board_nand_init(struct nand_chip *nand)
void nand_init(void)
{
- mtd.writesize = CONFIG_SYS_NAND_PAGE_SIZE;
- mtd.oobsize = CONFIG_SYS_NAND_OOBSIZE;
- mtd.priv = &nand_chip;
+ mtd = &nand_chip.mtd;
+ mtd->writesize = CONFIG_SYS_NAND_PAGE_SIZE;
+ mtd->oobsize = CONFIG_SYS_NAND_OOBSIZE;
nand_chip.IO_ADDR_R = (void __iomem *)CONFIG_SYS_NAND_BASE;
nand_chip.IO_ADDR_W = (void __iomem *)CONFIG_SYS_NAND_BASE;
board_nand_init(&nand_chip);
@@ -1462,13 +1463,13 @@ void nand_init(void)
#endif
if (nand_chip.select_chip)
- nand_chip.select_chip(&mtd, 0);
+ nand_chip.select_chip(mtd, 0);
}
void nand_deselect(void)
{
if (nand_chip.select_chip)
- nand_chip.select_chip(&mtd, -1);
+ nand_chip.select_chip(mtd, -1);
}
#else
@@ -1482,10 +1483,9 @@ static ulong base_addr[CONFIG_SYS_MAX_NAND_DEVICE] = CONFIG_SYS_NAND_BASE_LIST;
int atmel_nand_chip_init(int devnum, ulong base_addr)
{
int ret;
- struct mtd_info *mtd = &nand_info[devnum];
struct nand_chip *nand = &nand_chip[devnum];
+ struct mtd_info *mtd = nand_to_mtd(nand);
- mtd->priv = nand;
nand->IO_ADDR_R = nand->IO_ADDR_W = (void __iomem *)base_addr;
#ifdef CONFIG_NAND_ECC_BCH
@@ -1521,7 +1521,7 @@ int atmel_nand_chip_init(int devnum, ulong base_addr)
ret = nand_scan_tail(mtd);
if (!ret)
- nand_register(devnum);
+ nand_register(devnum, mtd);
return ret;
}
diff --git a/drivers/mtd/nand/davinci_nand.c b/drivers/mtd/nand/davinci_nand.c
index a3970745c9..48a8ca78e7 100644
--- a/drivers/mtd/nand/davinci_nand.c
+++ b/drivers/mtd/nand/davinci_nand.c
@@ -54,7 +54,7 @@
*/
static void nand_davinci_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
{
- struct nand_chip *chip = mtd->priv;
+ struct nand_chip *chip = mtd_to_nand(mtd);
const u32 *nand = chip->IO_ADDR_R;
/* Make sure that buf is 32 bit aligned */
@@ -99,7 +99,7 @@ static void nand_davinci_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
static void nand_davinci_write_buf(struct mtd_info *mtd, const uint8_t *buf,
int len)
{
- struct nand_chip *chip = mtd->priv;
+ struct nand_chip *chip = mtd_to_nand(mtd);
const u32 *nand = chip->IO_ADDR_W;
/* Make sure that buf is 32 bit aligned */
@@ -144,7 +144,7 @@ static void nand_davinci_write_buf(struct mtd_info *mtd, const uint8_t *buf,
static void nand_davinci_hwcontrol(struct mtd_info *mtd, int cmd,
unsigned int ctrl)
{
- struct nand_chip *this = mtd->priv;
+ struct nand_chip *this = mtd_to_nand(mtd);
u_int32_t IO_ADDR_W = (u_int32_t)this->IO_ADDR_W;
if (ctrl & NAND_CTRL_CHANGE) {
@@ -223,7 +223,7 @@ static int nand_davinci_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
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;
+ struct nand_chip *this = mtd_to_nand(mtd);
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) |
@@ -243,7 +243,7 @@ static int nand_davinci_correct_data(struct mtd_info *mtd, u_char *dat,
"%d\n", find_byte, find_bit);
return 1;
} else {
- return -1;
+ return -EBADMSG;
}
} else if (!(diff & (diff - 1))) {
/* Single bit ECC error in the ECC itself,
@@ -254,7 +254,7 @@ static int nand_davinci_correct_data(struct mtd_info *mtd, u_char *dat,
} else {
/* Uncorrectable error */
MTDDEBUG(MTD_DEBUG_LEVEL0, "ECC UNCORRECTED_ERROR 1\n");
- return -1;
+ return -EBADMSG;
}
}
return 0;
@@ -380,10 +380,13 @@ static int nand_davinci_write_page(struct mtd_info *mtd, struct nand_chip *chip,
chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page);
- if (unlikely(raw))
- status = chip->ecc.write_page_raw(mtd, chip, buf, oob_required);
- else
- status = chip->ecc.write_page(mtd, chip, buf, oob_required);
+ if (unlikely(raw)) {
+ status = chip->ecc.write_page_raw(mtd, chip, buf,
+ oob_required, page);
+ } else {
+ status = chip->ecc.write_page(mtd, chip, buf,
+ oob_required, page);
+ }
if (status < 0) {
ret = status;
@@ -698,7 +701,7 @@ static int nand_davinci_4bit_correct_data(struct mtd_info *mtd, uint8_t *dat,
return 0;
} else if (iserror == ECC_STATE_TOO_MANY_ERRS) {
val = __raw_readl(&davinci_emif_regs->nanderrval1);
- return -1;
+ return -EBADMSG;
}
numerrors = ((__raw_readl(&davinci_emif_regs->nandfsr) >> 16)
diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c
index 5894fcc4a8..601e744a08 100644
--- a/drivers/mtd/nand/denali.c
+++ b/drivers/mtd/nand/denali.c
@@ -48,7 +48,10 @@ static int onfi_timing_mode = NAND_DEFAULT_TIMINGS;
* this macro allows us to convert from an MTD structure to our own
* device context (denali) structure.
*/
-#define mtd_to_denali(m) container_of(m->priv, struct denali_nand_info, nand)
+static inline struct denali_nand_info *mtd_to_denali(struct mtd_info *mtd)
+{
+ return container_of(mtd_to_nand(mtd), struct denali_nand_info, nand);
+}
/*
* These constants are defined by the driver to enable common driver
@@ -865,7 +868,7 @@ static int write_page(struct mtd_info *mtd, struct nand_chip *chip,
* by write_page above.
*/
static int denali_write_page(struct mtd_info *mtd, struct nand_chip *chip,
- const uint8_t *buf, int oob_required)
+ const uint8_t *buf, int oob_required, int page)
{
struct denali_nand_info *denali = mtd_to_denali(mtd);
@@ -889,7 +892,8 @@ static int denali_write_page(struct mtd_info *mtd, struct nand_chip *chip,
* write_page() function above.
*/
static int denali_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
- const uint8_t *buf, int oob_required)
+ const uint8_t *buf, int oob_required,
+ int page)
{
struct denali_nand_info *denali = mtd_to_denali(mtd);
@@ -988,7 +992,7 @@ static int denali_read_page(struct mtd_info *mtd, struct nand_chip *chip,
debug(" ECC error cause by erased block\n");
/* false alarm, return the 0xFF */
} else {
- return -EIO;
+ return -EBADMSG;
}
}
memcpy(buf, denali->buf.dma_buf, mtd->writesize);
@@ -1173,13 +1177,13 @@ static struct nand_ecclayout nand_oob;
static int denali_init(struct denali_nand_info *denali)
{
+ struct mtd_info *mtd = nand_to_mtd(&denali->nand);
int ret;
denali_hw_init(denali);
- denali->mtd->name = "denali-nand";
- denali->mtd->owner = THIS_MODULE;
- denali->mtd->priv = &denali->nand;
+ mtd->name = "denali-nand";
+ mtd->owner = THIS_MODULE;
/* register the driver with the NAND core subsystem */
denali->nand.select_chip = denali_select_chip;
@@ -1193,7 +1197,7 @@ static int denali_init(struct denali_nand_info *denali)
* this is the first stage in a two step process to register
* with the nand subsystem
*/
- if (nand_scan_ident(denali->mtd, denali->max_banks, NULL)) {
+ if (nand_scan_ident(mtd, denali->max_banks, NULL)) {
ret = -ENXIO;
goto fail;
}
@@ -1239,13 +1243,13 @@ static int denali_init(struct denali_nand_info *denali)
nand_oob.eccbytes = denali->nand.ecc.bytes;
denali->nand.ecc.layout = &nand_oob;
- writel(denali->mtd->erasesize / denali->mtd->writesize,
+ writel(mtd->erasesize / mtd->writesize,
denali->flash_reg + PAGES_PER_BLOCK);
writel(denali->nand.options & NAND_BUSWIDTH_16 ? 1 : 0,
denali->flash_reg + DEVICE_WIDTH);
- writel(denali->mtd->writesize,
+ writel(mtd->writesize,
denali->flash_reg + DEVICE_MAIN_AREA_SIZE);
- writel(denali->mtd->oobsize,
+ writel(mtd->oobsize,
denali->flash_reg + DEVICE_SPARE_AREA_SIZE);
if (readl(denali->flash_reg + DEVICES_CONNECTED) == 0)
writel(1, denali->flash_reg + DEVICES_CONNECTED);
@@ -1258,12 +1262,12 @@ static int denali_init(struct denali_nand_info *denali)
denali->nand.ecc.read_oob = denali_read_oob;
denali->nand.ecc.write_oob = denali_write_oob;
- if (nand_scan_tail(denali->mtd)) {
+ if (nand_scan_tail(mtd)) {
ret = -ENXIO;
goto fail;
}
- ret = nand_register(0);
+ ret = nand_register(0, mtd);
fail:
return ret;
@@ -1278,13 +1282,6 @@ static int __board_nand_init(void)
return -ENOMEM;
/*
- * If CONFIG_SYS_NAND_SELF_INIT is defined, each driver is responsible
- * for instantiating struct nand_chip, while drivers/mtd/nand/nand.c
- * still provides a "struct mtd_info nand_info" instance.
- */
- denali->mtd = &nand_info[0];
-
- /*
* In the future, these base addresses should be taken from
* Device Tree or platform data.
*/
diff --git a/drivers/mtd/nand/denali.h b/drivers/mtd/nand/denali.h
index db1457a680..0e098bddf1 100644
--- a/drivers/mtd/nand/denali.h
+++ b/drivers/mtd/nand/denali.h
@@ -436,7 +436,6 @@ struct nand_buf {
#define DT 3
struct denali_nand_info {
- struct mtd_info *mtd;
struct nand_chip nand;
int flash_bank; /* currently selected chip */
int status;
diff --git a/drivers/mtd/nand/denali_spl.c b/drivers/mtd/nand/denali_spl.c
index 1587413540..c693032530 100644
--- a/drivers/mtd/nand/denali_spl.c
+++ b/drivers/mtd/nand/denali_spl.c
@@ -41,7 +41,7 @@ static int wait_for_irq(uint32_t irq_mask)
if (intr_status & INTR_STATUS__ECC_UNCOR_ERR) {
debug("Uncorrected ECC detected\n");
- return -EIO;
+ return -EBADMSG;
}
if (intr_status & irq_mask)
diff --git a/drivers/mtd/nand/docg4.c b/drivers/mtd/nand/docg4.c
deleted file mode 100644
index c1c1ff876a..0000000000
--- a/drivers/mtd/nand/docg4.c
+++ /dev/null
@@ -1,1030 +0,0 @@
-/*
- * drivers/mtd/nand/docg4.c
- *
- * Copyright (C) 2013 Mike Dunn <mikedunn@newsguy.com>
- *
- * SPDX-License-Identifier: GPL-2.0+
- *
- * mtd nand driver for M-Systems DiskOnChip G4
- *
- * Tested on the Palm Treo 680. The G4 is also present on Toshiba Portege, Asus
- * P526, some HTC smartphones (Wizard, Prophet, ...), O2 XDA Zinc, maybe others.
- * Should work on these as well. Let me know!
- *
- * TODO:
- *
- * Mechanism for management of password-protected areas
- *
- * Hamming ecc when reading oob only
- *
- * According to the M-Sys documentation, this device is also available in a
- * "dual-die" configuration having a 256MB capacity, but no mechanism for
- * detecting this variant is documented. Currently this driver assumes 128MB
- * capacity.
- *
- * Support for multiple cascaded devices ("floors"). Not sure which gadgets
- * contain multiple G4s in a cascaded configuration, if any.
- */
-
-
-#include <common.h>
-#include <asm/arch/hardware.h>
-#include <asm/io.h>
-#include <asm/bitops.h>
-#include <asm/errno.h>
-#include <malloc.h>
-#include <nand.h>
-#include <linux/bch.h>
-#include <linux/bitrev.h>
-#include <linux/mtd/docg4.h>
-
-/*
- * The device has a nop register which M-Sys claims is for the purpose of
- * inserting precise delays. But beware; at least some operations fail if the
- * nop writes are replaced with a generic delay!
- */
-static inline void write_nop(void __iomem *docptr)
-{
- writew(0, docptr + DOC_NOP);
-}
-
-
-static int poll_status(void __iomem *docptr)
-{
- /*
- * Busy-wait for the FLASHREADY bit to be set in the FLASHCONTROL
- * register. Operations known to take a long time (e.g., block erase)
- * should sleep for a while before calling this.
- */
-
- uint8_t flash_status;
-
- /* hardware quirk requires reading twice initially */
- flash_status = readb(docptr + DOC_FLASHCONTROL);
-
- do {
- flash_status = readb(docptr + DOC_FLASHCONTROL);
- } while (!(flash_status & DOC_CTRL_FLASHREADY));
-
- return 0;
-}
-
-static void write_addr(void __iomem *docptr, uint32_t docg4_addr)
-{
- /* write the four address bytes packed in docg4_addr to the device */
-
- writeb(docg4_addr & 0xff, docptr + DOC_FLASHADDRESS);
- docg4_addr >>= 8;
- writeb(docg4_addr & 0xff, docptr + DOC_FLASHADDRESS);
- docg4_addr >>= 8;
- writeb(docg4_addr & 0xff, docptr + DOC_FLASHADDRESS);
- docg4_addr >>= 8;
- writeb(docg4_addr & 0xff, docptr + DOC_FLASHADDRESS);
-}
-
-/*
- * This is a module parameter in the linux kernel version of this driver. It is
- * hard-coded to 'off' for u-boot. This driver uses oob to mark bad blocks.
- * This can be problematic when dealing with data not intended for the mtd/nand
- * subsystem. For example, on boards that boot from the docg4 and use the IPL
- * to load an spl + u-boot image, the blocks containing the image will be
- * reported as "bad" because the oob of the first page of each block contains a
- * magic number that the IPL looks for, which causes the badblock scan to
- * erroneously add them to the bad block table. To erase such a block, use
- * u-boot's 'nand scrub'. scrub is safe for the docg4. The device does have a
- * factory bad block table, but it is read-only, and is used in conjunction with
- * oob bad block markers that are written by mtd/nand when a block is deemed to
- * be bad. To read data from "bad" blocks, use 'read.raw'. Unfortunately,
- * read.raw does not use ecc, which would still work fine on such misidentified
- * bad blocks. TODO: u-boot nand utilities need the ability to ignore bad
- * blocks.
- */
-static const int ignore_badblocks; /* remains false */
-
-struct docg4_priv {
- int status;
- struct {
- unsigned int command;
- int column;
- int page;
- } last_command;
- uint8_t oob_buf[16];
- uint8_t ecc_buf[7];
- int oob_page;
- struct bch_control *bch;
-};
-/*
- * Oob bytes 0 - 6 are available to the user.
- * Byte 7 is hamming ecc for first 7 bytes. Bytes 8 - 14 are hw-generated ecc.
- * Byte 15 (the last) is used by the driver as a "page written" flag.
- */
-static struct nand_ecclayout docg4_oobinfo = {
- .eccbytes = 9,
- .eccpos = {7, 8, 9, 10, 11, 12, 13, 14, 15},
- .oobavail = 7,
- .oobfree = { {0, 7} }
-};
-
-static void reset(void __iomem *docptr)
-{
- /* full device reset */
-
- writew(DOC_ASICMODE_RESET | DOC_ASICMODE_MDWREN, docptr + DOC_ASICMODE);
- writew(~(DOC_ASICMODE_RESET | DOC_ASICMODE_MDWREN),
- docptr + DOC_ASICMODECONFIRM);
- write_nop(docptr);
-
- writew(DOC_ASICMODE_NORMAL | DOC_ASICMODE_MDWREN,
- docptr + DOC_ASICMODE);
- writew(~(DOC_ASICMODE_NORMAL | DOC_ASICMODE_MDWREN),
- docptr + DOC_ASICMODECONFIRM);
-
- writew(DOC_ECCCONF1_ECC_ENABLE, docptr + DOC_ECCCONF1);
-
- poll_status(docptr);
-}
-
-static void docg4_select_chip(struct mtd_info *mtd, int chip)
-{
- /*
- * Select among multiple cascaded chips ("floors"). Multiple floors are
- * not yet supported, so the only valid non-negative value is 0.
- */
- void __iomem *docptr = CONFIG_SYS_NAND_BASE;
-
- if (chip < 0)
- return; /* deselected */
-
- if (chip > 0)
- printf("multiple floors currently unsupported\n");
-
- writew(0, docptr + DOC_DEVICESELECT);
-}
-
-static void read_hw_ecc(void __iomem *docptr, uint8_t *ecc_buf)
-{
- /* read the 7 hw-generated ecc bytes */
-
- int i;
- for (i = 0; i < 7; i++) { /* hw quirk; read twice */
- ecc_buf[i] = readb(docptr + DOC_BCH_SYNDROM(i));
- ecc_buf[i] = readb(docptr + DOC_BCH_SYNDROM(i));
- }
-}
-
-static int correct_data(struct mtd_info *mtd, uint8_t *buf, int page)
-{
- /*
- * Called after a page read when hardware reports bitflips.
- * Up to four bitflips can be corrected.
- */
-
- struct nand_chip *nand = mtd->priv;
- struct docg4_priv *doc = nand->priv;
- void __iomem *docptr = CONFIG_SYS_NAND_BASE;
- int i, numerrs;
- unsigned int errpos[4];
- const uint8_t blank_read_hwecc[8] = {
- 0xcf, 0x72, 0xfc, 0x1b, 0xa9, 0xc7, 0xb9, 0 };
-
- read_hw_ecc(docptr, doc->ecc_buf); /* read 7 hw-generated ecc bytes */
-
- /* check if read error is due to a blank page */
- if (!memcmp(doc->ecc_buf, blank_read_hwecc, 7))
- return 0; /* yes */
-
- /* skip additional check of "written flag" if ignore_badblocks */
- if (!ignore_badblocks) {
- /*
- * If the hw ecc bytes are not those of a blank page, there's
- * still a chance that the page is blank, but was read with
- * errors. Check the "written flag" in last oob byte, which
- * is set to zero when a page is written. If more than half
- * the bits are set, assume a blank page. Unfortunately, the
- * bit flips(s) are not reported in stats.
- */
-
- if (doc->oob_buf[15]) {
- int bit, numsetbits = 0;
- unsigned long written_flag = doc->oob_buf[15];
-
- for (bit = 0; bit < 8; bit++) {
- if (written_flag & 0x01)
- numsetbits++;
- written_flag >>= 1;
- }
- if (numsetbits > 4) { /* assume blank */
- printf("errors in blank page at offset %08x\n",
- page * DOCG4_PAGE_SIZE);
- return 0;
- }
- }
- }
-
- /*
- * The hardware ecc unit produces oob_ecc ^ calc_ecc. The kernel's bch
- * algorithm is used to decode this. However the hw operates on page
- * data in a bit order that is the reverse of that of the bch alg,
- * requiring that the bits be reversed on the result. Thanks to Ivan
- * Djelic for his analysis!
- */
- for (i = 0; i < 7; i++)
- doc->ecc_buf[i] = bitrev8(doc->ecc_buf[i]);
-
- numerrs = decode_bch(doc->bch, NULL, DOCG4_USERDATA_LEN, NULL,
- doc->ecc_buf, NULL, errpos);
-
- if (numerrs == -EBADMSG) {
- printf("uncorrectable errors at offset %08x\n",
- page * DOCG4_PAGE_SIZE);
- return -EBADMSG;
- }
-
- BUG_ON(numerrs < 0); /* -EINVAL, or anything other than -EBADMSG */
-
- /* undo last step in BCH alg (modulo mirroring not needed) */
- for (i = 0; i < numerrs; i++)
- errpos[i] = (errpos[i] & ~7)|(7-(errpos[i] & 7));
-
- /* fix the errors */
- for (i = 0; i < numerrs; i++) {
- /* ignore if error within oob ecc bytes */
- if (errpos[i] > DOCG4_USERDATA_LEN * 8)
- continue;
-
- /* if error within oob area preceeding ecc bytes... */
- if (errpos[i] > DOCG4_PAGE_SIZE * 8)
- __change_bit(errpos[i] - DOCG4_PAGE_SIZE * 8,
- (unsigned long *)doc->oob_buf);
-
- else /* error in page data */
- __change_bit(errpos[i], (unsigned long *)buf);
- }
-
- printf("%d error(s) corrected at offset %08x\n",
- numerrs, page * DOCG4_PAGE_SIZE);
-
- return numerrs;
-}
-
-static int read_progstatus(struct docg4_priv *doc, void __iomem *docptr)
-{
- /*
- * This apparently checks the status of programming. Done after an
- * erasure, and after page data is written. On error, the status is
- * saved, to be later retrieved by the nand infrastructure code.
- */
-
- /* status is read from the I/O reg */
- uint16_t status1 = readw(docptr + DOC_IOSPACE_DATA);
- uint16_t status2 = readw(docptr + DOC_IOSPACE_DATA);
- uint16_t status3 = readw(docptr + DOCG4_MYSTERY_REG);
-
- MTDDEBUG(MTD_DEBUG_LEVEL3, "docg4: %s: %02x %02x %02x\n",
- __func__, status1, status2, status3);
-
- if (status1 != DOCG4_PROGSTATUS_GOOD ||
- status2 != DOCG4_PROGSTATUS_GOOD_2 ||
- status3 != DOCG4_PROGSTATUS_GOOD_2) {
- doc->status = NAND_STATUS_FAIL;
- printf("read_progstatus failed: %02x, %02x, %02x\n",
- status1, status2, status3);
- return -EIO;
- }
- return 0;
-}
-
-static int pageprog(struct mtd_info *mtd)
-{
- /*
- * Final step in writing a page. Writes the contents of its
- * internal buffer out to the flash array, or some such.
- */
-
- struct nand_chip *nand = mtd->priv;
- struct docg4_priv *doc = nand->priv;
- void __iomem *docptr = CONFIG_SYS_NAND_BASE;
- int retval = 0;
-
- MTDDEBUG(MTD_DEBUG_LEVEL3, "docg4: %s\n", __func__);
-
- writew(DOCG4_SEQ_PAGEPROG, docptr + DOC_FLASHSEQUENCE);
- writew(DOC_CMD_PROG_CYCLE2, docptr + DOC_FLASHCOMMAND);
- write_nop(docptr);
- write_nop(docptr);
-
- /* Just busy-wait; usleep_range() slows things down noticeably. */
- poll_status(docptr);
-
- writew(DOCG4_SEQ_FLUSH, docptr + DOC_FLASHSEQUENCE);
- writew(DOCG4_CMD_FLUSH, docptr + DOC_FLASHCOMMAND);
- writew(DOC_ECCCONF0_READ_MODE | 4, docptr + DOC_ECCCONF0);
- write_nop(docptr);
- write_nop(docptr);
- write_nop(docptr);
- write_nop(docptr);
- write_nop(docptr);
-
- retval = read_progstatus(doc, docptr);
- writew(0, docptr + DOC_DATAEND);
- write_nop(docptr);
- poll_status(docptr);
- write_nop(docptr);
-
- return retval;
-}
-
-static void sequence_reset(void __iomem *docptr)
-{
- /* common starting sequence for all operations */
-
- writew(DOC_CTRL_UNKNOWN | DOC_CTRL_CE, docptr + DOC_FLASHCONTROL);
- writew(DOC_SEQ_RESET, docptr + DOC_FLASHSEQUENCE);
- writew(DOC_CMD_RESET, docptr + DOC_FLASHCOMMAND);
- write_nop(docptr);
- write_nop(docptr);
- poll_status(docptr);
- write_nop(docptr);
-}
-
-static void read_page_prologue(void __iomem *docptr, uint32_t docg4_addr)
-{
- /* first step in reading a page */
-
- sequence_reset(docptr);
-
- writew(DOCG4_SEQ_PAGE_READ, docptr + DOC_FLASHSEQUENCE);
- writew(DOCG4_CMD_PAGE_READ, docptr + DOC_FLASHCOMMAND);
- write_nop(docptr);
-
- write_addr(docptr, docg4_addr);
-
- write_nop(docptr);
- writew(DOCG4_CMD_READ2, docptr + DOC_FLASHCOMMAND);
- write_nop(docptr);
- write_nop(docptr);
-
- poll_status(docptr);
-}
-
-static void write_page_prologue(void __iomem *docptr, uint32_t docg4_addr)
-{
- /* first step in writing a page */
-
- sequence_reset(docptr);
- writew(DOCG4_SEQ_PAGEWRITE, docptr + DOC_FLASHSEQUENCE);
- writew(DOCG4_CMD_PAGEWRITE, docptr + DOC_FLASHCOMMAND);
- write_nop(docptr);
- write_addr(docptr, docg4_addr);
- write_nop(docptr);
- write_nop(docptr);
- poll_status(docptr);
-}
-
-static uint32_t mtd_to_docg4_address(int page, int column)
-{
- /*
- * Convert mtd address to format used by the device, 32 bit packed.
- *
- * Some notes on G4 addressing... The M-Sys documentation on this device
- * claims that pages are 2K in length, and indeed, the format of the
- * address used by the device reflects that. But within each page are
- * four 512 byte "sub-pages", each with its own oob data that is
- * read/written immediately after the 512 bytes of page data. This oob
- * data contains the ecc bytes for the preceeding 512 bytes.
- *
- * Rather than tell the mtd nand infrastructure that page size is 2k,
- * with four sub-pages each, we engage in a little subterfuge and tell
- * the infrastructure code that pages are 512 bytes in size. This is
- * done because during the course of reverse-engineering the device, I
- * never observed an instance where an entire 2K "page" was read or
- * written as a unit. Each "sub-page" is always addressed individually,
- * its data read/written, and ecc handled before the next "sub-page" is
- * addressed.
- *
- * This requires us to convert addresses passed by the mtd nand
- * infrastructure code to those used by the device.
- *
- * The address that is written to the device consists of four bytes: the
- * first two are the 2k page number, and the second is the index into
- * the page. The index is in terms of 16-bit half-words and includes
- * the preceeding oob data, so e.g., the index into the second
- * "sub-page" is 0x108, and the full device address of the start of mtd
- * page 0x201 is 0x00800108.
- */
- int g4_page = page / 4; /* device's 2K page */
- int g4_index = (page % 4) * 0x108 + column/2; /* offset into page */
- return (g4_page << 16) | g4_index; /* pack */
-}
-
-static void docg4_command(struct mtd_info *mtd, unsigned command, int column,
- int page_addr)
-{
- /* handle standard nand commands */
-
- struct nand_chip *nand = mtd->priv;
- struct docg4_priv *doc = nand->priv;
- uint32_t g4_addr = mtd_to_docg4_address(page_addr, column);
-
- MTDDEBUG(MTD_DEBUG_LEVEL3, "%s %x, page_addr=%x, column=%x\n",
- __func__, command, page_addr, column);
-
- /*
- * Save the command and its arguments. This enables emulation of
- * standard flash devices, and also some optimizations.
- */
- doc->last_command.command = command;
- doc->last_command.column = column;
- doc->last_command.page = page_addr;
-
- switch (command) {
- case NAND_CMD_RESET:
- reset(CONFIG_SYS_NAND_BASE);
- break;
-
- case NAND_CMD_READ0:
- read_page_prologue(CONFIG_SYS_NAND_BASE, g4_addr);
- break;
-
- case NAND_CMD_STATUS:
- /* next call to read_byte() will expect a status */
- break;
-
- case NAND_CMD_SEQIN:
- write_page_prologue(CONFIG_SYS_NAND_BASE, g4_addr);
-
- /* hack for deferred write of oob bytes */
- if (doc->oob_page == page_addr)
- memcpy(nand->oob_poi, doc->oob_buf, 16);
- break;
-
- case NAND_CMD_PAGEPROG:
- pageprog(mtd);
- break;
-
- /* we don't expect these, based on review of nand_base.c */
- case NAND_CMD_READOOB:
- case NAND_CMD_READID:
- case NAND_CMD_ERASE1:
- case NAND_CMD_ERASE2:
- printf("docg4_command: unexpected nand command 0x%x\n",
- command);
- break;
- }
-}
-
-static void docg4_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
-{
- int i;
- struct nand_chip *nand = mtd->priv;
- uint16_t *p = (uint16_t *)buf;
- len >>= 1;
-
- for (i = 0; i < len; i++)
- p[i] = readw(nand->IO_ADDR_R);
-}
-
-static int docg4_read_oob(struct mtd_info *mtd, struct nand_chip *nand,
- int page)
-{
- struct docg4_priv *doc = nand->priv;
- void __iomem *docptr = CONFIG_SYS_NAND_BASE;
- uint16_t status;
-
- MTDDEBUG(MTD_DEBUG_LEVEL3, "%s: page %x\n", __func__, page);
-
- /*
- * Oob bytes are read as part of a normal page read. If the previous
- * nand command was a read of the page whose oob is now being read, just
- * copy the oob bytes that we saved in a local buffer and avoid a
- * separate oob read.
- */
- if (doc->last_command.command == NAND_CMD_READ0 &&
- doc->last_command.page == page) {
- memcpy(nand->oob_poi, doc->oob_buf, 16);
- return 0;
- }
-
- /*
- * Separate read of oob data only.
- */
- docg4_command(mtd, NAND_CMD_READ0, nand->ecc.size, page);
-
- writew(DOC_ECCCONF0_READ_MODE | DOCG4_OOB_SIZE, docptr + DOC_ECCCONF0);
- write_nop(docptr);
- write_nop(docptr);
- write_nop(docptr);
- write_nop(docptr);
- write_nop(docptr);
-
- /* the 1st byte from the I/O reg is a status; the rest is oob data */
- status = readw(docptr + DOC_IOSPACE_DATA);
- if (status & DOCG4_READ_ERROR) {
- printf("docg4_read_oob failed: status = 0x%02x\n", status);
- return -EIO;
- }
-
- MTDDEBUG(MTD_DEBUG_LEVEL3, "%s: status = 0x%x\n", __func__, status);
-
- docg4_read_buf(mtd, nand->oob_poi, 16);
-
- write_nop(docptr);
- write_nop(docptr);
- write_nop(docptr);
- writew(0, docptr + DOC_DATAEND);
- write_nop(docptr);
-
- return 0;
-}
-
-static int docg4_write_oob(struct mtd_info *mtd, struct nand_chip *nand,
- int page)
-{
- /*
- * Writing oob-only is not really supported, because MLC nand must write
- * oob bytes at the same time as page data. Nonetheless, we save the
- * oob buffer contents here, and then write it along with the page data
- * if the same page is subsequently written. This allows user space
- * utilities that write the oob data prior to the page data to work
- * (e.g., nandwrite). The disdvantage is that, if the intention was to
- * write oob only, the operation is quietly ignored. Also, oob can get
- * corrupted if two concurrent processes are running nandwrite.
- */
-
- /* note that bytes 7..14 are hw generated hamming/ecc and overwritten */
- struct docg4_priv *doc = nand->priv;
- doc->oob_page = page;
- memcpy(doc->oob_buf, nand->oob_poi, 16);
- return 0;
-}
-
-static int docg4_block_neverbad(struct mtd_info *mtd, loff_t ofs, int getchip)
-{
- /* only called when module_param ignore_badblocks is set */
- return 0;
-}
-
-static void docg4_write_buf16(struct mtd_info *mtd, const uint8_t *buf, int len)
-{
- int i;
- struct nand_chip *nand = mtd->priv;
- uint16_t *p = (uint16_t *)buf;
- len >>= 1;
-
- for (i = 0; i < len; i++)
- writew(p[i], nand->IO_ADDR_W);
-}
-
-static int write_page(struct mtd_info *mtd, struct nand_chip *nand,
- const uint8_t *buf, int use_ecc)
-{
- void __iomem *docptr = CONFIG_SYS_NAND_BASE;
- uint8_t ecc_buf[8];
-
- writew(DOC_ECCCONF0_ECC_ENABLE |
- DOC_ECCCONF0_UNKNOWN |
- DOCG4_BCH_SIZE,
- docptr + DOC_ECCCONF0);
- write_nop(docptr);
-
- /* write the page data */
- docg4_write_buf16(mtd, buf, DOCG4_PAGE_SIZE);
-
- /* oob bytes 0 through 5 are written to I/O reg */
- docg4_write_buf16(mtd, nand->oob_poi, 6);
-
- /* oob byte 6 written to a separate reg */
- writew(nand->oob_poi[6], docptr + DOCG4_OOB_6_7);
-
- write_nop(docptr);
- write_nop(docptr);
-
- /* write hw-generated ecc bytes to oob */
- if (likely(use_ecc)) {
- /* oob byte 7 is hamming code */
- uint8_t hamming = readb(docptr + DOC_HAMMINGPARITY);
- hamming = readb(docptr + DOC_HAMMINGPARITY); /* 2nd read */
- writew(hamming, docptr + DOCG4_OOB_6_7);
- write_nop(docptr);
-
- /* read the 7 bch bytes from ecc regs */
- read_hw_ecc(docptr, ecc_buf);
- ecc_buf[7] = 0; /* clear the "page written" flag */
- }
-
- /* write user-supplied bytes to oob */
- else {
- writew(nand->oob_poi[7], docptr + DOCG4_OOB_6_7);
- write_nop(docptr);
- memcpy(ecc_buf, &nand->oob_poi[8], 8);
- }
-
- docg4_write_buf16(mtd, ecc_buf, 8);
- write_nop(docptr);
- write_nop(docptr);
- writew(0, docptr + DOC_DATAEND);
- write_nop(docptr);
-
- return 0;
-}
-
-static int docg4_write_page_raw(struct mtd_info *mtd, struct nand_chip *nand,
- const uint8_t *buf, int oob_required)
-{
- return write_page(mtd, nand, buf, 0);
-}
-
-static int docg4_write_page(struct mtd_info *mtd, struct nand_chip *nand,
- const uint8_t *buf, int oob_required)
-{
- return write_page(mtd, nand, buf, 1);
-}
-
-static int read_page(struct mtd_info *mtd, struct nand_chip *nand,
- uint8_t *buf, int page, int use_ecc)
-{
- struct docg4_priv *doc = nand->priv;
- void __iomem *docptr = CONFIG_SYS_NAND_BASE;
- uint16_t status, edc_err, *buf16;
-
- writew(DOC_ECCCONF0_READ_MODE |
- DOC_ECCCONF0_ECC_ENABLE |
- DOC_ECCCONF0_UNKNOWN |
- DOCG4_BCH_SIZE,
- docptr + DOC_ECCCONF0);
- write_nop(docptr);
- write_nop(docptr);
- write_nop(docptr);
- write_nop(docptr);
- write_nop(docptr);
-
- /* the 1st byte from the I/O reg is a status; the rest is page data */
- status = readw(docptr + DOC_IOSPACE_DATA);
- if (status & DOCG4_READ_ERROR) {
- printf("docg4_read_page: bad status: 0x%02x\n", status);
- writew(0, docptr + DOC_DATAEND);
- return -EIO;
- }
-
- docg4_read_buf(mtd, buf, DOCG4_PAGE_SIZE); /* read the page data */
-
- /* first 14 oob bytes read from I/O reg */
- docg4_read_buf(mtd, nand->oob_poi, 14);
-
- /* last 2 read from another reg */
- buf16 = (uint16_t *)(nand->oob_poi + 14);
- *buf16 = readw(docptr + DOCG4_MYSTERY_REG);
-
- /*
- * Diskonchips read oob immediately after a page read. Mtd
- * infrastructure issues a separate command for reading oob after the
- * page is read. So we save the oob bytes in a local buffer and just
- * copy it if the next command reads oob from the same page.
- */
- memcpy(doc->oob_buf, nand->oob_poi, 16);
-
- write_nop(docptr);
-
- if (likely(use_ecc)) {
- /* read the register that tells us if bitflip(s) detected */
- edc_err = readw(docptr + DOC_ECCCONF1);
- edc_err = readw(docptr + DOC_ECCCONF1);
-
- /* If bitflips are reported, attempt to correct with ecc */
- if (edc_err & DOC_ECCCONF1_BCH_SYNDROM_ERR) {
- int bits_corrected = correct_data(mtd, buf, page);
- if (bits_corrected == -EBADMSG)
- mtd->ecc_stats.failed++;
- else
- mtd->ecc_stats.corrected += bits_corrected;
- }
- }
-
- writew(0, docptr + DOC_DATAEND);
- return 0;
-}
-
-
-static int docg4_read_page_raw(struct mtd_info *mtd, struct nand_chip *nand,
- uint8_t *buf, int oob_required, int page)
-{
- return read_page(mtd, nand, buf, page, 0);
-}
-
-static int docg4_read_page(struct mtd_info *mtd, struct nand_chip *nand,
- uint8_t *buf, int oob_required, int page)
-{
- return read_page(mtd, nand, buf, page, 1);
-}
-
-static int docg4_erase_block(struct mtd_info *mtd, int page)
-{
- struct nand_chip *nand = mtd->priv;
- struct docg4_priv *doc = nand->priv;
- void __iomem *docptr = CONFIG_SYS_NAND_BASE;
- uint16_t g4_page;
-
- MTDDEBUG(MTD_DEBUG_LEVEL3, "%s: page %04x\n", __func__, page);
-
- sequence_reset(docptr);
-
- writew(DOCG4_SEQ_BLOCKERASE, docptr + DOC_FLASHSEQUENCE);
- writew(DOC_CMD_PROG_BLOCK_ADDR, docptr + DOC_FLASHCOMMAND);
- write_nop(docptr);
-
- /* only 2 bytes of address are written to specify erase block */
- g4_page = (uint16_t)(page / 4); /* to g4's 2k page addressing */
- writeb(g4_page & 0xff, docptr + DOC_FLASHADDRESS);
- g4_page >>= 8;
- writeb(g4_page & 0xff, docptr + DOC_FLASHADDRESS);
- write_nop(docptr);
-
- /* start the erasure */
- writew(DOC_CMD_ERASECYCLE2, docptr + DOC_FLASHCOMMAND);
- write_nop(docptr);
- write_nop(docptr);
-
- poll_status(docptr);
- writew(DOCG4_SEQ_FLUSH, docptr + DOC_FLASHSEQUENCE);
- writew(DOCG4_CMD_FLUSH, docptr + DOC_FLASHCOMMAND);
- writew(DOC_ECCCONF0_READ_MODE | 4, docptr + DOC_ECCCONF0);
- write_nop(docptr);
- write_nop(docptr);
- write_nop(docptr);
- write_nop(docptr);
- write_nop(docptr);
-
- read_progstatus(doc, docptr);
-
- writew(0, docptr + DOC_DATAEND);
- write_nop(docptr);
- poll_status(docptr);
- write_nop(docptr);
-
- return nand->waitfunc(mtd, nand);
-}
-
-static int read_factory_bbt(struct mtd_info *mtd)
-{
- /*
- * The device contains a read-only factory bad block table. Read it and
- * update the memory-based bbt accordingly.
- */
-
- struct nand_chip *nand = mtd->priv;
- uint32_t g4_addr = mtd_to_docg4_address(DOCG4_FACTORY_BBT_PAGE, 0);
- uint8_t *buf;
- int i, block, status;
-
- buf = kzalloc(DOCG4_PAGE_SIZE, GFP_KERNEL);
- if (buf == NULL)
- return -ENOMEM;
-
- read_page_prologue(CONFIG_SYS_NAND_BASE, g4_addr);
- status = docg4_read_page(mtd, nand, buf, 0, DOCG4_FACTORY_BBT_PAGE);
- if (status)
- goto exit;
-
- /*
- * If no memory-based bbt was created, exit. This will happen if module
- * parameter ignore_badblocks is set. Then why even call this function?
- * For an unknown reason, block erase always fails if it's the first
- * operation after device power-up. The above read ensures it never is.
- * Ugly, I know.
- */
- if (nand->bbt == NULL) /* no memory-based bbt */
- goto exit;
-
- /*
- * Parse factory bbt and update memory-based bbt. Factory bbt format is
- * simple: one bit per block, block numbers increase left to right (msb
- * to lsb). Bit clear means bad block.
- */
- for (i = block = 0; block < DOCG4_NUMBLOCKS; block += 8, i++) {
- int bitnum;
- uint8_t mask;
- for (bitnum = 0, mask = 0x80;
- bitnum < 8; bitnum++, mask >>= 1) {
- if (!(buf[i] & mask)) {
- int badblock = block + bitnum;
- nand->bbt[badblock / 4] |=
- 0x03 << ((badblock % 4) * 2);
- mtd->ecc_stats.badblocks++;
- printf("factory-marked bad block: %d\n",
- badblock);
- }
- }
- }
- exit:
- kfree(buf);
- return status;
-}
-
-static int docg4_block_markbad(struct mtd_info *mtd, loff_t ofs)
-{
- /*
- * Mark a block as bad. Bad blocks are marked in the oob area of the
- * first page of the block. The default scan_bbt() in the nand
- * infrastructure code works fine for building the memory-based bbt
- * during initialization, as does the nand infrastructure function that
- * checks if a block is bad by reading the bbt. This function replaces
- * the nand default because writes to oob-only are not supported.
- */
-
- int ret, i;
- uint8_t *buf;
- struct nand_chip *nand = mtd->priv;
- struct nand_bbt_descr *bbtd = nand->badblock_pattern;
- int block = (int)(ofs >> nand->bbt_erase_shift);
- int page = (int)(ofs >> nand->page_shift);
- uint32_t g4_addr = mtd_to_docg4_address(page, 0);
-
- MTDDEBUG(MTD_DEBUG_LEVEL3, "%s: %08llx\n", __func__, ofs);
-
- if (unlikely(ofs & (DOCG4_BLOCK_SIZE - 1)))
- printf("%s: ofs %llx not start of block!\n",
- __func__, ofs);
-
- /* allocate blank buffer for page data */
- buf = kzalloc(DOCG4_PAGE_SIZE, GFP_KERNEL);
- if (buf == NULL)
- return -ENOMEM;
-
- /* update bbt in memory */
- nand->bbt[block / 4] |= 0x01 << ((block & 0x03) * 2);
-
- /* write bit-wise negation of pattern to oob buffer */
- memset(nand->oob_poi, 0xff, mtd->oobsize);
- for (i = 0; i < bbtd->len; i++)
- nand->oob_poi[bbtd->offs + i] = ~bbtd->pattern[i];
-
- /* write first page of block */
- write_page_prologue(CONFIG_SYS_NAND_BASE, g4_addr);
- docg4_write_page(mtd, nand, buf, 1);
- ret = pageprog(mtd);
- if (!ret)
- mtd->ecc_stats.badblocks++;
-
- kfree(buf);
-
- return ret;
-}
-
-static uint8_t docg4_read_byte(struct mtd_info *mtd)
-{
- struct nand_chip *nand = mtd->priv;
- struct docg4_priv *doc = nand->priv;
-
- MTDDEBUG(MTD_DEBUG_LEVEL3, "%s\n", __func__);
-
- if (doc->last_command.command == NAND_CMD_STATUS) {
- int status;
-
- /*
- * Previous nand command was status request, so nand
- * infrastructure code expects to read the status here. If an
- * error occurred in a previous operation, report it.
- */
- doc->last_command.command = 0;
-
- if (doc->status) {
- status = doc->status;
- doc->status = 0;
- }
-
- /* why is NAND_STATUS_WP inverse logic?? */
- else
- status = NAND_STATUS_WP | NAND_STATUS_READY;
-
- return status;
- }
-
- printf("unexpectd call to read_byte()\n");
-
- return 0;
-}
-
-static int docg4_wait(struct mtd_info *mtd, struct nand_chip *nand)
-{
- struct docg4_priv *doc = nand->priv;
- int status = NAND_STATUS_WP; /* inverse logic?? */
- MTDDEBUG(MTD_DEBUG_LEVEL3, "%s...\n", __func__);
-
- /* report any previously unreported error */
- if (doc->status) {
- status |= doc->status;
- doc->status = 0;
- return status;
- }
-
- status |= poll_status(CONFIG_SYS_NAND_BASE);
- return status;
-}
-
-int docg4_nand_init(struct mtd_info *mtd, struct nand_chip *nand, int devnum)
-{
- uint16_t id1, id2;
- struct docg4_priv *docg4;
- int retval;
-
- docg4 = kzalloc(sizeof(*docg4), GFP_KERNEL);
- if (!docg4)
- return -1;
-
- mtd->priv = nand;
- nand->priv = docg4;
-
- /* These must be initialized here because the docg4 is non-standard
- * and doesn't produce an id that the nand code can use to look up
- * these values (nand_scan_ident() not called).
- */
- mtd->size = DOCG4_CHIP_SIZE;
- mtd->name = "Msys_Diskonchip_G4";
- mtd->writesize = DOCG4_PAGE_SIZE;
- mtd->erasesize = DOCG4_BLOCK_SIZE;
- mtd->oobsize = DOCG4_OOB_SIZE;
-
- nand->IO_ADDR_R =
- (void __iomem *)CONFIG_SYS_NAND_BASE + DOC_IOSPACE_DATA;
- nand->IO_ADDR_W = nand->IO_ADDR_R;
- nand->chipsize = DOCG4_CHIP_SIZE;
- nand->chip_shift = DOCG4_CHIP_SHIFT;
- nand->bbt_erase_shift = DOCG4_ERASE_SHIFT;
- nand->phys_erase_shift = DOCG4_ERASE_SHIFT;
- nand->chip_delay = 20;
- nand->page_shift = DOCG4_PAGE_SHIFT;
- nand->pagemask = 0x3ffff;
- nand->badblockpos = NAND_LARGE_BADBLOCK_POS;
- nand->badblockbits = 8;
- nand->ecc.layout = &docg4_oobinfo;
- nand->ecc.mode = NAND_ECC_HW_SYNDROME;
- nand->ecc.size = DOCG4_PAGE_SIZE;
- nand->ecc.prepad = 8;
- nand->ecc.bytes = 8;
- nand->ecc.strength = DOCG4_T;
- nand->options = NAND_BUSWIDTH_16 | NAND_NO_SUBPAGE_WRITE;
- nand->controller = &nand->hwcontrol;
-
- /* methods */
- nand->cmdfunc = docg4_command;
- nand->waitfunc = docg4_wait;
- nand->select_chip = docg4_select_chip;
- nand->read_byte = docg4_read_byte;
- nand->block_markbad = docg4_block_markbad;
- nand->read_buf = docg4_read_buf;
- nand->write_buf = docg4_write_buf16;
- nand->scan_bbt = nand_default_bbt;
- nand->erase = docg4_erase_block;
- nand->ecc.read_page = docg4_read_page;
- nand->ecc.write_page = docg4_write_page;
- nand->ecc.read_page_raw = docg4_read_page_raw;
- nand->ecc.write_page_raw = docg4_write_page_raw;
- nand->ecc.read_oob = docg4_read_oob;
- nand->ecc.write_oob = docg4_write_oob;
-
- /*
- * The way the nand infrastructure code is written, a memory-based bbt
- * is not created if NAND_SKIP_BBTSCAN is set. With no memory bbt,
- * nand->block_bad() is used. So when ignoring bad blocks, we skip the
- * scan and define a dummy block_bad() which always returns 0.
- */
- if (ignore_badblocks) {
- nand->options |= NAND_SKIP_BBTSCAN;
- nand->block_bad = docg4_block_neverbad;
- }
-
- reset(CONFIG_SYS_NAND_BASE);
-
- /* check for presence of g4 chip by reading id registers */
- id1 = readw(CONFIG_SYS_NAND_BASE + DOC_CHIPID);
- id1 = readw(CONFIG_SYS_NAND_BASE + DOCG4_MYSTERY_REG);
- id2 = readw(CONFIG_SYS_NAND_BASE + DOC_CHIPID_INV);
- id2 = readw(CONFIG_SYS_NAND_BASE + DOCG4_MYSTERY_REG);
- if (id1 != DOCG4_IDREG1_VALUE || id2 != DOCG4_IDREG2_VALUE)
- return -1;
-
- /* initialize bch algorithm */
- docg4->bch = init_bch(DOCG4_M, DOCG4_T, DOCG4_PRIMITIVE_POLY);
- if (docg4->bch == NULL)
- return -1;
-
- retval = nand_scan_tail(mtd);
- if (retval)
- return -1;
-
- /*
- * Scan for bad blocks and create bbt here, then add the factory-marked
- * bad blocks to the bbt.
- */
- nand->scan_bbt(mtd);
- nand->options |= NAND_BBT_SCANNED;
- retval = read_factory_bbt(mtd);
- if (retval)
- return -1;
-
- retval = nand_register(devnum);
- if (retval)
- return -1;
-
- return 0;
-}
diff --git a/drivers/mtd/nand/docg4_spl.c b/drivers/mtd/nand/docg4_spl.c
deleted file mode 100644
index 351b75a090..0000000000
--- a/drivers/mtd/nand/docg4_spl.c
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
- * SPL driver for Diskonchip G4 nand flash
- *
- * Copyright (C) 2013 Mike Dunn <mikedunn@newsguy.com>
- *
- * SPDX-License-Identifier: GPL-2.0+
- *
- * This driver basically mimics the load functionality of a typical IPL (initial
- * program loader) resident in the 2k NOR-like region of the docg4 that is
- * mapped to the reset vector. It allows the u-boot SPL to continue loading if
- * the IPL loads a fixed number of flash blocks that is insufficient to contain
- * the entire u-boot image. In this case, a concatenated spl + u-boot image is
- * written at the flash offset from which the IPL loads an image, and when the
- * IPL jumps to the SPL, the SPL resumes loading where the IPL left off. See
- * the palmtreo680 for an example.
- *
- * This driver assumes that the data was written to the flash using the device's
- * "reliable" mode, and also assumes that each 512 byte page is stored
- * redundantly in the subsequent page. This storage format is likely to be used
- * by all boards that boot from the docg4. The format compensates for the lack
- * of ecc in the IPL.
- *
- * Reliable mode reduces the capacity of a block by half, and the redundant
- * pages reduce it by half again. As a result, the normal 256k capacity of a
- * block is reduced to 64k for the purposes of the IPL/SPL.
- */
-
-#include <asm/io.h>
-#include <linux/mtd/docg4.h>
-
-/* forward declarations */
-static inline void write_nop(void __iomem *docptr);
-static int poll_status(void __iomem *docptr);
-static void write_addr(void __iomem *docptr, uint32_t docg4_addr);
-static void address_sequence(unsigned int g4_page, unsigned int g4_index,
- void __iomem *docptr);
-static int docg4_load_block_reliable(uint32_t flash_offset, void *dest_addr);
-
-int nand_spl_load_image(uint32_t offs, unsigned int size, void *dst)
-{
- void *load_addr = dst;
- uint32_t flash_offset = offs;
- const unsigned int block_count =
- (size + DOCG4_BLOCK_CAPACITY_SPL - 1)
- / DOCG4_BLOCK_CAPACITY_SPL;
- int i;
-
- for (i = 0; i < block_count; i++) {
- int ret = docg4_load_block_reliable(flash_offset, load_addr);
- if (ret)
- return ret;
- load_addr += DOCG4_BLOCK_CAPACITY_SPL;
- flash_offset += DOCG4_BLOCK_SIZE;
- }
- return 0;
-}
-
-static inline void write_nop(void __iomem *docptr)
-{
- writew(0, docptr + DOC_NOP);
-}
-
-static int poll_status(void __iomem *docptr)
-{
- /*
- * Busy-wait for the FLASHREADY bit to be set in the FLASHCONTROL
- * register. Operations known to take a long time (e.g., block erase)
- * should sleep for a while before calling this.
- */
-
- uint8_t flash_status;
-
- /* hardware quirk requires reading twice initially */
- flash_status = readb(docptr + DOC_FLASHCONTROL);
-
- do {
- flash_status = readb(docptr + DOC_FLASHCONTROL);
- } while (!(flash_status & DOC_CTRL_FLASHREADY));
-
- return 0;
-}
-
-static void write_addr(void __iomem *docptr, uint32_t docg4_addr)
-{
- /* write the four address bytes packed in docg4_addr to the device */
-
- writeb(docg4_addr & 0xff, docptr + DOC_FLASHADDRESS);
- docg4_addr >>= 8;
- writeb(docg4_addr & 0xff, docptr + DOC_FLASHADDRESS);
- docg4_addr >>= 8;
- writeb(docg4_addr & 0xff, docptr + DOC_FLASHADDRESS);
- docg4_addr >>= 8;
- writeb(docg4_addr & 0xff, docptr + DOC_FLASHADDRESS);
-}
-
-static void address_sequence(unsigned int g4_page, unsigned int g4_index,
- void __iomem *docptr)
-{
- writew(DOCG4_SEQ_PAGE_READ, docptr + DOC_FLASHSEQUENCE);
- writew(DOCG4_CMD_PAGE_READ, docptr + DOC_FLASHCOMMAND);
- write_nop(docptr);
- write_addr(docptr, ((uint32_t)g4_page << 16) | g4_index);
- write_nop(docptr);
-}
-
-static int docg4_load_block_reliable(uint32_t flash_offset, void *dest_addr)
-{
- void __iomem *docptr = (void *)CONFIG_SYS_NAND_BASE;
- unsigned int g4_page = flash_offset >> 11; /* 2k page */
- const unsigned int last_g4_page = g4_page + 0x80; /* last in block */
- int g4_index = 0;
- uint16_t flash_status;
- uint16_t *buf;
-
- /* flash_offset must be aligned to the start of a block */
- if (flash_offset & 0x3ffff)
- return -1;
-
- writew(DOC_SEQ_RESET, docptr + DOC_FLASHSEQUENCE);
- writew(DOC_CMD_RESET, docptr + DOC_FLASHCOMMAND);
- write_nop(docptr);
- write_nop(docptr);
- poll_status(docptr);
- write_nop(docptr);
- writew(0x45, docptr + DOC_FLASHSEQUENCE);
- writew(0xa3, docptr + DOC_FLASHCOMMAND);
- write_nop(docptr);
- writew(0x22, docptr + DOC_FLASHCOMMAND);
- write_nop(docptr);
-
- /* read 1st 4 oob bytes of first subpage of block */
- address_sequence(g4_page, 0x0100, docptr); /* index at oob */
- write_nop(docptr);
- flash_status = readw(docptr + DOC_FLASHCONTROL);
- flash_status = readw(docptr + DOC_FLASHCONTROL);
- if (flash_status & 0x06) /* sequence or protection errors */
- return -1;
- writew(DOCG4_CMD_READ2, docptr + DOC_FLASHCOMMAND);
- write_nop(docptr);
- write_nop(docptr);
- poll_status(docptr);
- writew(DOC_ECCCONF0_READ_MODE | 4, docptr + DOC_ECCCONF0);
- write_nop(docptr);
- write_nop(docptr);
- write_nop(docptr);
- write_nop(docptr);
- write_nop(docptr);
-
- /*
- * Here we read the first four oob bytes of the first page of the block.
- * The IPL on the palmtreo680 requires that this contain a 32 bit magic
- * number, or the load aborts. We'll ignore it.
- */
- readw(docptr + 0x103c); /* hw quirk; 1st read discarded */
- readw(docptr + 0x103c); /* lower 16 bits of magic number */
- readw(docptr + DOCG4_MYSTERY_REG); /* upper 16 bits of magic number */
- writew(0, docptr + DOC_DATAEND);
- write_nop(docptr);
- write_nop(docptr);
-
- /* load contents of block to memory */
- buf = (uint16_t *)dest_addr;
- do {
- int i;
-
- address_sequence(g4_page, g4_index, docptr);
- writew(DOCG4_CMD_READ2,
- docptr + DOC_FLASHCOMMAND);
- write_nop(docptr);
- write_nop(docptr);
- poll_status(docptr);
- writew(DOC_ECCCONF0_READ_MODE |
- DOC_ECCCONF0_ECC_ENABLE |
- DOCG4_BCH_SIZE,
- docptr + DOC_ECCCONF0);
- write_nop(docptr);
- write_nop(docptr);
- write_nop(docptr);
- write_nop(docptr);
- write_nop(docptr);
-
- /* read the 512 bytes of page data, 2 bytes at a time */
- readw(docptr + 0x103c); /* hw quirk */
- for (i = 0; i < 256; i++)
- *buf++ = readw(docptr + 0x103c);
-
- /* read oob, but discard it */
- for (i = 0; i < 7; i++)
- readw(docptr + 0x103c);
- readw(docptr + DOCG4_OOB_6_7);
- readw(docptr + DOCG4_OOB_6_7);
-
- writew(0, docptr + DOC_DATAEND);
- write_nop(docptr);
- write_nop(docptr);
-
- if (!(g4_index & 0x100)) {
- /* not redundant subpage read; check for ecc error */
- write_nop(docptr);
- flash_status = readw(docptr + DOC_ECCCONF1);
- flash_status = readw(docptr + DOC_ECCCONF1);
- if (flash_status & 0x80) { /* ecc error */
- g4_index += 0x108; /* read redundant subpage */
- buf -= 256; /* back up ram ptr */
- continue;
- } else /* no ecc error */
- g4_index += 0x210; /* skip redundant subpage */
- } else /* redundant page was just read; skip ecc error check */
- g4_index += 0x108;
-
- if (g4_index == 0x420) { /* finished with 2k page */
- g4_index = 0;
- g4_page += 2; /* odd-numbered 2k pages skipped */
- }
-
- } while (g4_page != last_g4_page); /* while still on same block */
-
- return 0;
-}
diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c
index d457d53574..f621f14122 100644
--- a/drivers/mtd/nand/fsl_elbc_nand.c
+++ b/drivers/mtd/nand/fsl_elbc_nand.c
@@ -154,8 +154,8 @@ static struct nand_bbt_descr bbt_mirror_descr = {
*/
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 nand_chip *chip = mtd_to_nand(mtd);
+ struct fsl_elbc_mtd *priv = nand_get_controller_data(chip);
struct fsl_elbc_ctrl *ctrl = priv->ctrl;
fsl_lbc_t *lbc = ctrl->regs;
int buf_num;
@@ -194,8 +194,8 @@ static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob)
*/
static int fsl_elbc_run_command(struct mtd_info *mtd)
{
- struct nand_chip *chip = mtd->priv;
- struct fsl_elbc_mtd *priv = chip->priv;
+ struct nand_chip *chip = mtd_to_nand(mtd);
+ struct fsl_elbc_mtd *priv = nand_get_controller_data(chip);
struct fsl_elbc_ctrl *ctrl = priv->ctrl;
fsl_lbc_t *lbc = ctrl->regs;
u32 timeo = (CONFIG_SYS_HZ * 10) / 1000;
@@ -246,7 +246,7 @@ static int fsl_elbc_run_command(struct mtd_info *mtd)
static void fsl_elbc_do_read(struct nand_chip *chip, int oob)
{
- struct fsl_elbc_mtd *priv = chip->priv;
+ struct fsl_elbc_mtd *priv = nand_get_controller_data(chip);
struct fsl_elbc_ctrl *ctrl = priv->ctrl;
fsl_lbc_t *lbc = ctrl->regs;
@@ -279,8 +279,8 @@ static void fsl_elbc_do_read(struct nand_chip *chip, int oob)
static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
int column, int page_addr)
{
- struct nand_chip *chip = mtd->priv;
- struct fsl_elbc_mtd *priv = chip->priv;
+ struct nand_chip *chip = mtd_to_nand(mtd);
+ struct fsl_elbc_mtd *priv = nand_get_controller_data(chip);
struct fsl_elbc_ctrl *ctrl = priv->ctrl;
fsl_lbc_t *lbc = ctrl->regs;
@@ -489,8 +489,8 @@ static void fsl_elbc_select_chip(struct mtd_info *mtd, int chip)
*/
static void fsl_elbc_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
{
- struct nand_chip *chip = mtd->priv;
- struct fsl_elbc_mtd *priv = chip->priv;
+ struct nand_chip *chip = mtd_to_nand(mtd);
+ struct fsl_elbc_mtd *priv = nand_get_controller_data(chip);
struct fsl_elbc_ctrl *ctrl = priv->ctrl;
unsigned int bufsize = mtd->writesize + mtd->oobsize;
@@ -526,8 +526,8 @@ static void fsl_elbc_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
*/
static u8 fsl_elbc_read_byte(struct mtd_info *mtd)
{
- struct nand_chip *chip = mtd->priv;
- struct fsl_elbc_mtd *priv = chip->priv;
+ struct nand_chip *chip = mtd_to_nand(mtd);
+ struct fsl_elbc_mtd *priv = nand_get_controller_data(chip);
struct fsl_elbc_ctrl *ctrl = priv->ctrl;
/* If there are still bytes in the FCM, then use the next byte. */
@@ -543,8 +543,8 @@ static u8 fsl_elbc_read_byte(struct mtd_info *mtd)
*/
static void fsl_elbc_read_buf(struct mtd_info *mtd, u8 *buf, int len)
{
- struct nand_chip *chip = mtd->priv;
- struct fsl_elbc_mtd *priv = chip->priv;
+ struct nand_chip *chip = mtd_to_nand(mtd);
+ struct fsl_elbc_mtd *priv = nand_get_controller_data(chip);
struct fsl_elbc_ctrl *ctrl = priv->ctrl;
int avail;
@@ -566,7 +566,7 @@ static void fsl_elbc_read_buf(struct mtd_info *mtd, u8 *buf, int len)
*/
static int fsl_elbc_wait(struct mtd_info *mtd, struct nand_chip *chip)
{
- struct fsl_elbc_mtd *priv = chip->priv;
+ struct fsl_elbc_mtd *priv = nand_get_controller_data(chip);
struct fsl_elbc_ctrl *ctrl = priv->ctrl;
fsl_lbc_t *lbc = ctrl->regs;
@@ -611,7 +611,8 @@ static int fsl_elbc_read_page(struct mtd_info *mtd, struct nand_chip *chip,
* waitfunc.
*/
static int fsl_elbc_write_page(struct mtd_info *mtd, struct nand_chip *chip,
- const uint8_t *buf, int oob_required)
+ const uint8_t *buf, int oob_required,
+ int page)
{
fsl_elbc_write_buf(mtd, buf, mtd->writesize);
fsl_elbc_write_buf(mtd, chip->oob_poi, mtd->oobsize);
@@ -626,7 +627,7 @@ static struct fsl_elbc_ctrl *elbc_ctrl;
*/
static int fsl_elbc_write_subpage(struct mtd_info *mtd, struct nand_chip *chip,
uint32_t offset, uint32_t data_len,
- const uint8_t *buf, int oob_required)
+ const uint8_t *buf, int oob_required, int page)
{
fsl_elbc_write_buf(mtd, buf, mtd->writesize);
fsl_elbc_write_buf(mtd, chip->oob_poi, mtd->oobsize);
@@ -656,7 +657,7 @@ static void fsl_elbc_ctrl_init(void)
static int fsl_elbc_chip_init(int devnum, u8 *addr)
{
- struct mtd_info *mtd = &nand_info[devnum];
+ struct mtd_info *mtd;
struct nand_chip *nand;
struct fsl_elbc_mtd *priv;
uint32_t br = 0, or = 0;
@@ -697,7 +698,7 @@ static int fsl_elbc_chip_init(int devnum, u8 *addr)
}
nand = &priv->chip;
- mtd->priv = nand;
+ mtd = nand_to_mtd(nand);
elbc_ctrl->chips[priv->bank] = priv;
@@ -719,7 +720,7 @@ static int fsl_elbc_chip_init(int devnum, u8 *addr)
nand->bbt_options = NAND_BBT_USE_FLASH;
nand->controller = &elbc_ctrl->controller;
- nand->priv = priv;
+ nand_set_controller_data(nand, priv);
nand->ecc.read_page = fsl_elbc_read_page;
nand->ecc.write_page = fsl_elbc_write_page;
@@ -787,7 +788,7 @@ static int fsl_elbc_chip_init(int devnum, u8 *addr)
if (ret)
return ret;
- ret = nand_register(devnum);
+ ret = nand_register(devnum, mtd);
if (ret)
return ret;
diff --git a/drivers/mtd/nand/fsl_ifc_nand.c b/drivers/mtd/nand/fsl_ifc_nand.c
index 975b0d4613..7001cbd62d 100644
--- a/drivers/mtd/nand/fsl_ifc_nand.c
+++ b/drivers/mtd/nand/fsl_ifc_nand.c
@@ -222,8 +222,8 @@ static struct nand_bbt_descr bbt_mirror_descr = {
*/
static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob)
{
- struct nand_chip *chip = mtd->priv;
- struct fsl_ifc_mtd *priv = chip->priv;
+ struct nand_chip *chip = mtd_to_nand(mtd);
+ struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
struct fsl_ifc_ctrl *ctrl = priv->ctrl;
struct fsl_ifc_runtime *ifc = ctrl->regs.rregs;
int buf_num;
@@ -247,8 +247,8 @@ static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob)
static int is_blank(struct mtd_info *mtd, struct fsl_ifc_ctrl *ctrl,
unsigned int bufnum)
{
- struct nand_chip *chip = mtd->priv;
- struct fsl_ifc_mtd *priv = chip->priv;
+ struct nand_chip *chip = mtd_to_nand(mtd);
+ struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
u8 __iomem *addr = priv->vbase + bufnum * (mtd->writesize * 2);
u32 __iomem *main = (u32 *)addr;
u8 __iomem *oob = addr + mtd->writesize;
@@ -286,8 +286,8 @@ static int check_read_ecc(struct mtd_info *mtd, struct fsl_ifc_ctrl *ctrl,
*/
static int fsl_ifc_run_command(struct mtd_info *mtd)
{
- struct nand_chip *chip = mtd->priv;
- struct fsl_ifc_mtd *priv = chip->priv;
+ struct nand_chip *chip = mtd_to_nand(mtd);
+ struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
struct fsl_ifc_ctrl *ctrl = priv->ctrl;
struct fsl_ifc_runtime *ifc = ctrl->regs.rregs;
u32 timeo = (CONFIG_SYS_HZ * 10) / 1000;
@@ -367,7 +367,7 @@ static void fsl_ifc_do_read(struct nand_chip *chip,
int oob,
struct mtd_info *mtd)
{
- struct fsl_ifc_mtd *priv = chip->priv;
+ struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
struct fsl_ifc_ctrl *ctrl = priv->ctrl;
struct fsl_ifc_runtime *ifc = ctrl->regs.rregs;
@@ -404,8 +404,8 @@ static void fsl_ifc_do_read(struct nand_chip *chip,
static void fsl_ifc_cmdfunc(struct mtd_info *mtd, unsigned int command,
int column, int page_addr)
{
- struct nand_chip *chip = mtd->priv;
- struct fsl_ifc_mtd *priv = chip->priv;
+ struct nand_chip *chip = mtd_to_nand(mtd);
+ struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
struct fsl_ifc_ctrl *ctrl = priv->ctrl;
struct fsl_ifc_runtime *ifc = ctrl->regs.rregs;
@@ -607,8 +607,8 @@ static void fsl_ifc_cmdfunc(struct mtd_info *mtd, unsigned int command,
*/
static void fsl_ifc_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
{
- struct nand_chip *chip = mtd->priv;
- struct fsl_ifc_mtd *priv = chip->priv;
+ struct nand_chip *chip = mtd_to_nand(mtd);
+ struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
struct fsl_ifc_ctrl *ctrl = priv->ctrl;
unsigned int bufsize = mtd->writesize + mtd->oobsize;
@@ -635,8 +635,8 @@ static void fsl_ifc_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
*/
static u8 fsl_ifc_read_byte(struct mtd_info *mtd)
{
- struct nand_chip *chip = mtd->priv;
- struct fsl_ifc_mtd *priv = chip->priv;
+ struct nand_chip *chip = mtd_to_nand(mtd);
+ struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
struct fsl_ifc_ctrl *ctrl = priv->ctrl;
unsigned int offset;
@@ -659,8 +659,8 @@ static u8 fsl_ifc_read_byte(struct mtd_info *mtd)
*/
static uint8_t fsl_ifc_read_byte16(struct mtd_info *mtd)
{
- struct nand_chip *chip = mtd->priv;
- struct fsl_ifc_mtd *priv = chip->priv;
+ struct nand_chip *chip = mtd_to_nand(mtd);
+ struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
struct fsl_ifc_ctrl *ctrl = priv->ctrl;
uint16_t data;
@@ -683,8 +683,8 @@ static uint8_t fsl_ifc_read_byte16(struct mtd_info *mtd)
*/
static void fsl_ifc_read_buf(struct mtd_info *mtd, u8 *buf, int len)
{
- struct nand_chip *chip = mtd->priv;
- struct fsl_ifc_mtd *priv = chip->priv;
+ struct nand_chip *chip = mtd_to_nand(mtd);
+ struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
struct fsl_ifc_ctrl *ctrl = priv->ctrl;
int avail;
@@ -706,7 +706,7 @@ static void fsl_ifc_read_buf(struct mtd_info *mtd, u8 *buf, int len)
*/
static int fsl_ifc_wait(struct mtd_info *mtd, struct nand_chip *chip)
{
- struct fsl_ifc_mtd *priv = chip->priv;
+ struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
struct fsl_ifc_ctrl *ctrl = priv->ctrl;
struct fsl_ifc_runtime *ifc = ctrl->regs.rregs;
u32 nand_fsr;
@@ -739,7 +739,7 @@ static int fsl_ifc_wait(struct mtd_info *mtd, struct nand_chip *chip)
static int fsl_ifc_read_page(struct mtd_info *mtd, struct nand_chip *chip,
uint8_t *buf, int oob_required, int page)
{
- struct fsl_ifc_mtd *priv = chip->priv;
+ struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
struct fsl_ifc_ctrl *ctrl = priv->ctrl;
fsl_ifc_read_buf(mtd, buf, mtd->writesize);
@@ -755,7 +755,7 @@ static int fsl_ifc_read_page(struct mtd_info *mtd, struct nand_chip *chip,
* waitfunc.
*/
static int fsl_ifc_write_page(struct mtd_info *mtd, struct nand_chip *chip,
- const uint8_t *buf, int oob_required)
+ const uint8_t *buf, int oob_required, int page)
{
fsl_ifc_write_buf(mtd, buf, mtd->writesize);
fsl_ifc_write_buf(mtd, chip->oob_poi, mtd->oobsize);
@@ -880,7 +880,7 @@ static int fsl_ifc_sram_init(uint32_t ver)
static int fsl_ifc_chip_init(int devnum, u8 *addr)
{
- struct mtd_info *mtd = &nand_info[devnum];
+ struct mtd_info *mtd;
struct nand_chip *nand;
struct fsl_ifc_mtd *priv;
struct nand_ecclayout *layout;
@@ -925,7 +925,7 @@ static int fsl_ifc_chip_init(int devnum, u8 *addr)
}
nand = &priv->chip;
- mtd->priv = nand;
+ mtd = nand_to_mtd(nand);
ifc_ctrl->chips[priv->bank] = priv;
@@ -954,7 +954,7 @@ static int fsl_ifc_chip_init(int devnum, u8 *addr)
}
nand->controller = &ifc_ctrl->controller;
- nand->priv = priv;
+ nand_set_controller_data(nand, priv);
nand->ecc.read_page = fsl_ifc_read_page;
nand->ecc.write_page = fsl_ifc_write_page;
@@ -1044,7 +1044,7 @@ static int fsl_ifc_chip_init(int devnum, u8 *addr)
if (ret)
return ret;
- ret = nand_register(devnum);
+ ret = nand_register(devnum, mtd);
if (ret)
return ret;
return 0;
diff --git a/drivers/mtd/nand/fsl_upm.c b/drivers/mtd/nand/fsl_upm.c
index 5426c32114..d2b388197b 100644
--- a/drivers/mtd/nand/fsl_upm.c
+++ b/drivers/mtd/nand/fsl_upm.c
@@ -64,8 +64,8 @@ static void fun_wait(struct fsl_upm_nand *fun)
#if CONFIG_SYS_NAND_MAX_CHIPS > 1
static void fun_select_chip(struct mtd_info *mtd, int chip_nr)
{
- struct nand_chip *chip = mtd->priv;
- struct fsl_upm_nand *fun = chip->priv;
+ struct nand_chip *chip = mtd_to_nand(mtd);
+ struct fsl_upm_nand *fun = nand_get_controller_data(chip);
if (chip_nr >= 0) {
fun->chip_nr = chip_nr;
@@ -79,8 +79,8 @@ static void fun_select_chip(struct mtd_info *mtd, int chip_nr)
static void fun_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
{
- struct nand_chip *chip = mtd->priv;
- struct fsl_upm_nand *fun = chip->priv;
+ struct nand_chip *chip = mtd_to_nand(mtd);
+ struct fsl_upm_nand *fun = nand_get_controller_data(chip);
void __iomem *io_addr;
u32 mar;
@@ -123,7 +123,7 @@ static void fun_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
static u8 upm_nand_read_byte(struct mtd_info *mtd)
{
- struct nand_chip *chip = mtd->priv;
+ struct nand_chip *chip = mtd_to_nand(mtd);
return in_8(chip->IO_ADDR_R);
}
@@ -131,8 +131,8 @@ static u8 upm_nand_read_byte(struct mtd_info *mtd)
static void upm_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
{
int i;
- struct nand_chip *chip = mtd->priv;
- struct fsl_upm_nand *fun = chip->priv;
+ struct nand_chip *chip = mtd_to_nand(mtd);
+ struct fsl_upm_nand *fun = nand_get_controller_data(chip);
for (i = 0; i < len; i++) {
out_8(chip->IO_ADDR_W, buf[i]);
@@ -147,7 +147,7 @@ static void upm_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
static void upm_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
{
int i;
- struct nand_chip *chip = mtd->priv;
+ struct nand_chip *chip = mtd_to_nand(mtd);
for (i = 0; i < len; i++)
buf[i] = in_8(chip->IO_ADDR_R);
@@ -155,8 +155,8 @@ static void upm_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
static int nand_dev_ready(struct mtd_info *mtd)
{
- struct nand_chip *chip = mtd->priv;
- struct fsl_upm_nand *fun = chip->priv;
+ struct nand_chip *chip = mtd_to_nand(mtd);
+ struct fsl_upm_nand *fun = nand_get_controller_data(chip);
return fun->dev_ready(fun->chip_nr);
}
@@ -168,7 +168,7 @@ int fsl_upm_nand_init(struct nand_chip *chip, struct fsl_upm_nand *fun)
fun->last_ctrl = NAND_CLE;
- chip->priv = fun;
+ nand_set_controller_data(chip, fun);
chip->chip_delay = fun->chip_delay;
chip->ecc.mode = NAND_ECC_SOFT;
chip->cmd_ctrl = fun_cmd_ctrl;
diff --git a/drivers/mtd/nand/fsmc_nand.c b/drivers/mtd/nand/fsmc_nand.c
index e0e9e1ebd0..a1f2cbae33 100644
--- a/drivers/mtd/nand/fsmc_nand.c
+++ b/drivers/mtd/nand/fsmc_nand.c
@@ -165,7 +165,7 @@ static int count_written_bits(uint8_t *buff, int size, int max_bits)
static void fsmc_nand_hwcontrol(struct mtd_info *mtd, int cmd, uint ctrl)
{
- struct nand_chip *this = mtd->priv;
+ struct nand_chip *this = mtd_to_nand(mtd);
ulong IO_ADDR_W;
if (ctrl & NAND_CTRL_CHANGE) {
@@ -409,8 +409,8 @@ int fsmc_nand_switch_ecc(uint32_t eccstrength)
* Nomadik SoC is currently supporting this fsmc_nand_switch_ecc()
* function, as it doesn't need to switch to a different ECC layout.
*/
- mtd = &nand_info[nand_curr_device];
- nand = mtd->priv;
+ mtd = nand_info[nand_curr_device];
+ nand = mtd_to_nand(mtd);
/* Setup the ecc configurations again */
if (eccstrength == 1) {
@@ -443,7 +443,6 @@ int fsmc_nand_init(struct nand_chip *nand)
{
static int chip_nr;
struct mtd_info *mtd;
- int i;
u32 peripid2 = readl(&fsmc_regs_p->peripid2);
fsmc_version = (peripid2 >> FSMC_REVISION_SHFT) &
@@ -480,8 +479,7 @@ int fsmc_nand_init(struct nand_chip *nand)
(void __iomem *)CONFIG_SYS_NAND_BASE;
nand->badblockbits = 7;
- mtd = &nand_info[chip_nr++];
- mtd->priv = nand;
+ mtd = nand_to_mtd(nand);
switch (fsmc_version) {
case FSMC_VER8:
@@ -514,9 +512,8 @@ int fsmc_nand_init(struct nand_chip *nand)
if (nand_scan_tail(mtd))
return -ENXIO;
- for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++)
- if (nand_register(i))
- return -ENXIO;
+ if (nand_register(chip_nr++, mtd))
+ return -ENXIO;
return 0;
}
diff --git a/drivers/mtd/nand/jz4740_nand.c b/drivers/mtd/nand/jz4740_nand.c
deleted file mode 100644
index abcedc2102..0000000000
--- a/drivers/mtd/nand/jz4740_nand.c
+++ /dev/null
@@ -1,258 +0,0 @@
-/*
- * Platform independend driver for JZ4740.
- *
- * Copyright (c) 2007 Ingenic Semiconductor Inc.
- * Author: <jlwei@ingenic.cn>
- *
- * SPDX-License-Identifier: GPL-2.0+
- */
-#include <common.h>
-
-#include <nand.h>
-#include <asm/io.h>
-#include <asm/jz4740.h>
-
-#define JZ_NAND_DATA_ADDR ((void __iomem *)0xB8000000)
-#define JZ_NAND_CMD_ADDR (JZ_NAND_DATA_ADDR + 0x8000)
-#define JZ_NAND_ADDR_ADDR (JZ_NAND_DATA_ADDR + 0x10000)
-
-#define JZ_NAND_ECC_CTRL_ENCODING BIT(3)
-#define JZ_NAND_ECC_CTRL_RS BIT(2)
-#define JZ_NAND_ECC_CTRL_RESET BIT(1)
-#define JZ_NAND_ECC_CTRL_ENABLE BIT(0)
-
-#define EMC_SMCR1_OPT_NAND 0x094c4400
-/* Optimize the timing of nand */
-
-static struct jz4740_emc * emc = (struct jz4740_emc *)JZ4740_EMC_BASE;
-
-static struct nand_ecclayout qi_lb60_ecclayout_2gb = {
- .eccbytes = 72,
- .eccpos = {
- 12, 13, 14, 15, 16, 17, 18, 19,
- 20, 21, 22, 23, 24, 25, 26, 27,
- 28, 29, 30, 31, 32, 33, 34, 35,
- 36, 37, 38, 39, 40, 41, 42, 43,
- 44, 45, 46, 47, 48, 49, 50, 51,
- 52, 53, 54, 55, 56, 57, 58, 59,
- 60, 61, 62, 63, 64, 65, 66, 67,
- 68, 69, 70, 71, 72, 73, 74, 75,
- 76, 77, 78, 79, 80, 81, 82, 83 },
- .oobfree = {
- {.offset = 2,
- .length = 10 },
- {.offset = 84,
- .length = 44 } }
-};
-
-static int is_reading;
-
-static void jz_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
-{
- struct nand_chip *this = mtd->priv;
- uint32_t reg;
-
- if (ctrl & NAND_CTRL_CHANGE) {
- if (ctrl & NAND_ALE)
- this->IO_ADDR_W = JZ_NAND_ADDR_ADDR;
- else if (ctrl & NAND_CLE)
- this->IO_ADDR_W = JZ_NAND_CMD_ADDR;
- else
- this->IO_ADDR_W = JZ_NAND_DATA_ADDR;
-
- reg = readl(&emc->nfcsr);
- if (ctrl & NAND_NCE)
- reg |= EMC_NFCSR_NFCE1;
- else
- reg &= ~EMC_NFCSR_NFCE1;
- writel(reg, &emc->nfcsr);
- }
-
- if (cmd != NAND_CMD_NONE)
- writeb(cmd, this->IO_ADDR_W);
-}
-
-static int jz_nand_device_ready(struct mtd_info *mtd)
-{
- return (readl(GPIO_PXPIN(2)) & 0x40000000) ? 1 : 0;
-}
-
-void board_nand_select_device(struct nand_chip *nand, int chip)
-{
- /*
- * Don't use "chip" to address the NAND device,
- * generate the cs from the address where it is encoded.
- */
-}
-
-static int jz_nand_rs_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
- u_char *ecc_code)
-{
- uint32_t status;
- int i;
-
- if (is_reading)
- return 0;
-
- do {
- status = readl(&emc->nfints);
- } while (!(status & EMC_NFINTS_ENCF));
-
- /* disable ecc */
- writel(readl(&emc->nfecr) & ~EMC_NFECR_ECCE, &emc->nfecr);
-
- for (i = 0; i < 9; i++)
- ecc_code[i] = readb(&emc->nfpar[i]);
-
- return 0;
-}
-
-static void jz_nand_hwctl(struct mtd_info *mtd, int mode)
-{
- uint32_t reg;
-
- writel(0, &emc->nfints);
- reg = readl(&emc->nfecr);
- reg |= JZ_NAND_ECC_CTRL_RESET;
- reg |= JZ_NAND_ECC_CTRL_ENABLE;
- reg |= JZ_NAND_ECC_CTRL_RS;
-
- switch (mode) {
- case NAND_ECC_READ:
- reg &= ~JZ_NAND_ECC_CTRL_ENCODING;
- is_reading = 1;
- break;
- case NAND_ECC_WRITE:
- reg |= JZ_NAND_ECC_CTRL_ENCODING;
- is_reading = 0;
- break;
- default:
- break;
- }
-
- writel(reg, &emc->nfecr);
-}
-
-/* Correct 1~9-bit errors in 512-bytes data */
-static void jz_rs_correct(unsigned char *dat, int idx, int mask)
-{
- int i;
-
- idx--;
-
- i = idx + (idx >> 3);
- if (i >= 512)
- return;
-
- mask <<= (idx & 0x7);
-
- dat[i] ^= mask & 0xff;
- if (i < 511)
- dat[i + 1] ^= (mask >> 8) & 0xff;
-}
-
-static int jz_nand_rs_correct_data(struct mtd_info *mtd, u_char *dat,
- u_char *read_ecc, u_char *calc_ecc)
-{
- int k;
- uint32_t errcnt, index, mask, status;
-
- /* Set PAR values */
- const uint8_t all_ff_ecc[] = {
- 0xcd, 0x9d, 0x90, 0x58, 0xf4, 0x8b, 0xff, 0xb7, 0x6f };
-
- if (read_ecc[0] == 0xff && read_ecc[1] == 0xff &&
- read_ecc[2] == 0xff && read_ecc[3] == 0xff &&
- read_ecc[4] == 0xff && read_ecc[5] == 0xff &&
- read_ecc[6] == 0xff && read_ecc[7] == 0xff &&
- read_ecc[8] == 0xff) {
- for (k = 0; k < 9; k++)
- writeb(all_ff_ecc[k], &emc->nfpar[k]);
- } else {
- for (k = 0; k < 9; k++)
- writeb(read_ecc[k], &emc->nfpar[k]);
- }
- /* Set PRDY */
- writel(readl(&emc->nfecr) | EMC_NFECR_PRDY, &emc->nfecr);
-
- /* Wait for completion */
- do {
- status = readl(&emc->nfints);
- } while (!(status & EMC_NFINTS_DECF));
-
- /* disable ecc */
- writel(readl(&emc->nfecr) & ~EMC_NFECR_ECCE, &emc->nfecr);
-
- /* Check decoding */
- if (!(status & EMC_NFINTS_ERR))
- return 0;
-
- if (status & EMC_NFINTS_UNCOR) {
- printf("uncorrectable ecc\n");
- return -1;
- }
-
- errcnt = (status & EMC_NFINTS_ERRCNT_MASK) >> EMC_NFINTS_ERRCNT_BIT;
-
- switch (errcnt) {
- case 4:
- index = (readl(&emc->nferr[3]) & EMC_NFERR_INDEX_MASK) >>
- EMC_NFERR_INDEX_BIT;
- mask = (readl(&emc->nferr[3]) & EMC_NFERR_MASK_MASK) >>
- EMC_NFERR_MASK_BIT;
- jz_rs_correct(dat, index, mask);
- case 3:
- index = (readl(&emc->nferr[2]) & EMC_NFERR_INDEX_MASK) >>
- EMC_NFERR_INDEX_BIT;
- mask = (readl(&emc->nferr[2]) & EMC_NFERR_MASK_MASK) >>
- EMC_NFERR_MASK_BIT;
- jz_rs_correct(dat, index, mask);
- case 2:
- index = (readl(&emc->nferr[1]) & EMC_NFERR_INDEX_MASK) >>
- EMC_NFERR_INDEX_BIT;
- mask = (readl(&emc->nferr[1]) & EMC_NFERR_MASK_MASK) >>
- EMC_NFERR_MASK_BIT;
- jz_rs_correct(dat, index, mask);
- case 1:
- index = (readl(&emc->nferr[0]) & EMC_NFERR_INDEX_MASK) >>
- EMC_NFERR_INDEX_BIT;
- mask = (readl(&emc->nferr[0]) & EMC_NFERR_MASK_MASK) >>
- EMC_NFERR_MASK_BIT;
- jz_rs_correct(dat, index, mask);
- default:
- break;
- }
-
- return errcnt;
-}
-
-/*
- * Main initialization routine
- */
-int board_nand_init(struct nand_chip *nand)
-{
- uint32_t reg;
-
- reg = readl(&emc->nfcsr);
- reg |= EMC_NFCSR_NFE1; /* EMC setup, Set NFE bit */
- writel(reg, &emc->nfcsr);
-
- writel(EMC_SMCR1_OPT_NAND, &emc->smcr[1]);
-
- nand->IO_ADDR_R = JZ_NAND_DATA_ADDR;
- nand->IO_ADDR_W = JZ_NAND_DATA_ADDR;
- nand->cmd_ctrl = jz_nand_cmd_ctrl;
- nand->dev_ready = jz_nand_device_ready;
- nand->ecc.hwctl = jz_nand_hwctl;
- nand->ecc.correct = jz_nand_rs_correct_data;
- nand->ecc.calculate = jz_nand_rs_calculate_ecc;
- nand->ecc.mode = NAND_ECC_HW_OOB_FIRST;
- nand->ecc.size = CONFIG_SYS_NAND_ECCSIZE;
- nand->ecc.bytes = CONFIG_SYS_NAND_ECCBYTES;
- nand->ecc.strength = 4;
- nand->ecc.layout = &qi_lb60_ecclayout_2gb;
- nand->chip_delay = 50;
- nand->bbt_options |= NAND_BBT_USE_FLASH;
-
- return 0;
-}
diff --git a/drivers/mtd/nand/kb9202_nand.c b/drivers/mtd/nand/kb9202_nand.c
index 22c5625407..e978cf8c82 100644
--- a/drivers/mtd/nand/kb9202_nand.c
+++ b/drivers/mtd/nand/kb9202_nand.c
@@ -35,7 +35,7 @@
*/
static void kb9202_nand_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
{
- struct nand_chip *this = mtd->priv;
+ struct nand_chip *this = mtd_to_nand(mtd);
if (ctrl & NAND_CTRL_CHANGE) {
ulong IO_ADDR_W = (ulong) this->IO_ADDR_W;
diff --git a/drivers/mtd/nand/kirkwood_nand.c b/drivers/mtd/nand/kirkwood_nand.c
index d734113f64..d0a68bdcb9 100644
--- a/drivers/mtd/nand/kirkwood_nand.c
+++ b/drivers/mtd/nand/kirkwood_nand.c
@@ -33,7 +33,7 @@ static u32 nand_mpp_backup[9] = { 0 };
static void kw_nand_hwcontrol(struct mtd_info *mtd, int cmd,
unsigned int ctrl)
{
- struct nand_chip *nc = mtd->priv;
+ struct nand_chip *nc = mtd_to_nand(mtd);
u32 offs;
if (cmd == NAND_CMD_NONE)
diff --git a/drivers/mtd/nand/lpc32xx_nand_mlc.c b/drivers/mtd/nand/lpc32xx_nand_mlc.c
index 8156fe9613..4262029819 100644
--- a/drivers/mtd/nand/lpc32xx_nand_mlc.c
+++ b/drivers/mtd/nand/lpc32xx_nand_mlc.c
@@ -378,7 +378,8 @@ static int lpc32xx_read_oob(struct mtd_info *mtd, struct nand_chip *chip,
*/
static int lpc32xx_write_page_hwecc(struct mtd_info *mtd,
- struct nand_chip *chip, const uint8_t *buf, int oob_required)
+ struct nand_chip *chip, const uint8_t *buf, int oob_required,
+ int page)
{
unsigned int i, status, timeout;
struct lpc32xx_oob *oob = (struct lpc32xx_oob *)chip->oob_poi;
@@ -435,7 +436,8 @@ static int lpc32xx_write_page_hwecc(struct mtd_info *mtd,
*/
static int lpc32xx_write_page_raw(struct mtd_info *mtd,
- struct nand_chip *chip, const uint8_t *buf, int oob_required)
+ struct nand_chip *chip, const uint8_t *buf, int oob_required,
+ int page)
{
unsigned int i;
struct lpc32xx_oob *oob = (struct lpc32xx_oob *)chip->oob_poi;
@@ -539,11 +541,7 @@ static struct nand_chip lpc32xx_chip;
void board_nand_init(void)
{
- /* we have only one device anyway */
- struct mtd_info *mtd = &nand_info[0];
- /* chip is struct nand_chip, and is now provided by the driver. */
- mtd->priv = &lpc32xx_chip;
- /* to store return status in case we need to print it */
+ struct mtd_info *mtd = &lpc32xx_chip.mtd;
int ret;
/* Set all BOARDSPECIFIC (actually core-specific) fields */
@@ -597,7 +595,7 @@ void board_nand_init(void)
}
/* chip is good, register it */
- ret = nand_register(0);
+ ret = nand_register(0, mtd);
if (ret)
error("nand_register returned %i", ret);
}
diff --git a/drivers/mtd/nand/lpc32xx_nand_slc.c b/drivers/mtd/nand/lpc32xx_nand_slc.c
index 4e1be36654..daa1e7a501 100644
--- a/drivers/mtd/nand/lpc32xx_nand_slc.c
+++ b/drivers/mtd/nand/lpc32xx_nand_slc.c
@@ -291,7 +291,7 @@ static void lpc32xx_nand_dma_configure(struct nand_chip *chip,
static void lpc32xx_nand_xfer(struct mtd_info *mtd, const u8 *buf,
int len, int read)
{
- struct nand_chip *chip = mtd->priv;
+ struct nand_chip *chip = mtd_to_nand(mtd);
u32 config;
int ret;
@@ -486,7 +486,8 @@ static int lpc32xx_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
/* Reuse the logic from "nand_write_page_hwecc()" */
static int lpc32xx_write_page_hwecc(struct mtd_info *mtd,
struct nand_chip *chip,
- const uint8_t *buf, int oob_required)
+ const uint8_t *buf, int oob_required,
+ int page)
{
int i;
uint8_t *ecc_calc = chip->buffers->ecccalc;
diff --git a/drivers/mtd/nand/mpc5121_nfc.c b/drivers/mtd/nand/mpc5121_nfc.c
index e621c3665e..8a8775c4c5 100644
--- a/drivers/mtd/nand/mpc5121_nfc.c
+++ b/drivers/mtd/nand/mpc5121_nfc.c
@@ -100,7 +100,6 @@
#define NFC_WPC_UNLOCK (1 << 2)
struct mpc5121_nfc_prv {
- struct mtd_info mtd;
struct nand_chip chip;
int irq;
void __iomem *regs;
@@ -117,8 +116,8 @@ static void mpc5121_nfc_done(struct mtd_info *mtd);
/* Read NFC register */
static inline u16 nfc_read(struct mtd_info *mtd, uint reg)
{
- struct nand_chip *chip = mtd->priv;
- struct mpc5121_nfc_prv *prv = chip->priv;
+ struct nand_chip *chip = mtd_to_nand(mtd);
+ struct mpc5121_nfc_prv *prv = nand_get_controller_data(chip);
return in_be16(prv->regs + reg);
}
@@ -126,8 +125,8 @@ static inline u16 nfc_read(struct mtd_info *mtd, uint reg)
/* Write NFC register */
static inline void nfc_write(struct mtd_info *mtd, uint reg, u16 val)
{
- struct nand_chip *chip = mtd->priv;
- struct mpc5121_nfc_prv *prv = chip->priv;
+ struct nand_chip *chip = mtd_to_nand(mtd);
+ struct mpc5121_nfc_prv *prv = nand_get_controller_data(chip);
out_be16(prv->regs + reg, val);
}
@@ -211,7 +210,7 @@ static void mpc5121_nfc_done(struct mtd_info *mtd)
/* Do address cycle(s) */
static void mpc5121_nfc_addr_cycle(struct mtd_info *mtd, int column, int page)
{
- struct nand_chip *chip = mtd->priv;
+ struct nand_chip *chip = mtd_to_nand(mtd);
u32 pagemask = chip->pagemask;
if (column != -1) {
@@ -283,8 +282,8 @@ static int mpc5121_nfc_dev_ready(struct mtd_info *mtd)
static void mpc5121_nfc_command(struct mtd_info *mtd, unsigned command,
int column, int page)
{
- struct nand_chip *chip = mtd->priv;
- struct mpc5121_nfc_prv *prv = chip->priv;
+ struct nand_chip *chip = mtd_to_nand(mtd);
+ struct mpc5121_nfc_prv *prv = nand_get_controller_data(chip);
prv->column = (column >= 0) ? column : 0;
prv->spareonly = 0;
@@ -357,8 +356,8 @@ static void mpc5121_nfc_command(struct mtd_info *mtd, unsigned command,
static void mpc5121_nfc_copy_spare(struct mtd_info *mtd, uint offset,
u8 * buffer, uint size, int wr)
{
- struct nand_chip *nand = mtd->priv;
- struct mpc5121_nfc_prv *prv = nand->priv;
+ struct nand_chip *nand = mtd_to_nand(mtd);
+ struct mpc5121_nfc_prv *prv = nand_get_controller_data(nand);
uint o, s, sbsize, blksize;
/*
@@ -410,8 +409,8 @@ static void mpc5121_nfc_copy_spare(struct mtd_info *mtd, uint offset,
static void mpc5121_nfc_buf_copy(struct mtd_info *mtd, u_char * buf, int len,
int wr)
{
- struct nand_chip *chip = mtd->priv;
- struct mpc5121_nfc_prv *prv = chip->priv;
+ struct nand_chip *chip = mtd_to_nand(mtd);
+ struct mpc5121_nfc_prv *prv = nand_get_controller_data(chip);
uint c = prv->column;
uint l;
@@ -489,7 +488,7 @@ static u16 mpc5121_nfc_read_word(struct mtd_info *mtd)
static int mpc5121_nfc_read_hw_config(struct mtd_info *mtd)
{
immap_t *im = (immap_t *)CONFIG_SYS_IMMR;
- struct nand_chip *chip = mtd->priv;
+ struct nand_chip *chip = mtd_to_nand(mtd);
uint rcw_pagesize = 0;
uint rcw_sparesize = 0;
uint rcw_width;
@@ -549,7 +548,6 @@ int board_nand_init(struct nand_chip *chip)
int resettime = 0;
int retval = 0;
int rev;
- static int chip_nr = 0;
/*
* Check SoC revision. This driver supports only NFC
@@ -568,9 +566,8 @@ int board_nand_init(struct nand_chip *chip)
return -ENOMEM;
}
- mtd = &nand_info[chip_nr++];
- mtd->priv = chip;
- chip->priv = prv;
+ mtd = &chip->mtd;
+ nand_set_controller_data(chip, prv);
/* Read NFC configuration from Reset Config Word */
retval = mpc5121_nfc_read_hw_config(mtd);
diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c
index f12b07e7ad..7221d0ba0d 100644
--- a/drivers/mtd/nand/mxc_nand.c
+++ b/drivers/mtd/nand/mxc_nand.c
@@ -19,7 +19,6 @@
#define DRIVER_NAME "mxc_nand"
struct mxc_nand_host {
- struct mtd_info mtd;
struct nand_chip *nand;
struct mxc_nand_regs __iomem *regs;
@@ -351,8 +350,8 @@ static int mxc_nand_dev_ready(struct mtd_info *mtd)
static void _mxc_nand_enable_hwecc(struct mtd_info *mtd, int on)
{
- struct nand_chip *nand_chip = mtd->priv;
- struct mxc_nand_host *host = nand_chip->priv;
+ struct nand_chip *nand_chip = mtd_to_nand(mtd);
+ struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
#if defined(MXC_NFC_V1) || defined(MXC_NFC_V2_1)
uint16_t tmp = readnfc(&host->regs->config1);
@@ -386,7 +385,7 @@ static int mxc_nand_read_oob_syndrome(struct mtd_info *mtd,
struct nand_chip *chip,
int page)
{
- struct mxc_nand_host *host = chip->priv;
+ struct mxc_nand_host *host = nand_get_controller_data(chip);
uint8_t *buf = chip->oob_poi;
int length = mtd->oobsize;
int eccpitch = chip->ecc.bytes + chip->ecc.prepad + chip->ecc.postpad;
@@ -441,7 +440,7 @@ static int mxc_nand_read_page_raw_syndrome(struct mtd_info *mtd,
int oob_required,
int page)
{
- struct mxc_nand_host *host = chip->priv;
+ struct mxc_nand_host *host = nand_get_controller_data(chip);
int eccsize = chip->ecc.size;
int eccbytes = chip->ecc.bytes;
int eccpitch = eccbytes + chip->ecc.prepad + chip->ecc.postpad;
@@ -486,7 +485,7 @@ static int mxc_nand_read_page_syndrome(struct mtd_info *mtd,
int oob_required,
int page)
{
- struct mxc_nand_host *host = chip->priv;
+ struct mxc_nand_host *host = nand_get_controller_data(chip);
int n, eccsize = chip->ecc.size;
int eccbytes = chip->ecc.bytes;
int eccpitch = eccbytes + chip->ecc.prepad + chip->ecc.postpad;
@@ -550,7 +549,7 @@ static int mxc_nand_read_page_syndrome(struct mtd_info *mtd,
static int mxc_nand_write_oob_syndrome(struct mtd_info *mtd,
struct nand_chip *chip, int page)
{
- struct mxc_nand_host *host = chip->priv;
+ struct mxc_nand_host *host = nand_get_controller_data(chip);
int eccpitch = chip->ecc.bytes + chip->ecc.prepad + chip->ecc.postpad;
int length = mtd->oobsize;
int i, len, status, steps = chip->ecc.steps;
@@ -576,9 +575,9 @@ static int mxc_nand_write_oob_syndrome(struct mtd_info *mtd,
static int mxc_nand_write_page_raw_syndrome(struct mtd_info *mtd,
struct nand_chip *chip,
const uint8_t *buf,
- int oob_required)
+ int oob_required, int page)
{
- struct mxc_nand_host *host = chip->priv;
+ struct mxc_nand_host *host = nand_get_controller_data(chip);
int eccsize = chip->ecc.size;
int eccbytes = chip->ecc.bytes;
int eccpitch = eccbytes + chip->ecc.prepad + chip->ecc.postpad;
@@ -616,9 +615,9 @@ static int mxc_nand_write_page_raw_syndrome(struct mtd_info *mtd,
static int mxc_nand_write_page_syndrome(struct mtd_info *mtd,
struct nand_chip *chip,
const uint8_t *buf,
- int oob_required)
+ int oob_required, int page)
{
- struct mxc_nand_host *host = chip->priv;
+ struct mxc_nand_host *host = nand_get_controller_data(chip);
int i, n, eccsize = chip->ecc.size;
int eccbytes = chip->ecc.bytes;
int eccpitch = eccbytes + chip->ecc.prepad + chip->ecc.postpad;
@@ -661,8 +660,8 @@ static int mxc_nand_write_page_syndrome(struct mtd_info *mtd,
static int mxc_nand_correct_data(struct mtd_info *mtd, u_char *dat,
u_char *read_ecc, u_char *calc_ecc)
{
- struct nand_chip *nand_chip = mtd->priv;
- struct mxc_nand_host *host = nand_chip->priv;
+ struct nand_chip *nand_chip = mtd_to_nand(mtd);
+ struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
uint32_t ecc_status = readl(&host->regs->ecc_status_result);
int subpages = mtd->writesize / nand_chip->subpagesize;
int pg2blk_shift = nand_chip->phys_erase_shift -
@@ -681,7 +680,7 @@ static int mxc_nand_correct_data(struct mtd_info *mtd, u_char *dat,
mtd->writesize / nand_chip->subpagesize
- subpages);
}
- return -1;
+ return -EBADMSG;
}
ecc_status >>= 4;
subpages--;
@@ -700,8 +699,8 @@ static int mxc_nand_correct_data(struct mtd_info *mtd, u_char *dat,
static int mxc_nand_correct_data(struct mtd_info *mtd, u_char *dat,
u_char *read_ecc, u_char *calc_ecc)
{
- struct nand_chip *nand_chip = mtd->priv;
- struct mxc_nand_host *host = nand_chip->priv;
+ struct nand_chip *nand_chip = mtd_to_nand(mtd);
+ struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
/*
* 1-Bit errors are automatically corrected in HW. No need for
@@ -713,7 +712,7 @@ static int mxc_nand_correct_data(struct mtd_info *mtd, u_char *dat,
if (((ecc_status & 0x3) == 2) || ((ecc_status >> 2) == 2)) {
MTDDEBUG(MTD_DEBUG_LEVEL0,
"MXC_NAND: HWECC uncorrectable 2-bit ECC error\n");
- return -1;
+ return -EBADMSG;
}
return 0;
@@ -729,8 +728,8 @@ static int mxc_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
static u_char mxc_nand_read_byte(struct mtd_info *mtd)
{
- struct nand_chip *nand_chip = mtd->priv;
- struct mxc_nand_host *host = nand_chip->priv;
+ struct nand_chip *nand_chip = mtd_to_nand(mtd);
+ struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
uint8_t ret = 0;
uint16_t col;
uint16_t __iomem *main_buf =
@@ -769,8 +768,8 @@ static u_char mxc_nand_read_byte(struct mtd_info *mtd)
static uint16_t mxc_nand_read_word(struct mtd_info *mtd)
{
- struct nand_chip *nand_chip = mtd->priv;
- struct mxc_nand_host *host = nand_chip->priv;
+ struct nand_chip *nand_chip = mtd_to_nand(mtd);
+ struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
uint16_t col, ret;
uint16_t __iomem *p;
@@ -821,8 +820,8 @@ static uint16_t mxc_nand_read_word(struct mtd_info *mtd)
static void mxc_nand_write_buf(struct mtd_info *mtd,
const u_char *buf, int len)
{
- struct nand_chip *nand_chip = mtd->priv;
- struct mxc_nand_host *host = nand_chip->priv;
+ struct nand_chip *nand_chip = mtd_to_nand(mtd);
+ struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
int n, col, i = 0;
MTDDEBUG(MTD_DEBUG_LEVEL3,
@@ -895,8 +894,8 @@ static void mxc_nand_write_buf(struct mtd_info *mtd,
*/
static void mxc_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
{
- struct nand_chip *nand_chip = mtd->priv;
- struct mxc_nand_host *host = nand_chip->priv;
+ struct nand_chip *nand_chip = mtd_to_nand(mtd);
+ struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
int n, col, i = 0;
MTDDEBUG(MTD_DEBUG_LEVEL3,
@@ -955,8 +954,8 @@ static void mxc_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
*/
static void mxc_nand_select_chip(struct mtd_info *mtd, int chip)
{
- struct nand_chip *nand_chip = mtd->priv;
- struct mxc_nand_host *host = nand_chip->priv;
+ struct nand_chip *nand_chip = mtd_to_nand(mtd);
+ struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
switch (chip) {
case -1:
@@ -982,8 +981,8 @@ static void mxc_nand_select_chip(struct mtd_info *mtd, int chip)
void mxc_nand_command(struct mtd_info *mtd, unsigned command,
int column, int page_addr)
{
- struct nand_chip *nand_chip = mtd->priv;
- struct mxc_nand_host *host = nand_chip->priv;
+ struct nand_chip *nand_chip = mtd_to_nand(mtd);
+ struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
MTDDEBUG(MTD_DEBUG_LEVEL3,
"mxc_nand_command (cmd = 0x%x, col = 0x%x, page = 0x%x)\n",
@@ -1164,14 +1163,13 @@ int board_nand_init(struct nand_chip *this)
#endif
/* structures must be linked */
- mtd = &host->mtd;
- mtd->priv = this;
+ mtd = &this->mtd;
host->nand = this;
/* 5 us command delay time */
this->chip_delay = 5;
- this->priv = host;
+ nand_set_controller_data(this, host);
this->dev_ready = mxc_nand_dev_ready;
this->cmdfunc = mxc_nand_command;
this->select_chip = mxc_nand_select_chip;
diff --git a/drivers/mtd/nand/mxc_nand_spl.c b/drivers/mtd/nand/mxc_nand_spl.c
index 6ac2c96eeb..841fb5bd96 100644
--- a/drivers/mtd/nand/mxc_nand_spl.c
+++ b/drivers/mtd/nand/mxc_nand_spl.c
@@ -232,7 +232,7 @@ static int nfc_read_page(unsigned int page_address, unsigned char *buf)
nfc_nand_read_page(page_address);
if (nfc_nand_check_ecc())
- return -1;
+ return -EBADMSG;
src = (u32 *)&nfc->main_area[0][0];
dst = (u32 *)buf;
diff --git a/drivers/mtd/nand/mxs_nand.c b/drivers/mtd/nand/mxs_nand.c
index b5bbd889ff..7be1f86bc2 100644
--- a/drivers/mtd/nand/mxs_nand.c
+++ b/drivers/mtd/nand/mxs_nand.c
@@ -264,8 +264,8 @@ static int mxs_nand_wait_for_bch_complete(void)
*/
static void mxs_nand_cmd_ctrl(struct mtd_info *mtd, int data, unsigned int ctrl)
{
- struct nand_chip *nand = mtd->priv;
- struct mxs_nand_info *nand_info = nand->priv;
+ struct nand_chip *nand = mtd_to_nand(mtd);
+ struct mxs_nand_info *nand_info = nand_get_controller_data(nand);
struct mxs_dma_desc *d;
uint32_t channel = MXS_DMA_CHANNEL_AHB_APBH_GPMI0 + nand_info->cur_chip;
int ret;
@@ -343,8 +343,8 @@ static void mxs_nand_cmd_ctrl(struct mtd_info *mtd, int data, unsigned int ctrl)
*/
static int mxs_nand_device_ready(struct mtd_info *mtd)
{
- struct nand_chip *chip = mtd->priv;
- struct mxs_nand_info *nand_info = chip->priv;
+ struct nand_chip *chip = mtd_to_nand(mtd);
+ struct mxs_nand_info *nand_info = nand_get_controller_data(chip);
struct mxs_gpmi_regs *gpmi_regs =
(struct mxs_gpmi_regs *)MXS_GPMI_BASE;
uint32_t tmp;
@@ -360,8 +360,8 @@ static int mxs_nand_device_ready(struct mtd_info *mtd)
*/
static void mxs_nand_select_chip(struct mtd_info *mtd, int chip)
{
- struct nand_chip *nand = mtd->priv;
- struct mxs_nand_info *nand_info = nand->priv;
+ struct nand_chip *nand = mtd_to_nand(mtd);
+ struct mxs_nand_info *nand_info = nand_get_controller_data(nand);
nand_info->cur_chip = chip;
}
@@ -410,8 +410,8 @@ static void mxs_nand_swap_block_mark(struct mtd_info *mtd,
*/
static void mxs_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int length)
{
- struct nand_chip *nand = mtd->priv;
- struct mxs_nand_info *nand_info = nand->priv;
+ struct nand_chip *nand = mtd_to_nand(mtd);
+ struct mxs_nand_info *nand_info = nand_get_controller_data(nand);
struct mxs_dma_desc *d;
uint32_t channel = MXS_DMA_CHANNEL_AHB_APBH_GPMI0 + nand_info->cur_chip;
int ret;
@@ -494,8 +494,8 @@ rtn:
static void mxs_nand_write_buf(struct mtd_info *mtd, const uint8_t *buf,
int length)
{
- struct nand_chip *nand = mtd->priv;
- struct mxs_nand_info *nand_info = nand->priv;
+ struct nand_chip *nand = mtd_to_nand(mtd);
+ struct mxs_nand_info *nand_info = nand_get_controller_data(nand);
struct mxs_dma_desc *d;
uint32_t channel = MXS_DMA_CHANNEL_AHB_APBH_GPMI0 + nand_info->cur_chip;
int ret;
@@ -559,7 +559,7 @@ static int mxs_nand_ecc_read_page(struct mtd_info *mtd, struct nand_chip *nand,
uint8_t *buf, int oob_required,
int page)
{
- struct mxs_nand_info *nand_info = nand->priv;
+ struct mxs_nand_info *nand_info = nand_get_controller_data(nand);
struct mxs_dma_desc *d;
uint32_t channel = MXS_DMA_CHANNEL_AHB_APBH_GPMI0 + nand_info->cur_chip;
uint32_t corrected = 0, failed = 0;
@@ -707,9 +707,9 @@ rtn:
*/
static int mxs_nand_ecc_write_page(struct mtd_info *mtd,
struct nand_chip *nand, const uint8_t *buf,
- int oob_required)
+ int oob_required, int page)
{
- struct mxs_nand_info *nand_info = nand->priv;
+ struct mxs_nand_info *nand_info = nand_get_controller_data(nand);
struct mxs_dma_desc *d;
uint32_t channel = MXS_DMA_CHANNEL_AHB_APBH_GPMI0 + nand_info->cur_chip;
int ret;
@@ -775,8 +775,8 @@ rtn:
static int mxs_nand_hook_read_oob(struct mtd_info *mtd, loff_t from,
struct mtd_oob_ops *ops)
{
- struct nand_chip *chip = mtd->priv;
- struct mxs_nand_info *nand_info = chip->priv;
+ struct nand_chip *chip = mtd_to_nand(mtd);
+ struct mxs_nand_info *nand_info = nand_get_controller_data(chip);
int ret;
if (ops->mode == MTD_OPS_RAW)
@@ -800,8 +800,8 @@ static int mxs_nand_hook_read_oob(struct mtd_info *mtd, loff_t from,
static int mxs_nand_hook_write_oob(struct mtd_info *mtd, loff_t to,
struct mtd_oob_ops *ops)
{
- struct nand_chip *chip = mtd->priv;
- struct mxs_nand_info *nand_info = chip->priv;
+ struct nand_chip *chip = mtd_to_nand(mtd);
+ struct mxs_nand_info *nand_info = nand_get_controller_data(chip);
int ret;
if (ops->mode == MTD_OPS_RAW)
@@ -824,8 +824,8 @@ static int mxs_nand_hook_write_oob(struct mtd_info *mtd, loff_t to,
*/
static int mxs_nand_hook_block_markbad(struct mtd_info *mtd, loff_t ofs)
{
- struct nand_chip *chip = mtd->priv;
- struct mxs_nand_info *nand_info = chip->priv;
+ struct nand_chip *chip = mtd_to_nand(mtd);
+ struct mxs_nand_info *nand_info = nand_get_controller_data(chip);
int ret;
nand_info->marking_block_bad = 1;
@@ -884,7 +884,7 @@ static int mxs_nand_hook_block_markbad(struct mtd_info *mtd, loff_t ofs)
static int mxs_nand_ecc_read_oob(struct mtd_info *mtd, struct nand_chip *nand,
int page)
{
- struct mxs_nand_info *nand_info = nand->priv;
+ struct mxs_nand_info *nand_info = nand_get_controller_data(nand);
/*
* First, fill in the OOB buffer. If we're doing a raw read, we need to
@@ -919,7 +919,7 @@ static int mxs_nand_ecc_read_oob(struct mtd_info *mtd, struct nand_chip *nand,
static int mxs_nand_ecc_write_oob(struct mtd_info *mtd, struct nand_chip *nand,
int page)
{
- struct mxs_nand_info *nand_info = nand->priv;
+ struct mxs_nand_info *nand_info = nand_get_controller_data(nand);
uint8_t block_mark = 0;
/*
@@ -961,7 +961,7 @@ static int mxs_nand_ecc_write_oob(struct mtd_info *mtd, struct nand_chip *nand,
* Thus, this function is only called when we want *all* blocks to look good,
* so it *always* return success.
*/
-static int mxs_nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)
+static int mxs_nand_block_bad(struct mtd_info *mtd, loff_t ofs)
{
return 0;
}
@@ -982,8 +982,8 @@ static int mxs_nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)
*/
static int mxs_nand_scan_bbt(struct mtd_info *mtd)
{
- struct nand_chip *nand = mtd->priv;
- struct mxs_nand_info *nand_info = nand->priv;
+ struct nand_chip *nand = mtd_to_nand(mtd);
+ struct mxs_nand_info *nand_info = nand_get_controller_data(nand);
struct mxs_bch_regs *bch_regs = (struct mxs_bch_regs *)MXS_BCH_BASE;
uint32_t tmp;
@@ -1175,7 +1175,7 @@ int board_nand_init(struct nand_chip *nand)
memset(&fake_ecc_layout, 0, sizeof(fake_ecc_layout));
- nand->priv = nand_info;
+ nand_set_controller_data(nand, nand_info);
nand->options |= NAND_NO_SUBPAGE_WRITE;
nand->cmd_ctrl = mxs_nand_cmd_ctrl;
diff --git a/drivers/mtd/nand/mxs_nand_spl.c b/drivers/mtd/nand/mxs_nand_spl.c
index 0e7c364a22..a8a3084d03 100644
--- a/drivers/mtd/nand/mxs_nand_spl.c
+++ b/drivers/mtd/nand/mxs_nand_spl.c
@@ -8,13 +8,13 @@
#include <nand.h>
#include <malloc.h>
-static nand_info_t mtd;
+static struct mtd_info *mtd;
static struct nand_chip nand_chip;
static void mxs_nand_command(struct mtd_info *mtd, unsigned int command,
int column, int page_addr)
{
- register struct nand_chip *chip = mtd->priv;
+ register struct nand_chip *chip = mtd_to_nand(mtd);
u32 timeo, time_start;
/* write out the command to the device */
@@ -51,7 +51,7 @@ static void mxs_nand_command(struct mtd_info *mtd, unsigned int command,
static int mxs_flash_ident(struct mtd_info *mtd)
{
- register struct nand_chip *chip = mtd->priv;
+ register struct nand_chip *chip = mtd_to_nand(mtd);
int i;
u8 mfg_id, dev_id;
u8 id_data[8];
@@ -111,7 +111,7 @@ static int mxs_flash_ident(struct mtd_info *mtd)
static int mxs_read_page_ecc(struct mtd_info *mtd, void *buf, unsigned int page)
{
- register struct nand_chip *chip = mtd->priv;
+ register struct nand_chip *chip = mtd_to_nand(mtd);
int ret;
chip->cmdfunc(mtd, NAND_CMD_READ0, 0x0, page);
@@ -125,7 +125,7 @@ static int mxs_read_page_ecc(struct mtd_info *mtd, void *buf, unsigned int page)
static int is_badblock(struct mtd_info *mtd, loff_t offs, int allowbbt)
{
- register struct nand_chip *chip = mtd->priv;
+ register struct nand_chip *chip = mtd_to_nand(mtd);
unsigned int block = offs >> chip->phys_erase_shift;
unsigned int page = offs >> chip->page_shift;
@@ -147,14 +147,14 @@ static int mxs_nand_init(void)
/* init mxs nand driver */
board_nand_init(&nand_chip);
- mtd.priv = &nand_chip;
+ mtd = &nand_chip.mtd;
/* set mtd functions */
nand_chip.cmdfunc = mxs_nand_command;
nand_chip.numchips = 1;
/* identify flash device */
puts("NAND : ");
- if (mxs_flash_ident(&mtd)) {
+ if (mxs_flash_ident(mtd)) {
printf("Failed to identify\n");
return -1;
}
@@ -162,12 +162,12 @@ static int mxs_nand_init(void)
/* allocate and initialize buffers */
nand_chip.buffers = memalign(ARCH_DMA_MINALIGN,
sizeof(*nand_chip.buffers));
- nand_chip.oob_poi = nand_chip.buffers->databuf + mtd.writesize;
+ nand_chip.oob_poi = nand_chip.buffers->databuf + mtd->writesize;
/* setup flash layout (does not scan as we override that) */
- mtd.size = nand_chip.chipsize;
- nand_chip.scan_bbt(&mtd);
+ mtd->size = nand_chip.chipsize;
+ nand_chip.scan_bbt(mtd);
- printf("%llu MiB\n", (mtd.size / (1024 * 1024)));
+ printf("%llu MiB\n", (mtd->size / (1024 * 1024)));
return 0;
}
@@ -180,20 +180,20 @@ int nand_spl_load_image(uint32_t offs, unsigned int size, void *buf)
if (mxs_nand_init())
return -ENODEV;
- chip = mtd.priv;
+ chip = mtd_to_nand(mtd);
page = offs >> chip->page_shift;
- nand_page_per_block = mtd.erasesize / mtd.writesize;
+ nand_page_per_block = mtd->erasesize / mtd->writesize;
debug("%s offset:0x%08x len:%d page:%d\n", __func__, offs, size, page);
- size = roundup(size, mtd.writesize);
+ size = roundup(size, mtd->writesize);
while (sz < size) {
- if (mxs_read_page_ecc(&mtd, buf, page) < 0)
+ if (mxs_read_page_ecc(mtd, buf, page) < 0)
return -1;
- sz += mtd.writesize;
- offs += mtd.writesize;
+ sz += mtd->writesize;
+ offs += mtd->writesize;
page++;
- buf += mtd.writesize;
+ buf += mtd->writesize;
/*
* Check if we have crossed a block boundary, and if so
@@ -204,10 +204,10 @@ int nand_spl_load_image(uint32_t offs, unsigned int size, void *buf)
* Yes, new block. See if this block is good. If not,
* loop until we find a good block.
*/
- while (is_badblock(&mtd, offs, 1)) {
+ while (is_badblock(mtd, offs, 1)) {
page = page + nand_page_per_block;
/* Check i we've reached the end of flash. */
- if (page >= mtd.size >> chip->page_shift)
+ if (page >= mtd->size >> chip->page_shift)
return -ENOMEM;
}
}
diff --git a/drivers/mtd/nand/nand.c b/drivers/mtd/nand/nand.c
index 8f0a9210ec..f449316853 100644
--- a/drivers/mtd/nand/nand.c
+++ b/drivers/mtd/nand/nand.c
@@ -19,7 +19,7 @@ DECLARE_GLOBAL_DATA_PTR;
int nand_curr_device = -1;
-nand_info_t nand_info[CONFIG_SYS_MAX_NAND_DEVICE];
+struct mtd_info *nand_info[CONFIG_SYS_MAX_NAND_DEVICE];
#ifndef CONFIG_SYS_NAND_SELF_INIT
static struct nand_chip nand_chip[CONFIG_SYS_MAX_NAND_DEVICE];
@@ -30,15 +30,25 @@ static char dev_name[CONFIG_SYS_MAX_NAND_DEVICE][8];
static unsigned long total_nand_size; /* in kiB */
-/* Register an initialized NAND mtd device with the U-Boot NAND command. */
-int nand_register(int devnum)
+int nand_mtd_to_devnum(struct mtd_info *mtd)
{
- struct mtd_info *mtd;
+ int i;
+ for (i = 0; i < ARRAY_SIZE(nand_info); i++) {
+ if (mtd && nand_info[i] == mtd)
+ return i;
+ }
+
+ return -ENODEV;
+}
+
+/* Register an initialized NAND mtd device with the U-Boot NAND command. */
+int nand_register(int devnum, struct mtd_info *mtd)
+{
if (devnum >= CONFIG_SYS_MAX_NAND_DEVICE)
return -EINVAL;
- mtd = &nand_info[devnum];
+ nand_info[devnum] = mtd;
sprintf(dev_name[devnum], "nand%d", devnum);
mtd->name = dev_name[devnum];
@@ -62,15 +72,14 @@ int nand_register(int devnum)
#ifndef CONFIG_SYS_NAND_SELF_INIT
static void nand_init_chip(int i)
{
- struct mtd_info *mtd = &nand_info[i];
struct nand_chip *nand = &nand_chip[i];
+ struct mtd_info *mtd = nand_to_mtd(nand);
ulong base_addr = base_address[i];
int maxchips = CONFIG_SYS_NAND_MAX_CHIPS;
if (maxchips < 1)
maxchips = 1;
- mtd->priv = nand;
nand->IO_ADDR_R = nand->IO_ADDR_W = (void __iomem *)base_addr;
if (board_nand_init(nand))
@@ -79,7 +88,7 @@ static void nand_init_chip(int i)
if (nand_scan(mtd, maxchips))
return;
- nand_register(i);
+ nand_register(i, mtd);
}
#endif
@@ -100,6 +109,7 @@ void nand_init(void)
/*
* Select the chip in the board/cpu specific driver
*/
- board_nand_select_device(nand_info[nand_curr_device].priv, nand_curr_device);
+ board_nand_select_device(mtd_to_nand(nand_info[nand_curr_device]),
+ nand_curr_device);
#endif
}
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index 9e8fc1ffe2..74c563c495 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -1,6 +1,4 @@
/*
- * drivers/mtd/nand.c
- *
* Overview:
* This is the generic MTD driver for NAND flash devices. It should be
* capable of working with almost all NAND chips currently available.
@@ -45,8 +43,6 @@
#include <asm/io.h>
#include <asm/errno.h>
-static bool is_module_text_address(unsigned long addr) {return 0;}
-
/* Define default oob placement schemes for large and small page devices */
static struct nand_ecclayout nand_oob_8 = {
.eccbytes = 3,
@@ -105,7 +101,7 @@ DEFINE_LED_TRIGGER(nand_led_trigger);
static int check_offs_len(struct mtd_info *mtd,
loff_t ofs, uint64_t len)
{
- struct nand_chip *chip = mtd->priv;
+ struct nand_chip *chip = mtd_to_nand(mtd);
int ret = 0;
/* Start address must align on block boundary */
@@ -131,7 +127,7 @@ static int check_offs_len(struct mtd_info *mtd,
*/
static void nand_release_device(struct mtd_info *mtd)
{
- struct nand_chip *chip = mtd->priv;
+ struct nand_chip *chip = mtd_to_nand(mtd);
/* De-select the NAND device */
chip->select_chip(mtd, -1);
@@ -145,7 +141,7 @@ static void nand_release_device(struct mtd_info *mtd)
*/
uint8_t nand_read_byte(struct mtd_info *mtd)
{
- struct nand_chip *chip = mtd->priv;
+ struct nand_chip *chip = mtd_to_nand(mtd);
return readb(chip->IO_ADDR_R);
}
@@ -158,7 +154,7 @@ uint8_t nand_read_byte(struct mtd_info *mtd)
*/
static uint8_t nand_read_byte16(struct mtd_info *mtd)
{
- struct nand_chip *chip = mtd->priv;
+ struct nand_chip *chip = mtd_to_nand(mtd);
return (uint8_t) cpu_to_le16(readw(chip->IO_ADDR_R));
}
@@ -170,7 +166,7 @@ static uint8_t nand_read_byte16(struct mtd_info *mtd)
*/
static u16 nand_read_word(struct mtd_info *mtd)
{
- struct nand_chip *chip = mtd->priv;
+ struct nand_chip *chip = mtd_to_nand(mtd);
return readw(chip->IO_ADDR_R);
}
@@ -183,7 +179,7 @@ static u16 nand_read_word(struct mtd_info *mtd)
*/
static void nand_select_chip(struct mtd_info *mtd, int chipnr)
{
- struct nand_chip *chip = mtd->priv;
+ struct nand_chip *chip = mtd_to_nand(mtd);
switch (chipnr) {
case -1:
@@ -206,7 +202,7 @@ static void nand_select_chip(struct mtd_info *mtd, int chipnr)
*/
static void nand_write_byte(struct mtd_info *mtd, uint8_t byte)
{
- struct nand_chip *chip = mtd->priv;
+ struct nand_chip *chip = mtd_to_nand(mtd);
chip->write_buf(mtd, &byte, 1);
}
@@ -220,7 +216,7 @@ static void nand_write_byte(struct mtd_info *mtd, uint8_t byte)
*/
static void nand_write_byte16(struct mtd_info *mtd, uint8_t byte)
{
- struct nand_chip *chip = mtd->priv;
+ struct nand_chip *chip = mtd_to_nand(mtd);
uint16_t word = byte;
/*
@@ -287,7 +283,7 @@ static void iowrite16_rep(void *addr, void *buf, int len)
*/
void nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
{
- struct nand_chip *chip = mtd->priv;
+ struct nand_chip *chip = mtd_to_nand(mtd);
iowrite8_rep(chip->IO_ADDR_W, buf, len);
}
@@ -302,7 +298,7 @@ void nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
*/
void nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
{
- struct nand_chip *chip = mtd->priv;
+ struct nand_chip *chip = mtd_to_nand(mtd);
ioread8_rep(chip->IO_ADDR_R, buf, len);
}
@@ -317,7 +313,7 @@ void nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
*/
void nand_write_buf16(struct mtd_info *mtd, const uint8_t *buf, int len)
{
- struct nand_chip *chip = mtd->priv;
+ struct nand_chip *chip = mtd_to_nand(mtd);
u16 *p = (u16 *) buf;
iowrite16_rep(chip->IO_ADDR_W, p, len >> 1);
@@ -333,7 +329,7 @@ void nand_write_buf16(struct mtd_info *mtd, const uint8_t *buf, int len)
*/
void nand_read_buf16(struct mtd_info *mtd, uint8_t *buf, int len)
{
- struct nand_chip *chip = mtd->priv;
+ struct nand_chip *chip = mtd_to_nand(mtd);
u16 *p = (u16 *) buf;
ioread16_rep(chip->IO_ADDR_R, p, len >> 1);
@@ -343,14 +339,13 @@ void nand_read_buf16(struct mtd_info *mtd, uint8_t *buf, int len)
* nand_block_bad - [DEFAULT] Read bad block marker from the chip
* @mtd: MTD device structure
* @ofs: offset from device start
- * @getchip: 0, if the chip is already selected
*
* Check, if the block is bad.
*/
-static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)
+static int nand_block_bad(struct mtd_info *mtd, loff_t ofs)
{
- int page, chipnr, res = 0, i = 0;
- struct nand_chip *chip = mtd->priv;
+ int page, res = 0, i = 0;
+ struct nand_chip *chip = mtd_to_nand(mtd);
u16 bad;
if (chip->bbt_options & NAND_BBT_SCANLASTPAGE)
@@ -358,15 +353,6 @@ static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)
page = (int)(ofs >> chip->page_shift) & chip->pagemask;
- if (getchip) {
- chipnr = (int)(ofs >> chip->chip_shift);
-
- nand_get_device(mtd, FL_READING);
-
- /* Select the NAND device */
- chip->select_chip(mtd, chipnr);
- }
-
do {
if (chip->options & NAND_BUSWIDTH_16) {
chip->cmdfunc(mtd, NAND_CMD_READOOB,
@@ -391,11 +377,6 @@ static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)
i++;
} while (!res && i < 2 && (chip->bbt_options & NAND_BBT_SCAN2NDPAGE));
- if (getchip) {
- chip->select_chip(mtd, -1);
- nand_release_device(mtd);
- }
-
return res;
}
@@ -410,7 +391,7 @@ static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)
*/
static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
{
- struct nand_chip *chip = mtd->priv;
+ struct nand_chip *chip = mtd_to_nand(mtd);
struct mtd_oob_ops ops;
uint8_t buf[2] = { 0, 0 };
int ret = 0, res, i = 0;
@@ -460,7 +441,7 @@ static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
*/
static int nand_block_markbad_lowlevel(struct mtd_info *mtd, loff_t ofs)
{
- struct nand_chip *chip = mtd->priv;
+ struct nand_chip *chip = mtd_to_nand(mtd);
int res, ret = 0;
if (!(chip->bbt_options & NAND_BBT_NO_OOB_BBM)) {
@@ -501,7 +482,7 @@ static int nand_block_markbad_lowlevel(struct mtd_info *mtd, loff_t ofs)
*/
static int nand_check_wp(struct mtd_info *mtd)
{
- struct nand_chip *chip = mtd->priv;
+ struct nand_chip *chip = mtd_to_nand(mtd);
/* Broken xD cards report WP despite being writable */
if (chip->options & NAND_BROKEN_XD)
@@ -521,7 +502,7 @@ static int nand_check_wp(struct mtd_info *mtd)
*/
static int nand_block_isreserved(struct mtd_info *mtd, loff_t ofs)
{
- struct nand_chip *chip = mtd->priv;
+ struct nand_chip *chip = mtd_to_nand(mtd);
if (!chip->bbt)
return 0;
@@ -533,16 +514,14 @@ static int nand_block_isreserved(struct mtd_info *mtd, loff_t ofs)
* nand_block_checkbad - [GENERIC] Check if a block is marked bad
* @mtd: MTD device structure
* @ofs: offset from device start
- * @getchip: 0, if the chip is already selected
* @allowbbt: 1, if its allowed to access the bbt area
*
* Check, if the block is bad. Either by reading the bad block table or
* calling of the scan function.
*/
-static int nand_block_checkbad(struct mtd_info *mtd, loff_t ofs, int getchip,
- int allowbbt)
+static int nand_block_checkbad(struct mtd_info *mtd, loff_t ofs, int allowbbt)
{
- struct nand_chip *chip = mtd->priv;
+ struct nand_chip *chip = mtd_to_nand(mtd);
if (!(chip->options & NAND_SKIP_BBTSCAN) &&
!(chip->options & NAND_BBT_SCANNED)) {
@@ -551,17 +530,22 @@ static int nand_block_checkbad(struct mtd_info *mtd, loff_t ofs, int getchip,
}
if (!chip->bbt)
- return chip->block_bad(mtd, ofs, getchip);
+ return chip->block_bad(mtd, ofs);
/* Return info from the table */
return nand_isbad_bbt(mtd, ofs, allowbbt);
}
-/* Wait for the ready pin, after a command. The timeout is caught later. */
+/**
+ * nand_wait_ready - [GENERIC] Wait for the ready pin after commands.
+ * @mtd: MTD device structure
+ *
+ * Wait for the ready pin after a command, and warn if a timeout occurs.
+ */
void nand_wait_ready(struct mtd_info *mtd)
{
- struct nand_chip *chip = mtd->priv;
- u32 timeo = (CONFIG_SYS_HZ * 20) / 1000;
+ struct nand_chip *chip = mtd_to_nand(mtd);
+ u32 timeo = (CONFIG_SYS_HZ * 400) / 1000;
u32 time_start;
time_start = get_timer(0);
@@ -571,6 +555,9 @@ void nand_wait_ready(struct mtd_info *mtd)
if (chip->dev_ready(mtd))
break;
}
+
+ if (!chip->dev_ready(mtd))
+ pr_warn("timeout while waiting for chip to become ready\n");
}
EXPORT_SYMBOL_GPL(nand_wait_ready);
@@ -583,7 +570,7 @@ EXPORT_SYMBOL_GPL(nand_wait_ready);
*/
static void nand_wait_status_ready(struct mtd_info *mtd, unsigned long timeo)
{
- register struct nand_chip *chip = mtd->priv;
+ register struct nand_chip *chip = mtd_to_nand(mtd);
u32 time_start;
timeo = (CONFIG_SYS_HZ * timeo) / 1000;
@@ -608,7 +595,7 @@ static void nand_wait_status_ready(struct mtd_info *mtd, unsigned long timeo)
static void nand_command(struct mtd_info *mtd, unsigned int command,
int column, int page_addr)
{
- register struct nand_chip *chip = mtd->priv;
+ register struct nand_chip *chip = mtd_to_nand(mtd);
int ctrl = NAND_CTRL_CLE | NAND_CTRL_CHANGE;
/* Write out the command to the device */
@@ -711,7 +698,7 @@ static void nand_command(struct mtd_info *mtd, unsigned int command,
static void nand_command_lp(struct mtd_info *mtd, unsigned int command,
int column, int page_addr)
{
- register struct nand_chip *chip = mtd->priv;
+ register struct nand_chip *chip = mtd_to_nand(mtd);
/* Emulate NAND_CMD_READOOB */
if (command == NAND_CMD_READOOB) {
@@ -835,7 +822,7 @@ static void panic_nand_get_device(struct nand_chip *chip,
static int
nand_get_device(struct mtd_info *mtd, int new_state)
{
- struct nand_chip *chip = mtd->priv;
+ struct nand_chip *chip = mtd_to_nand(mtd);
chip->state = new_state;
return 0;
}
@@ -871,15 +858,13 @@ static void panic_nand_wait(struct mtd_info *mtd, struct nand_chip *chip,
* @mtd: MTD device structure
* @chip: NAND chip structure
*
- * Wait for command done. This applies to erase and program only. Erase can
- * take up to 400ms and program up to 20ms according to general NAND and
- * SmartMedia specs.
+ * Wait for command done. This applies to erase and program only.
*/
static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip)
{
- int status, state = chip->state;
- unsigned long timeo = (state == FL_ERASING ? 400 : 20);
+ int status;
+ unsigned long timeo = 400;
led_trigger_event(nand_led_trigger, LED_FULL);
@@ -912,6 +897,135 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip)
return status;
}
+#define BITS_PER_BYTE 8
+
+/**
+ * nand_check_erased_buf - check if a buffer contains (almost) only 0xff data
+ * @buf: buffer to test
+ * @len: buffer length
+ * @bitflips_threshold: maximum number of bitflips
+ *
+ * Check if a buffer contains only 0xff, which means the underlying region
+ * has been erased and is ready to be programmed.
+ * The bitflips_threshold specify the maximum number of bitflips before
+ * considering the region is not erased.
+ * Note: The logic of this function has been extracted from the memweight
+ * implementation, except that nand_check_erased_buf function exit before
+ * testing the whole buffer if the number of bitflips exceed the
+ * bitflips_threshold value.
+ *
+ * Returns a positive number of bitflips less than or equal to
+ * bitflips_threshold, or -ERROR_CODE for bitflips in excess of the
+ * threshold.
+ */
+static int nand_check_erased_buf(void *buf, int len, int bitflips_threshold)
+{
+ const unsigned char *bitmap = buf;
+ int bitflips = 0;
+ int weight;
+
+ for (; len && ((uintptr_t)bitmap) % sizeof(long);
+ len--, bitmap++) {
+ weight = hweight8(*bitmap);
+ bitflips += BITS_PER_BYTE - weight;
+ if (unlikely(bitflips > bitflips_threshold))
+ return -EBADMSG;
+ }
+
+ for (; len >= 4; len -= 4, bitmap += 4) {
+ weight = hweight32(*((u32 *)bitmap));
+ bitflips += 32 - weight;
+ if (unlikely(bitflips > bitflips_threshold))
+ return -EBADMSG;
+ }
+
+ for (; len > 0; len--, bitmap++) {
+ weight = hweight8(*bitmap);
+ bitflips += BITS_PER_BYTE - weight;
+ if (unlikely(bitflips > bitflips_threshold))
+ return -EBADMSG;
+ }
+
+ return bitflips;
+}
+
+/**
+ * nand_check_erased_ecc_chunk - check if an ECC chunk contains (almost) only
+ * 0xff data
+ * @data: data buffer to test
+ * @datalen: data length
+ * @ecc: ECC buffer
+ * @ecclen: ECC length
+ * @extraoob: extra OOB buffer
+ * @extraooblen: extra OOB length
+ * @bitflips_threshold: maximum number of bitflips
+ *
+ * Check if a data buffer and its associated ECC and OOB data contains only
+ * 0xff pattern, which means the underlying region has been erased and is
+ * ready to be programmed.
+ * The bitflips_threshold specify the maximum number of bitflips before
+ * considering the region as not erased.
+ *
+ * Note:
+ * 1/ ECC algorithms are working on pre-defined block sizes which are usually
+ * different from the NAND page size. When fixing bitflips, ECC engines will
+ * report the number of errors per chunk, and the NAND core infrastructure
+ * expect you to return the maximum number of bitflips for the whole page.
+ * This is why you should always use this function on a single chunk and
+ * not on the whole page. After checking each chunk you should update your
+ * max_bitflips value accordingly.
+ * 2/ When checking for bitflips in erased pages you should not only check
+ * the payload data but also their associated ECC data, because a user might
+ * have programmed almost all bits to 1 but a few. In this case, we
+ * shouldn't consider the chunk as erased, and checking ECC bytes prevent
+ * this case.
+ * 3/ The extraoob argument is optional, and should be used if some of your OOB
+ * data are protected by the ECC engine.
+ * It could also be used if you support subpages and want to attach some
+ * extra OOB data to an ECC chunk.
+ *
+ * Returns a positive number of bitflips less than or equal to
+ * bitflips_threshold, or -ERROR_CODE for bitflips in excess of the
+ * threshold. In case of success, the passed buffers are filled with 0xff.
+ */
+int nand_check_erased_ecc_chunk(void *data, int datalen,
+ void *ecc, int ecclen,
+ void *extraoob, int extraooblen,
+ int bitflips_threshold)
+{
+ int data_bitflips = 0, ecc_bitflips = 0, extraoob_bitflips = 0;
+
+ data_bitflips = nand_check_erased_buf(data, datalen,
+ bitflips_threshold);
+ if (data_bitflips < 0)
+ return data_bitflips;
+
+ bitflips_threshold -= data_bitflips;
+
+ ecc_bitflips = nand_check_erased_buf(ecc, ecclen, bitflips_threshold);
+ if (ecc_bitflips < 0)
+ return ecc_bitflips;
+
+ bitflips_threshold -= ecc_bitflips;
+
+ extraoob_bitflips = nand_check_erased_buf(extraoob, extraooblen,
+ bitflips_threshold);
+ if (extraoob_bitflips < 0)
+ return extraoob_bitflips;
+
+ if (data_bitflips)
+ memset(data, 0xff, datalen);
+
+ if (ecc_bitflips)
+ memset(ecc, 0xff, ecclen);
+
+ if (extraoob_bitflips)
+ memset(extraoob, 0xff, extraooblen);
+
+ return data_bitflips + ecc_bitflips + extraoob_bitflips;
+}
+EXPORT_SYMBOL(nand_check_erased_ecc_chunk);
+
/**
* nand_read_page_raw - [INTERN] read raw page data without ecc
* @mtd: mtd info structure
@@ -1103,6 +1217,16 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip,
stat = chip->ecc.correct(mtd, p,
&chip->buffers->ecccode[i], &chip->buffers->ecccalc[i]);
+ if (stat == -EBADMSG &&
+ (chip->ecc.options & NAND_ECC_GENERIC_ERASED_CHECK)) {
+ /* check for empty pages with bitflips */
+ stat = nand_check_erased_ecc_chunk(p, chip->ecc.size,
+ &chip->buffers->ecccode[i],
+ chip->ecc.bytes,
+ NULL, 0,
+ chip->ecc.strength);
+ }
+
if (stat < 0) {
mtd->ecc_stats.failed++;
} else {
@@ -1152,6 +1276,15 @@ static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
int stat;
stat = chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]);
+ if (stat == -EBADMSG &&
+ (chip->ecc.options & NAND_ECC_GENERIC_ERASED_CHECK)) {
+ /* check for empty pages with bitflips */
+ stat = nand_check_erased_ecc_chunk(p, eccsize,
+ &ecc_code[i], eccbytes,
+ NULL, 0,
+ chip->ecc.strength);
+ }
+
if (stat < 0) {
mtd->ecc_stats.failed++;
} else {
@@ -1204,6 +1337,15 @@ static int nand_read_page_hwecc_oob_first(struct mtd_info *mtd,
chip->ecc.calculate(mtd, p, &ecc_calc[i]);
stat = chip->ecc.correct(mtd, p, &ecc_code[i], NULL);
+ if (stat == -EBADMSG &&
+ (chip->ecc.options & NAND_ECC_GENERIC_ERASED_CHECK)) {
+ /* check for empty pages with bitflips */
+ stat = nand_check_erased_ecc_chunk(p, eccsize,
+ &ecc_code[i], eccbytes,
+ NULL, 0,
+ chip->ecc.strength);
+ }
+
if (stat < 0) {
mtd->ecc_stats.failed++;
} else {
@@ -1231,6 +1373,7 @@ static int nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip,
int i, eccsize = chip->ecc.size;
int eccbytes = chip->ecc.bytes;
int eccsteps = chip->ecc.steps;
+ int eccpadbytes = eccbytes + chip->ecc.prepad + chip->ecc.postpad;
uint8_t *p = buf;
uint8_t *oob = chip->oob_poi;
unsigned int max_bitflips = 0;
@@ -1250,19 +1393,29 @@ 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 < 0) {
- mtd->ecc_stats.failed++;
- } else {
- mtd->ecc_stats.corrected += stat;
- max_bitflips = max_t(unsigned int, max_bitflips, stat);
- }
-
oob += eccbytes;
if (chip->ecc.postpad) {
chip->read_buf(mtd, oob, chip->ecc.postpad);
oob += chip->ecc.postpad;
}
+
+ if (stat == -EBADMSG &&
+ (chip->ecc.options & NAND_ECC_GENERIC_ERASED_CHECK)) {
+ /* check for empty pages with bitflips */
+ stat = nand_check_erased_ecc_chunk(p, chip->ecc.size,
+ oob - eccpadbytes,
+ eccpadbytes,
+ NULL, 0,
+ chip->ecc.strength);
+ }
+
+ if (stat < 0) {
+ mtd->ecc_stats.failed++;
+ } else {
+ mtd->ecc_stats.corrected += stat;
+ max_bitflips = max_t(unsigned int, max_bitflips, stat);
+ }
}
/* Calculate remaining oob bytes */
@@ -1332,7 +1485,7 @@ static uint8_t *nand_transfer_oob(struct nand_chip *chip, uint8_t *oob,
*/
static int nand_setup_read_retry(struct mtd_info *mtd, int retry_mode)
{
- struct nand_chip *chip = mtd->priv;
+ struct nand_chip *chip = mtd_to_nand(mtd);
pr_debug("setting READ RETRY mode %d\n", retry_mode);
@@ -1357,12 +1510,11 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
struct mtd_oob_ops *ops)
{
int chipnr, page, realpage, col, bytes, aligned, oob_required;
- struct nand_chip *chip = mtd->priv;
+ struct nand_chip *chip = mtd_to_nand(mtd);
int ret = 0;
uint32_t readlen = ops->len;
uint32_t oobreadlen = ops->ooblen;
- uint32_t max_oobsize = ops->mode == MTD_OPS_AUTO_OOB ?
- mtd->oobavail : mtd->oobsize;
+ uint32_t max_oobsize = mtd_oobavail(mtd, ops);
uint8_t *bufpoi, *oob, *buf;
int use_bufpoi;
@@ -1700,7 +1852,7 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from,
struct mtd_oob_ops *ops)
{
int page, realpage, chipnr;
- struct nand_chip *chip = mtd->priv;
+ struct nand_chip *chip = mtd_to_nand(mtd);
struct mtd_ecc_stats stats;
int readlen = ops->ooblen;
int len;
@@ -1712,10 +1864,7 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from,
stats = mtd->ecc_stats;
- if (ops->mode == MTD_OPS_AUTO_OOB)
- len = chip->ecc.layout->oobavail;
- else
- len = mtd->oobsize;
+ len = mtd_oobavail(mtd, ops);
if (unlikely(ops->ooboffs >= len)) {
pr_debug("%s: attempt to start read outside oob\n",
@@ -1840,11 +1989,12 @@ out:
* @chip: nand chip info structure
* @buf: data buffer
* @oob_required: must write chip->oob_poi to OOB
+ * @page: page number to write
*
* Not for syndrome calculating ECC controllers, which use a special oob layout.
*/
static int nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
- const uint8_t *buf, int oob_required)
+ const uint8_t *buf, int oob_required, int page)
{
chip->write_buf(mtd, buf, mtd->writesize);
if (oob_required)
@@ -1859,12 +2009,14 @@ static int nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
* @chip: nand chip info structure
* @buf: data buffer
* @oob_required: must write chip->oob_poi to OOB
+ * @page: page number to write
*
* We need a special oob layout and handling even when ECC isn't checked.
*/
static int nand_write_page_raw_syndrome(struct mtd_info *mtd,
struct nand_chip *chip,
- const uint8_t *buf, int oob_required)
+ const uint8_t *buf, int oob_required,
+ int page)
{
int eccsize = chip->ecc.size;
int eccbytes = chip->ecc.bytes;
@@ -1901,9 +2053,11 @@ static int nand_write_page_raw_syndrome(struct mtd_info *mtd,
* @chip: nand chip info structure
* @buf: data buffer
* @oob_required: must write chip->oob_poi to OOB
+ * @page: page number to write
*/
static int nand_write_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
- const uint8_t *buf, int oob_required)
+ const uint8_t *buf, int oob_required,
+ int page)
{
int i, eccsize = chip->ecc.size;
int eccbytes = chip->ecc.bytes;
@@ -1919,7 +2073,7 @@ static int nand_write_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
for (i = 0; i < chip->ecc.total; i++)
chip->oob_poi[eccpos[i]] = ecc_calc[i];
- return chip->ecc.write_page_raw(mtd, chip, buf, 1);
+ return chip->ecc.write_page_raw(mtd, chip, buf, 1, page);
}
/**
@@ -1928,9 +2082,11 @@ static int nand_write_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
* @chip: nand chip info structure
* @buf: data buffer
* @oob_required: must write chip->oob_poi to OOB
+ * @page: page number to write
*/
static int nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
- const uint8_t *buf, int oob_required)
+ const uint8_t *buf, int oob_required,
+ int page)
{
int i, eccsize = chip->ecc.size;
int eccbytes = chip->ecc.bytes;
@@ -1962,11 +2118,12 @@ static int nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
* @data_len: data length
* @buf: data buffer
* @oob_required: must write chip->oob_poi to OOB
+ * @page: page number to write
*/
static int nand_write_subpage_hwecc(struct mtd_info *mtd,
struct nand_chip *chip, uint32_t offset,
uint32_t data_len, const uint8_t *buf,
- int oob_required)
+ int oob_required, int page)
{
uint8_t *oob_buf = chip->oob_poi;
uint8_t *ecc_calc = chip->buffers->ecccalc;
@@ -2021,13 +2178,15 @@ static int nand_write_subpage_hwecc(struct mtd_info *mtd,
* @chip: nand chip info structure
* @buf: data buffer
* @oob_required: must write chip->oob_poi to OOB
+ * @page: page number to write
*
* The hw generator calculates the error syndrome automatically. Therefore we
* need a special oob layout and handling.
*/
static int nand_write_page_syndrome(struct mtd_info *mtd,
struct nand_chip *chip,
- const uint8_t *buf, int oob_required)
+ const uint8_t *buf, int oob_required,
+ int page)
{
int i, eccsize = chip->ecc.size;
int eccbytes = chip->ecc.bytes;
@@ -2091,12 +2250,13 @@ static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip,
if (unlikely(raw))
status = chip->ecc.write_page_raw(mtd, chip, buf,
- oob_required);
+ oob_required, page);
else if (subpage)
status = chip->ecc.write_subpage(mtd, chip, offset, data_len,
- buf, oob_required);
+ buf, oob_required, page);
else
- status = chip->ecc.write_page(mtd, chip, buf, oob_required);
+ status = chip->ecc.write_page(mtd, chip, buf, oob_required,
+ page);
if (status < 0)
return status;
@@ -2139,7 +2299,7 @@ static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip,
static uint8_t *nand_fill_oob(struct mtd_info *mtd, uint8_t *oob, size_t len,
struct mtd_oob_ops *ops)
{
- struct nand_chip *chip = mtd->priv;
+ struct nand_chip *chip = mtd_to_nand(mtd);
/*
* Initialise to all 0xFF, to avoid the possibility of left over OOB
@@ -2199,12 +2359,11 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
struct mtd_oob_ops *ops)
{
int chipnr, realpage, page, blockmask, column;
- struct nand_chip *chip = mtd->priv;
+ struct nand_chip *chip = mtd_to_nand(mtd);
uint32_t writelen = ops->len;
uint32_t oobwritelen = ops->ooblen;
- uint32_t oobmaxlen = ops->mode == MTD_OPS_AUTO_OOB ?
- mtd->oobavail : mtd->oobsize;
+ uint32_t oobmaxlen = mtd_oobavail(mtd, ops);
uint8_t *oob = ops->oobbuf;
uint8_t *buf = ops->datbuf;
@@ -2328,7 +2487,7 @@ err_out:
static int panic_nand_write(struct mtd_info *mtd, loff_t to, size_t len,
size_t *retlen, const uint8_t *buf)
{
- struct nand_chip *chip = mtd->priv;
+ struct nand_chip *chip = mtd_to_nand(mtd);
struct mtd_oob_ops ops;
int ret;
@@ -2388,15 +2547,12 @@ static int nand_do_write_oob(struct mtd_info *mtd, loff_t to,
struct mtd_oob_ops *ops)
{
int chipnr, page, status, len;
- struct nand_chip *chip = mtd->priv;
+ struct nand_chip *chip = mtd_to_nand(mtd);
pr_debug("%s: to = 0x%08x, len = %i\n",
__func__, (unsigned int)to, (int)ops->ooblen);
- if (ops->mode == MTD_OPS_AUTO_OOB)
- len = chip->ecc.layout->oobavail;
- else
- len = mtd->oobsize;
+ len = mtd_oobavail(mtd, ops);
/* Do not allow write past end of page */
if ((ops->ooboffs + ops->ooblen) > len) {
@@ -2513,7 +2669,7 @@ out:
*/
static int single_erase(struct mtd_info *mtd, int page)
{
- struct nand_chip *chip = mtd->priv;
+ struct nand_chip *chip = mtd_to_nand(mtd);
/* Send commands to erase a block */
chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page);
chip->cmdfunc(mtd, NAND_CMD_ERASE2, -1, -1);
@@ -2545,7 +2701,7 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
int allowbbt)
{
int page, status, pages_per_block, ret, chipnr;
- struct nand_chip *chip = mtd->priv;
+ struct nand_chip *chip = mtd_to_nand(mtd);
loff_t len;
pr_debug("%s: start = 0x%012llx, len = %llu\n",
@@ -2586,7 +2742,7 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
/* Check if we have a bad block, we do not erase bad blocks! */
if (!instr->scrub && nand_block_checkbad(mtd, ((loff_t) page) <<
- chip->page_shift, 0, allowbbt)) {
+ chip->page_shift, allowbbt)) {
pr_warn("%s: attempt to erase a bad block at page 0x%08x\n",
__func__, page);
instr->state = MTD_ERASE_FAILED;
@@ -2673,7 +2829,20 @@ static void nand_sync(struct mtd_info *mtd)
*/
static int nand_block_isbad(struct mtd_info *mtd, loff_t offs)
{
- return nand_block_checkbad(mtd, offs, 1, 0);
+ struct nand_chip *chip = mtd_to_nand(mtd);
+ int chipnr = (int)(offs >> chip->chip_shift);
+ int ret;
+
+ /* Select the NAND device */
+ nand_get_device(mtd, FL_READING);
+ chip->select_chip(mtd, chipnr);
+
+ ret = nand_block_checkbad(mtd, offs, 0);
+
+ chip->select_chip(mtd, -1);
+ nand_release_device(mtd);
+
+ return ret;
}
/**
@@ -2745,9 +2914,6 @@ static int nand_onfi_get_features(struct mtd_info *mtd, struct nand_chip *chip,
return -EINVAL;
#endif
- /* clear the sub feature parameters */
- memset(subfeature_param, 0, ONFI_SUBFEATURE_PARAM_LEN);
-
chip->cmdfunc(mtd, NAND_CMD_GET_FEATURES, addr, -1);
for (i = 0; i < ONFI_SUBFEATURE_PARAM_LEN; ++i)
*subfeature_param++ = chip->read_byte(mtd);
@@ -2908,7 +3074,7 @@ ext_out:
static int nand_setup_read_retry_micron(struct mtd_info *mtd, int retry_mode)
{
- struct nand_chip *chip = mtd->priv;
+ struct nand_chip *chip = mtd_to_nand(mtd);
uint8_t feature[ONFI_SUBFEATURE_PARAM_LEN] = {retry_mode};
return chip->onfi_set_features(mtd, chip, ONFI_FEATURE_ADDR_READ_RETRY,
@@ -3480,7 +3646,7 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
if (find_full_id_nand(mtd, chip, type, id_data, &busw))
goto ident_done;
} else if (*dev_id == type->dev_id) {
- break;
+ break;
}
}
@@ -3503,10 +3669,7 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
chip->chipsize = (uint64_t)type->chipsize << 20;
- if (!type->pagesize && chip->init_size) {
- /* Set the pagesize, oobsize, erasesize by the driver */
- busw = chip->init_size(mtd, chip, id_data);
- } else if (!type->pagesize) {
+ if (!type->pagesize) {
/* Decode parameters from extended ID */
nand_decode_ext_id(mtd, chip, id_data, &busw);
} else {
@@ -3610,13 +3773,12 @@ ident_done:
* This is the first phase of the normal nand_scan() function. It reads the
* flash ID and sets up MTD fields accordingly.
*
- * The mtd->owner field must be set to the module of the caller.
*/
int nand_scan_ident(struct mtd_info *mtd, int maxchips,
struct nand_flash_dev *table)
{
int i, nand_maf_id, nand_dev_id;
- struct nand_chip *chip = mtd->priv;
+ struct nand_chip *chip = mtd_to_nand(mtd);
struct nand_flash_dev *type;
/* Set the default functions */
@@ -3680,7 +3842,7 @@ EXPORT_SYMBOL(nand_scan_ident);
*/
static bool nand_ecc_strength_good(struct mtd_info *mtd)
{
- struct nand_chip *chip = mtd->priv;
+ struct nand_chip *chip = mtd_to_nand(mtd);
struct nand_ecc_ctrl *ecc = &chip->ecc;
int corr, ds_corr;
@@ -3709,7 +3871,7 @@ static bool nand_ecc_strength_good(struct mtd_info *mtd)
int nand_scan_tail(struct mtd_info *mtd)
{
int i;
- struct nand_chip *chip = mtd->priv;
+ struct nand_chip *chip = mtd_to_nand(mtd);
struct nand_ecc_ctrl *ecc = &chip->ecc;
struct nand_buffers *nbuf;
@@ -3786,7 +3948,7 @@ int nand_scan_tail(struct mtd_info *mtd)
ecc->write_oob = nand_write_oob_std;
if (!ecc->read_subpage)
ecc->read_subpage = nand_read_subpage;
- if (!ecc->write_subpage)
+ if (!ecc->write_subpage && ecc->hwctl && ecc->calculate)
ecc->write_subpage = nand_write_subpage_hwecc;
case NAND_ECC_HW_SYNDROME:
@@ -3864,10 +4026,8 @@ int nand_scan_tail(struct mtd_info *mtd)
}
/* See nand_bch_init() for details. */
- ecc->bytes = DIV_ROUND_UP(
- ecc->strength * fls(8 * ecc->size), 8);
- ecc->priv = nand_bch_init(mtd, ecc->size, ecc->bytes,
- &ecc->layout);
+ ecc->bytes = 0;
+ ecc->priv = nand_bch_init(mtd);
if (!ecc->priv) {
pr_warn("BCH ECC initialization failed!\n");
BUG();
@@ -3902,11 +4062,11 @@ int nand_scan_tail(struct mtd_info *mtd)
* The number of bytes available for a client to place data into
* the out of band area.
*/
- ecc->layout->oobavail = 0;
- for (i = 0; ecc->layout->oobfree[i].length
- && i < ARRAY_SIZE(ecc->layout->oobfree); i++)
- ecc->layout->oobavail += ecc->layout->oobfree[i].length;
- mtd->oobavail = ecc->layout->oobavail;
+ mtd->oobavail = 0;
+ if (ecc->layout) {
+ for (i = 0; ecc->layout->oobfree[i].length; i++)
+ mtd->oobavail += ecc->layout->oobfree[i].length;
+ }
/* ECC sanity check: warn if it's too weak */
if (!nand_ecc_strength_good(mtd))
@@ -3991,18 +4151,6 @@ int nand_scan_tail(struct mtd_info *mtd)
}
EXPORT_SYMBOL(nand_scan_tail);
-/*
- * is_module_text_address() isn't exported, and it's mostly a pointless
- * test if this is a module _anyway_ -- they'd have to try _really_ hard
- * to call us from in-kernel code if the core NAND support is modular.
- */
-#ifdef MODULE
-#define caller_is_module() (1)
-#else
-#define caller_is_module() \
- is_module_text_address((unsigned long)__builtin_return_address(0))
-#endif
-
/**
* nand_scan - [NAND Interface] Scan for the NAND device
* @mtd: MTD device structure
@@ -4010,19 +4158,12 @@ EXPORT_SYMBOL(nand_scan_tail);
*
* This fills out all the uninitialized function pointers with the defaults.
* The flash ID is read and the mtd/chip structures are filled with the
- * appropriate values. The mtd->owner field must be set to the module of the
- * caller.
+ * appropriate values.
*/
int nand_scan(struct mtd_info *mtd, int maxchips)
{
int ret;
- /* Many callers got this wrong, so check for it for a while... */
- if (!mtd->owner && caller_is_module()) {
- pr_crit("%s called with NULL mtd->owner!\n", __func__);
- BUG();
- }
-
ret = nand_scan_ident(mtd, maxchips, NULL);
if (!ret)
ret = nand_scan_tail(mtd);
@@ -4030,9 +4171,6 @@ int nand_scan(struct mtd_info *mtd, int maxchips)
}
EXPORT_SYMBOL(nand_scan);
-module_init(nand_base_init);
-module_exit(nand_base_exit);
-
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Steven J. Hill <sjhill@realitydiluted.com>");
MODULE_AUTHOR("Thomas Gleixner <tglx@linutronix.de>");
diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c
index 00f28a4157..74c4c9a3c8 100644
--- a/drivers/mtd/nand/nand_bbt.c
+++ b/drivers/mtd/nand/nand_bbt.c
@@ -1,6 +1,4 @@
/*
- * drivers/mtd/nand_bbt.c
- *
* Overview:
* Bad block table support for the NAND driver
*
@@ -65,7 +63,6 @@
#include <linux/mtd/mtd.h>
#include <linux/mtd/bbm.h>
#include <linux/mtd/nand.h>
-#include <linux/mtd/nand_ecc.h>
#include <linux/bitops.h>
#include <linux/string.h>
@@ -173,7 +170,7 @@ static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num,
struct nand_bbt_descr *td, int offs)
{
int res, ret = 0, i, j, act = 0;
- struct nand_chip *this = mtd->priv;
+ struct nand_chip *this = mtd_to_nand(mtd);
size_t retlen, len, totlen;
loff_t from;
int bits = td->options & NAND_BBT_NRBITS_MSK;
@@ -264,7 +261,7 @@ static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num,
*/
static int read_abs_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td, int chip)
{
- struct nand_chip *this = mtd->priv;
+ struct nand_chip *this = mtd_to_nand(mtd);
int res = 0, i;
if (td->options & NAND_BBT_PERCHIP) {
@@ -389,7 +386,7 @@ static u32 bbt_get_ver_offs(struct mtd_info *mtd, struct nand_bbt_descr *td)
static void read_abs_bbts(struct mtd_info *mtd, uint8_t *buf,
struct nand_bbt_descr *td, struct nand_bbt_descr *md)
{
- struct nand_chip *this = mtd->priv;
+ struct nand_chip *this = mtd_to_nand(mtd);
/* Read the primary version, if available */
if (td->options & NAND_BBT_VERSION) {
@@ -455,7 +452,7 @@ static int scan_block_fast(struct mtd_info *mtd, struct nand_bbt_descr *bd,
static int create_bbt(struct mtd_info *mtd, uint8_t *buf,
struct nand_bbt_descr *bd, int chip)
{
- struct nand_chip *this = mtd->priv;
+ struct nand_chip *this = mtd_to_nand(mtd);
int i, numblocks, numpages;
int startblock;
loff_t from;
@@ -524,7 +521,7 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf,
*/
static int search_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td)
{
- struct nand_chip *this = mtd->priv;
+ struct nand_chip *this = mtd_to_nand(mtd);
int i, chips;
int startblock, block, dir;
int scanlen = mtd->writesize + mtd->oobsize;
@@ -619,7 +616,7 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
struct nand_bbt_descr *td, struct nand_bbt_descr *md,
int chipsel)
{
- struct nand_chip *this = mtd->priv;
+ struct nand_chip *this = mtd_to_nand(mtd);
struct erase_info einfo;
int i, res, chip = 0;
int bits, startblock, dir, page, offs, numblocks, sft, sftmsk;
@@ -718,7 +715,7 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
/* Must we save the block contents? */
if (td->options & NAND_BBT_SAVECONTENT) {
/* Make it block aligned */
- to &= ~((loff_t)((1 << this->bbt_erase_shift) - 1));
+ to &= ~(((loff_t)1 << this->bbt_erase_shift) - 1);
len = 1 << this->bbt_erase_shift;
res = mtd_read(mtd, to, len, &retlen, buf);
if (res < 0) {
@@ -820,7 +817,7 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
*/
static inline int nand_memory_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
{
- struct nand_chip *this = mtd->priv;
+ struct nand_chip *this = mtd_to_nand(mtd);
return create_bbt(mtd, this->buffers->databuf, bd, -1);
}
@@ -839,7 +836,7 @@ static inline int nand_memory_bbt(struct mtd_info *mtd, struct nand_bbt_descr *b
static int check_create(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *bd)
{
int i, chips, writeops, create, chipsel, res, res2;
- struct nand_chip *this = mtd->priv;
+ struct nand_chip *this = mtd_to_nand(mtd);
struct nand_bbt_descr *td = this->bbt_td;
struct nand_bbt_descr *md = this->bbt_md;
struct nand_bbt_descr *rd, *rd2;
@@ -963,7 +960,7 @@ static int check_create(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_desc
*/
static void mark_bbt_region(struct mtd_info *mtd, struct nand_bbt_descr *td)
{
- struct nand_chip *this = mtd->priv;
+ struct nand_chip *this = mtd_to_nand(mtd);
int i, j, chips, block, nrblocks, update;
uint8_t oldval;
@@ -1023,7 +1020,7 @@ static void mark_bbt_region(struct mtd_info *mtd, struct nand_bbt_descr *td)
*/
static void verify_bbt_descr(struct mtd_info *mtd, struct nand_bbt_descr *bd)
{
- struct nand_chip *this = mtd->priv;
+ struct nand_chip *this = mtd_to_nand(mtd);
u32 pattern_len;
u32 bits;
u32 table_size;
@@ -1073,15 +1070,15 @@ static void verify_bbt_descr(struct mtd_info *mtd, struct nand_bbt_descr *bd)
* The bad block table memory is allocated here. It must be freed by calling
* the nand_free_bbt function.
*/
-int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
+static int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
{
- struct nand_chip *this = mtd->priv;
- int len, res = 0;
+ struct nand_chip *this = mtd_to_nand(mtd);
+ int len, res;
uint8_t *buf;
struct nand_bbt_descr *td = this->bbt_td;
struct nand_bbt_descr *md = this->bbt_md;
- len = mtd->size >> (this->bbt_erase_shift + 2);
+ len = (mtd->size >> (this->bbt_erase_shift + 2)) ? : 1;
/*
* Allocate memory (2bit per block) and clear the memory bad block
* table.
@@ -1097,10 +1094,9 @@ int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
if (!td) {
if ((res = nand_memory_bbt(mtd, bd))) {
pr_err("nand_bbt: can't scan flash and build the RAM-based BBT\n");
- kfree(this->bbt);
- this->bbt = NULL;
+ goto err;
}
- return res;
+ return 0;
}
verify_bbt_descr(mtd, td);
verify_bbt_descr(mtd, md);
@@ -1110,9 +1106,8 @@ int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
len += (len >> this->page_shift) * mtd->oobsize;
buf = vmalloc(len);
if (!buf) {
- kfree(this->bbt);
- this->bbt = NULL;
- return -ENOMEM;
+ res = -ENOMEM;
+ goto err;
}
/* Is the bbt at a given page? */
@@ -1124,6 +1119,8 @@ int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
}
res = check_create(mtd, buf, bd);
+ if (res)
+ goto err;
/* Prevent the bbt regions from erasing / writing */
mark_bbt_region(mtd, td);
@@ -1131,6 +1128,11 @@ int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
mark_bbt_region(mtd, md);
vfree(buf);
+ return 0;
+
+err:
+ kfree(this->bbt);
+ this->bbt = NULL;
return res;
}
@@ -1143,7 +1145,7 @@ int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
*/
static int nand_update_bbt(struct mtd_info *mtd, loff_t offs)
{
- struct nand_chip *this = mtd->priv;
+ struct nand_chip *this = mtd_to_nand(mtd);
int len, res = 0;
int chip, chipsel;
uint8_t *buf;
@@ -1277,7 +1279,7 @@ static int nand_create_badblock_pattern(struct nand_chip *this)
*/
int nand_default_bbt(struct mtd_info *mtd)
{
- struct nand_chip *this = mtd->priv;
+ struct nand_chip *this = mtd_to_nand(mtd);
int ret;
/* Is a flash based bad block table requested? */
@@ -1313,7 +1315,7 @@ int nand_default_bbt(struct mtd_info *mtd)
*/
int nand_isreserved_bbt(struct mtd_info *mtd, loff_t offs)
{
- struct nand_chip *this = mtd->priv;
+ struct nand_chip *this = mtd_to_nand(mtd);
int block;
block = (int)(offs >> this->bbt_erase_shift);
@@ -1328,7 +1330,7 @@ int nand_isreserved_bbt(struct mtd_info *mtd, loff_t offs)
*/
int nand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt)
{
- struct nand_chip *this = mtd->priv;
+ struct nand_chip *this = mtd_to_nand(mtd);
int block, res;
block = (int)(offs >> this->bbt_erase_shift);
@@ -1355,7 +1357,7 @@ int nand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt)
*/
int nand_markbad_bbt(struct mtd_info *mtd, loff_t offs)
{
- struct nand_chip *this = mtd->priv;
+ struct nand_chip *this = mtd_to_nand(mtd);
int block, ret = 0;
block = (int)(offs >> this->bbt_erase_shift);
@@ -1369,5 +1371,3 @@ int nand_markbad_bbt(struct mtd_info *mtd, loff_t offs)
return ret;
}
-
-EXPORT_SYMBOL(nand_scan_bbt);
diff --git a/drivers/mtd/nand/nand_bch.c b/drivers/mtd/nand/nand_bch.c
index 35d2140dab..c14520380e 100644
--- a/drivers/mtd/nand/nand_bch.c
+++ b/drivers/mtd/nand/nand_bch.c
@@ -41,7 +41,7 @@ struct nand_bch_control {
int nand_bch_calculate_ecc(struct mtd_info *mtd, const unsigned char *buf,
unsigned char *code)
{
- const struct nand_chip *chip = mtd->priv;
+ const struct nand_chip *chip = mtd_to_nand(mtd);
struct nand_bch_control *nbc = chip->ecc.priv;
unsigned int i;
@@ -67,7 +67,7 @@ int nand_bch_calculate_ecc(struct mtd_info *mtd, const unsigned char *buf,
int nand_bch_correct_data(struct mtd_info *mtd, unsigned char *buf,
unsigned char *read_ecc, unsigned char *calc_ecc)
{
- const struct nand_chip *chip = mtd->priv;
+ const struct nand_chip *chip = mtd_to_nand(mtd);
struct nand_bch_control *nbc = chip->ecc.priv;
unsigned int *errloc = nbc->errloc;
int i, count;
@@ -86,7 +86,7 @@ int nand_bch_correct_data(struct mtd_info *mtd, unsigned char *buf,
}
} else if (count < 0) {
printk(KERN_ERR "ecc unrecoverable error\n");
- count = -1;
+ count = -EBADMSG;
}
return count;
}
@@ -94,9 +94,6 @@ int nand_bch_correct_data(struct mtd_info *mtd, unsigned char *buf,
/**
* nand_bch_init - [NAND Interface] Initialize NAND BCH error correction
* @mtd: MTD block structure
- * @eccsize: ecc block size in bytes
- * @eccbytes: ecc length in bytes
- * @ecclayout: output default layout
*
* Returns:
* a pointer to a new NAND BCH control structure, or NULL upon failure
@@ -110,14 +107,21 @@ int nand_bch_correct_data(struct mtd_info *mtd, unsigned char *buf,
* @eccsize = 512 (thus, m=13 is the smallest integer such that 2^m-1 > 512*8)
* @eccbytes = 7 (7 bytes are required to store m*t = 13*4 = 52 bits)
*/
-struct nand_bch_control *
-nand_bch_init(struct mtd_info *mtd, unsigned int eccsize, unsigned int eccbytes,
- struct nand_ecclayout **ecclayout)
+struct nand_bch_control *nand_bch_init(struct mtd_info *mtd)
{
+ struct nand_chip *nand = mtd_to_nand(mtd);
unsigned int m, t, eccsteps, i;
- struct nand_ecclayout *layout;
+ struct nand_ecclayout *layout = nand->ecc.layout;
struct nand_bch_control *nbc = NULL;
unsigned char *erased_page;
+ unsigned int eccsize = nand->ecc.size;
+ unsigned int eccbytes = nand->ecc.bytes;
+ unsigned int eccstrength = nand->ecc.strength;
+
+ if (!eccbytes && eccstrength) {
+ eccbytes = DIV_ROUND_UP(eccstrength * fls(8 * eccsize), 8);
+ nand->ecc.bytes = eccbytes;
+ }
if (!eccsize || !eccbytes) {
printk(KERN_WARNING "ecc parameters not supplied\n");
@@ -145,7 +149,7 @@ nand_bch_init(struct mtd_info *mtd, unsigned int eccsize, unsigned int eccbytes,
eccsteps = mtd->writesize/eccsize;
/* if no ecc placement scheme was provided, build one */
- if (!*ecclayout) {
+ if (!layout) {
/* handle large page devices only */
if (mtd->oobsize < 64) {
@@ -171,7 +175,7 @@ nand_bch_init(struct mtd_info *mtd, unsigned int eccsize, unsigned int eccbytes,
layout->oobfree[0].offset = 2;
layout->oobfree[0].length = mtd->oobsize-2-layout->eccbytes;
- *ecclayout = layout;
+ nand->ecc.layout = layout;
}
/* sanity checks */
@@ -179,7 +183,7 @@ nand_bch_init(struct mtd_info *mtd, unsigned int eccsize, unsigned int eccbytes,
printk(KERN_WARNING "eccsize %u is too large\n", eccsize);
goto fail;
}
- if ((*ecclayout)->eccbytes != (eccsteps*eccbytes)) {
+ if (layout->eccbytes != (eccsteps*eccbytes)) {
printk(KERN_WARNING "invalid ecc layout\n");
goto fail;
}
@@ -203,6 +207,9 @@ nand_bch_init(struct mtd_info *mtd, unsigned int eccsize, unsigned int eccbytes,
for (i = 0; i < eccbytes; i++)
nbc->eccmask[i] ^= 0xff;
+ if (!eccstrength)
+ nand->ecc.strength = (eccbytes * 8) / fls(8 * eccsize);
+
return nbc;
fail:
nand_bch_free(nbc);
diff --git a/drivers/mtd/nand/nand_ids.c b/drivers/mtd/nand/nand_ids.c
index fdd00741dc..561d2cd63b 100644
--- a/drivers/mtd/nand/nand_ids.c
+++ b/drivers/mtd/nand/nand_ids.c
@@ -1,6 +1,4 @@
/*
- * drivers/mtd/nandids.c
- *
* Copyright (C) 2002 Thomas Gleixner (tglx@linutronix.de)
*
* This program is free software; you can redistribute it and/or modify
@@ -41,6 +39,10 @@ struct nand_flash_dev nand_flash_ids[] = {
* listed by full ID. We list them first so that we can easily identify
* the most specific match.
*/
+ {"TC58NVG0S3E 1G 3.3V 8-bit",
+ { .id = {0x98, 0xd1, 0x90, 0x15, 0x76, 0x14, 0x01, 0x00} },
+ SZ_2K, SZ_128, SZ_128K, 0, 8, 64, NAND_ECC_INFO(1, SZ_512),
+ 2 },
{"TC58NVG2S0F 4G 3.3V 8-bit",
{ .id = {0x98, 0xdc, 0x90, 0x26, 0x76, 0x15, 0x01, 0x08} },
SZ_4K, SZ_512, SZ_256K, 0, 8, 224, NAND_ECC_INFO(4, SZ_512) },
@@ -58,8 +60,8 @@ struct nand_flash_dev nand_flash_ids[] = {
SZ_16K, SZ_8K, SZ_4M, 0, 6, 1280, NAND_ECC_INFO(40, SZ_1K) },
{"H27UCG8T2ATR-BC 64G 3.3V 8-bit",
{ .id = {0xad, 0xde, 0x94, 0xda, 0x74, 0xc4} },
- SZ_8K, SZ_8K, SZ_2M, 0, 6, 640, NAND_ECC_INFO(40, SZ_1K),
- 4 },
+ SZ_8K, SZ_8K, SZ_2M, NAND_NEED_SCRAMBLING, 6, 640,
+ NAND_ECC_INFO(40, SZ_1K), 4 },
LEGACY_ID_NAND("NAND 4MiB 5V 8-bit", 0x6B, 4, SZ_8K, SP_OPTIONS),
LEGACY_ID_NAND("NAND 4MiB 3,3V 8-bit", 0xE3, 4, SZ_8K, SP_OPTIONS),
diff --git a/drivers/mtd/nand/nand_plat.c b/drivers/mtd/nand/nand_plat.c
index 37a0206ad6..335c3e3471 100644
--- a/drivers/mtd/nand/nand_plat.c
+++ b/drivers/mtd/nand/nand_plat.c
@@ -25,7 +25,7 @@
static void plat_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
{
- struct nand_chip *this = mtd->priv;
+ struct nand_chip *this = mtd_to_nand(mtd);
if (cmd == NAND_CMD_NONE)
return;
@@ -39,7 +39,7 @@ static void plat_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
#ifdef NAND_PLAT_DEV_READY
static int plat_dev_ready(struct mtd_info *mtd)
{
- return NAND_PLAT_DEV_READY((struct nand_chip *)mtd->priv);
+ return NAND_PLAT_DEV_READY((struct nand_chip *)mtd_to_nand(mtd));
}
#else
# define plat_dev_ready NULL
diff --git a/drivers/mtd/nand/nand_spl_simple.c b/drivers/mtd/nand/nand_spl_simple.c
index e69f66226d..b023e00313 100644
--- a/drivers/mtd/nand/nand_spl_simple.c
+++ b/drivers/mtd/nand/nand_spl_simple.c
@@ -11,7 +11,7 @@
#include <linux/mtd/nand_ecc.h>
static int nand_ecc_pos[] = CONFIG_SYS_NAND_ECCPOS;
-static nand_info_t mtd;
+static struct mtd_info *mtd;
static struct nand_chip nand_chip;
#define ECCSTEPS (CONFIG_SYS_NAND_PAGE_SIZE / \
@@ -26,32 +26,32 @@ static struct nand_chip nand_chip;
static int nand_command(int block, int page, uint32_t offs,
u8 cmd)
{
- struct nand_chip *this = mtd.priv;
+ struct nand_chip *this = mtd_to_nand(mtd);
int page_addr = page + block * CONFIG_SYS_NAND_PAGE_COUNT;
- while (!this->dev_ready(&mtd))
+ while (!this->dev_ready(mtd))
;
/* Begin command latch cycle */
- this->cmd_ctrl(&mtd, cmd, NAND_CTRL_CLE | NAND_CTRL_CHANGE);
+ this->cmd_ctrl(mtd, cmd, NAND_CTRL_CLE | NAND_CTRL_CHANGE);
/* 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, NAND_CTRL_ALE); /* A[16:9] */
- this->cmd_ctrl(&mtd, (page_addr >> 8) & 0xff,
+ this->cmd_ctrl(mtd, offs, NAND_CTRL_ALE | NAND_CTRL_CHANGE);
+ 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,
+ 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);
+ this->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
/*
* Wait a while for the data to be ready
*/
- while (!this->dev_ready(&mtd))
+ while (!this->dev_ready(mtd))
;
return 0;
@@ -63,12 +63,12 @@ static int nand_command(int block, int page, uint32_t offs,
static int nand_command(int block, int page, uint32_t offs,
u8 cmd)
{
- struct nand_chip *this = mtd.priv;
+ struct nand_chip *this = mtd_to_nand(mtd);
int page_addr = page + block * CONFIG_SYS_NAND_PAGE_COUNT;
void (*hwctrl)(struct mtd_info *mtd, int cmd,
unsigned int ctrl) = this->cmd_ctrl;
- while (!this->dev_ready(&mtd))
+ while (!this->dev_ready(mtd))
;
/* Emulate NAND_CMD_READOOB */
@@ -82,30 +82,30 @@ static int nand_command(int block, int page, uint32_t offs,
offs >>= 1;
/* Begin command latch cycle */
- hwctrl(&mtd, cmd, NAND_CTRL_CLE | NAND_CTRL_CHANGE);
+ hwctrl(mtd, cmd, NAND_CTRL_CLE | NAND_CTRL_CHANGE);
/* Set ALE and clear CLE to start address cycle */
/* Column address */
- hwctrl(&mtd, offs & 0xff,
- NAND_CTRL_ALE | NAND_CTRL_CHANGE); /* A[7:0] */
- hwctrl(&mtd, (offs >> 8) & 0xff, NAND_CTRL_ALE); /* A[11:9] */
+ hwctrl(mtd, offs & 0xff,
+ NAND_CTRL_ALE | NAND_CTRL_CHANGE); /* A[7:0] */
+ hwctrl(mtd, (offs >> 8) & 0xff, NAND_CTRL_ALE); /* A[11:9] */
/* Row address */
- hwctrl(&mtd, (page_addr & 0xff), NAND_CTRL_ALE); /* A[19:12] */
- hwctrl(&mtd, ((page_addr >> 8) & 0xff),
- NAND_CTRL_ALE); /* A[27:20] */
+ hwctrl(mtd, (page_addr & 0xff), NAND_CTRL_ALE); /* A[19:12] */
+ hwctrl(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 */
- hwctrl(&mtd, (page_addr >> 16) & 0x0f,
+ hwctrl(mtd, (page_addr >> 16) & 0x0f,
NAND_CTRL_ALE); /* A[31:28] */
#endif
/* Latch in address */
- hwctrl(&mtd, NAND_CMD_READSTART,
- NAND_CTRL_CLE | NAND_CTRL_CHANGE);
- hwctrl(&mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
+ hwctrl(mtd, NAND_CMD_READSTART,
+ NAND_CTRL_CLE | NAND_CTRL_CHANGE);
+ hwctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
/*
* Wait a while for the data to be ready
*/
- while (!this->dev_ready(&mtd))
+ while (!this->dev_ready(mtd))
;
return 0;
@@ -114,7 +114,7 @@ static int nand_command(int block, int page, uint32_t offs,
static int nand_is_bad_block(int block)
{
- struct nand_chip *this = mtd.priv;
+ struct nand_chip *this = mtd_to_nand(mtd);
u_char bb_data[2];
nand_command(block, 0, CONFIG_SYS_NAND_BAD_BLOCK_POS,
@@ -124,11 +124,11 @@ static int nand_is_bad_block(int block)
* Read one byte (or two if it's a 16 bit chip).
*/
if (this->options & NAND_BUSWIDTH_16) {
- this->read_buf(&mtd, bb_data, 2);
+ this->read_buf(mtd, bb_data, 2);
if (bb_data[0] != 0xff || bb_data[1] != 0xff)
return 1;
} else {
- this->read_buf(&mtd, bb_data, 1);
+ this->read_buf(mtd, bb_data, 1);
if (bb_data[0] != 0xff)
return 1;
}
@@ -139,7 +139,7 @@ static int nand_is_bad_block(int block)
#if defined(CONFIG_SYS_NAND_HW_ECC_OOBFIRST)
static int nand_read_page(int block, int page, uchar *dst)
{
- struct nand_chip *this = mtd.priv;
+ struct nand_chip *this = mtd_to_nand(mtd);
u_char ecc_calc[ECCTOTAL];
u_char ecc_code[ECCTOTAL];
u_char oob_data[CONFIG_SYS_NAND_OOBSIZE];
@@ -150,7 +150,7 @@ static int nand_read_page(int block, int page, uchar *dst)
uint8_t *p = dst;
nand_command(block, page, 0, NAND_CMD_READOOB);
- this->read_buf(&mtd, oob_data, CONFIG_SYS_NAND_OOBSIZE);
+ this->read_buf(mtd, oob_data, CONFIG_SYS_NAND_OOBSIZE);
nand_command(block, page, 0, NAND_CMD_READ0);
/* Pick the ECC bytes out of the oob data */
@@ -159,10 +159,10 @@ static int nand_read_page(int block, int page, uchar *dst)
for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
- this->ecc.hwctl(&mtd, NAND_ECC_READ);
- this->read_buf(&mtd, p, eccsize);
- this->ecc.calculate(&mtd, p, &ecc_calc[i]);
- this->ecc.correct(&mtd, p, &ecc_code[i], &ecc_calc[i]);
+ this->ecc.hwctl(mtd, NAND_ECC_READ);
+ this->read_buf(mtd, p, eccsize);
+ this->ecc.calculate(mtd, p, &ecc_calc[i]);
+ this->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]);
}
return 0;
@@ -170,7 +170,7 @@ static int nand_read_page(int block, int page, uchar *dst)
#else
static int nand_read_page(int block, int page, void *dst)
{
- struct nand_chip *this = mtd.priv;
+ struct nand_chip *this = mtd_to_nand(mtd);
u_char ecc_calc[ECCTOTAL];
u_char ecc_code[ECCTOTAL];
u_char oob_data[CONFIG_SYS_NAND_OOBSIZE];
@@ -184,11 +184,11 @@ static int nand_read_page(int block, int page, void *dst)
for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
if (this->ecc.mode != NAND_ECC_SOFT)
- this->ecc.hwctl(&mtd, NAND_ECC_READ);
- this->read_buf(&mtd, p, eccsize);
- this->ecc.calculate(&mtd, p, &ecc_calc[i]);
+ this->ecc.hwctl(mtd, NAND_ECC_READ);
+ this->read_buf(mtd, p, eccsize);
+ this->ecc.calculate(mtd, p, &ecc_calc[i]);
}
- this->read_buf(&mtd, oob_data, CONFIG_SYS_NAND_OOBSIZE);
+ this->read_buf(mtd, oob_data, CONFIG_SYS_NAND_OOBSIZE);
/* Pick the ECC bytes out of the oob data */
for (i = 0; i < ECCTOTAL; i++)
@@ -202,7 +202,7 @@ static int nand_read_page(int block, int page, void *dst)
* from correct_data(). We just hope that all possible errors
* are corrected by this routine.
*/
- this->ecc.correct(&mtd, p, &ecc_code[i], &ecc_calc[i]);
+ this->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]);
}
return 0;
@@ -249,7 +249,7 @@ void nand_init(void)
/*
* Init board specific nand support
*/
- mtd.priv = &nand_chip;
+ mtd = &nand_chip.mtd;
nand_chip.IO_ADDR_R = nand_chip.IO_ADDR_W =
(void __iomem *)CONFIG_SYS_NAND_BASE;
board_nand_init(&nand_chip);
@@ -262,12 +262,12 @@ void nand_init(void)
#endif
if (nand_chip.select_chip)
- nand_chip.select_chip(&mtd, 0);
+ nand_chip.select_chip(mtd, 0);
}
/* Unselect after operation */
void nand_deselect(void)
{
if (nand_chip.select_chip)
- nand_chip.select_chip(&mtd, -1);
+ nand_chip.select_chip(mtd, -1);
}
diff --git a/drivers/mtd/nand/nand_util.c b/drivers/mtd/nand/nand_util.c
index 71285b6669..5bba66a728 100644
--- a/drivers/mtd/nand/nand_util.c
+++ b/drivers/mtd/nand/nand_util.c
@@ -42,25 +42,26 @@ typedef struct mtd_info mtd_info_t;
* nand_erase_opts: - erase NAND flash with support for various options
* (jffs2 formatting)
*
- * @param meminfo NAND device to erase
+ * @param mtd nand mtd instance to erase
* @param opts options, @see struct nand_erase_options
* @return 0 in case of success
*
* This code is ported from flash_eraseall.c from Linux mtd utils by
* Arcom Control System Ltd.
*/
-int nand_erase_opts(nand_info_t *meminfo, const nand_erase_options_t *opts)
+int nand_erase_opts(struct mtd_info *mtd,
+ const nand_erase_options_t *opts)
{
struct jffs2_unknown_node cleanmarker;
erase_info_t erase;
unsigned long erase_length, erased_length; /* in blocks */
int result;
int percent_complete = -1;
- const char *mtd_device = meminfo->name;
+ const char *mtd_device = mtd->name;
struct mtd_oob_ops oob_opts;
- struct nand_chip *chip = meminfo->priv;
+ struct nand_chip *chip = mtd_to_nand(mtd);
- if ((opts->offset & (meminfo->erasesize - 1)) != 0) {
+ if ((opts->offset & (mtd->erasesize - 1)) != 0) {
printf("Attempt to erase non block-aligned data\n");
return -1;
}
@@ -68,11 +69,11 @@ int nand_erase_opts(nand_info_t *meminfo, const nand_erase_options_t *opts)
memset(&erase, 0, sizeof(erase));
memset(&oob_opts, 0, sizeof(oob_opts));
- erase.mtd = meminfo;
- erase.len = meminfo->erasesize;
+ erase.mtd = mtd;
+ erase.len = mtd->erasesize;
erase.addr = opts->offset;
- erase_length = lldiv(opts->length + meminfo->erasesize - 1,
- meminfo->erasesize);
+ erase_length = lldiv(opts->length + mtd->erasesize - 1,
+ mtd->erasesize);
cleanmarker.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
cleanmarker.nodetype = cpu_to_je16(JFFS2_NODETYPE_CLEANMARKER);
@@ -97,7 +98,7 @@ int nand_erase_opts(nand_info_t *meminfo, const nand_erase_options_t *opts)
for (erased_length = 0;
erased_length < erase_length;
- erase.addr += meminfo->erasesize) {
+ erase.addr += mtd->erasesize) {
WATCHDOG_RESET();
@@ -106,7 +107,7 @@ int nand_erase_opts(nand_info_t *meminfo, const nand_erase_options_t *opts)
return -EFBIG;
}
if (!opts->scrub) {
- int ret = mtd_block_isbad(meminfo, erase.addr);
+ int ret = mtd_block_isbad(mtd, erase.addr);
if (ret > 0) {
if (!opts->quiet)
printf("\rSkipping bad block at "
@@ -129,7 +130,7 @@ int nand_erase_opts(nand_info_t *meminfo, const nand_erase_options_t *opts)
erased_length++;
- result = mtd_erase(meminfo, &erase);
+ result = mtd_erase(mtd, &erase);
if (result != 0) {
printf("\n%s: MTD Erase failure: %d\n",
mtd_device, result);
@@ -145,9 +146,7 @@ int nand_erase_opts(nand_info_t *meminfo, const nand_erase_options_t *opts)
ops.ooboffs = 0;
ops.mode = MTD_OPS_AUTO_OOB;
- result = mtd_write_oob(meminfo,
- erase.addr,
- &ops);
+ result = mtd_write_oob(mtd, erase.addr, &ops);
if (result != 0) {
printf("\n%s: MTD writeoob failure: %d\n",
mtd_device, result);
@@ -218,7 +217,7 @@ int nand_lock(struct mtd_info *mtd, int tight)
{
int ret = 0;
int status;
- struct nand_chip *chip = mtd->priv;
+ struct nand_chip *chip = mtd_to_nand(mtd);
/* select the NAND device */
chip->select_chip(mtd, 0);
@@ -268,7 +267,7 @@ int nand_get_lock_status(struct mtd_info *mtd, loff_t offset)
int ret = 0;
int chipnr;
int page;
- struct nand_chip *chip = mtd->priv;
+ struct nand_chip *chip = mtd_to_nand(mtd);
/* select the NAND device */
chipnr = (int)(offset >> chip->chip_shift);
@@ -303,7 +302,7 @@ int nand_get_lock_status(struct mtd_info *mtd, loff_t offset)
* @param mtd nand mtd instance
* @param start start byte address
* @param length number of bytes to unlock (must be a multiple of
- * page size nand->writesize)
+ * page size mtd->writesize)
* @param allexcept if set, unlock everything not selected
*
* @return 0 on success, -1 in case of error
@@ -315,7 +314,7 @@ int nand_unlock(struct mtd_info *mtd, loff_t start, size_t length,
int chipnr;
int status;
int page;
- struct nand_chip *chip = mtd->priv;
+ struct nand_chip *chip = mtd_to_nand(mtd);
debug("nand_unlock%s: start: %08llx, length: %zd!\n",
allexcept ? " (allexcept)" : "", start, length);
@@ -399,7 +398,7 @@ int nand_unlock(struct mtd_info *mtd, loff_t start, size_t length,
* Check if there are any bad blocks, and whether length including bad
* blocks fits into device
*
- * @param nand NAND device
+ * @param mtd nand mtd instance
* @param offset offset in flash
* @param length image length
* @param used length of flash needed for the requested length
@@ -407,8 +406,8 @@ int nand_unlock(struct mtd_info *mtd, loff_t start, size_t length,
* 1 if the image fits, but there are bad blocks
* -1 if the image does not fit
*/
-static int check_skip_len(nand_info_t *nand, loff_t offset, size_t length,
- size_t *used)
+static int check_skip_len(struct mtd_info *mtd, loff_t offset, size_t length,
+ size_t *used)
{
size_t len_excl_bad = 0;
int ret = 0;
@@ -417,14 +416,14 @@ static int check_skip_len(nand_info_t *nand, loff_t offset, size_t length,
size_t block_len, block_off;
loff_t block_start;
- if (offset >= nand->size)
+ if (offset >= mtd->size)
return -1;
- block_start = offset & ~(loff_t)(nand->erasesize - 1);
- block_off = offset & (nand->erasesize - 1);
- block_len = nand->erasesize - block_off;
+ block_start = offset & ~(loff_t)(mtd->erasesize - 1);
+ block_off = offset & (mtd->erasesize - 1);
+ block_len = mtd->erasesize - block_off;
- if (!nand_block_isbad(nand, block_start))
+ if (!nand_block_isbad(mtd, block_start))
len_excl_bad += block_len;
else
ret = 1;
@@ -441,7 +440,7 @@ static int check_skip_len(nand_info_t *nand, loff_t offset, size_t length,
}
#ifdef CONFIG_CMD_NAND_TRIMFFS
-static size_t drop_ffs(const nand_info_t *nand, const u_char *buf,
+static size_t drop_ffs(const struct mtd_info *mtd, const u_char *buf,
const size_t *len)
{
size_t l = *len;
@@ -453,8 +452,8 @@ static size_t drop_ffs(const nand_info_t *nand, const u_char *buf,
/* The resulting length must be aligned to the minimum flash I/O size */
l = i + 1;
- l = (l + nand->writesize - 1) / nand->writesize;
- l *= nand->writesize;
+ l = (l + mtd->writesize - 1) / mtd->writesize;
+ l *= mtd->writesize;
/*
* since the input length may be unaligned, prevent access past the end
@@ -471,16 +470,17 @@ static size_t drop_ffs(const nand_info_t *nand, const u_char *buf,
* Reads page of NAND and verifies the contents and OOB against the
* values in ops.
*
- * @param nand NAND device
+ * @param mtd nand mtd instance
* @param ops MTD operations, including data to verify
* @param ofs offset in flash
* @return 0 in case of success
*/
-int nand_verify_page_oob(nand_info_t *nand, struct mtd_oob_ops *ops, loff_t ofs)
+int nand_verify_page_oob(struct mtd_info *mtd, struct mtd_oob_ops *ops,
+ loff_t ofs)
{
int rval;
struct mtd_oob_ops vops;
- size_t verlen = nand->writesize + nand->oobsize;
+ size_t verlen = mtd->writesize + mtd->oobsize;
memcpy(&vops, ops, sizeof(vops));
@@ -489,9 +489,9 @@ int nand_verify_page_oob(nand_info_t *nand, struct mtd_oob_ops *ops, loff_t ofs)
if (!vops.datbuf)
return -ENOMEM;
- vops.oobbuf = vops.datbuf + nand->writesize;
+ vops.oobbuf = vops.datbuf + mtd->writesize;
- rval = mtd_read_oob(nand, ofs, &vops);
+ rval = mtd_read_oob(mtd, ofs, &vops);
if (!rval)
rval = memcmp(ops->datbuf, vops.datbuf, vops.len);
if (!rval)
@@ -510,17 +510,17 @@ int nand_verify_page_oob(nand_info_t *nand, struct mtd_oob_ops *ops, loff_t ofs)
* the contents of a buffer. The offset into the NAND must be
* page-aligned, and the function doesn't handle skipping bad blocks.
*
- * @param nand NAND device
+ * @param mtd nand mtd instance
* @param ofs offset in flash
* @param len buffer length
* @param buf buffer to read from
* @return 0 in case of success
*/
-int nand_verify(nand_info_t *nand, loff_t ofs, size_t len, u_char *buf)
+int nand_verify(struct mtd_info *mtd, loff_t ofs, size_t len, u_char *buf)
{
int rval = 0;
size_t verofs;
- size_t verlen = nand->writesize;
+ size_t verlen = mtd->writesize;
uint8_t *verbuf = memalign(ARCH_DMA_MINALIGN, verlen);
if (!verbuf)
@@ -529,8 +529,8 @@ int nand_verify(nand_info_t *nand, loff_t ofs, size_t len, u_char *buf)
/* Read the NAND back in page-size groups to limit malloc size */
for (verofs = ofs; verofs < ofs + len;
verofs += verlen, buf += verlen) {
- verlen = min(nand->writesize, (uint32_t)(ofs + len - verofs));
- rval = nand_read(nand, verofs, &verlen, verbuf);
+ verlen = min(mtd->writesize, (uint32_t)(ofs + len - verofs));
+ rval = nand_read(mtd, verofs, &verlen, verbuf);
if (!rval || (rval == -EUCLEAN))
rval = memcmp(buf, verbuf, verlen);
@@ -558,7 +558,7 @@ int nand_verify(nand_info_t *nand, loff_t ofs, size_t len, u_char *buf)
* beyond the limit we are passed, length is set to 0 and actual is set
* to the required length.
*
- * @param nand NAND device
+ * @param mtd nand mtd instance
* @param offset offset in flash
* @param length buffer length
* @param actual set to size required to write length worth of
@@ -569,8 +569,8 @@ int nand_verify(nand_info_t *nand, loff_t ofs, size_t len, u_char *buf)
* @param flags flags modifying the behaviour of the write to NAND
* @return 0 in case of success
*/
-int nand_write_skip_bad(nand_info_t *nand, loff_t offset, size_t *length,
- size_t *actual, loff_t lim, u_char *buffer, int flags)
+int nand_write_skip_bad(struct mtd_info *mtd, loff_t offset, size_t *length,
+ size_t *actual, loff_t lim, u_char *buffer, int flags)
{
int rval = 0, blocksize;
size_t left_to_write = *length;
@@ -581,7 +581,7 @@ int nand_write_skip_bad(nand_info_t *nand, loff_t offset, size_t *length,
if (actual)
*actual = 0;
- blocksize = nand->erasesize;
+ blocksize = mtd->erasesize;
/*
* nand_write() handles unaligned, partial page writes.
@@ -594,13 +594,13 @@ int nand_write_skip_bad(nand_info_t *nand, loff_t offset, size_t *length,
* you should only start a block skipping access at a
* partition boundary). So don't try to handle that.
*/
- if ((offset & (nand->writesize - 1)) != 0) {
+ if ((offset & (mtd->writesize - 1)) != 0) {
printf("Attempt to write non page-aligned data\n");
*length = 0;
return -EINVAL;
}
- need_skip = check_skip_len(nand, offset, *length, &used_for_write);
+ need_skip = check_skip_len(mtd, offset, *length, &used_for_write);
if (actual)
*actual = used_for_write;
@@ -618,10 +618,10 @@ int nand_write_skip_bad(nand_info_t *nand, loff_t offset, size_t *length,
}
if (!need_skip && !(flags & WITH_DROP_FFS)) {
- rval = nand_write(nand, offset, length, buffer);
+ rval = nand_write(mtd, offset, length, buffer);
if ((flags & WITH_WR_VERIFY) && !rval)
- rval = nand_verify(nand, offset, *length, buffer);
+ rval = nand_verify(mtd, offset, *length, buffer);
if (rval == 0)
return 0;
@@ -633,15 +633,15 @@ int nand_write_skip_bad(nand_info_t *nand, loff_t offset, size_t *length,
}
while (left_to_write > 0) {
- size_t block_offset = offset & (nand->erasesize - 1);
+ size_t block_offset = offset & (mtd->erasesize - 1);
size_t write_size, truncated_write_size;
WATCHDOG_RESET();
- if (nand_block_isbad(nand, offset & ~(nand->erasesize - 1))) {
+ if (nand_block_isbad(mtd, offset & ~(mtd->erasesize - 1))) {
printf("Skip bad block 0x%08llx\n",
- offset & ~(nand->erasesize - 1));
- offset += nand->erasesize - block_offset;
+ offset & ~(mtd->erasesize - 1));
+ offset += mtd->erasesize - block_offset;
continue;
}
@@ -653,15 +653,15 @@ int nand_write_skip_bad(nand_info_t *nand, loff_t offset, size_t *length,
truncated_write_size = write_size;
#ifdef CONFIG_CMD_NAND_TRIMFFS
if (flags & WITH_DROP_FFS)
- truncated_write_size = drop_ffs(nand, p_buffer,
+ truncated_write_size = drop_ffs(mtd, p_buffer,
&write_size);
#endif
- rval = nand_write(nand, offset, &truncated_write_size,
+ rval = nand_write(mtd, offset, &truncated_write_size,
p_buffer);
if ((flags & WITH_WR_VERIFY) && !rval)
- rval = nand_verify(nand, offset,
+ rval = nand_verify(mtd, offset,
truncated_write_size, p_buffer);
offset += write_size;
@@ -693,7 +693,7 @@ int nand_write_skip_bad(nand_info_t *nand, loff_t offset, size_t *length,
* the limit we are passed, length is set to 0 and actual is set to the
* required length.
*
- * @param nand NAND device
+ * @param mtd nand mtd instance
* @param offset offset in flash
* @param length buffer length, on return holds number of read bytes
* @param actual set to size required to read length worth of buffer or 0
@@ -703,8 +703,8 @@ int nand_write_skip_bad(nand_info_t *nand, loff_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, loff_t offset, size_t *length,
- size_t *actual, loff_t lim, u_char *buffer)
+int nand_read_skip_bad(struct mtd_info *mtd, loff_t offset, size_t *length,
+ size_t *actual, loff_t lim, u_char *buffer)
{
int rval;
size_t left_to_read = *length;
@@ -712,7 +712,7 @@ int nand_read_skip_bad(nand_info_t *nand, loff_t offset, size_t *length,
u_char *p_buffer = buffer;
int need_skip;
- if ((offset & (nand->writesize - 1)) != 0) {
+ if ((offset & (mtd->writesize - 1)) != 0) {
printf("Attempt to read non page-aligned data\n");
*length = 0;
if (actual)
@@ -720,7 +720,7 @@ int nand_read_skip_bad(nand_info_t *nand, loff_t offset, size_t *length,
return -EINVAL;
}
- need_skip = check_skip_len(nand, offset, *length, &used_for_read);
+ need_skip = check_skip_len(mtd, offset, *length, &used_for_read);
if (actual)
*actual = used_for_read;
@@ -738,7 +738,7 @@ int nand_read_skip_bad(nand_info_t *nand, loff_t offset, size_t *length,
}
if (!need_skip) {
- rval = nand_read(nand, offset, length, buffer);
+ rval = nand_read(mtd, offset, length, buffer);
if (!rval || rval == -EUCLEAN)
return 0;
@@ -749,24 +749,24 @@ int nand_read_skip_bad(nand_info_t *nand, loff_t offset, size_t *length,
}
while (left_to_read > 0) {
- size_t block_offset = offset & (nand->erasesize - 1);
+ size_t block_offset = offset & (mtd->erasesize - 1);
size_t read_length;
WATCHDOG_RESET();
- if (nand_block_isbad(nand, offset & ~(nand->erasesize - 1))) {
+ if (nand_block_isbad(mtd, offset & ~(mtd->erasesize - 1))) {
printf("Skipping bad block 0x%08llx\n",
- offset & ~(nand->erasesize - 1));
- offset += nand->erasesize - block_offset;
+ offset & ~(mtd->erasesize - 1));
+ offset += mtd->erasesize - block_offset;
continue;
}
- if (left_to_read < (nand->erasesize - block_offset))
+ if (left_to_read < (mtd->erasesize - block_offset))
read_length = left_to_read;
else
- read_length = nand->erasesize - block_offset;
+ read_length = mtd->erasesize - block_offset;
- rval = nand_read(nand, offset, &read_length, p_buffer);
+ rval = nand_read(mtd, offset, &read_length, p_buffer);
if (rval && rval != -EUCLEAN) {
printf("NAND read from offset %llx failed %d\n",
offset, rval);
@@ -812,57 +812,57 @@ static int check_pattern(const u_char *buf, u_char patt, int size)
* This is useful to determine if a block that caused a write error is still
* good or should be marked as bad.
*
- * @param nand NAND device
+ * @param mtd nand mtd instance
* @param offset offset in flash
* @return 0 if the block is still good
*/
-int nand_torture(nand_info_t *nand, loff_t offset)
+int nand_torture(struct mtd_info *mtd, loff_t offset)
{
u_char patterns[] = {0xa5, 0x5a, 0x00};
struct erase_info instr = {
.mtd = nand,
.addr = offset,
- .len = nand->erasesize,
+ .len = mtd->erasesize,
};
size_t retlen;
int err, ret = -1, i, patt_count;
u_char *buf;
- if ((offset & (nand->erasesize - 1)) != 0) {
+ if ((offset & (mtd->erasesize - 1)) != 0) {
puts("Attempt to torture a block at a non block-aligned offset\n");
return -EINVAL;
}
- if (offset + nand->erasesize > nand->size) {
+ if (offset + mtd->erasesize > mtd->size) {
puts("Attempt to torture a block outside the flash area\n");
return -EINVAL;
}
patt_count = ARRAY_SIZE(patterns);
- buf = malloc_cache_aligned(nand->erasesize);
+ buf = malloc_cache_aligned(mtd->erasesize);
if (buf == NULL) {
puts("Out of memory for erase block buffer\n");
return -ENOMEM;
}
for (i = 0; i < patt_count; i++) {
- err = nand->erase(nand, &instr);
+ err = mtd_erase(mtd, &instr);
if (err) {
printf("%s: erase() failed for block at 0x%llx: %d\n",
- nand->name, instr.addr, err);
+ mtd->name, instr.addr, err);
goto out;
}
/* Make sure the block contains only 0xff bytes */
- err = nand->read(nand, offset, nand->erasesize, &retlen, buf);
- if ((err && err != -EUCLEAN) || retlen != nand->erasesize) {
+ err = mtd_read(mtd, offset, mtd->erasesize, &retlen, buf);
+ if ((err && err != -EUCLEAN) || retlen != mtd->erasesize) {
printf("%s: read() failed for block at 0x%llx: %d\n",
- nand->name, instr.addr, err);
+ mtd->name, instr.addr, err);
goto out;
}
- err = check_pattern(buf, 0xff, nand->erasesize);
+ err = check_pattern(buf, 0xff, mtd->erasesize);
if (!err) {
printf("Erased block at 0x%llx, but a non-0xff byte was found\n",
offset);
@@ -871,22 +871,22 @@ int nand_torture(nand_info_t *nand, loff_t offset)
}
/* Write a pattern and check it */
- memset(buf, patterns[i], nand->erasesize);
- err = nand->write(nand, offset, nand->erasesize, &retlen, buf);
- if (err || retlen != nand->erasesize) {
+ memset(buf, patterns[i], mtd->erasesize);
+ err = mtd_write(mtd, offset, mtd->erasesize, &retlen, buf);
+ if (err || retlen != mtd->erasesize) {
printf("%s: write() failed for block at 0x%llx: %d\n",
- nand->name, instr.addr, err);
+ mtd->name, instr.addr, err);
goto out;
}
- err = nand->read(nand, offset, nand->erasesize, &retlen, buf);
- if ((err && err != -EUCLEAN) || retlen != nand->erasesize) {
+ err = mtd_read(mtd, offset, mtd->erasesize, &retlen, buf);
+ if ((err && err != -EUCLEAN) || retlen != mtd->erasesize) {
printf("%s: read() failed for block at 0x%llx: %d\n",
- nand->name, instr.addr, err);
+ mtd->name, instr.addr, err);
goto out;
}
- err = check_pattern(buf, patterns[i], nand->erasesize);
+ err = check_pattern(buf, patterns[i], mtd->erasesize);
if (!err) {
printf("Pattern 0x%.2x checking failed for block at "
"0x%llx\n", patterns[i], offset);
diff --git a/drivers/mtd/nand/ndfc.c b/drivers/mtd/nand/ndfc.c
index 8a68cb0a67..0a9849e9bc 100644
--- a/drivers/mtd/nand/ndfc.c
+++ b/drivers/mtd/nand/ndfc.c
@@ -1,6 +1,6 @@
/*
* Overview:
- * Platform independend driver for NDFC (NanD Flash Controller)
+ * Platform independent driver for NDFC (NanD Flash Controller)
* integrated into IBM/AMCC PPC4xx cores
*
* (C) Copyright 2006-2009
@@ -37,7 +37,7 @@ static int ndfc_cs[NDFC_MAX_BANKS];
static void ndfc_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
{
- struct nand_chip *this = mtd->priv;
+ struct nand_chip *this = mtd_to_nand(mtd);
ulong base = (ulong) this->IO_ADDR_W & 0xffffff00;
if (cmd == NAND_CMD_NONE)
@@ -51,7 +51,7 @@ static void ndfc_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
static int ndfc_dev_ready(struct mtd_info *mtdinfo)
{
- struct nand_chip *this = mtdinfo->priv;
+ struct nand_chip *this = mtd_to_nand(mtdinfo);
ulong base = (ulong) this->IO_ADDR_W & 0xffffff00;
return (in_be32((u32 *)(base + NDFC_STAT)) & NDFC_STAT_IS_READY);
@@ -59,7 +59,7 @@ static int ndfc_dev_ready(struct mtd_info *mtdinfo)
static void ndfc_enable_hwecc(struct mtd_info *mtdinfo, int mode)
{
- struct nand_chip *this = mtdinfo->priv;
+ struct nand_chip *this = mtd_to_nand(mtdinfo);
ulong base = (ulong) this->IO_ADDR_W & 0xffffff00;
u32 ccr;
@@ -71,7 +71,7 @@ static void ndfc_enable_hwecc(struct mtd_info *mtdinfo, int mode)
static int ndfc_calculate_ecc(struct mtd_info *mtdinfo,
const u_char *dat, u_char *ecc_code)
{
- struct nand_chip *this = mtdinfo->priv;
+ struct nand_chip *this = mtd_to_nand(mtdinfo);
ulong base = (ulong) this->IO_ADDR_W & 0xffffff00;
u32 ecc;
u8 *p = (u8 *)&ecc;
@@ -96,7 +96,7 @@ static int ndfc_calculate_ecc(struct mtd_info *mtdinfo,
*/
static void ndfc_read_buf(struct mtd_info *mtdinfo, uint8_t *buf, int len)
{
- struct nand_chip *this = mtdinfo->priv;
+ struct nand_chip *this = mtd_to_nand(mtdinfo);
ulong base = (ulong) this->IO_ADDR_W & 0xffffff00;
uint32_t *p = (uint32_t *) buf;
@@ -110,7 +110,7 @@ static void ndfc_read_buf(struct mtd_info *mtdinfo, uint8_t *buf, int len)
*/
static void ndfc_write_buf(struct mtd_info *mtdinfo, const uint8_t *buf, int len)
{
- struct nand_chip *this = mtdinfo->priv;
+ struct nand_chip *this = mtd_to_nand(mtdinfo);
ulong base = (ulong) this->IO_ADDR_W & 0xffffff00;
uint32_t *p = (uint32_t *) buf;
@@ -124,7 +124,7 @@ static void ndfc_write_buf(struct mtd_info *mtdinfo, const uint8_t *buf, int len
static uint8_t ndfc_read_byte(struct mtd_info *mtd)
{
- struct nand_chip *chip = mtd->priv;
+ struct nand_chip *chip = mtd_to_nand(mtd);
#ifdef CONFIG_SYS_NAND_BUSWIDTH_16BIT
return (uint8_t) readw(chip->IO_ADDR_R);
diff --git a/drivers/mtd/nand/omap_gpmc.c b/drivers/mtd/nand/omap_gpmc.c
index 6a45d28a72..37c4341763 100644
--- a/drivers/mtd/nand/omap_gpmc.c
+++ b/drivers/mtd/nand/omap_gpmc.c
@@ -58,8 +58,8 @@ static struct omap_nand_info omap_nand_info[GPMC_MAX_CS];
static void omap_nand_hwcontrol(struct mtd_info *mtd, int32_t cmd,
uint32_t ctrl)
{
- register struct nand_chip *this = mtd->priv;
- struct omap_nand_info *info = this->priv;
+ register struct nand_chip *this = mtd_to_nand(mtd);
+ struct omap_nand_info *info = nand_get_controller_data(this);
int cs = info->cs;
/*
@@ -85,8 +85,8 @@ static void omap_nand_hwcontrol(struct mtd_info *mtd, int32_t cmd,
/* Check wait pin as dev ready indicator */
static int omap_dev_ready(struct mtd_info *mtd)
{
- register struct nand_chip *this = mtd->priv;
- struct omap_nand_info *info = this->priv;
+ register struct nand_chip *this = mtd_to_nand(mtd);
+ struct omap_nand_info *info = nand_get_controller_data(this);
return gpmc_cfg->status & (1 << (8 + info->ws));
}
@@ -163,7 +163,7 @@ static int __maybe_unused omap_correct_data(struct mtd_info *mtd, uint8_t *dat,
return 0;
printf("Error: Bad compare! failed\n");
/* detected 2 bit error */
- return -1;
+ return -EBADMSG;
}
}
return 0;
@@ -177,8 +177,8 @@ static int __maybe_unused omap_correct_data(struct mtd_info *mtd, uint8_t *dat,
__maybe_unused
static void omap_enable_hwecc(struct mtd_info *mtd, int32_t mode)
{
- struct nand_chip *nand = mtd->priv;
- struct omap_nand_info *info = nand->priv;
+ struct nand_chip *nand = mtd_to_nand(mtd);
+ struct omap_nand_info *info = nand_get_controller_data(nand);
unsigned int dev_width = (nand->options & NAND_BUSWIDTH_16) ? 1 : 0;
unsigned int ecc_algo = 0;
unsigned int bch_type = 0;
@@ -262,8 +262,8 @@ static void omap_enable_hwecc(struct mtd_info *mtd, int32_t mode)
static int omap_calculate_ecc(struct mtd_info *mtd, const uint8_t *dat,
uint8_t *ecc_code)
{
- struct nand_chip *chip = mtd->priv;
- struct omap_nand_info *info = chip->priv;
+ struct nand_chip *chip = mtd_to_nand(mtd);
+ struct omap_nand_info *info = nand_get_controller_data(chip);
uint32_t *ptr, val = 0;
int8_t i = 0, j;
@@ -392,7 +392,7 @@ static int __read_prefetch_aligned(struct nand_chip *chip, uint32_t *buf, int le
{
int ret;
uint32_t cnt;
- struct omap_nand_info *info = chip->priv;
+ struct omap_nand_info *info = nand_get_controller_data(chip);
ret = omap_prefetch_enable(PREFETCH_FIFOTHRESHOLD_MAX, len, 0, info->cs);
if (ret < 0)
@@ -417,7 +417,7 @@ static int __read_prefetch_aligned(struct nand_chip *chip, uint32_t *buf, int le
static inline void omap_nand_read(struct mtd_info *mtd, uint8_t *buf, int len)
{
- struct nand_chip *chip = mtd->priv;
+ struct nand_chip *chip = mtd_to_nand(mtd);
if (chip->options & NAND_BUSWIDTH_16)
nand_read_buf16(mtd, buf, len);
@@ -429,7 +429,7 @@ static void omap_nand_read_prefetch(struct mtd_info *mtd, uint8_t *buf, int len)
{
int ret;
uint32_t head, tail;
- struct nand_chip *chip = mtd->priv;
+ struct nand_chip *chip = mtd_to_nand(mtd);
/*
* If the destination buffer is unaligned, start with reading
@@ -491,8 +491,8 @@ static void omap_reverse_list(u8 *list, unsigned int length)
static int omap_correct_data_bch(struct mtd_info *mtd, uint8_t *dat,
uint8_t *read_ecc, uint8_t *calc_ecc)
{
- struct nand_chip *chip = mtd->priv;
- struct omap_nand_info *info = chip->priv;
+ struct nand_chip *chip = mtd_to_nand(mtd);
+ struct omap_nand_info *info = nand_get_controller_data(chip);
struct nand_ecc_ctrl *ecc = &chip->ecc;
uint32_t error_count = 0, error_max;
uint32_t error_loc[ELM_MAX_ERROR_COUNT];
@@ -652,8 +652,8 @@ static int omap_correct_data_bch_sw(struct mtd_info *mtd, u_char *data,
int i, count;
/* cannot correct more than 8 errors */
unsigned int errloc[8];
- struct nand_chip *chip = mtd->priv;
- struct omap_nand_info *info = chip->priv;
+ struct nand_chip *chip = mtd_to_nand(mtd);
+ struct omap_nand_info *info = nand_get_controller_data(chip);
count = decode_bch(info->control, NULL, 512, read_ecc, calc_ecc,
NULL, errloc);
@@ -691,8 +691,8 @@ static int omap_correct_data_bch_sw(struct mtd_info *mtd, u_char *data,
*/
static void __maybe_unused omap_free_bch(struct mtd_info *mtd)
{
- struct nand_chip *chip = mtd->priv;
- struct omap_nand_info *info = chip->priv;
+ struct nand_chip *chip = mtd_to_nand(mtd);
+ struct omap_nand_info *info = nand_get_controller_data(chip);
if (info->control) {
free_bch(info->control);
@@ -710,7 +710,7 @@ static void __maybe_unused omap_free_bch(struct mtd_info *mtd)
*/
static int omap_select_ecc_scheme(struct nand_chip *nand,
enum omap_ecc ecc_scheme, unsigned int pagesize, unsigned int oobsize) {
- struct omap_nand_info *info = nand->priv;
+ struct omap_nand_info *info = nand_get_controller_data(nand);
struct nand_ecclayout *ecclayout = &omap_ecclayout;
int eccsteps = pagesize / SECTOR_BYTES;
int i;
@@ -898,13 +898,13 @@ int __maybe_unused omap_nand_switch_ecc(uint32_t hardware, uint32_t eccstrength)
if (nand_curr_device < 0 ||
nand_curr_device >= CONFIG_SYS_MAX_NAND_DEVICE ||
- !nand_info[nand_curr_device].name) {
+ !nand_info[nand_curr_device]->name) {
printf("nand: error: no NAND devices found\n");
return -ENODEV;
}
- mtd = &nand_info[nand_curr_device];
- nand = mtd->priv;
+ mtd = nand_info[nand_curr_device];
+ nand = mtd_to_nand(mtd);
nand->options |= NAND_OWN_BUFFERS;
nand->options &= ~NAND_SUBPAGE_READ;
/* Setup the ecc configurations again */
@@ -994,7 +994,7 @@ int board_nand_init(struct nand_chip *nand)
omap_nand_info[cs].control = NULL;
omap_nand_info[cs].cs = cs;
omap_nand_info[cs].ws = wscfg[cs];
- nand->priv = &omap_nand_info[cs];
+ nand_set_controller_data(nand, &omap_nand_info[cs]);
nand->cmd_ctrl = omap_nand_hwcontrol;
nand->options |= NAND_NO_PADDING | NAND_CACHEPRG;
nand->chip_delay = 100;
diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index d529467ebc..d3ac5391f1 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -900,7 +900,8 @@ static int prepare_set_command(struct pxa3xx_nand_info *info, int command,
static void nand_cmdfunc(struct mtd_info *mtd, unsigned command,
int column, int page_addr)
{
- struct pxa3xx_nand_host *host = mtd->priv;
+ struct nand_chip *chip = mtd_to_nand(mtd);
+ struct pxa3xx_nand_host *host = nand_get_controller_data(chip);
struct pxa3xx_nand_info *info = host->info_data;
int exec_cmd;
@@ -960,7 +961,8 @@ static void nand_cmdfunc_extended(struct mtd_info *mtd,
const unsigned command,
int column, int page_addr)
{
- struct pxa3xx_nand_host *host = mtd->priv;
+ struct nand_chip *chip = mtd_to_nand(mtd);
+ struct pxa3xx_nand_host *host = nand_get_controller_data(chip);
struct pxa3xx_nand_info *info = host->info_data;
int exec_cmd, ext_cmd_type;
@@ -1079,7 +1081,8 @@ static void nand_cmdfunc_extended(struct mtd_info *mtd,
}
static int pxa3xx_nand_write_page_hwecc(struct mtd_info *mtd,
- struct nand_chip *chip, const uint8_t *buf, int oob_required)
+ struct nand_chip *chip, const uint8_t *buf, int oob_required,
+ int page)
{
chip->write_buf(mtd, buf, mtd->writesize);
chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
@@ -1091,7 +1094,7 @@ static int pxa3xx_nand_read_page_hwecc(struct mtd_info *mtd,
struct nand_chip *chip, uint8_t *buf, int oob_required,
int page)
{
- struct pxa3xx_nand_host *host = mtd->priv;
+ struct pxa3xx_nand_host *host = nand_get_controller_data(chip);
struct pxa3xx_nand_info *info = host->info_data;
chip->read_buf(mtd, buf, mtd->writesize);
@@ -1117,7 +1120,8 @@ static int pxa3xx_nand_read_page_hwecc(struct mtd_info *mtd,
static uint8_t pxa3xx_nand_read_byte(struct mtd_info *mtd)
{
- struct pxa3xx_nand_host *host = mtd->priv;
+ struct nand_chip *chip = mtd_to_nand(mtd);
+ struct pxa3xx_nand_host *host = nand_get_controller_data(chip);
struct pxa3xx_nand_info *info = host->info_data;
char retval = 0xFF;
@@ -1130,7 +1134,8 @@ static uint8_t pxa3xx_nand_read_byte(struct mtd_info *mtd)
static u16 pxa3xx_nand_read_word(struct mtd_info *mtd)
{
- struct pxa3xx_nand_host *host = mtd->priv;
+ struct nand_chip *chip = mtd_to_nand(mtd);
+ struct pxa3xx_nand_host *host = nand_get_controller_data(chip);
struct pxa3xx_nand_info *info = host->info_data;
u16 retval = 0xFFFF;
@@ -1143,7 +1148,8 @@ static u16 pxa3xx_nand_read_word(struct mtd_info *mtd)
static void pxa3xx_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
{
- struct pxa3xx_nand_host *host = mtd->priv;
+ struct nand_chip *chip = mtd_to_nand(mtd);
+ struct pxa3xx_nand_host *host = nand_get_controller_data(chip);
struct pxa3xx_nand_info *info = host->info_data;
int real_len = min_t(size_t, len, info->buf_count - info->buf_start);
@@ -1154,7 +1160,8 @@ static void pxa3xx_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
static void pxa3xx_nand_write_buf(struct mtd_info *mtd,
const uint8_t *buf, int len)
{
- struct pxa3xx_nand_host *host = mtd->priv;
+ struct nand_chip *chip = mtd_to_nand(mtd);
+ struct pxa3xx_nand_host *host = nand_get_controller_data(chip);
struct pxa3xx_nand_info *info = host->info_data;
int real_len = min_t(size_t, len, info->buf_count - info->buf_start);
@@ -1169,7 +1176,8 @@ static void pxa3xx_nand_select_chip(struct mtd_info *mtd, int chip)
static int pxa3xx_nand_waitfunc(struct mtd_info *mtd, struct nand_chip *this)
{
- struct pxa3xx_nand_host *host = mtd->priv;
+ struct nand_chip *chip = mtd_to_nand(mtd);
+ struct pxa3xx_nand_host *host = nand_get_controller_data(chip);
struct pxa3xx_nand_info *info = host->info_data;
if (info->need_wait) {
@@ -1210,7 +1218,7 @@ static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info)
{
struct pxa3xx_nand_host *host = info->host[info->cs];
struct mtd_info *mtd = host->mtd;
- struct nand_chip *chip = mtd->priv;
+ struct nand_chip *chip = mtd_to_nand(mtd);
info->reg_ndcr |= (host->col_addr_cycles == 2) ? NDCR_RA_START : 0;
info->reg_ndcr |= (chip->page_shift == 6) ? NDCR_PG_PER_BLK : 0;
@@ -1262,7 +1270,7 @@ static int pxa3xx_nand_sensing(struct pxa3xx_nand_host *host)
int ret;
mtd = info->host[info->cs]->mtd;
- chip = mtd->priv;
+ chip = mtd_to_nand(mtd);
/* configure default flash values */
info->reg_ndcr = 0x0; /* enable all interrupts */
@@ -1354,10 +1362,10 @@ static int pxa_ecc_init(struct pxa3xx_nand_info *info,
static int pxa3xx_nand_scan(struct mtd_info *mtd)
{
- struct pxa3xx_nand_host *host = mtd->priv;
+ struct nand_chip *chip = mtd_to_nand(mtd);
+ struct pxa3xx_nand_host *host = nand_get_controller_data(chip);
struct pxa3xx_nand_info *info = host->info_data;
struct pxa3xx_nand_platform_data *pdata = info->pdata;
- struct nand_chip *chip = mtd->priv;
int ret;
uint16_t ecc_strength, ecc_step;
@@ -1477,16 +1485,15 @@ static int alloc_nand_resource(struct pxa3xx_nand_info *info)
info->variant = pxa3xx_nand_get_variant();
for (cs = 0; cs < pdata->num_cs; cs++) {
- mtd = &nand_info[cs];
chip = (struct nand_chip *)
((u8 *)&info[1] + sizeof(*host) * cs);
+ mtd = nand_to_mtd(chip);
host = (struct pxa3xx_nand_host *)chip;
info->host[cs] = host;
host->mtd = mtd;
host->cs = cs;
host->info_data = info;
host->read_id_bytes = 4;
- mtd->priv = host;
mtd->owner = THIS_MODULE;
chip->ecc.read_page = pxa3xx_nand_read_page_hwecc;
@@ -1573,8 +1580,10 @@ static int pxa3xx_nand_probe(struct pxa3xx_nand_info *info)
continue;
}
- if (!ret)
- probe_success = 1;
+ if (nand_register(cs, mtd))
+ continue;
+
+ probe_success = 1;
}
if (!probe_success)
@@ -1601,6 +1610,4 @@ void board_nand_init(void)
ret = pxa3xx_nand_probe(info);
if (ret)
return;
-
- nand_register(0);
}
diff --git a/drivers/mtd/nand/s3c2410_nand.c b/drivers/mtd/nand/s3c2410_nand.c
index b3a2a60bb2..dd742a6351 100644
--- a/drivers/mtd/nand/s3c2410_nand.c
+++ b/drivers/mtd/nand/s3c2410_nand.c
@@ -31,7 +31,7 @@
static void nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
{
int i;
- struct nand_chip *this = mtd->priv;
+ struct nand_chip *this = mtd_to_nand(mtd);
for (i = 0; i < len; i++)
buf[i] = readb(this->IO_ADDR_R);
@@ -40,7 +40,7 @@ static void nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
static void s3c24x0_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
{
- struct nand_chip *chip = mtd->priv;
+ struct nand_chip *chip = mtd_to_nand(mtd);
struct s3c24x0_nand *nand = s3c24x0_get_base_nand();
debug("hwcontrol(): 0x%02x 0x%02x\n", cmd, ctrl);
@@ -104,7 +104,7 @@ static int s3c24x0_nand_correct_data(struct mtd_info *mtd, u_char *dat,
return 0;
printf("s3c24x0_nand_correct_data: not implemented\n");
- return -1;
+ return -EBADMSG;
}
#endif
diff --git a/drivers/mtd/nand/tegra_nand.c b/drivers/mtd/nand/tegra_nand.c
index a77db7b65d..2032f65812 100644
--- a/drivers/mtd/nand/tegra_nand.c
+++ b/drivers/mtd/nand/tegra_nand.c
@@ -143,10 +143,10 @@ static int nand_waitfor_cmd_completion(struct nand_ctlr *reg)
*/
static uint8_t read_byte(struct mtd_info *mtd)
{
- struct nand_chip *chip = mtd->priv;
+ struct nand_chip *chip = mtd_to_nand(mtd);
struct nand_drv *info;
- info = (struct nand_drv *)chip->priv;
+ info = (struct nand_drv *)nand_get_controller_data(chip);
writel(CMD_GO | CMD_PIO | CMD_RX | CMD_CE0 | CMD_A_VALID,
&info->reg->command);
@@ -169,8 +169,8 @@ static void read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
{
int i, s;
unsigned int reg;
- struct nand_chip *chip = mtd->priv;
- struct nand_drv *info = (struct nand_drv *)chip->priv;
+ struct nand_chip *chip = mtd_to_nand(mtd);
+ struct nand_drv *info = (struct nand_drv *)nand_get_controller_data(chip);
for (i = 0; i < len; i += 4) {
s = (len - i) > 4 ? 4 : len - i;
@@ -194,11 +194,11 @@ static void read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
*/
static int nand_dev_ready(struct mtd_info *mtd)
{
- struct nand_chip *chip = mtd->priv;
+ struct nand_chip *chip = mtd_to_nand(mtd);
int reg_val;
struct nand_drv *info;
- info = (struct nand_drv *)chip->priv;
+ info = (struct nand_drv *)nand_get_controller_data(chip);
reg_val = readl(&info->reg->status);
if (reg_val & STATUS_RBSY0)
@@ -245,10 +245,10 @@ static void nand_clear_interrupt_status(struct nand_ctlr *reg)
static void nand_command(struct mtd_info *mtd, unsigned int command,
int column, int page_addr)
{
- struct nand_chip *chip = mtd->priv;
+ struct nand_chip *chip = mtd_to_nand(mtd);
struct nand_drv *info;
- info = (struct nand_drv *)chip->priv;
+ info = (struct nand_drv *)nand_get_controller_data(chip);
/*
* Write out the command to the device.
@@ -512,7 +512,7 @@ static int nand_rw_page(struct mtd_info *mtd, struct nand_chip *chip,
return -EINVAL;
}
- info = (struct nand_drv *)chip->priv;
+ info = (struct nand_drv *)nand_get_controller_data(chip);
config = &info->config;
if (set_bus_width_page_size(config, &reg_val))
return -EINVAL;
@@ -657,16 +657,9 @@ static int nand_read_page_hwecc(struct mtd_info *mtd,
* @param buf data buffer
*/
static int nand_write_page_hwecc(struct mtd_info *mtd,
- struct nand_chip *chip, const uint8_t *buf, int oob_required)
+ struct nand_chip *chip, const uint8_t *buf, int oob_required,
+ int page)
{
- int page;
- struct nand_drv *info;
-
- info = (struct nand_drv *)chip->priv;
-
- page = (readl(&info->reg->addr_reg1) >> 16) |
- (readl(&info->reg->addr_reg2) << 16);
-
nand_rw_page(mtd, chip, (uint8_t *)buf, page, 1, 1);
return 0;
}
@@ -697,15 +690,9 @@ static int nand_read_page_raw(struct mtd_info *mtd,
* @param buf data buffer
*/
static int nand_write_page_raw(struct mtd_info *mtd,
- struct nand_chip *chip, const uint8_t *buf, int oob_required)
+ struct nand_chip *chip, const uint8_t *buf,
+ int oob_required, int page)
{
- int page;
- struct nand_drv *info;
-
- info = (struct nand_drv *)chip->priv;
- page = (readl(&info->reg->addr_reg1) >> 16) |
- (readl(&info->reg->addr_reg2) << 16);
-
nand_rw_page(mtd, chip, (uint8_t *)buf, page, 0, 1);
return 0;
}
@@ -734,7 +721,7 @@ static int nand_rw_oob(struct mtd_info *mtd, struct nand_chip *chip,
if (((int)chip->oob_poi) & 0x03)
return -EINVAL;
- info = (struct nand_drv *)chip->priv;
+ info = (struct nand_drv *)nand_get_controller_data(chip);
if (set_bus_width_page_size(&info->config, &reg_val))
return -EINVAL;
@@ -963,7 +950,7 @@ int tegra_nand_init(struct nand_chip *nand, int devnum)
nand->ecc.strength = 1;
nand->select_chip = nand_select_chip;
nand->dev_ready = nand_dev_ready;
- nand->priv = &nand_ctrl;
+ nand_set_controller_data(nand, &nand_ctrl);
/* Disable subpage writes as we do not provide ecc->hwctl */
nand->options |= NAND_NO_SUBPAGE_WRITE;
@@ -976,8 +963,7 @@ int tegra_nand_init(struct nand_chip *nand, int devnum)
dm_gpio_set_value(&config->wp_gpio, 1);
- our_mtd = &nand_info[devnum];
- our_mtd->priv = nand;
+ our_mtd = nand_to_mtd(nand);
ret = nand_scan_ident(our_mtd, CONFIG_SYS_NAND_MAX_CHIPS, NULL);
if (ret)
return ret;
@@ -989,7 +975,7 @@ int tegra_nand_init(struct nand_chip *nand, int devnum)
if (ret)
return ret;
- ret = nand_register(devnum);
+ ret = nand_register(devnum, our_mtd);
if (ret)
return ret;
diff --git a/drivers/mtd/nand/vf610_nfc.c b/drivers/mtd/nand/vf610_nfc.c
index 1faec5e1f2..f99bdaf94d 100644
--- a/drivers/mtd/nand/vf610_nfc.c
+++ b/drivers/mtd/nand/vf610_nfc.c
@@ -146,7 +146,6 @@ enum vf610_nfc_alt_buf {
};
struct vf610_nfc {
- struct mtd_info *mtd;
struct nand_chip chip;
void __iomem *regs;
uint buf_offset;
@@ -155,8 +154,7 @@ struct vf610_nfc {
enum vf610_nfc_alt_buf alt_buf;
};
-#define mtd_to_nfc(_mtd) \
- (struct vf610_nfc *)((struct nand_chip *)_mtd->priv)->priv
+#define mtd_to_nfc(_mtd) nand_get_controller_data(mtd_to_nand(_mtd))
#if defined(CONFIG_SYS_NAND_VF610_NFC_45_ECC_BYTES)
#define ECC_HW_MODE ECC_45_BYTE
@@ -608,7 +606,7 @@ static int vf610_nfc_read_page(struct mtd_info *mtd, struct nand_chip *chip,
* ECC will be calculated automatically
*/
static int vf610_nfc_write_page(struct mtd_info *mtd, struct nand_chip *chip,
- const uint8_t *buf, int oob_required)
+ const uint8_t *buf, int oob_required, int page)
{
struct vf610_nfc *nfc = mtd_to_nfc(mtd);
@@ -630,7 +628,7 @@ struct vf610_nfc_config {
static int vf610_nfc_nand_init(int devnum, void __iomem *addr)
{
- struct mtd_info *mtd = &nand_info[devnum];
+ struct mtd_info *mtd;
struct nand_chip *chip;
struct vf610_nfc *nfc;
int err = 0;
@@ -653,8 +651,8 @@ static int vf610_nfc_nand_init(int devnum, void __iomem *addr)
chip = &nfc->chip;
nfc->regs = addr;
- mtd->priv = chip;
- chip->priv = nfc;
+ mtd = nand_to_mtd(chip);
+ nand_set_controller_data(chip, nfc);
if (cfg.width == 16)
chip->options |= NAND_BUSWIDTH_16;
@@ -753,7 +751,7 @@ static int vf610_nfc_nand_init(int devnum, void __iomem *addr)
if (err)
return err;
- err = nand_register(devnum);
+ err = nand_register(devnum, mtd);
if (err)
return err;
diff --git a/drivers/net/fm/fm.c b/drivers/net/fm/fm.c
index e2a8ed3919..00cdfd47b8 100644
--- a/drivers/net/fm/fm.c
+++ b/drivers/net/fm/fm.c
@@ -360,7 +360,7 @@ int fm_init_common(int index, struct ccsr_fman *reg)
size_t fw_length = CONFIG_SYS_QE_FMAN_FW_LENGTH;
void *addr = malloc(CONFIG_SYS_QE_FMAN_FW_LENGTH);
- rc = nand_read(&nand_info[0], (loff_t)CONFIG_SYS_FMAN_FW_ADDR,
+ rc = nand_read(nand_info[0], (loff_t)CONFIG_SYS_FMAN_FW_ADDR,
&fw_length, (u_char *)addr);
if (rc == -EUCLEAN) {
printf("NAND read of FMAN firmware at offset 0x%x failed %d\n",
diff --git a/drivers/net/phy/cortina.c b/drivers/net/phy/cortina.c
index f975fd8209..fd130d5b82 100644
--- a/drivers/net/phy/cortina.c
+++ b/drivers/net/phy/cortina.c
@@ -139,8 +139,8 @@ void cs4340_upload_firmware(struct phy_device *phydev)
size_t fw_length = CONFIG_CORTINA_FW_LENGTH;
addr = malloc(CONFIG_CORTINA_FW_LENGTH);
- ret = nand_read(&nand_info[0], (loff_t)CONFIG_CORTINA_FW_ADDR,
- &fw_length, (u_char *)addr);
+ ret = nand_read(nand_info[0], (loff_t)CONFIG_CORTINA_FW_ADDR,
+ &fw_length, (u_char *)addr);
if (ret == -EUCLEAN) {
printf("NAND read of Cortina firmware at 0x%x failed %d\n",
CONFIG_CORTINA_FW_ADDR, ret);
diff --git a/fs/jffs2/jffs2_1pass.c b/fs/jffs2/jffs2_1pass.c
index ba038b1122..f771e94f91 100644
--- a/fs/jffs2/jffs2_1pass.c
+++ b/fs/jffs2/jffs2_1pass.c
@@ -195,7 +195,7 @@ static int read_nand_cached(u32 off, u32 size, u_char *buf)
}
retlen = NAND_CACHE_SIZE;
- if (nand_read(&nand_info[id->num], nand_cache_off,
+ if (nand_read(nand_info[id->num], nand_cache_off,
&retlen, nand_cache) != 0 ||
retlen != NAND_CACHE_SIZE) {
printf("read_nand_cached: error reading nand off %#x size %d bytes\n",
diff --git a/fs/jffs2/jffs2_nand_1pass.c b/fs/jffs2/jffs2_nand_1pass.c
index 740f787dd2..d94c48f534 100644
--- a/fs/jffs2/jffs2_nand_1pass.c
+++ b/fs/jffs2/jffs2_nand_1pass.c
@@ -23,7 +23,7 @@
# define DEBUGF(fmt,args...)
#endif
-static nand_info_t *nand;
+static struct mtd_info *mtd;
/* Compression names */
static char *compr_names[] = {
@@ -304,7 +304,7 @@ jffs2_1pass_read_inode(struct b_lists *pL, u32 ino, char *dest,
len = sizeof(struct jffs2_raw_inode);
if (dest)
len += jNode->csize;
- nand_read(nand, jNode->offset, &len, inode);
+ nand_read(mtd, jNode->offset, &len, inode);
/* ignore data behind latest known EOF */
if (inode->offset > totalSize)
continue;
@@ -450,7 +450,7 @@ dump_inode(struct b_lists *pL, struct b_dirent *d, struct b_inode *i)
if(!d || !i) return -1;
len = d->nsize;
- nand_read(nand, d->offset + sizeof(struct jffs2_raw_dirent),
+ nand_read(mtd, d->offset + sizeof(struct jffs2_raw_dirent),
&len, &fname);
fname[d->nsize] = '\0';
@@ -592,7 +592,9 @@ jffs2_1pass_resolve_inode(struct b_lists * pL, u32 ino)
for (jNode = (struct b_inode *)pL->frag.listHead; jNode; jNode = jNode->next) {
if (jNode->ino == jDirFoundIno) {
size_t len = jNode->csize;
- nand_read(nand, jNode->offset + sizeof(struct jffs2_raw_inode), &len, &tmp);
+ nand_read(mtd,
+ jNode->offset + sizeof(struct jffs2_raw_inode),
+ &len, &tmp);
tmp[jNode->csize] = '\0';
break;
}
@@ -760,14 +762,14 @@ dump_dirents(struct b_lists *pL)
#endif
static int
-jffs2_fill_scan_buf(nand_info_t *nand, unsigned char *buf,
+jffs2_fill_scan_buf(struct mtd_info *mtd, unsigned char *buf,
unsigned ofs, unsigned len)
{
int ret;
unsigned olen;
olen = len;
- ret = nand_read(nand, ofs, &olen, buf);
+ ret = nand_read(mtd, ofs, &olen, buf);
if (ret) {
printf("nand_read(0x%x bytes from 0x%x) returned %d\n", len, ofs, ret);
return ret;
@@ -794,7 +796,7 @@ jffs2_1pass_build_lists(struct part_info * part)
u32 counterN = 0;
struct mtdids *id = part->dev->id;
- nand = nand_info + id->num;
+ mtd = nand_info[id->num];
/* if we are building a list we need to refresh the cache. */
jffs_init_1pass_list(part);
@@ -802,7 +804,7 @@ jffs2_1pass_build_lists(struct part_info * part)
pL->partOffset = part->offset;
puts ("Scanning JFFS2 FS: ");
- sectorsize = nand->erasesize;
+ sectorsize = mtd->erasesize;
nr_blocks = part->size / sectorsize;
buf = malloc(sectorsize);
if (!buf)
@@ -813,10 +815,10 @@ jffs2_1pass_build_lists(struct part_info * part)
offset = part->offset + i * sectorsize;
- if (nand_block_isbad(nand, offset))
+ if (nand_block_isbad(mtd, offset))
continue;
- if (jffs2_fill_scan_buf(nand, buf, offset, EMPTY_SCAN_SIZE))
+ if (jffs2_fill_scan_buf(mtd, buf, offset, EMPTY_SCAN_SIZE))
return 0;
ofs = 0;
@@ -826,7 +828,7 @@ jffs2_1pass_build_lists(struct part_info * part)
if (ofs == EMPTY_SCAN_SIZE)
continue;
- if (jffs2_fill_scan_buf(nand, buf + EMPTY_SCAN_SIZE, offset + EMPTY_SCAN_SIZE, sectorsize - EMPTY_SCAN_SIZE))
+ if (jffs2_fill_scan_buf(mtd, buf + EMPTY_SCAN_SIZE, offset + EMPTY_SCAN_SIZE, sectorsize - EMPTY_SCAN_SIZE))
return 0;
offset += ofs;
diff --git a/fs/yaffs2/yaffs_uboot_glue.c b/fs/yaffs2/yaffs_uboot_glue.c
index 50000a135b..25aa6d1564 100644
--- a/fs/yaffs2/yaffs_uboot_glue.c
+++ b/fs/yaffs2/yaffs_uboot_glue.c
@@ -141,8 +141,6 @@ static const char *yaffs_error_str(void)
}
}
-extern nand_info_t nand_info[];
-
void cmd_yaffs_tracemask(unsigned set, unsigned mask)
{
if (set)
@@ -171,7 +169,7 @@ void cmd_yaffs_devconfig(char *_mp, int flash_dev,
dev = calloc(1, sizeof(*dev));
mp = strdup(_mp);
- mtd = &nand_info[flash_dev];
+ mtd = nand_info[flash_dev];
if (!dev || !mp) {
/* Alloc error */
@@ -192,7 +190,7 @@ void cmd_yaffs_devconfig(char *_mp, int flash_dev,
goto err;
}
- chip = mtd->priv;
+ chip = mtd_to_nand(mtd);
/* Check for any conflicts */
yaffs_dev_rewind();
@@ -260,9 +258,7 @@ void cmd_yaffs_dev_ls(void)
dev = yaffs_next_dev();
if (!dev)
return;
- flash_dev =
- ((unsigned) dev->driver_context - (unsigned) nand_info)/
- sizeof(nand_info[0]);
+ flash_dev = nand_mtd_to_devnum(dev->driver_context);
printf("%-10s %5d 0x%05x 0x%05x %s",
dev->param.name, flash_dev,
dev->param.start_block, dev->param.end_block,
diff --git a/include/linux/mtd/docg4.h b/include/linux/mtd/docg4.h
deleted file mode 100644
index 741fc0db46..0000000000
--- a/include/linux/mtd/docg4.h
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Copyright (C) 2013 Mike Dunn <mikedunn@newsguy.com>
- *
- * SPDX-License-Identifier: GPL-2.0+
- */
-
-#ifndef __DOCG4_H__
-#define __DOCG4_H__
-
-#include <common.h>
-#include <linux/mtd/nand.h>
-
-extern int docg4_nand_init(struct mtd_info *mtd,
- struct nand_chip *nand, int devnum);
-
-/* SPL-related definitions */
-#define DOCG4_IPL_LOAD_BLOCK_COUNT 2 /* number of blocks that IPL loads */
-#define DOCG4_BLOCK_CAPACITY_SPL 0x10000 /* reliable mode; redundant pages */
-
-#define DOC_IOSPACE_DATA 0x0800
-
-/* register offsets */
-#define DOC_CHIPID 0x1000
-#define DOC_DEVICESELECT 0x100a
-#define DOC_ASICMODE 0x100c
-#define DOC_DATAEND 0x101e
-#define DOC_NOP 0x103e
-
-#define DOC_FLASHSEQUENCE 0x1032
-#define DOC_FLASHCOMMAND 0x1034
-#define DOC_FLASHADDRESS 0x1036
-#define DOC_FLASHCONTROL 0x1038
-#define DOC_ECCCONF0 0x1040
-#define DOC_ECCCONF1 0x1042
-#define DOC_HAMMINGPARITY 0x1046
-#define DOC_BCH_SYNDROM(idx) (0x1048 + idx)
-
-#define DOC_ASICMODECONFIRM 0x1072
-#define DOC_CHIPID_INV 0x1074
-#define DOC_POWERMODE 0x107c
-
-#define DOCG4_MYSTERY_REG 0x1050
-
-/* apparently used only to write oob bytes 6 and 7 */
-#define DOCG4_OOB_6_7 0x1052
-
-/* DOC_FLASHSEQUENCE register commands */
-#define DOC_SEQ_RESET 0x00
-#define DOCG4_SEQ_PAGE_READ 0x03
-#define DOCG4_SEQ_FLUSH 0x29
-#define DOCG4_SEQ_PAGEWRITE 0x16
-#define DOCG4_SEQ_PAGEPROG 0x1e
-#define DOCG4_SEQ_BLOCKERASE 0x24
-
-/* DOC_FLASHCOMMAND register commands */
-#define DOCG4_CMD_PAGE_READ 0x00
-#define DOC_CMD_ERASECYCLE2 0xd0
-#define DOCG4_CMD_FLUSH 0x70
-#define DOCG4_CMD_READ2 0x30
-#define DOC_CMD_PROG_BLOCK_ADDR 0x60
-#define DOCG4_CMD_PAGEWRITE 0x80
-#define DOC_CMD_PROG_CYCLE2 0x10
-#define DOC_CMD_RESET 0xff
-
-/* DOC_POWERMODE register bits */
-#define DOC_POWERDOWN_READY 0x80
-
-/* DOC_FLASHCONTROL register bits */
-#define DOC_CTRL_CE 0x10
-#define DOC_CTRL_UNKNOWN 0x40
-#define DOC_CTRL_FLASHREADY 0x01
-
-/* DOC_ECCCONF0 register bits */
-#define DOC_ECCCONF0_READ_MODE 0x8000
-#define DOC_ECCCONF0_UNKNOWN 0x2000
-#define DOC_ECCCONF0_ECC_ENABLE 0x1000
-#define DOC_ECCCONF0_DATA_BYTES_MASK 0x07ff
-
-/* DOC_ECCCONF1 register bits */
-#define DOC_ECCCONF1_BCH_SYNDROM_ERR 0x80
-#define DOC_ECCCONF1_ECC_ENABLE 0x07
-#define DOC_ECCCONF1_PAGE_IS_WRITTEN 0x20
-
-/* DOC_ASICMODE register bits */
-#define DOC_ASICMODE_RESET 0x00
-#define DOC_ASICMODE_NORMAL 0x01
-#define DOC_ASICMODE_POWERDOWN 0x02
-#define DOC_ASICMODE_MDWREN 0x04
-#define DOC_ASICMODE_BDETCT_RESET 0x08
-#define DOC_ASICMODE_RSTIN_RESET 0x10
-#define DOC_ASICMODE_RAM_WE 0x20
-
-/* good status values read after read/write/erase operations */
-#define DOCG4_PROGSTATUS_GOOD 0x51
-#define DOCG4_PROGSTATUS_GOOD_2 0xe0
-
-/*
- * On read operations (page and oob-only), the first byte read from I/O reg is a
- * status. On error, it reads 0x73; otherwise, it reads either 0x71 (first read
- * after reset only) or 0x51, so bit 1 is presumed to be an error indicator.
- */
-#define DOCG4_READ_ERROR 0x02 /* bit 1 indicates read error */
-
-/* anatomy of the device */
-#define DOCG4_CHIP_SIZE 0x8000000
-#define DOCG4_PAGE_SIZE 0x200
-#define DOCG4_PAGES_PER_BLOCK 0x200
-#define DOCG4_BLOCK_SIZE (DOCG4_PAGES_PER_BLOCK * DOCG4_PAGE_SIZE)
-#define DOCG4_NUMBLOCKS (DOCG4_CHIP_SIZE / DOCG4_BLOCK_SIZE)
-#define DOCG4_OOB_SIZE 0x10
-#define DOCG4_CHIP_SHIFT 27 /* log_2(DOCG4_CHIP_SIZE) */
-#define DOCG4_PAGE_SHIFT 9 /* log_2(DOCG4_PAGE_SIZE) */
-#define DOCG4_ERASE_SHIFT 18 /* log_2(DOCG4_BLOCK_SIZE) */
-
-/* all but the last byte is included in ecc calculation */
-#define DOCG4_BCH_SIZE (DOCG4_PAGE_SIZE + DOCG4_OOB_SIZE - 1)
-
-#define DOCG4_USERDATA_LEN 520 /* 512 byte page plus 8 oob avail to user */
-
-/* expected values from the ID registers */
-#define DOCG4_IDREG1_VALUE 0x0400
-#define DOCG4_IDREG2_VALUE 0xfbff
-
-/* primitive polynomial used to build the Galois field used by hw ecc gen */
-#define DOCG4_PRIMITIVE_POLY 0x4443
-
-#define DOCG4_M 14 /* Galois field is of order 2^14 */
-#define DOCG4_T 4 /* BCH alg corrects up to 4 bit errors */
-
-#define DOCG4_FACTORY_BBT_PAGE 16 /* page where read-only factory bbt lives */
-
-#endif /* __DOCG4_H__ */
diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h
index 9da77ec144..cf20674549 100644
--- a/include/linux/mtd/mtd.h
+++ b/include/linux/mtd/mtd.h
@@ -278,6 +278,11 @@ struct mtd_info {
int usecount;
};
+static inline int mtd_oobavail(struct mtd_info *mtd, struct mtd_oob_ops *ops)
+{
+ return ops->mode == MTD_OPS_AUTO_OOB ? mtd->oobavail : mtd->oobsize;
+}
+
int mtd_erase(struct mtd_info *mtd, struct erase_info *instr);
#ifndef __UBOOT__
int mtd_point(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen,
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
index 23072fdfc3..b5a02c3382 100644
--- a/include/linux/mtd/nand.h
+++ b/include/linux/mtd/nand.h
@@ -25,6 +25,8 @@
struct mtd_info;
struct nand_flash_dev;
+struct device_node;
+
/* Scan and identify a NAND device */
extern int nand_scan(struct mtd_info *mtd, int max_chips);
/*
@@ -144,6 +146,14 @@ typedef enum {
/* Enable Hardware ECC before syndrome is read back from flash */
#define NAND_ECC_READSYN 2
+/*
+ * Enable generic NAND 'page erased' check. This check is only done when
+ * ecc.correct() returns -EBADMSG.
+ * Set this flag if your implementation does not fix bitflips in erased
+ * pages and you want to rely on the default implementation.
+ */
+#define NAND_ECC_GENERIC_ERASED_CHECK BIT(0)
+
/* Bit mask for flags passed to do_nand_read_ecc */
#define NAND_GET_DEVICE 0x80
@@ -179,6 +189,12 @@ typedef enum {
/* Device supports subpage reads */
#define NAND_SUBPAGE_READ 0x00001000
+/*
+ * Some MLC NANDs need data scrambling to limit bitflips caused by repeated
+ * patterns.
+ */
+#define NAND_NEED_SCRAMBLING 0x00002000
+
/* Options valid for Samsung large page devices */
#define NAND_SAMSUNG_LP_OPTIONS NAND_CACHEPRG
@@ -203,6 +219,11 @@ typedef enum {
* before calling nand_scan_tail.
*/
#define NAND_BUSWIDTH_AUTO 0x00080000
+/*
+ * This option could be defined by controller drivers to protect against
+ * kmap'ed, vmalloc'ed highmem buffers being passed from upper layers
+ */
+#define NAND_USE_BOUNCE_BUFFER 0x00100000
/* Options set by nand scan */
/* bbt has already been read */
@@ -292,15 +313,15 @@ struct nand_onfi_params {
__le16 t_r;
__le16 t_ccs;
__le16 src_sync_timing_mode;
- __le16 src_ssync_features;
+ u8 src_ssync_features;
__le16 clk_pin_capacitance_typ;
__le16 io_pin_capacitance_typ;
__le16 input_pin_capacitance_typ;
u8 input_pin_capacitance_max;
u8 driver_strength_support;
__le16 t_int_r;
- __le16 t_ald;
- u8 reserved4[7];
+ __le16 t_adl;
+ u8 reserved4[8];
/* vendor */
__le16 vendor_revision;
@@ -423,7 +444,7 @@ struct nand_jedec_params {
__le16 input_pin_capacitance_typ;
__le16 clk_pin_capacitance_typ;
u8 driver_strength_support;
- __le16 t_ald;
+ __le16 t_adl;
u8 reserved4[36];
/* ECC and endurance block */
@@ -466,12 +487,19 @@ struct nand_hw_control {
* @total: total number of ECC bytes per page
* @prepad: padding information for syndrome based ECC generators
* @postpad: padding information for syndrome based ECC generators
+ * @options: ECC specific options (see NAND_ECC_XXX flags defined above)
* @layout: ECC layout control struct pointer
* @priv: pointer to private ECC control data
* @hwctl: function to control hardware ECC generator. Must only
* be provided if an hardware ECC is available
* @calculate: function for ECC calculation or readback from ECC hardware
- * @correct: function for ECC correction, matching to ECC generator (sw/hw)
+ * @correct: function for ECC correction, matching to ECC generator (sw/hw).
+ * Should return a positive number representing the number of
+ * corrected bitflips, -EBADMSG if the number of bitflips exceed
+ * ECC strength, or any other error code if the error is not
+ * directly related to correction.
+ * If -EBADMSG is returned the input buffers should be left
+ * untouched.
* @read_page_raw: function to read a raw page without ECC. This function
* should hide the specific layout used by the ECC
* controller and always return contiguous in-band and
@@ -509,6 +537,7 @@ struct nand_ecc_ctrl {
int strength;
int prepad;
int postpad;
+ unsigned int options;
struct nand_ecclayout *layout;
void *priv;
void (*hwctl)(struct mtd_info *mtd, int mode);
@@ -519,16 +548,16 @@ struct nand_ecc_ctrl {
int (*read_page_raw)(struct mtd_info *mtd, struct nand_chip *chip,
uint8_t *buf, int oob_required, int page);
int (*write_page_raw)(struct mtd_info *mtd, struct nand_chip *chip,
- const uint8_t *buf, int oob_required);
+ const uint8_t *buf, int oob_required, int page);
int (*read_page)(struct mtd_info *mtd, struct nand_chip *chip,
uint8_t *buf, int oob_required, int page);
int (*read_subpage)(struct mtd_info *mtd, struct nand_chip *chip,
uint32_t offs, uint32_t len, uint8_t *buf, int page);
int (*write_subpage)(struct mtd_info *mtd, struct nand_chip *chip,
uint32_t offset, uint32_t data_len,
- const uint8_t *data_buf, int oob_required);
+ const uint8_t *data_buf, int oob_required, int page);
int (*write_page)(struct mtd_info *mtd, struct nand_chip *chip,
- const uint8_t *buf, int oob_required);
+ const uint8_t *buf, int oob_required, int page);
int (*write_oob_raw)(struct mtd_info *mtd, struct nand_chip *chip,
int page);
int (*read_oob_raw)(struct mtd_info *mtd, struct nand_chip *chip,
@@ -556,6 +585,7 @@ struct nand_buffers {
/**
* struct nand_chip - NAND Private Flash Chip Data
+ * @mtd: MTD device registered to the MTD framework
* @IO_ADDR_R: [BOARDSPECIFIC] address to read the 8 I/O lines of the
* flash device
* @IO_ADDR_W: [BOARDSPECIFIC] address to write the 8 I/O lines of the
@@ -571,10 +601,6 @@ struct nand_buffers {
* @block_markbad: [REPLACEABLE] mark a block bad
* @cmd_ctrl: [BOARDSPECIFIC] hardwarespecific function for controlling
* ALE/CLE/nCE. Also used to write command and address
- * @init_size: [BOARDSPECIFIC] hardwarespecific function for setting
- * mtd->oobsize, mtd->writesize and so on.
- * @id_data contains the 8 bytes values of NAND_CMD_READID.
- * Return with the bus width.
* @dev_ready: [BOARDSPECIFIC] hardwarespecific function for accessing
* device ready/busy line. If set to NULL no access to
* ready/busy is available and the ready/busy information
@@ -659,6 +685,7 @@ struct nand_buffers {
*/
struct nand_chip {
+ struct mtd_info mtd;
void __iomem *IO_ADDR_R;
void __iomem *IO_ADDR_W;
@@ -668,11 +695,9 @@ struct nand_chip {
void (*write_buf)(struct mtd_info *mtd, const uint8_t *buf, int len);
void (*read_buf)(struct mtd_info *mtd, uint8_t *buf, int len);
void (*select_chip)(struct mtd_info *mtd, int chip);
- int (*block_bad)(struct mtd_info *mtd, loff_t ofs, int getchip);
+ int (*block_bad)(struct mtd_info *mtd, loff_t ofs);
int (*block_markbad)(struct mtd_info *mtd, loff_t ofs);
void (*cmd_ctrl)(struct mtd_info *mtd, int dat, unsigned int ctrl);
- int (*init_size)(struct mtd_info *mtd, struct nand_chip *this,
- u8 *id_data);
int (*dev_ready)(struct mtd_info *mtd);
void (*cmdfunc)(struct mtd_info *mtd, unsigned command, int column,
int page_addr);
@@ -739,6 +764,26 @@ struct nand_chip {
void *priv;
};
+static inline struct nand_chip *mtd_to_nand(struct mtd_info *mtd)
+{
+ return container_of(mtd, struct nand_chip, mtd);
+}
+
+static inline struct mtd_info *nand_to_mtd(struct nand_chip *chip)
+{
+ return &chip->mtd;
+}
+
+static inline void *nand_get_controller_data(struct nand_chip *chip)
+{
+ return chip->priv;
+}
+
+static inline void nand_set_controller_data(struct nand_chip *chip, void *priv)
+{
+ chip->priv = priv;
+}
+
/*
* NAND Flash Manufacturer ID Codes
*/
@@ -852,7 +897,6 @@ struct nand_manufacturers {
extern struct nand_flash_dev nand_flash_ids[];
extern struct nand_manufacturers nand_manuf_ids[];
-extern int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd);
extern int nand_default_bbt(struct mtd_info *mtd);
extern int nand_markbad_bbt(struct mtd_info *mtd, loff_t offs);
extern int nand_isreserved_bbt(struct mtd_info *mtd, loff_t offs);
@@ -877,7 +921,6 @@ extern int nand_do_read(struct mtd_info *mtd, loff_t from, size_t len,
* @chip_delay: R/B delay value in us
* @options: Option flags, e.g. 16bit buswidth
* @bbt_options: BBT option flags, e.g. NAND_BBT_USE_FLASH
- * @ecclayout: ECC layout info structure
* @part_probe_types: NULL-terminated array of probe types
*/
struct platform_nand_chip {
@@ -885,7 +928,6 @@ struct platform_nand_chip {
int chip_offset;
int nr_partitions;
struct mtd_partition *partitions;
- struct nand_ecclayout *ecclayout;
int chip_delay;
unsigned int options;
unsigned int bbt_options;
@@ -934,15 +976,6 @@ struct platform_nand_data {
struct platform_nand_ctrl ctrl;
};
-/* Some helpers to access the data structures */
-static inline
-struct platform_nand_chip *get_platform_nandchip(struct mtd_info *mtd)
-{
- struct nand_chip *chip = mtd->priv;
-
- return chip->priv;
-}
-
#ifdef CONFIG_SYS_NAND_ONFI_DETECTION
/* return the supported features. */
static inline int onfi_feature(struct nand_chip *chip)
@@ -1060,4 +1093,9 @@ struct nand_sdr_timings {
/* get timing characteristics from ONFI timing mode. */
const struct nand_sdr_timings *onfi_async_timing_mode_to_sdr_timings(int mode);
+
+int nand_check_erased_ecc_chunk(void *data, int datalen,
+ void *ecc, int ecclen,
+ void *extraoob, int extraooblen,
+ int threshold);
#endif /* __LINUX_MTD_NAND_H */
diff --git a/include/linux/mtd/nand_bch.h b/include/linux/mtd/nand_bch.h
index d8754dd8c8..8ea6b04cc3 100644
--- a/include/linux/mtd/nand_bch.h
+++ b/include/linux/mtd/nand_bch.h
@@ -32,9 +32,7 @@ int nand_bch_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc,
/*
* Initialize BCH encoder/decoder
*/
-struct nand_bch_control *
-nand_bch_init(struct mtd_info *mtd, unsigned int eccsize,
- unsigned int eccbytes, struct nand_ecclayout **ecclayout);
+struct nand_bch_control *nand_bch_init(struct mtd_info *mtd);
/*
* Release BCH encoder/decoder resources
*/
@@ -55,12 +53,10 @@ static inline int
nand_bch_correct_data(struct mtd_info *mtd, unsigned char *buf,
unsigned char *read_ecc, unsigned char *calc_ecc)
{
- return -1;
+ return -ENOTSUPP;
}
-static inline struct nand_bch_control *
-nand_bch_init(struct mtd_info *mtd, unsigned int eccsize,
- unsigned int eccbytes, struct nand_ecclayout **ecclayout)
+static inline struct nand_bch_control *nand_bch_init(struct mtd_info *mtd)
{
return NULL;
}
diff --git a/include/nand.h b/include/nand.h
index 7cbbbd327a..a4f0f9253d 100644
--- a/include/nand.h
+++ b/include/nand.h
@@ -33,34 +33,36 @@ extern void nand_init(void);
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
+int nand_mtd_to_devnum(struct mtd_info *mtd);
+
#ifdef CONFIG_SYS_NAND_SELF_INIT
void board_nand_init(void);
-int nand_register(int devnum);
+int nand_register(int devnum, struct mtd_info *mtd);
#else
extern int board_nand_init(struct nand_chip *nand);
#endif
-typedef struct mtd_info nand_info_t;
-
extern int nand_curr_device;
-extern nand_info_t nand_info[];
+extern struct mtd_info *nand_info[];
-static inline int nand_read(nand_info_t *info, loff_t ofs, size_t *len, u_char *buf)
+static inline int nand_read(struct mtd_info *info, loff_t ofs, size_t *len,
+ u_char *buf)
{
return mtd_read(info, ofs, *len, (size_t *)len, buf);
}
-static inline int nand_write(nand_info_t *info, loff_t ofs, size_t *len, u_char *buf)
+static inline int nand_write(struct mtd_info *info, loff_t ofs, size_t *len,
+ u_char *buf)
{
return mtd_write(info, ofs, *len, (size_t *)len, buf);
}
-static inline int nand_block_isbad(nand_info_t *info, loff_t ofs)
+static inline int nand_block_isbad(struct mtd_info *info, loff_t ofs)
{
return mtd_block_isbad(info, ofs);
}
-static inline int nand_erase(nand_info_t *info, loff_t off, size_t size)
+static inline int nand_erase(struct mtd_info *info, loff_t off, size_t size)
{
struct erase_info instr;
@@ -96,27 +98,28 @@ struct nand_erase_options {
typedef struct nand_erase_options nand_erase_options_t;
-int nand_read_skip_bad(nand_info_t *nand, loff_t offset, size_t *length,
+int nand_read_skip_bad(struct mtd_info *mtd, loff_t offset, size_t *length,
size_t *actual, loff_t lim, u_char *buffer);
#define WITH_DROP_FFS (1 << 0) /* drop trailing all-0xff pages */
#define WITH_WR_VERIFY (1 << 1) /* verify data was written correctly */
-int nand_write_skip_bad(nand_info_t *nand, loff_t offset, size_t *length,
+int nand_write_skip_bad(struct mtd_info *mtd, loff_t offset, size_t *length,
size_t *actual, loff_t lim, u_char *buffer, int flags);
-int nand_erase_opts(nand_info_t *meminfo, const nand_erase_options_t *opts);
-int nand_torture(nand_info_t *nand, loff_t offset);
-int nand_verify_page_oob(nand_info_t *nand, struct mtd_oob_ops *ops,
- loff_t ofs);
-int nand_verify(nand_info_t *nand, loff_t ofs, size_t len, u_char *buf);
+int nand_erase_opts(struct mtd_info *mtd,
+ const nand_erase_options_t *opts);
+int nand_torture(struct mtd_info *mtd, loff_t offset);
+int nand_verify_page_oob(struct mtd_info *mtd, struct mtd_oob_ops *ops,
+ loff_t ofs);
+int nand_verify(struct mtd_info *mtd, loff_t ofs, size_t len, u_char *buf);
#define NAND_LOCK_STATUS_TIGHT 0x01
#define NAND_LOCK_STATUS_UNLOCK 0x04
-int nand_lock(nand_info_t *meminfo, int tight);
-int nand_unlock(nand_info_t *meminfo, loff_t start, size_t length,
- int allexcept);
-int nand_get_lock_status(nand_info_t *meminfo, loff_t offset);
+int nand_lock(struct mtd_info *mtd, int tight);
+int nand_unlock(struct mtd_info *mtd, loff_t start, size_t length,
+ int allexcept);
+int nand_get_lock_status(struct mtd_info *mtd, loff_t offset);
int nand_spl_load_image(uint32_t offs, unsigned int size, void *dst);
void nand_deselect(void);
@@ -135,6 +138,6 @@ __attribute__((noreturn)) void nand_boot(void);
#define ENV_OOB_MARKER_OLD 0x30564e45 /*"ENV0" in little-endian -- offset is
stored as byte number */
#define ENV_OFFSET_SIZE 8
-int get_nand_env_oob(nand_info_t *nand, unsigned long *result);
+int get_nand_env_oob(struct mtd_info *mtd, unsigned long *result);
#endif
int spl_nand_erase_one(int block, int page);
diff --git a/tools/palmtreo680/flash_u-boot.c b/tools/palmtreo680/flash_u-boot.c
deleted file mode 100644
index 832d3fef7b..0000000000
--- a/tools/palmtreo680/flash_u-boot.c
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * Copyright (C) 2013 Mike Dunn <mikedunn@newsguy.com>
- *
- * This file is released under the terms of GPL v2 and any later version.
- * See the file COPYING in the root directory of the source tree for details.
- *
- *
- * This is a userspace Linux utility that, when run on the Treo 680, will
- * program u-boot to flash. The docg4 driver *must* be loaded with the
- * reliable_mode and ignore_badblocks parameters enabled:
- *
- * modprobe docg4 ignore_badblocks=1 reliable_mode=1
- *
- * This utility writes the concatenated spl + u-boot image to the start of the
- * mtd device in the format expected by the IPL/SPL. The image file and mtd
- * device node are passed to the utility as arguments. The blocks must have
- * been erased beforehand.
- *
- * When you compile this, note that it links to libmtd from mtd-utils, so ensure
- * that your include and lib paths include this.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <string.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include <errno.h>
-#include <mtd/mtd-user.h>
-#include "libmtd.h"
-
-#define RELIABLE_BLOCKSIZE 0x10000 /* block capacity in reliable mode */
-#define STANDARD_BLOCKSIZE 0x40000 /* block capacity in normal mode */
-#define PAGESIZE 512
-#define PAGES_PER_BLOCK 512
-#define OOBSIZE 7 /* available to user (16 total) */
-
-uint8_t ff_oob[OOBSIZE] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
-
-/* this is the magic number the IPL looks for (ASCII "BIPO") */
-uint8_t page0_oob[OOBSIZE] = {'B', 'I', 'P', 'O', 0xff, 0xff, 0xff};
-
-int main(int argc, char * const argv[])
-{
- int devfd, datafd, num_blocks, block;
- off_t file_size;
- libmtd_t mtd_desc;
- struct mtd_dev_info devinfo;
- uint8_t *blockbuf;
- char response[8];
-
- if (argc != 3) {
- printf("usage: %s <image file> <mtd dev node>\n", argv[0]);
- return -EINVAL;
- }
-
- mtd_desc = libmtd_open();
- if (mtd_desc == NULL) {
- int errsv = errno;
- fprintf(stderr, "can't initialize libmtd\n");
- return -errsv;
- }
-
- /* open the spl image file and mtd device */
- datafd = open(argv[1], O_RDONLY);
- if (datafd == -1) {
- int errsv = errno;
- perror(argv[1]);
- return -errsv;
- }
- devfd = open(argv[2], O_WRONLY);
- if (devfd == -1) {
- int errsv = errno;
- perror(argv[2]);
- return -errsv;
- }
- if (mtd_get_dev_info(mtd_desc, argv[2], &devinfo) < 0) {
- int errsv = errno;
- perror(argv[2]);
- return -errsv;
- }
-
- /* determine the number of blocks needed by the image */
- file_size = lseek(datafd, 0, SEEK_END);
- if (file_size == (off_t)-1) {
- int errsv = errno;
- perror("lseek");
- return -errsv;
- }
- num_blocks = (file_size + RELIABLE_BLOCKSIZE - 1) / RELIABLE_BLOCKSIZE;
- file_size = lseek(datafd, 0, SEEK_SET);
- if (file_size == (off_t)-1) {
- int errsv = errno;
- perror("lseek");
- return -errsv;
- }
- printf("The mtd partition contains %d blocks\n", devinfo.eb_cnt);
- printf("U-Boot will occupy %d blocks\n", num_blocks);
- if (num_blocks > devinfo.eb_cnt) {
- fprintf(stderr, "Insufficient blocks on partition\n");
- return -EINVAL;
- }
-
- printf("IMPORTANT: These blocks must be in an erased state!\n");
- printf("Do you want to proceed?\n");
- scanf("%s", response);
- if ((response[0] != 'y') && (response[0] != 'Y')) {
- printf("Exiting\n");
- close(devfd);
- close(datafd);
- return 0;
- }
-
- blockbuf = calloc(RELIABLE_BLOCKSIZE, 1);
- if (blockbuf == NULL) {
- int errsv = errno;
- perror("calloc");
- return -errsv;
- }
-
- for (block = 0; block < num_blocks; block++) {
- int ofs, page;
- uint8_t *pagebuf = blockbuf, *buf = blockbuf;
- uint8_t *oobbuf = page0_oob; /* magic num in oob of 1st page */
- size_t len = RELIABLE_BLOCKSIZE;
- int ret;
-
- /* read data for one block from file */
- while (len) {
- ssize_t read_ret = read(datafd, buf, len);
- if (read_ret == -1) {
- int errsv = errno;
- if (errno == EINTR)
- continue;
- perror("read");
- return -errsv;
- } else if (read_ret == 0) {
- break; /* EOF */
- }
- len -= read_ret;
- buf += read_ret;
- }
-
- printf("Block %d: writing\r", block + 1);
- fflush(stdout);
-
- for (page = 0, ofs = 0;
- page < PAGES_PER_BLOCK;
- page++, ofs += PAGESIZE) {
- if (page & 0x04) /* Odd-numbered 2k page */
- continue; /* skipped in reliable mode */
-
- ret = mtd_write(mtd_desc, &devinfo, devfd, block, ofs,
- pagebuf, PAGESIZE, oobbuf, OOBSIZE,
- MTD_OPS_PLACE_OOB);
- if (ret) {
- fprintf(stderr,
- "\nmtd_write returned %d on block %d, ofs %x\n",
- ret, block + 1, ofs);
- return -EIO;
- }
- oobbuf = ff_oob; /* oob for subsequent pages */
-
- if (page & 0x01) /* odd-numbered subpage */
- pagebuf += PAGESIZE;
- }
- }
-
- printf("\nDone\n");
-
- close(devfd);
- close(datafd);
- free(blockbuf);
- return 0;
-}
OpenPOWER on IntegriCloud