summaryrefslogtreecommitdiffstats
path: root/drivers/mtd
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd')
-rw-r--r--drivers/mtd/nand/fsl_elbc_nand.c98
-rw-r--r--drivers/mtd/nand/nand_util.c12
-rw-r--r--drivers/mtd/onenand/onenand_base.c185
-rw-r--r--drivers/mtd/onenand/onenand_bbt.c4
4 files changed, 178 insertions, 121 deletions
diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c
index 0bd1bdbcf0..674c542005 100644
--- a/drivers/mtd/nand/fsl_elbc_nand.c
+++ b/drivers/mtd/nand/fsl_elbc_nand.c
@@ -141,14 +141,14 @@ static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob)
if (priv->page_size) {
out_be32(&lbc->fbar, page_addr >> 6);
out_be32(&lbc->fpar,
- ((page_addr << FPAR_LP_PI_SHIFT) & FPAR_LP_PI) |
- (oob ? FPAR_LP_MS : 0) | column);
+ ((page_addr << FPAR_LP_PI_SHIFT) & FPAR_LP_PI) |
+ (oob ? FPAR_LP_MS : 0) | column);
buf_num = (page_addr & 1) << 2;
} else {
out_be32(&lbc->fbar, page_addr >> 5);
out_be32(&lbc->fpar,
- ((page_addr << FPAR_SP_PI_SHIFT) & FPAR_SP_PI) |
- (oob ? FPAR_SP_MS : 0) | column);
+ ((page_addr << FPAR_SP_PI_SHIFT) & FPAR_SP_PI) |
+ (oob ? FPAR_SP_MS : 0) | column);
buf_num = page_addr & 7;
}
@@ -227,24 +227,24 @@ static void fsl_elbc_do_read(struct nand_chip *chip, int oob)
if (priv->page_size) {
out_be32(&lbc->fir,
- (FIR_OP_CW0 << FIR_OP0_SHIFT) |
- (FIR_OP_CA << FIR_OP1_SHIFT) |
- (FIR_OP_PA << FIR_OP2_SHIFT) |
- (FIR_OP_CW1 << FIR_OP3_SHIFT) |
- (FIR_OP_RBW << FIR_OP4_SHIFT));
+ (FIR_OP_CW0 << FIR_OP0_SHIFT) |
+ (FIR_OP_CA << FIR_OP1_SHIFT) |
+ (FIR_OP_PA << FIR_OP2_SHIFT) |
+ (FIR_OP_CW1 << FIR_OP3_SHIFT) |
+ (FIR_OP_RBW << FIR_OP4_SHIFT));
out_be32(&lbc->fcr, (NAND_CMD_READ0 << FCR_CMD0_SHIFT) |
- (NAND_CMD_READSTART << FCR_CMD1_SHIFT));
+ (NAND_CMD_READSTART << FCR_CMD1_SHIFT));
} else {
out_be32(&lbc->fir,
- (FIR_OP_CW0 << FIR_OP0_SHIFT) |
- (FIR_OP_CA << FIR_OP1_SHIFT) |
- (FIR_OP_PA << FIR_OP2_SHIFT) |
- (FIR_OP_RBW << FIR_OP3_SHIFT));
+ (FIR_OP_CW0 << FIR_OP0_SHIFT) |
+ (FIR_OP_CA << FIR_OP1_SHIFT) |
+ (FIR_OP_PA << FIR_OP2_SHIFT) |
+ (FIR_OP_RBW << FIR_OP3_SHIFT));
if (oob)
out_be32(&lbc->fcr,
- NAND_CMD_READOOB << FCR_CMD0_SHIFT);
+ NAND_CMD_READOOB << FCR_CMD0_SHIFT);
else
out_be32(&lbc->fcr, NAND_CMD_READ0 << FCR_CMD0_SHIFT);
}
@@ -252,7 +252,7 @@ static void fsl_elbc_do_read(struct nand_chip *chip, int oob)
/* cmdfunc send commands to the FCM */
static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
- int column, int page_addr)
+ int column, int page_addr)
{
struct nand_chip *chip = mtd->priv;
struct fsl_elbc_mtd *priv = chip->priv;
@@ -306,8 +306,8 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
vdbg("fsl_elbc_cmdfunc: NAND_CMD_READID.\n");
out_be32(&lbc->fir, (FIR_OP_CW0 << FIR_OP0_SHIFT) |
- (FIR_OP_UA << FIR_OP1_SHIFT) |
- (FIR_OP_RBW << FIR_OP2_SHIFT));
+ (FIR_OP_UA << FIR_OP1_SHIFT) |
+ (FIR_OP_RBW << FIR_OP2_SHIFT));
out_be32(&lbc->fcr, NAND_CMD_READID << FCR_CMD0_SHIFT);
/* 5 bytes for manuf, device and exts */
out_be32(&lbc->fbcr, 5);
@@ -331,13 +331,13 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
vdbg("fsl_elbc_cmdfunc: NAND_CMD_ERASE2.\n");
out_be32(&lbc->fir,
- (FIR_OP_CW0 << FIR_OP0_SHIFT) |
- (FIR_OP_PA << FIR_OP1_SHIFT) |
- (FIR_OP_CM1 << FIR_OP2_SHIFT));
+ (FIR_OP_CW0 << FIR_OP0_SHIFT) |
+ (FIR_OP_PA << FIR_OP1_SHIFT) |
+ (FIR_OP_CM1 << FIR_OP2_SHIFT));
out_be32(&lbc->fcr,
- (NAND_CMD_ERASE1 << FCR_CMD0_SHIFT) |
- (NAND_CMD_ERASE2 << FCR_CMD1_SHIFT));
+ (NAND_CMD_ERASE1 << FCR_CMD0_SHIFT) |
+ (NAND_CMD_ERASE2 << FCR_CMD1_SHIFT));
out_be32(&lbc->fbcr, 0);
ctrl->read_bytes = 0;
@@ -360,22 +360,22 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
(NAND_CMD_PAGEPROG << FCR_CMD1_SHIFT);
out_be32(&lbc->fir,
- (FIR_OP_CW0 << FIR_OP0_SHIFT) |
- (FIR_OP_CA << FIR_OP1_SHIFT) |
- (FIR_OP_PA << FIR_OP2_SHIFT) |
- (FIR_OP_WB << FIR_OP3_SHIFT) |
- (FIR_OP_CW1 << FIR_OP4_SHIFT));
+ (FIR_OP_CW0 << FIR_OP0_SHIFT) |
+ (FIR_OP_CA << FIR_OP1_SHIFT) |
+ (FIR_OP_PA << FIR_OP2_SHIFT) |
+ (FIR_OP_WB << FIR_OP3_SHIFT) |
+ (FIR_OP_CW1 << FIR_OP4_SHIFT));
} else {
fcr = (NAND_CMD_PAGEPROG << FCR_CMD1_SHIFT) |
(NAND_CMD_SEQIN << FCR_CMD2_SHIFT);
out_be32(&lbc->fir,
- (FIR_OP_CW0 << FIR_OP0_SHIFT) |
- (FIR_OP_CM2 << FIR_OP1_SHIFT) |
- (FIR_OP_CA << FIR_OP2_SHIFT) |
- (FIR_OP_PA << FIR_OP3_SHIFT) |
- (FIR_OP_WB << FIR_OP4_SHIFT) |
- (FIR_OP_CW1 << FIR_OP5_SHIFT));
+ (FIR_OP_CW0 << FIR_OP0_SHIFT) |
+ (FIR_OP_CM2 << FIR_OP1_SHIFT) |
+ (FIR_OP_CA << FIR_OP2_SHIFT) |
+ (FIR_OP_PA << FIR_OP3_SHIFT) |
+ (FIR_OP_WB << FIR_OP4_SHIFT) |
+ (FIR_OP_CW1 << FIR_OP5_SHIFT));
if (column >= mtd->writesize) {
/* OOB area --> READOOB */
@@ -430,7 +430,7 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
fsl_elbc_run_command(mtd);
memcpy_fromio(ctrl->oob_poi + 6,
- &ctrl->addr[ctrl->index], 3);
+ &ctrl->addr[ctrl->index], 3);
ctrl->index += 3;
}
@@ -442,8 +442,8 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
/* Note - it does not wait for the ready line */
case NAND_CMD_STATUS:
out_be32(&lbc->fir,
- (FIR_OP_CM0 << FIR_OP0_SHIFT) |
- (FIR_OP_RBW << FIR_OP1_SHIFT));
+ (FIR_OP_CM0 << FIR_OP0_SHIFT) |
+ (FIR_OP_RBW << FIR_OP1_SHIFT));
out_be32(&lbc->fcr, NAND_CMD_STATUS << FCR_CMD0_SHIFT);
out_be32(&lbc->fbcr, 1);
set_addr(mtd, 0, 0, 0);
@@ -467,7 +467,7 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
default:
printf("fsl_elbc_cmdfunc: error, unsupported command 0x%x.\n",
- command);
+ command);
}
}
@@ -559,7 +559,7 @@ static void fsl_elbc_read_buf(struct mtd_info *mtd, u8 *buf, int len)
* Verify buffer against the FCM Controller Data Buffer
*/
static int fsl_elbc_verify_buf(struct mtd_info *mtd,
- const u_char *buf, int len)
+ const u_char *buf, int len)
{
struct nand_chip *chip = mtd->priv;
struct fsl_elbc_mtd *priv = chip->priv;
@@ -603,8 +603,8 @@ static int fsl_elbc_wait(struct mtd_info *mtd, struct nand_chip *chip)
/* Use READ_STATUS command, but wait for the device to be ready */
ctrl->use_mdr = 0;
out_be32(&lbc->fir,
- (FIR_OP_CW0 << FIR_OP0_SHIFT) |
- (FIR_OP_RBW << FIR_OP1_SHIFT));
+ (FIR_OP_CW0 << FIR_OP0_SHIFT) |
+ (FIR_OP_RBW << FIR_OP1_SHIFT));
out_be32(&lbc->fcr, NAND_CMD_STATUS << FCR_CMD0_SHIFT);
out_be32(&lbc->fbcr, 1);
set_addr(mtd, 0, 0, 0);
@@ -623,8 +623,8 @@ static int fsl_elbc_wait(struct mtd_info *mtd, struct nand_chip *chip)
}
static int fsl_elbc_read_page(struct mtd_info *mtd,
- struct nand_chip *chip,
- uint8_t *buf)
+ struct nand_chip *chip,
+ uint8_t *buf)
{
fsl_elbc_read_buf(mtd, buf, mtd->writesize);
fsl_elbc_read_buf(mtd, chip->oob_poi, mtd->oobsize);
@@ -639,8 +639,8 @@ static int fsl_elbc_read_page(struct mtd_info *mtd,
* waitfunc.
*/
static void fsl_elbc_write_page(struct mtd_info *mtd,
- struct nand_chip *chip,
- const uint8_t *buf)
+ struct nand_chip *chip,
+ const uint8_t *buf)
{
struct fsl_elbc_mtd *priv = chip->priv;
struct fsl_elbc_ctrl *ctrl = priv->ctrl;
@@ -737,8 +737,8 @@ int board_nand_init(struct nand_chip *nand)
nand->ecc.mode = NAND_ECC_HW;
nand->ecc.layout = (priv->fmr & FMR_ECCM) ?
- &fsl_elbc_oob_sp_eccm1 :
- &fsl_elbc_oob_sp_eccm0;
+ &fsl_elbc_oob_sp_eccm1 :
+ &fsl_elbc_oob_sp_eccm0;
nand->ecc.size = 512;
nand->ecc.bytes = 3;
@@ -758,8 +758,8 @@ int board_nand_init(struct nand_chip *nand)
if ((br & BR_DECC) == BR_DECC_CHK_GEN) {
nand->ecc.steps = 4;
nand->ecc.layout = (priv->fmr & FMR_ECCM) ?
- &fsl_elbc_oob_lp_eccm1 :
- &fsl_elbc_oob_lp_eccm0;
+ &fsl_elbc_oob_lp_eccm1 :
+ &fsl_elbc_oob_lp_eccm0;
}
}
diff --git a/drivers/mtd/nand/nand_util.c b/drivers/mtd/nand/nand_util.c
index 22820d55d0..52b3d21b8f 100644
--- a/drivers/mtd/nand/nand_util.c
+++ b/drivers/mtd/nand/nand_util.c
@@ -435,7 +435,7 @@ int nand_unlock(nand_info_t *meminfo, ulong start, ulong length)
* @return image length including bad blocks
*/
static size_t get_len_incl_bad (nand_info_t *nand, size_t offset,
- const size_t length)
+ const size_t length)
{
size_t len_incl_bad = 0;
size_t len_excl_bad = 0;
@@ -472,7 +472,7 @@ static size_t get_len_incl_bad (nand_info_t *nand, size_t offset,
* @return 0 in case of success
*/
int nand_write_skip_bad(nand_info_t *nand, size_t offset, size_t *length,
- u_char *buffer)
+ u_char *buffer)
{
int rval;
size_t left_to_write = *length;
@@ -497,7 +497,7 @@ int nand_write_skip_bad(nand_info_t *nand, size_t offset, size_t *length,
rval = nand_write (nand, offset, length, buffer);
if (rval != 0) {
printf ("NAND write to offset %x failed %d\n",
- offset, rval);
+ offset, rval);
return rval;
}
}
@@ -521,7 +521,7 @@ int nand_write_skip_bad(nand_info_t *nand, size_t offset, size_t *length,
rval = nand_write (nand, offset, &write_size, p_buffer);
if (rval != 0) {
printf ("NAND write to offset %x failed %d\n",
- offset, rval);
+ offset, rval);
*length -= left_to_write;
return rval;
}
@@ -567,7 +567,7 @@ int nand_read_skip_bad(nand_info_t *nand, size_t offset, size_t *length,
rval = nand_read (nand, offset, length, buffer);
if (rval != 0) {
printf ("NAND read from offset %x failed %d\n",
- offset, rval);
+ offset, rval);
return rval;
}
}
@@ -591,7 +591,7 @@ int nand_read_skip_bad(nand_info_t *nand, size_t offset, size_t *length,
rval = nand_read (nand, offset, &read_length, p_buffer);
if (rval != 0) {
printf ("NAND read from offset %x failed %d\n",
- offset, rval);
+ offset, rval);
*length -= left_to_read;
return rval;
}
diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c
index 7c9438be31..9ce68e1a47 100644
--- a/drivers/mtd/onenand/onenand_base.c
+++ b/drivers/mtd/onenand/onenand_base.c
@@ -292,13 +292,13 @@ static int onenand_wait(struct mtd_info *mtd, int state)
if (ctrl & ONENAND_CTRL_ERROR) {
MTDDEBUG (MTD_DEBUG_LEVEL0,
- "onenand_wait: controller error = 0x%04x\n", ctrl);
+ "onenand_wait: controller error = 0x%04x\n", ctrl);
return -EAGAIN;
}
if (ctrl & ONENAND_CTRL_LOCK) {
MTDDEBUG (MTD_DEBUG_LEVEL0,
- "onenand_wait: it's locked error = 0x%04x\n", ctrl);
+ "onenand_wait: it's locked error = 0x%04x\n", ctrl);
return -EIO;
}
@@ -306,7 +306,7 @@ static int onenand_wait(struct mtd_info *mtd, int state)
ecc = this->read_word(this->base + ONENAND_REG_ECC_STATUS);
if (ecc & ONENAND_ECC_2BIT_ALL) {
MTDDEBUG (MTD_DEBUG_LEVEL0,
- "onenand_wait: ECC error = 0x%04x\n", ecc);
+ "onenand_wait: ECC error = 0x%04x\n", ecc);
return -EBADMSG;
}
}
@@ -328,7 +328,7 @@ static inline int onenand_bufferram_offset(struct mtd_info *mtd, int area)
if (ONENAND_CURRENT_BUFFERRAM(this)) {
if (area == ONENAND_DATARAM)
- return mtd->oobblock;
+ return mtd->writesize;
if (area == ONENAND_SPARERAM)
return mtd->oobsize;
}
@@ -479,6 +479,30 @@ static int onenand_update_bufferram(struct mtd_info *mtd, loff_t addr,
}
/**
+ * onenand_invalidate_bufferram - [GENERIC] Invalidate BufferRAM information
+ * @param mtd MTD data structure
+ * @param addr start address to invalidate
+ * @param len length to invalidate
+ *
+ * Invalidate BufferRAM information
+ */
+static void onenand_invalidate_bufferram(struct mtd_info *mtd, loff_t addr,
+ unsigned int len)
+{
+ struct onenand_chip *this = mtd->priv;
+ int i;
+ loff_t end_addr = addr + len;
+
+ /* Invalidate BufferRAM */
+ for (i = 0; i < MAX_BUFFERRAM; i++) {
+ loff_t buf_addr = this->bufferram[i].block << this->erase_shift;
+
+ if (buf_addr >= addr && buf_addr < end_addr)
+ this->bufferram[i].valid = 0;
+ }
+}
+
+/**
* onenand_get_device - [GENERIC] Get chip for selected access
* @param mtd MTD device structure
* @param new_state the state which is requested
@@ -523,13 +547,13 @@ static int onenand_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
int ret = 0;
MTDDEBUG (MTD_DEBUG_LEVEL3, "onenand_read_ecc: "
- "from = 0x%08x, len = %i\n",
- (unsigned int)from, (int)len);
+ "from = 0x%08x, len = %i\n",
+ (unsigned int)from, (int)len);
/* Do not allow reads past end of device */
if ((from + len) > mtd->size) {
MTDDEBUG (MTD_DEBUG_LEVEL0, "onenand_read_ecc: "
- "Attempt read beyond end of device\n");
+ "Attempt read beyond end of device\n");
*retlen = 0;
return -EINVAL;
}
@@ -538,15 +562,15 @@ static int onenand_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
onenand_get_device(mtd, FL_READING);
while (read < len) {
- thislen = min_t(int, mtd->oobblock, len - read);
+ thislen = min_t(int, mtd->writesize, len - read);
- column = from & (mtd->oobblock - 1);
- if (column + thislen > mtd->oobblock)
- thislen = mtd->oobblock - column;
+ column = from & (mtd->writesize - 1);
+ if (column + thislen > mtd->writesize)
+ thislen = mtd->writesize - column;
if (!onenand_check_bufferram(mtd, from)) {
this->command(mtd, ONENAND_CMD_READ, from,
- mtd->oobblock);
+ mtd->writesize);
ret = this->wait(mtd, FL_READING);
/* First copy data and check return value for ECC handling */
onenand_update_bufferram(mtd, from, 1);
@@ -561,7 +585,7 @@ static int onenand_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
if (ret) {
MTDDEBUG (MTD_DEBUG_LEVEL0,
- "onenand_read_ecc: read failed = %d\n", ret);
+ "onenand_read_ecc: read failed = %d\n", ret);
break;
}
@@ -615,8 +639,8 @@ int onenand_read_oob(struct mtd_info *mtd, loff_t from, size_t len,
int ret = 0;
MTDDEBUG (MTD_DEBUG_LEVEL3, "onenand_read_oob: "
- "from = 0x%08x, len = %i\n",
- (unsigned int)from, (int)len);
+ "from = 0x%08x, len = %i\n",
+ (unsigned int)from, (int)len);
/* Initialize return length value */
*retlen = 0;
@@ -624,7 +648,7 @@ int onenand_read_oob(struct mtd_info *mtd, loff_t from, size_t len,
/* Do not allow reads past end of device */
if (unlikely((from + len) > mtd->size)) {
MTDDEBUG (MTD_DEBUG_LEVEL0, "onenand_read_oob: "
- "Attempt read beyond end of device\n");
+ "Attempt read beyond end of device\n");
return -EINVAL;
}
@@ -653,7 +677,7 @@ int onenand_read_oob(struct mtd_info *mtd, loff_t from, size_t len,
if (ret) {
MTDDEBUG (MTD_DEBUG_LEVEL0,
- "onenand_read_oob: read failed = %d\n", ret);
+ "onenand_read_oob: read failed = %d\n", ret);
break;
}
@@ -661,7 +685,7 @@ int onenand_read_oob(struct mtd_info *mtd, loff_t from, size_t len,
/* Read more? */
if (read < len) {
/* Page size */
- from += mtd->oobblock;
+ from += mtd->writesize;
column = 0;
}
}
@@ -688,7 +712,7 @@ static int onenand_verify_page(struct mtd_info *mtd, u_char * buf,
void __iomem *dataram0, *dataram1;
int ret = 0;
- this->command(mtd, ONENAND_CMD_READ, addr, mtd->oobblock);
+ this->command(mtd, ONENAND_CMD_READ, addr, mtd->writesize);
ret = this->wait(mtd, FL_READING);
if (ret)
@@ -698,9 +722,9 @@ static int onenand_verify_page(struct mtd_info *mtd, u_char * buf,
/* Check, if the two dataram areas are same */
dataram0 = this->base + ONENAND_DATARAM;
- dataram1 = dataram0 + mtd->oobblock;
+ dataram1 = dataram0 + mtd->writesize;
- if (memcmp(dataram0, dataram1, mtd->oobblock))
+ if (memcmp(dataram0, dataram1, mtd->writesize))
return -EBADMSG;
return 0;
@@ -709,7 +733,7 @@ static int onenand_verify_page(struct mtd_info *mtd, u_char * buf,
#define onenand_verify_page(...) (0)
#endif
-#define NOTALIGNED(x) ((x & (mtd->oobblock - 1)) != 0)
+#define NOTALIGNED(x) ((x & (mtd->writesize - 1)) != 0)
/**
* onenand_write_ecc - [MTD Interface] OneNAND write with ECC
@@ -732,8 +756,8 @@ static int onenand_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
int ret = 0;
MTDDEBUG (MTD_DEBUG_LEVEL3, "onenand_write_ecc: "
- "to = 0x%08x, len = %i\n",
- (unsigned int)to, (int)len);
+ "to = 0x%08x, len = %i\n",
+ (unsigned int)to, (int)len);
/* Initialize retlen, in case of early exit */
*retlen = 0;
@@ -741,14 +765,14 @@ static int onenand_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
/* Do not allow writes past end of device */
if (unlikely((to + len) > mtd->size)) {
MTDDEBUG (MTD_DEBUG_LEVEL0, "onenand_write_ecc: "
- "Attempt write to past end of device\n");
+ "Attempt write to past end of device\n");
return -EINVAL;
}
/* Reject writes, which are not page aligned */
if (unlikely(NOTALIGNED(to)) || unlikely(NOTALIGNED(len))) {
MTDDEBUG (MTD_DEBUG_LEVEL0, "onenand_write_ecc: "
- "Attempt to write not page aligned data\n");
+ "Attempt to write not page aligned data\n");
return -EINVAL;
}
@@ -757,22 +781,22 @@ static int onenand_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
/* Loop until all data write */
while (written < len) {
- int thislen = min_t(int, mtd->oobblock, len - written);
+ int thislen = min_t(int, mtd->writesize, len - written);
- this->command(mtd, ONENAND_CMD_BUFFERRAM, to, mtd->oobblock);
+ this->command(mtd, ONENAND_CMD_BUFFERRAM, to, mtd->writesize);
this->write_bufferram(mtd, ONENAND_DATARAM, buf, 0, thislen);
this->write_bufferram(mtd, ONENAND_SPARERAM, ffchars, 0,
mtd->oobsize);
- this->command(mtd, ONENAND_CMD_PROG, to, mtd->oobblock);
+ this->command(mtd, ONENAND_CMD_PROG, to, mtd->writesize);
onenand_update_bufferram(mtd, to, 1);
ret = this->wait(mtd, FL_WRITING);
if (ret) {
MTDDEBUG (MTD_DEBUG_LEVEL0,
- "onenand_write_ecc: write filaed %d\n", ret);
+ "onenand_write_ecc: write filaed %d\n", ret);
break;
}
@@ -782,7 +806,7 @@ static int onenand_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
ret = onenand_verify_page(mtd, (u_char *) buf, to);
if (ret) {
MTDDEBUG (MTD_DEBUG_LEVEL0,
- "onenand_write_ecc: verify failed %d\n", ret);
+ "onenand_write_ecc: verify failed %d\n", ret);
break;
}
@@ -836,8 +860,8 @@ int onenand_write_oob(struct mtd_info *mtd, loff_t to, size_t len,
int written = 0;
MTDDEBUG (MTD_DEBUG_LEVEL3, "onenand_write_oob: "
- "to = 0x%08x, len = %i\n",
- (unsigned int)to, (int)len);
+ "to = 0x%08x, len = %i\n",
+ (unsigned int)to, (int)len);
/* Initialize retlen, in case of early exit */
*retlen = 0;
@@ -845,7 +869,7 @@ int onenand_write_oob(struct mtd_info *mtd, loff_t to, size_t len,
/* Do not allow writes past end of device */
if (unlikely((to + len) > mtd->size)) {
MTDDEBUG (MTD_DEBUG_LEVEL0, "onenand_write_oob: "
- "Attempt write to past end of device\n");
+ "Attempt write to past end of device\n");
return -EINVAL;
}
@@ -890,6 +914,25 @@ int onenand_write_oob(struct mtd_info *mtd, loff_t to, size_t len,
}
/**
+ * onenand_block_isbad_nolock - [GENERIC] Check if a block is marked bad
+ * @param mtd MTD device structure
+ * @param ofs offset from device start
+ * @param 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 onenand_block_isbad_nolock(struct mtd_info *mtd, loff_t ofs, int allowbbt)
+{
+ struct onenand_chip *this = mtd->priv;
+ struct bbm_info *bbm = this->bbm;
+
+ /* Return info from the table */
+ return bbm->isbad_bbt(mtd, ofs, allowbbt);
+}
+
+
+/**
* onenand_erase - [MTD Interface] erase block(s)
* @param mtd MTD device structure
* @param instr erase instruction
@@ -905,28 +948,28 @@ int onenand_erase(struct mtd_info *mtd, struct erase_info *instr)
int ret = 0;
MTDDEBUG (MTD_DEBUG_LEVEL3, "onenand_erase: start = 0x%08x, len = %i\n",
- (unsigned int)instr->addr, (unsigned int)instr->len);
+ (unsigned int)instr->addr, (unsigned int)instr->len);
block_size = (1 << this->erase_shift);
/* Start address must align on block boundary */
if (unlikely(instr->addr & (block_size - 1))) {
MTDDEBUG (MTD_DEBUG_LEVEL0,
- "onenand_erase: Unaligned address\n");
+ "onenand_erase: Unaligned address\n");
return -EINVAL;
}
/* Length must align on block boundary */
if (unlikely(instr->len & (block_size - 1))) {
MTDDEBUG (MTD_DEBUG_LEVEL0,
- "onenand_erase: Length not block aligned\n");
+ "onenand_erase: Length not block aligned\n");
return -EINVAL;
}
/* Do not allow erase past end of device */
if (unlikely((instr->len + instr->addr) > mtd->size)) {
MTDDEBUG (MTD_DEBUG_LEVEL0,
- "onenand_erase: Erase past end of device\n");
+ "onenand_erase: Erase past end of device\n");
return -EINVAL;
}
@@ -947,16 +990,18 @@ int onenand_erase(struct mtd_info *mtd, struct erase_info *instr)
this->command(mtd, ONENAND_CMD_ERASE, addr, block_size);
+ onenand_invalidate_bufferram(mtd, addr, block_size);
+
ret = this->wait(mtd, FL_ERASING);
/* Check, if it is write protected */
if (ret) {
if (ret == -EPERM)
MTDDEBUG (MTD_DEBUG_LEVEL0, "onenand_erase: "
- "Device is write protected!!!\n");
+ "Device is write protected!!!\n");
else
MTDDEBUG (MTD_DEBUG_LEVEL0, "onenand_erase: "
- "Failed erase, block %d\n",
- (unsigned)(addr >> this->erase_shift));
+ "Failed erase, block %d\n",
+ (unsigned)(addr >> this->erase_shift));
instr->state = MTD_ERASE_FAILED;
instr->fail_addr = addr;
goto erase_exit;
@@ -1002,30 +1047,45 @@ void onenand_sync(struct mtd_info *mtd)
* onenand_block_isbad - [MTD Interface] Check whether the block at the given offset is bad
* @param mtd MTD device structure
* @param ofs offset relative to mtd start
+ *
+ * Check whether the block is bad
*/
int onenand_block_isbad(struct mtd_info *mtd, loff_t ofs)
{
- /*
- * TODO
- * 1. Bad block table (BBT)
- * -> using NAND BBT to support JFFS2
- * 2. Bad block management (BBM)
- * -> bad block replace scheme
- *
- * Currently we do nothing
- */
- return 0;
+ int ret;
+
+ /* Check for invalid offset */
+ if (ofs > mtd->size)
+ return -EINVAL;
+
+ onenand_get_device(mtd, FL_READING);
+ ret = onenand_block_isbad_nolock(mtd,ofs, 0);
+ onenand_release_device(mtd);
+ return ret;
}
/**
* onenand_block_markbad - [MTD Interface] Mark the block at the given offset as bad
* @param mtd MTD device structure
* @param ofs offset relative to mtd start
+ *
+ * Mark the block as bad
*/
int onenand_block_markbad(struct mtd_info *mtd, loff_t ofs)
{
- /* see above */
- return 0;
+ struct onenand_chip *this = mtd->priv;
+ int ret;
+
+ ret = onenand_block_isbad(mtd, ofs);
+ if (ret) {
+ /* If it was bad already, return success and do nothing */
+ if (ret > 0)
+ return 0;
+ return ret;
+ }
+
+ ret = this->block_markbad(mtd, ofs);
+ return ret;
}
/**
@@ -1181,10 +1241,8 @@ static int onenand_probe(struct mtd_info *mtd)
/* Reset OneNAND to read default register values */
this->write_word(ONENAND_CMD_RESET, this->base + ONENAND_BOOTRAM);
- {
- int i;
- for (i = 0; i < 10000; i++) ;
- }
+ /* Wait reset */
+ this->wait(mtd, FL_RESETING);
/* Read manufacturer and device IDs from Register */
maf_id = this->read_word(this->base + ONENAND_REG_MANUFACTURER_ID);
@@ -1209,16 +1267,16 @@ static int onenand_probe(struct mtd_info *mtd)
/* OneNAND page size & block size */
/* The data buffer size is equal to page size */
- mtd->oobblock =
+ mtd->writesize =
this->read_word(this->base + ONENAND_REG_DATA_BUFFER_SIZE);
- mtd->oobsize = mtd->oobblock >> 5;
+ mtd->oobsize = mtd->writesize >> 5;
/* Pagers per block is always 64 in OneNAND */
- mtd->erasesize = mtd->oobblock << 6;
+ mtd->erasesize = mtd->writesize << 6;
this->erase_shift = ffs(mtd->erasesize) - 1;
- this->page_shift = ffs(mtd->oobblock) - 1;
+ this->page_shift = ffs(mtd->writesize) - 1;
this->ppb_shift = (this->erase_shift - this->page_shift);
- this->page_mask = (mtd->erasesize / mtd->oobblock) - 1;
+ this->page_mask = (mtd->erasesize / mtd->writesize) - 1;
/* REVIST: Multichip handling */
@@ -1237,11 +1295,10 @@ static int onenand_probe(struct mtd_info *mtd)
this->options |= ONENAND_CONT_LOCK;
}
+ mtd->flags = MTD_CAP_NANDFLASH;
mtd->erase = onenand_erase;
mtd->read = onenand_read;
mtd->write = onenand_write;
- mtd->read_ecc = onenand_read_ecc;
- mtd->write_ecc = onenand_write_ecc;
mtd->read_oob = onenand_read_oob;
mtd->write_oob = onenand_write_oob;
mtd->sync = onenand_sync;
diff --git a/drivers/mtd/onenand/onenand_bbt.c b/drivers/mtd/onenand/onenand_bbt.c
index 0abaa1ab38..d13d2777e2 100644
--- a/drivers/mtd/onenand/onenand_bbt.c
+++ b/drivers/mtd/onenand/onenand_bbt.c
@@ -94,7 +94,7 @@ static int create_bbt(struct mtd_info *mtd, uint8_t * buf,
/* No need to read pages fully,
* just read required OOB bytes */
ret = onenand_read_oob(mtd,
- from + j * mtd->oobblock +
+ from + j * mtd->writesize +
bd->offs, readlen, &retlen,
&buf[0]);
@@ -104,7 +104,7 @@ static int create_bbt(struct mtd_info *mtd, uint8_t * buf,
}
if (check_short_pattern
- (&buf[j * scanlen], scanlen, mtd->oobblock, bd)) {
+ (&buf[j * scanlen], scanlen, mtd->writesize, bd)) {
bbm->bbt[i >> 3] |= 0x03 << (i & 0x6);
printk(KERN_WARNING
"Bad eraseblock %d at 0x%08x\n", i >> 1,
OpenPOWER on IntegriCloud