summaryrefslogtreecommitdiffstats
path: root/drivers/mtd/nand/nand_denali.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd/nand/nand_denali.c')
-rw-r--r--drivers/mtd/nand/nand_denali.c67
1 files changed, 29 insertions, 38 deletions
diff --git a/drivers/mtd/nand/nand_denali.c b/drivers/mtd/nand/nand_denali.c
index bffcbd8a7f..49028bf082 100644
--- a/drivers/mtd/nand/nand_denali.c
+++ b/drivers/mtd/nand/nand_denali.c
@@ -23,6 +23,7 @@
#include <malloc.h>
#include <init.h>
#include <linux/mtd/mtd.h>
+#include <linux/mtd/rawnand.h>
#include <linux/mtd/nand.h>
#include <io.h>
#include <clock.h>
@@ -888,6 +889,8 @@ static bool is_erased(uint8_t *buf, int len)
static bool handle_ecc(struct denali_nand_info *denali, uint8_t *buf,
uint32_t irq_status, unsigned int *max_bitflips)
{
+ struct nand_chip *chip = &denali->nand;
+ struct mtd_info *mtd = nand_to_mtd(chip);
bool check_erased_page = false;
unsigned int bitflips = 0;
@@ -933,7 +936,7 @@ static bool handle_ecc(struct denali_nand_info *denali, uint8_t *buf,
err_device;
/* correct the ECC error */
buf[offset] ^= err_correction_value;
- denali->nand.mtd.ecc_stats.corrected++;
+ mtd->ecc_stats.corrected++;
bitflips++;
}
} else {
@@ -995,7 +998,8 @@ static void denali_setup_dma(struct denali_nand_info *denali, int op)
* writes a page. user specifies type, and this function handles the
* configuration details.
*/
-static int write_page(struct nand_chip *chip, const uint8_t *buf, bool raw_xfer)
+static int write_page(struct nand_chip *chip, const uint8_t *buf, bool raw_xfer,
+ int page)
{
struct mtd_info *mtd = nand_to_mtd(chip);
struct denali_nand_info *denali = nand_to_denali(chip);
@@ -1012,6 +1016,8 @@ static int write_page(struct nand_chip *chip, const uint8_t *buf, bool raw_xfer)
*/
setup_ecc_for_xfer(denali, !raw_xfer, raw_xfer);
+ nand_prog_page_begin_op(chip, page, 0, NULL, 0);
+
/* copy buffer into DMA buffer */
memcpy(denali->buf.buf, buf, mtd->writesize);
@@ -1041,7 +1047,7 @@ static int write_page(struct nand_chip *chip, const uint8_t *buf, bool raw_xfer)
denali_enable_dma(denali, false);
dma_sync_single_for_cpu(addr, size, DMA_TO_DEVICE);
- return 0;
+ return nand_prog_page_end_op(chip);
}
/* NAND core entry points */
@@ -1052,13 +1058,13 @@ static int write_page(struct nand_chip *chip, const uint8_t *buf, bool raw_xfer)
* by write_page above.
*/
static int denali_write_page(struct nand_chip *chip,
- const uint8_t *buf, int oob_required)
+ const uint8_t *buf, int oob_required, int page)
{
/*
* for regular page writes, we let HW handle all the ECC
* data written to the device.
*/
- return write_page(chip, buf, false);
+ return write_page(chip, buf, false, page);
}
/*
@@ -1067,13 +1073,13 @@ static int denali_write_page(struct nand_chip *chip,
* write_page() function above.
*/
static int denali_write_page_raw(struct nand_chip *chip,
- const uint8_t *buf, int oob_required)
+ const uint8_t *buf, int oob_required, int page)
{
/*
* for raw page writes, we want to disable ECC and simply write
* whatever data is in the buffer.
*/
- return write_page(chip, buf, true);
+ return write_page(chip, buf, true, page);
}
static int denali_write_oob(struct nand_chip *chip, int page)
@@ -1104,15 +1110,10 @@ static int denali_read_page(struct nand_chip *chip,
(INTR_STATUS__ECC_TRANSACTION_DONE | INTR_STATUS__ECC_ERR);
bool check_erased_page = false;
- if (page != denali->page) {
- dev_err(denali->dev,
- "IN %s: page %d is not equal to denali->page %d",
- __func__, page, denali->page);
- BUG();
- }
-
setup_ecc_for_xfer(denali, true, false);
+ nand_read_page_op(chip, page, 0, NULL, 0);
+
denali_enable_dma(denali, true);
dma_sync_single_for_device(addr, size, DMA_FROM_DEVICE);
@@ -1161,6 +1162,8 @@ static int denali_read_page_raw(struct nand_chip *chip,
size_t size = mtd->writesize + mtd->oobsize;
uint32_t irq_mask = INTR_STATUS__DMA_CMD_COMP;
+ nand_read_page_op(chip, page, 0, NULL, 0);
+
if (page != denali->page) {
dev_err(denali->dev,
"IN %s: page %d is not equal to denali->page %d",
@@ -1227,11 +1230,8 @@ static int denali_waitfunc(struct nand_chip *chip)
static void denali_cmdfunc(struct nand_chip *chip, unsigned int cmd, int col,
int page)
{
- struct mtd_info *mtd = nand_to_mtd(chip);
struct denali_nand_info *denali = nand_to_denali(chip);
uint32_t addr, id;
- uint32_t pages_per_block;
- uint32_t block;
int i;
switch (cmd) {
@@ -1296,18 +1296,6 @@ static void denali_cmdfunc(struct nand_chip *chip, unsigned int cmd, int col,
case NAND_CMD_READOOB:
/* TODO: Read OOB data */
break;
- case NAND_CMD_UNLOCK1:
- pages_per_block = mtd->erasesize / mtd->writesize;
- block = page / pages_per_block;
- addr = (uint32_t)MODE_10 | (block * pages_per_block);
- index_addr(denali, addr, 0x10);
- break;
- case NAND_CMD_UNLOCK2:
- pages_per_block = mtd->erasesize / mtd->writesize;
- block = (page+pages_per_block-1) / pages_per_block;
- addr = (uint32_t)MODE_10 | (block * pages_per_block);
- index_addr(denali, addr, 0x11);
- break;
case NAND_CMD_ERASE1:
case NAND_CMD_ERASE2:
addr = MODE_10 | BANK(denali->flash_bank) | page;
@@ -1376,9 +1364,10 @@ static void denali_drv_init(struct denali_nand_info *denali)
int denali_init(struct denali_nand_info *denali)
{
struct nand_chip *nand = &denali->nand;
- struct mtd_info *mtd = &nand->mtd;
+ struct mtd_info *mtd = nand_to_mtd(nand);
int ret = 0;
uint32_t val;
+ struct nand_ecclayout *ecclayout;
if (denali->platform == INTEL_CE4100) {
/*
@@ -1477,7 +1466,7 @@ int denali_init(struct denali_nand_info *denali)
ECC_SECTOR_SIZE)))) {
/* if MLC OOB size is large enough, use 15bit ECC*/
nand->ecc.strength = 15;
- nand->ecc.layout = &nand_15bit_oob;
+ ecclayout = &nand_15bit_oob;
nand->ecc.bytes = ECC_15BITS;
iowrite32(15, denali->flash_reg + ECC_CORRECTION);
} else if (mtd->oobsize < (denali->bbtskipbytes +
@@ -1487,24 +1476,26 @@ int denali_init(struct denali_nand_info *denali)
goto failed_req_irq;
} else {
nand->ecc.strength = 8;
- nand->ecc.layout = &nand_8bit_oob;
+ ecclayout = &nand_8bit_oob;
nand->ecc.bytes = ECC_8BITS;
iowrite32(8, denali->flash_reg + ECC_CORRECTION);
}
- nand->ecc.layout->oobfree[0].offset =
- denali->bbtskipbytes + nand->ecc.layout->eccbytes;
- nand->ecc.layout->oobfree[0].length =
- mtd->oobsize - nand->ecc.layout->eccbytes -
+ ecclayout->oobfree[0].offset =
+ denali->bbtskipbytes + ecclayout->eccbytes;
+ ecclayout->oobfree[0].length =
+ mtd->oobsize - ecclayout->eccbytes -
denali->bbtskipbytes;
+ mtd_set_ecclayout(mtd, ecclayout);
+
/*
* Let driver know the total blocks number and how many blocks
* contained by each nand chip. blksperchip will help driver to
* know how many blocks is taken by FW.
*/
denali->totalblks = mtd->size >> nand->phys_erase_shift;
- denali->blksperchip = denali->totalblks / nand->numchips;
+ denali->blksperchip = denali->totalblks;
/* override the default read operations */
nand->ecc.size = ECC_SECTOR_SIZE;
@@ -1534,7 +1525,7 @@ int denali_init(struct denali_nand_info *denali)
goto failed_req_irq;
}
- return add_mtd_nand_device(nand, "nand");
+ return add_mtd_nand_device(mtd, "nand");
failed_req_irq:
denali_irq_cleanup(denali->irq, denali);