diff options
-rw-r--r-- | drivers/mtd/nand/pxa3xx_nand.c | 182 |
1 files changed, 172 insertions, 10 deletions
diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index c17c28594a29..72dce4546451 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c @@ -103,6 +103,8 @@ #define NDCB0_ST_ROW_EN (0x1 << 26) #define NDCB0_AUTO_RS (0x1 << 25) #define NDCB0_CSEL (0x1 << 24) +#define NDCB0_EXT_CMD_TYPE_MASK (0x7 << 29) +#define NDCB0_EXT_CMD_TYPE(x) (((x) << 29) & NDCB0_EXT_CMD_TYPE_MASK) #define NDCB0_CMD_TYPE_MASK (0x7 << 21) #define NDCB0_CMD_TYPE(x) (((x) << 21) & NDCB0_CMD_TYPE_MASK) #define NDCB0_NC (0x1 << 20) @@ -113,6 +115,14 @@ #define NDCB0_CMD1_MASK (0xff) #define NDCB0_ADDR_CYC_SHIFT (16) +#define EXT_CMD_TYPE_DISPATCH 6 /* Command dispatch */ +#define EXT_CMD_TYPE_NAKED_RW 5 /* Naked read or Naked write */ +#define EXT_CMD_TYPE_READ 4 /* Read */ +#define EXT_CMD_TYPE_DISP_WR 4 /* Command dispatch with write */ +#define EXT_CMD_TYPE_FINAL 3 /* Final command */ +#define EXT_CMD_TYPE_LAST_RW 1 /* Last naked read/write */ +#define EXT_CMD_TYPE_MONO 0 /* Monolithic read/write */ + /* macros for registers read/write */ #define nand_writel(info, off, val) \ __raw_writel((val), (info)->mmio_base + (off)) @@ -206,8 +216,8 @@ struct pxa3xx_nand_info { int use_spare; /* use spare ? */ int need_wait; - unsigned int fifo_size; /* max. data size in the FIFO */ unsigned int data_size; /* data to be read from FIFO */ + unsigned int chunk_size; /* split commands chunk size */ unsigned int oob_size; unsigned int spare_size; unsigned int ecc_size; @@ -271,6 +281,31 @@ static struct nand_bbt_descr bbt_mirror_descr = { .pattern = bbt_mirror_pattern }; +static struct nand_ecclayout ecc_layout_4KB_bch4bit = { + .eccbytes = 64, + .eccpos = { + 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, + 96, 97, 98, 99, 100, 101, 102, 103, + 104, 105, 106, 107, 108, 109, 110, 111, + 112, 113, 114, 115, 116, 117, 118, 119, + 120, 121, 122, 123, 124, 125, 126, 127}, + /* Bootrom looks in bytes 0 & 5 for bad blocks */ + .oobfree = { {6, 26}, { 64, 32} } +}; + +static struct nand_ecclayout ecc_layout_4KB_bch8bit = { + .eccbytes = 128, + .eccpos = { + 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}, + .oobfree = { } +}; + /* Define a default flash type setting serve as flash detecting only */ #define DEFAULT_FLASH_TYPE (&builtin_flash_types[0]) @@ -429,7 +464,7 @@ static void disable_int(struct pxa3xx_nand_info *info, uint32_t int_mask) static void handle_data_pio(struct pxa3xx_nand_info *info) { - unsigned int do_bytes = min(info->data_size, info->fifo_size); + unsigned int do_bytes = min(info->data_size, info->chunk_size); switch (info->state) { case STATE_PIO_WRITING: @@ -666,7 +701,7 @@ static void prepare_start_command(struct pxa3xx_nand_info *info, int command) } static int prepare_set_command(struct pxa3xx_nand_info *info, int command, - uint16_t column, int page_addr) + int ext_cmd_type, uint16_t column, int page_addr) { int addr_cycle, exec_cmd; struct pxa3xx_nand_host *host; @@ -699,9 +734,20 @@ static int prepare_set_command(struct pxa3xx_nand_info *info, int command, if (command == NAND_CMD_READOOB) info->buf_start += mtd->writesize; - /* Second command setting for large pages */ - if (mtd->writesize >= PAGE_CHUNK_SIZE) + /* + * Multiple page read needs an 'extended command type' field, + * which is either naked-read or last-read according to the + * state. + */ + if (mtd->writesize == PAGE_CHUNK_SIZE) { info->ndcb0 |= NDCB0_DBC | (NAND_CMD_READSTART << 8); + } else if (mtd->writesize > PAGE_CHUNK_SIZE) { + info->ndcb0 |= NDCB0_DBC | (NAND_CMD_READSTART << 8) + | NDCB0_LEN_OVRD + | NDCB0_EXT_CMD_TYPE(ext_cmd_type); + info->ndcb3 = info->chunk_size + + info->oob_size; + } set_command_address(info, mtd->writesize, column, page_addr); break; @@ -817,7 +863,8 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command, prepare_start_command(info, command); info->state = STATE_PREPARED; - exec_cmd = prepare_set_command(info, command, column, page_addr); + exec_cmd = prepare_set_command(info, command, 0, column, page_addr); + if (exec_cmd) { init_completion(&info->cmd_complete); init_completion(&info->dev_ready); @@ -835,6 +882,93 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command, info->state = STATE_IDLE; } +static void armada370_nand_cmdfunc(struct mtd_info *mtd, + const unsigned command, + int column, int page_addr) +{ + struct pxa3xx_nand_host *host = mtd->priv; + struct pxa3xx_nand_info *info = host->info_data; + int ret, exec_cmd, ext_cmd_type; + + /* + * if this is a x16 device then convert the input + * "byte" address into a "word" address appropriate + * for indexing a word-oriented device + */ + if (info->reg_ndcr & NDCR_DWIDTH_M) + column /= 2; + + /* + * There may be different NAND chip hooked to + * different chip select, so check whether + * chip select has been changed, if yes, reset the timing + */ + if (info->cs != host->cs) { + info->cs = host->cs; + nand_writel(info, NDTR0CS0, info->ndtr0cs0); + nand_writel(info, NDTR1CS0, info->ndtr1cs0); + } + + /* Select the extended command for the first command */ + switch (command) { + case NAND_CMD_READ0: + case NAND_CMD_READOOB: + ext_cmd_type = EXT_CMD_TYPE_MONO; + break; + default: + ext_cmd_type = 0; + } + + prepare_start_command(info, command); + + /* + * Prepare the "is ready" completion before starting a command + * transaction sequence. If the command is not executed the + * completion will be completed, see below. + * + * We can do that inside the loop because the command variable + * is invariant and thus so is the exec_cmd. + */ + info->need_wait = 1; + init_completion(&info->dev_ready); + do { + info->state = STATE_PREPARED; + exec_cmd = prepare_set_command(info, command, ext_cmd_type, + column, page_addr); + if (!exec_cmd) { + info->need_wait = 0; + complete(&info->dev_ready); + break; + } + + init_completion(&info->cmd_complete); + pxa3xx_nand_start(info); + + ret = wait_for_completion_timeout(&info->cmd_complete, + CHIP_DELAY_TIMEOUT); + if (!ret) { + dev_err(&info->pdev->dev, "Wait time out!!!\n"); + /* Stop State Machine for next command cycle */ + pxa3xx_nand_stop(info); + break; + } + + /* Check if the sequence is complete */ + if (info->data_size == 0) + break; + + if (command == NAND_CMD_READ0 || command == NAND_CMD_READOOB) { + /* Last read: issue a 'last naked read' */ + if (info->data_size == info->chunk_size) + ext_cmd_type = EXT_CMD_TYPE_LAST_RW; + else + ext_cmd_type = EXT_CMD_TYPE_NAKED_RW; + } + } while (1); + + info->state = STATE_IDLE; +} + static int pxa3xx_nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, const uint8_t *buf, int oob_required) { @@ -1015,13 +1149,14 @@ static int pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info) if (ndcr & NDCR_PAGE_SZ) { /* Controller's FIFO size */ - info->fifo_size = 2048; + info->chunk_size = 2048; host->read_id_bytes = 4; } else { - info->fifo_size = 512; + info->chunk_size = 512; host->read_id_bytes = 2; } + /* Set an initial chunk size */ info->reg_ndcr = ndcr & ~NDCR_INT_MASK; info->ndtr0cs0 = nand_readl(info, NDTR0CS0); info->ndtr1cs0 = nand_readl(info, NDTR1CS0); @@ -1125,6 +1260,7 @@ static int pxa_ecc_init(struct pxa3xx_nand_info *info, * is used with non-ONFI compliant devices. */ if (page_size == 2048) { + info->chunk_size = 2048; info->spare_size = 40; info->ecc_size = 24; ecc->mode = NAND_ECC_HW; @@ -1133,6 +1269,7 @@ static int pxa_ecc_init(struct pxa3xx_nand_info *info, return 1; } else if (page_size == 512) { + info->chunk_size = 512; info->spare_size = 8; info->ecc_size = 8; ecc->mode = NAND_ECC_HW; @@ -1147,7 +1284,28 @@ static int armada370_ecc_init(struct pxa3xx_nand_info *info, struct nand_ecc_ctrl *ecc, int strength, int page_size) { - /* Unimplemented yet */ + if (strength == 4 && page_size == 4096) { + info->ecc_bch = 1; + info->chunk_size = 2048; + info->spare_size = 32; + info->ecc_size = 32; + ecc->mode = NAND_ECC_HW; + ecc->size = info->chunk_size; + ecc->layout = &ecc_layout_4KB_bch4bit; + ecc->strength = 16; + return 1; + + } else if (strength == 8 && page_size == 4096) { + info->ecc_bch = 1; + info->chunk_size = 1024; + info->spare_size = 0; + info->ecc_size = 32; + ecc->mode = NAND_ECC_HW; + ecc->size = info->chunk_size; + ecc->layout = &ecc_layout_4KB_bch8bit; + ecc->strength = 16; + return 1; + } return 0; } @@ -1315,12 +1473,16 @@ static int alloc_nand_resource(struct platform_device *pdev) chip->controller = &info->controller; chip->waitfunc = pxa3xx_nand_waitfunc; chip->select_chip = pxa3xx_nand_select_chip; - chip->cmdfunc = pxa3xx_nand_cmdfunc; chip->read_word = pxa3xx_nand_read_word; chip->read_byte = pxa3xx_nand_read_byte; chip->read_buf = pxa3xx_nand_read_buf; chip->write_buf = pxa3xx_nand_write_buf; chip->options |= NAND_NO_SUBPAGE_WRITE; + + if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370) + chip->cmdfunc = armada370_nand_cmdfunc; + else + chip->cmdfunc = pxa3xx_nand_cmdfunc; } spin_lock_init(&chip->controller->lock); |