summaryrefslogtreecommitdiffstats
path: root/drivers/mtd
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 /drivers/mtd
parentc41c649c2fdec7bf6ef84173597cc3feabdb7828 (diff)
parent667067faa18334f1e28c01b47530b5cce1b6182f (diff)
downloadblackbird-obmc-uboot-715b3a9b2486e8d7a32365d817c77209b35ee796.tar.gz
blackbird-obmc-uboot-715b3a9b2486e8d7a32365d817c77209b35ee796.zip
Merge git://git.denx.de/u-boot-nand-flash
Diffstat (limited to 'drivers/mtd')
-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
38 files changed, 876 insertions, 2247 deletions
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;
OpenPOWER on IntegriCloud