mtd: rawnand: tango: Convert the driver to exec_op()
authorBoris Brezillon <boris.brezillon@collabora.com>
Mon, 18 May 2020 17:09:12 +0000 (19:09 +0200)
committerMiquel Raynal <miquel.raynal@bootlin.com>
Fri, 26 Jun 2020 06:34:23 +0000 (08:34 +0200)
Let's convert the driver to exec_op() to have one less driver relying
on the legacy interface.

Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
Link: https://lore.kernel.org/linux-mtd/20200518170912.328988-1-boris.brezillon@collabora.com
drivers/mtd/nand/raw/tango_nand.c

index 246871e..b3a0d08 100644 (file)
@@ -113,59 +113,80 @@ struct tango_chip {
 
 #define TIMING(t0, t1, t2, t3) ((t0) << 24 | (t1) << 16 | (t2) << 8 | (t3))
 
-static void tango_cmd_ctrl(struct nand_chip *chip, int dat, unsigned int ctrl)
+static void tango_select_target(struct nand_chip *chip, unsigned int cs)
 {
+       struct tango_nfc *nfc = to_tango_nfc(chip->controller);
        struct tango_chip *tchip = to_tango_chip(chip);
 
-       if (ctrl & NAND_CLE)
-               writeb_relaxed(dat, tchip->base + PBUS_CMD);
-
-       if (ctrl & NAND_ALE)
-               writeb_relaxed(dat, tchip->base + PBUS_ADDR);
+       writel_relaxed(tchip->timing1, nfc->reg_base + NFC_TIMING1);
+       writel_relaxed(tchip->timing2, nfc->reg_base + NFC_TIMING2);
+       writel_relaxed(tchip->xfer_cfg, nfc->reg_base + NFC_XFER_CFG);
+       writel_relaxed(tchip->pkt_0_cfg, nfc->reg_base + NFC_PKT_0_CFG);
+       writel_relaxed(tchip->pkt_n_cfg, nfc->reg_base + NFC_PKT_N_CFG);
+       writel_relaxed(tchip->bb_cfg, nfc->reg_base + NFC_BB_CFG);
 }
 
-static int tango_dev_ready(struct nand_chip *chip)
+static int tango_waitrdy(struct nand_chip *chip, unsigned int timeout_ms)
 {
        struct tango_nfc *nfc = to_tango_nfc(chip->controller);
+       u32 status;
 
-       return readl_relaxed(nfc->pbus_base + PBUS_CS_CTRL) & PBUS_IORDY;
+       return readl_relaxed_poll_timeout(nfc->pbus_base + PBUS_CS_CTRL,
+                                         status, status & PBUS_IORDY, 20,
+                                         timeout_ms);
 }
 
-static u8 tango_read_byte(struct nand_chip *chip)
+static int tango_exec_instr(struct nand_chip *chip,
+                           const struct nand_op_instr *instr)
 {
        struct tango_chip *tchip = to_tango_chip(chip);
+       unsigned int i;
 
-       return readb_relaxed(tchip->base + PBUS_DATA);
-}
-
-static void tango_read_buf(struct nand_chip *chip, u8 *buf, int len)
-{
-       struct tango_chip *tchip = to_tango_chip(chip);
+       switch (instr->type) {
+       case NAND_OP_CMD_INSTR:
+               writeb_relaxed(instr->ctx.cmd.opcode, tchip->base + PBUS_CMD);
+               return 0;
+       case NAND_OP_ADDR_INSTR:
+               for (i = 0; i < instr->ctx.addr.naddrs; i++)
+                       writeb_relaxed(instr->ctx.addr.addrs[i],
+                                      tchip->base + PBUS_ADDR);
+               return 0;
+       case NAND_OP_DATA_IN_INSTR:
+               ioread8_rep(tchip->base + PBUS_DATA, instr->ctx.data.buf.in,
+                           instr->ctx.data.len);
+               return 0;
+       case NAND_OP_DATA_OUT_INSTR:
+               iowrite8_rep(tchip->base + PBUS_DATA, instr->ctx.data.buf.out,
+                            instr->ctx.data.len);
+               return 0;
+       case NAND_OP_WAITRDY_INSTR:
+               return tango_waitrdy(chip,
+                                    instr->ctx.waitrdy.timeout_ms);
+       default:
+               break;
+       }
 
-       ioread8_rep(tchip->base + PBUS_DATA, buf, len);
+       return -EINVAL;
 }
 
-static void tango_write_buf(struct nand_chip *chip, const u8 *buf, int len)
+static int tango_exec_op(struct nand_chip *chip,
+                        const struct nand_operation *op,
+                        bool check_only)
 {
-       struct tango_chip *tchip = to_tango_chip(chip);
-
-       iowrite8_rep(tchip->base + PBUS_DATA, buf, len);
-}
+       unsigned int i;
+       int ret = 0;
 
-static void tango_select_chip(struct nand_chip *chip, int idx)
-{
-       struct tango_nfc *nfc = to_tango_nfc(chip->controller);
-       struct tango_chip *tchip = to_tango_chip(chip);
+       if (check_only)
+               return 0;
 
-       if (idx < 0)
-               return; /* No "chip unselect" function */
+       tango_select_target(chip, op->cs);
+       for (i = 0; i < op->ninstrs; i++) {
+               ret = tango_exec_instr(chip, &op->instrs[i]);
+               if (ret)
+                       break;
+       }
 
-       writel_relaxed(tchip->timing1, nfc->reg_base + NFC_TIMING1);
-       writel_relaxed(tchip->timing2, nfc->reg_base + NFC_TIMING2);
-       writel_relaxed(tchip->xfer_cfg, nfc->reg_base + NFC_XFER_CFG);
-       writel_relaxed(tchip->pkt_0_cfg, nfc->reg_base + NFC_PKT_0_CFG);
-       writel_relaxed(tchip->pkt_n_cfg, nfc->reg_base + NFC_PKT_N_CFG);
-       writel_relaxed(tchip->bb_cfg, nfc->reg_base + NFC_BB_CFG);
+       return ret;
 }
 
 /*
@@ -279,6 +300,7 @@ static int tango_read_page(struct nand_chip *chip, u8 *buf,
        struct tango_nfc *nfc = to_tango_nfc(chip->controller);
        int err, res, len = mtd->writesize;
 
+       tango_select_target(chip, chip->cur_cs);
        if (oob_required)
                chip->ecc.read_oob(chip, page);
 
@@ -300,22 +322,30 @@ static int tango_write_page(struct nand_chip *chip, const u8 *buf,
 {
        struct mtd_info *mtd = nand_to_mtd(chip);
        struct tango_nfc *nfc = to_tango_nfc(chip->controller);
-       int err, status, len = mtd->writesize;
+       const struct nand_sdr_timings *timings;
+       int err, len = mtd->writesize;
+       u8 status;
 
        /* Calling tango_write_oob() would send PAGEPROG twice */
        if (oob_required)
                return -ENOTSUPP;
 
+       tango_select_target(chip, chip->cur_cs);
        writel_relaxed(0xffffffff, nfc->mem_base + METADATA);
        err = do_dma(nfc, DMA_TO_DEVICE, NFC_WRITE, buf, len, page);
        if (err)
                return err;
 
-       status = chip->legacy.waitfunc(chip);
-       if (status & NAND_STATUS_FAIL)
-               return -EIO;
+       timings = nand_get_sdr_timings(&chip->data_interface);
+       err = tango_waitrdy(chip, PSEC_TO_MSEC(timings->tR_max));
+       if (err)
+               return err;
 
-       return 0;
+       err = nand_status_op(chip, &status);
+       if (err)
+               return err;
+
+       return (status & NAND_STATUS_FAIL) ? -EIO : 0;
 }
 
 static void aux_read(struct nand_chip *chip, u8 **buf, int len, int *pos)
