aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/mtd/nand/raw/fsmc_nand.c150
1 files changed, 99 insertions, 51 deletions
diff --git a/drivers/mtd/nand/raw/fsmc_nand.c b/drivers/mtd/nand/raw/fsmc_nand.c
index 75a825dc5a4c..28c48dcc514e 100644
--- a/drivers/mtd/nand/raw/fsmc_nand.c
+++ b/drivers/mtd/nand/raw/fsmc_nand.c
@@ -254,43 +254,6 @@ static inline struct fsmc_nand_data *mtd_to_fsmc(struct mtd_info *mtd)
254} 254}
255 255
256/* 256/*
257 * fsmc_cmd_ctrl - For facilitaing Hardware access
258 * This routine allows hardware specific access to control-lines(ALE,CLE)
259 */
260static void fsmc_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
261{
262 struct nand_chip *this = mtd_to_nand(mtd);
263 struct fsmc_nand_data *host = mtd_to_fsmc(mtd);
264
265 if (ctrl & NAND_CTRL_CHANGE) {
266 u32 pc;
267
268 if (ctrl & NAND_CLE) {
269 this->IO_ADDR_R = host->cmd_va;
270 this->IO_ADDR_W = host->cmd_va;
271 } else if (ctrl & NAND_ALE) {
272 this->IO_ADDR_R = host->addr_va;
273 this->IO_ADDR_W = host->addr_va;
274 } else {
275 this->IO_ADDR_R = host->data_va;
276 this->IO_ADDR_W = host->data_va;
277 }
278
279 pc = readl(host->regs_va + PC);
280 if (ctrl & NAND_NCE)
281 pc |= FSMC_ENABLE;
282 else
283 pc &= ~FSMC_ENABLE;
284 writel_relaxed(pc, host->regs_va + PC);
285 }
286
287 mb();
288
289 if (cmd != NAND_CMD_NONE)
290 writeb_relaxed(cmd, this->IO_ADDR_W);
291}
292
293/*
294 * fsmc_nand_setup - FSMC (Flexible Static Memory Controller) init routine 257 * fsmc_nand_setup - FSMC (Flexible Static Memory Controller) init routine
295 * 258 *
296 * This routine initializes timing parameters related to NAND memory access in 259 * This routine initializes timing parameters related to NAND memory access in
@@ -645,6 +608,102 @@ static void fsmc_write_buf_dma(struct mtd_info *mtd, const uint8_t *buf,
645 dma_xfer(host, (void *)buf, len, DMA_TO_DEVICE); 608 dma_xfer(host, (void *)buf, len, DMA_TO_DEVICE);
646} 609}
647 610
611/* fsmc_select_chip - assert or deassert nCE */
612static void fsmc_select_chip(struct mtd_info *mtd, int chipnr)
613{
614 struct fsmc_nand_data *host = mtd_to_fsmc(mtd);
615 u32 pc;
616
617 /* Support only one CS */
618 if (chipnr > 0)
619 return;
620
621 pc = readl(host->regs_va + PC);
622 if (chipnr < 0)
623 writel_relaxed(pc & ~FSMC_ENABLE, host->regs_va + PC);
624 else
625 writel_relaxed(pc | FSMC_ENABLE, host->regs_va + PC);
626
627 /* nCE line must be asserted before starting any operation */
628 mb();
629}
630
631/*
632 * fsmc_exec_op - hook called by the core to execute NAND operations
633 *
634 * This controller is simple enough and thus does not need to use the parser
635 * provided by the core, instead, handle every situation here.
636 */
637static int fsmc_exec_op(struct nand_chip *chip, const struct nand_operation *op,
638 bool check_only)
639{
640 struct mtd_info *mtd = nand_to_mtd(chip);
641 struct fsmc_nand_data *host = mtd_to_fsmc(mtd);
642 const struct nand_op_instr *instr = NULL;
643 int ret = 0;
644 unsigned int op_id;
645 int i;
646
647 pr_debug("Executing operation [%d instructions]:\n", op->ninstrs);
648 for (op_id = 0; op_id < op->ninstrs; op_id++) {
649 instr = &op->instrs[op_id];
650
651 switch (instr->type) {
652 case NAND_OP_CMD_INSTR:
653 pr_debug(" ->CMD [0x%02x]\n",
654 instr->ctx.cmd.opcode);
655
656 writeb_relaxed(instr->ctx.cmd.opcode, host->cmd_va);
657 break;
658
659 case NAND_OP_ADDR_INSTR:
660 pr_debug(" ->ADDR [%d cyc]",
661 instr->ctx.addr.naddrs);
662
663 for (i = 0; i < instr->ctx.addr.naddrs; i++)
664 writeb_relaxed(instr->ctx.addr.addrs[i],
665 host->addr_va);
666 break;
667
668 case NAND_OP_DATA_IN_INSTR:
669 pr_debug(" ->DATA_IN [%d B%s]\n", instr->ctx.data.len,
670 instr->ctx.data.force_8bit ?
671 ", force 8-bit" : "");
672
673 if (host->mode == USE_DMA_ACCESS)
674 fsmc_read_buf_dma(mtd, instr->ctx.data.buf.in,
675 instr->ctx.data.len);
676 else
677 fsmc_read_buf(mtd, instr->ctx.data.buf.in,
678 instr->ctx.data.len);
679 break;
680
681 case NAND_OP_DATA_OUT_INSTR:
682 pr_debug(" ->DATA_OUT [%d B%s]\n", instr->ctx.data.len,
683 instr->ctx.data.force_8bit ?
684 ", force 8-bit" : "");
685
686 if (host->mode == USE_DMA_ACCESS)
687 fsmc_write_buf_dma(mtd, instr->ctx.data.buf.out,
688 instr->ctx.data.len);
689 else
690 fsmc_write_buf(mtd, instr->ctx.data.buf.out,
691 instr->ctx.data.len);
692 break;
693
694 case NAND_OP_WAITRDY_INSTR:
695 pr_debug(" ->WAITRDY [max %d ms]\n",
696 instr->ctx.waitrdy.timeout_ms);
697
698 ret = nand_soft_waitrdy(chip,
699 instr->ctx.waitrdy.timeout_ms);
700 break;
701 }
702 }
703
704 return ret;
705}
706
648/* 707/*
649 * fsmc_read_page_hwecc 708 * fsmc_read_page_hwecc
650 * @mtd: mtd info structure 709 * @mtd: mtd info structure
@@ -944,9 +1003,8 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
944 nand_set_flash_node(nand, pdev->dev.of_node); 1003 nand_set_flash_node(nand, pdev->dev.of_node);
945 1004
946 mtd->dev.parent = &pdev->dev; 1005 mtd->dev.parent = &pdev->dev;
947 nand->IO_ADDR_R = host->data_va; 1006 nand->exec_op = fsmc_exec_op;
948 nand->IO_ADDR_W = host->data_va; 1007 nand->select_chip = fsmc_select_chip;
949 nand->cmd_ctrl = fsmc_cmd_ctrl;
950 nand->chip_delay = 30; 1008 nand->chip_delay = 30;
951 1009
952 /* 1010 /*
@@ -958,8 +1016,7 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
958 nand->ecc.size = 512; 1016 nand->ecc.size = 512;
959 nand->badblockbits = 7; 1017 nand->badblockbits = 7;
960 1018
961 switch (host->mode) { 1019 if (host->mode == USE_DMA_ACCESS) {
962 case USE_DMA_ACCESS:
963 dma_cap_zero(mask); 1020 dma_cap_zero(mask);
964 dma_cap_set(DMA_MEMCPY, mask); 1021 dma_cap_set(DMA_MEMCPY, mask);
965 host->read_dma_chan = dma_request_channel(mask, filter, NULL); 1022 host->read_dma_chan = dma_request_channel(mask, filter, NULL);
@@ -972,15 +1029,6 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
972 dev_err(&pdev->dev, "Unable to get write dma channel\n"); 1029 dev_err(&pdev->dev, "Unable to get write dma channel\n");
973 goto err_req_write_chnl; 1030 goto err_req_write_chnl;
974 } 1031 }
975 nand->read_buf = fsmc_read_buf_dma;
976 nand->write_buf = fsmc_write_buf_dma;
977 break;
978
979 default:
980 case USE_WORD_ACCESS:
981 nand->read_buf = fsmc_read_buf;
982 nand->write_buf = fsmc_write_buf;
983 break;
984 } 1032 }
985 1033
986 if (host->dev_timings) 1034 if (host->dev_timings)