Skip to content

Commit

Permalink
mtd: nand: fsmc: use ->exec_op()
Browse files Browse the repository at this point in the history
Remove the deprecated ->cmd_ctrl() implementation to use ->exec_op() in
the fsmc_nand driver.

Implement the ->select_chip() hook to avoid having to support the hack
from the core that send a NAND_CMD_NONE with NAND_NCE to signal a
deassertion of nCE.

Also get rid of the last references to ->IO_ADDR_[R|W] that are not used
anymore.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
  • Loading branch information
Miquel Raynal authored and Boris Brezillon committed Feb 17, 2018
1 parent 4df6ed4 commit 4da712e
Showing 1 changed file with 99 additions and 51 deletions.
150 changes: 99 additions & 51 deletions drivers/mtd/nand/raw/fsmc_nand.c
Original file line number Diff line number Diff line change
Expand Up @@ -253,43 +253,6 @@ static inline struct fsmc_nand_data *mtd_to_fsmc(struct mtd_info *mtd)
return container_of(mtd_to_nand(mtd), struct fsmc_nand_data, nand);
}

/*
* fsmc_cmd_ctrl - For facilitaing Hardware access
* This routine allows hardware specific access to control-lines(ALE,CLE)
*/
static void fsmc_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
{
struct nand_chip *this = mtd_to_nand(mtd);
struct fsmc_nand_data *host = mtd_to_fsmc(mtd);

if (ctrl & NAND_CTRL_CHANGE) {
u32 pc;

if (ctrl & NAND_CLE) {
this->IO_ADDR_R = host->cmd_va;
this->IO_ADDR_W = host->cmd_va;
} else if (ctrl & NAND_ALE) {
this->IO_ADDR_R = host->addr_va;
this->IO_ADDR_W = host->addr_va;
} else {
this->IO_ADDR_R = host->data_va;
this->IO_ADDR_W = host->data_va;
}

pc = readl(host->regs_va + PC);
if (ctrl & NAND_NCE)
pc |= FSMC_ENABLE;
else
pc &= ~FSMC_ENABLE;
writel_relaxed(pc, host->regs_va + PC);
}

mb();

if (cmd != NAND_CMD_NONE)
writeb_relaxed(cmd, this->IO_ADDR_W);
}

/*
* fsmc_nand_setup - FSMC (Flexible Static Memory Controller) init routine
*
Expand Down Expand Up @@ -645,6 +608,102 @@ static void fsmc_write_buf_dma(struct mtd_info *mtd, const uint8_t *buf,
dma_xfer(host, (void *)buf, len, DMA_TO_DEVICE);
}

/* fsmc_select_chip - assert or deassert nCE */
static void fsmc_select_chip(struct mtd_info *mtd, int chipnr)
{
struct fsmc_nand_data *host = mtd_to_fsmc(mtd);
u32 pc;

/* Support only one CS */
if (chipnr > 0)
return;

pc = readl(host->regs_va + PC);
if (chipnr < 0)
writel_relaxed(pc & ~FSMC_ENABLE, host->regs_va + PC);
else
writel_relaxed(pc | FSMC_ENABLE, host->regs_va + PC);

/* nCE line must be asserted before starting any operation */
mb();
}

/*
* fsmc_exec_op - hook called by the core to execute NAND operations
*
* This controller is simple enough and thus does not need to use the parser
* provided by the core, instead, handle every situation here.
*/
static int fsmc_exec_op(struct nand_chip *chip, const struct nand_operation *op,
bool check_only)
{
struct mtd_info *mtd = nand_to_mtd(chip);
struct fsmc_nand_data *host = mtd_to_fsmc(mtd);
const struct nand_op_instr *instr = NULL;
int ret = 0;
unsigned int op_id;
int i;

pr_debug("Executing operation [%d instructions]:\n", op->ninstrs);
for (op_id = 0; op_id < op->ninstrs; op_id++) {
instr = &op->instrs[op_id];

switch (instr->type) {
case NAND_OP_CMD_INSTR:
pr_debug(" ->CMD [0x%02x]\n",
instr->ctx.cmd.opcode);

writeb_relaxed(instr->ctx.cmd.opcode, host->cmd_va);
break;

case NAND_OP_ADDR_INSTR:
pr_debug(" ->ADDR [%d cyc]",
instr->ctx.addr.naddrs);

for (i = 0; i < instr->ctx.addr.naddrs; i++)
writeb_relaxed(instr->ctx.addr.addrs[i],
host->addr_va);
break;

case NAND_OP_DATA_IN_INSTR:
pr_debug(" ->DATA_IN [%d B%s]\n", instr->ctx.data.len,
instr->ctx.data.force_8bit ?
", force 8-bit" : "");

if (host->mode == USE_DMA_ACCESS)
fsmc_read_buf_dma(mtd, instr->ctx.data.buf.in,
instr->ctx.data.len);
else
fsmc_read_buf(mtd, instr->ctx.data.buf.in,
instr->ctx.data.len);
break;

case NAND_OP_DATA_OUT_INSTR:
pr_debug(" ->DATA_OUT [%d B%s]\n", instr->ctx.data.len,
instr->ctx.data.force_8bit ?
", force 8-bit" : "");

if (host->mode == USE_DMA_ACCESS)
fsmc_write_buf_dma(mtd, instr->ctx.data.buf.out,
instr->ctx.data.len);
else
fsmc_write_buf(mtd, instr->ctx.data.buf.out,
instr->ctx.data.len);
break;

case NAND_OP_WAITRDY_INSTR:
pr_debug(" ->WAITRDY [max %d ms]\n",
instr->ctx.waitrdy.timeout_ms);

ret = nand_soft_waitrdy(chip,
instr->ctx.waitrdy.timeout_ms);
break;
}
}

return ret;
}

/*
* fsmc_read_page_hwecc
* @mtd: mtd info structure
Expand Down Expand Up @@ -944,9 +1003,8 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
nand_set_flash_node(nand, pdev->dev.of_node);

mtd->dev.parent = &pdev->dev;
nand->IO_ADDR_R = host->data_va;
nand->IO_ADDR_W = host->data_va;
nand->cmd_ctrl = fsmc_cmd_ctrl;
nand->exec_op = fsmc_exec_op;
nand->select_chip = fsmc_select_chip;
nand->chip_delay = 30;

/*
Expand All @@ -958,8 +1016,7 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
nand->ecc.size = 512;
nand->badblockbits = 7;

switch (host->mode) {
case USE_DMA_ACCESS:
if (host->mode == USE_DMA_ACCESS) {
dma_cap_zero(mask);
dma_cap_set(DMA_MEMCPY, mask);
host->read_dma_chan = dma_request_channel(mask, filter, NULL);
Expand All @@ -972,15 +1029,6 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "Unable to get write dma channel\n");
goto err_req_write_chnl;
}
nand->read_buf = fsmc_read_buf_dma;
nand->write_buf = fsmc_write_buf_dma;
break;

default:
case USE_WORD_ACCESS:
nand->read_buf = fsmc_read_buf;
nand->write_buf = fsmc_write_buf;
break;
}

if (host->dev_timings)
Expand Down

0 comments on commit 4da712e

Please sign in to comment.