@@ -326,7 +356,9 @@ static void aux_read(struct nand_chip *chip, u8 **buf, int len, int *pos)
                /* skip over "len" bytes */
                nand_change_read_column_op(chip, *pos, NULL, 0, false);
        } else {
-               tango_read_buf(chip, *buf, len);
+               struct tango_chip *tchip = to_tango_chip(chip);
+
+               ioread8_rep(tchip->base + PBUS_DATA, *buf, len);
                *buf += len;
        }
 }
@@ -339,7 +371,9 @@ static void aux_write(struct nand_chip *chip, const u8 **buf, int len, int *pos)
                /* skip over "len" bytes */
                nand_change_write_column_op(chip, *pos, NULL, 0, false);
        } else {
-               tango_write_buf(chip, *buf, len);
+               struct tango_chip *tchip = to_tango_chip(chip);
+
+               iowrite8_rep(tchip->base + PBUS_DATA, *buf, len);
                *buf += len;
        }
 }
@@ -420,6 +454,7 @@ static void raw_write(struct nand_chip *chip, const u8 *buf, const u8 *oob)
 static int tango_read_page_raw(struct nand_chip *chip, u8 *buf,
                               int oob_required, int page)
 {
+       tango_select_target(chip, chip->cur_cs);
        nand_read_page_op(chip, page, 0, NULL, 0);
        raw_read(chip, buf, chip->oob_poi);
        return 0;
@@ -428,6 +463,7 @@ static int tango_read_page_raw(struct nand_chip *chip, u8 *buf,
 static int tango_write_page_raw(struct nand_chip *chip, const u8 *buf,
                                int oob_required, int page)
 {
+       tango_select_target(chip, chip->cur_cs);
        nand_prog_page_begin_op(chip, page, 0, NULL, 0);
        raw_write(chip, buf, chip->oob_poi);
        return nand_prog_page_end_op(chip);
@@ -435,6 +471,7 @@ static int tango_write_page_raw(struct nand_chip *chip, const u8 *buf,
 
 static int tango_read_oob(struct nand_chip *chip, int page)
 {
+       tango_select_target(chip, chip->cur_cs);
        nand_read_page_op(chip, page, 0, NULL, 0);
        raw_read(chip, NULL, chip->oob_poi);
        return 0;
@@ -442,6 +479,7 @@ static int tango_read_oob(struct nand_chip *chip, int page)
 
 static int tango_write_oob(struct nand_chip *chip, int page)
 {
+       tango_select_target(chip, chip->cur_cs);
        nand_prog_page_begin_op(chip, page, 0, NULL, 0);
        raw_write(chip, NULL, chip->oob_poi);
        return nand_prog_page_end_op(chip);
@@ -528,6 +566,7 @@ static int tango_attach_chip(struct nand_chip *chip)
 static const struct nand_controller_ops tango_controller_ops = {
        .attach_chip = tango_attach_chip,
        .setup_data_interface = tango_set_timings,
+       .exec_op = tango_exec_op,
 };
 
 static int chip_init(struct device *dev, struct device_node *np)
@@ -562,12 +601,6 @@ static int chip_init(struct device *dev, struct device_node *np)
        ecc = &chip->ecc;
        mtd = nand_to_mtd(chip);
 
-       chip->legacy.read_byte = tango_read_byte;
-       chip->legacy.write_buf = tango_write_buf;
-       chip->legacy.read_buf = tango_read_buf;
-       chip->legacy.select_chip = tango_select_chip;
-       chip->legacy.cmd_ctrl = tango_cmd_ctrl;
-       chip->legacy.dev_ready = tango_dev_ready;
        chip->options = NAND_USES_DMA |
                        NAND_NO_SUBPAGE_WRITE |
                        NAND_WAIT_TCCS;