From b4c719685491983628155c5c8b677332709c4c6f Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Wed, 3 Jun 2020 17:07:44 +0200 Subject: mtd: rawnand: gpio: Inherit from nand_controller Inherit from nand_controller so we don't rely on the nand_chip.legacy.dummy_controller field. Signed-off-by: Boris Brezillon Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20200603150746.1423257-2-boris.brezillon@collabora.com --- drivers/mtd/nand/raw/gpio.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/mtd/nand/raw/gpio.c') diff --git a/drivers/mtd/nand/raw/gpio.c b/drivers/mtd/nand/raw/gpio.c index 938077e5c6a9..33828fb20a13 100644 --- a/drivers/mtd/nand/raw/gpio.c +++ b/drivers/mtd/nand/raw/gpio.c @@ -27,6 +27,7 @@ #include struct gpiomtd { + struct nand_controller base; void __iomem *io_sync; struct nand_chip nand_chip; struct gpio_nand_platdata plat; @@ -273,6 +274,7 @@ static int gpio_nand_probe(struct platform_device *pdev) if (gpiomtd->rdy) chip->legacy.dev_ready = gpio_nand_devready; + nand_controller_init(&gpiomtd->base); nand_set_flash_node(chip, pdev->dev.of_node); chip->legacy.IO_ADDR_W = chip->legacy.IO_ADDR_R; chip->ecc.mode = NAND_ECC_SOFT; @@ -280,6 +282,7 @@ static int gpio_nand_probe(struct platform_device *pdev) chip->options = gpiomtd->plat.options; chip->legacy.chip_delay = gpiomtd->plat.chip_delay; chip->legacy.cmd_ctrl = gpio_nand_cmd_ctrl; + chip->controller = &gpiomtd->base; mtd = nand_to_mtd(chip); mtd->dev.parent = dev; -- cgit v1.2.3 From 22b27a675d714499848d4f389082eb0d959a7b34 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Wed, 3 Jun 2020 17:07:45 +0200 Subject: mtd: rawnand: gpio: Implement exec_op() Implement exec_op() so we can get rid of the legacy interface implementation. Signed-off-by: Boris Brezillon Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20200603150746.1423257-3-boris.brezillon@collabora.com --- drivers/mtd/nand/raw/gpio.c | 104 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 101 insertions(+), 3 deletions(-) (limited to 'drivers/mtd/nand/raw/gpio.c') diff --git a/drivers/mtd/nand/raw/gpio.c b/drivers/mtd/nand/raw/gpio.c index 33828fb20a13..115998011192 100644 --- a/drivers/mtd/nand/raw/gpio.c +++ b/drivers/mtd/nand/raw/gpio.c @@ -25,9 +25,11 @@ #include #include #include +#include struct gpiomtd { struct nand_controller base; + void __iomem *io; void __iomem *io_sync; struct nand_chip nand_chip; struct gpio_nand_platdata plat; @@ -98,6 +100,99 @@ static int gpio_nand_devready(struct nand_chip *chip) return gpiod_get_value(gpiomtd->rdy); } +static int gpio_nand_exec_instr(struct nand_chip *chip, + const struct nand_op_instr *instr) +{ + struct gpiomtd *gpiomtd = gpio_nand_getpriv(nand_to_mtd(chip)); + unsigned int i; + + switch (instr->type) { + case NAND_OP_CMD_INSTR: + gpio_nand_dosync(gpiomtd); + gpiod_set_value(gpiomtd->cle, 1); + gpio_nand_dosync(gpiomtd); + writeb(instr->ctx.cmd.opcode, gpiomtd->io); + gpio_nand_dosync(gpiomtd); + gpiod_set_value(gpiomtd->cle, 0); + return 0; + + case NAND_OP_ADDR_INSTR: + gpio_nand_dosync(gpiomtd); + gpiod_set_value(gpiomtd->ale, 1); + gpio_nand_dosync(gpiomtd); + for (i = 0; i < instr->ctx.addr.naddrs; i++) + writeb(instr->ctx.addr.addrs[i], gpiomtd->io); + gpio_nand_dosync(gpiomtd); + gpiod_set_value(gpiomtd->ale, 0); + return 0; + + case NAND_OP_DATA_IN_INSTR: + gpio_nand_dosync(gpiomtd); + if ((chip->options & NAND_BUSWIDTH_16) && + !instr->ctx.data.force_8bit) + ioread16_rep(gpiomtd->io, instr->ctx.data.buf.in, + instr->ctx.data.len / 2); + else + ioread8_rep(gpiomtd->io, instr->ctx.data.buf.in, + instr->ctx.data.len); + return 0; + + case NAND_OP_DATA_OUT_INSTR: + gpio_nand_dosync(gpiomtd); + if ((chip->options & NAND_BUSWIDTH_16) && + !instr->ctx.data.force_8bit) + iowrite16_rep(gpiomtd->io, instr->ctx.data.buf.out, + instr->ctx.data.len / 2); + else + iowrite8_rep(gpiomtd->io, instr->ctx.data.buf.out, + instr->ctx.data.len); + return 0; + + case NAND_OP_WAITRDY_INSTR: + if (!gpiomtd->rdy) + return nand_soft_waitrdy(chip, instr->ctx.waitrdy.timeout_ms); + + return nand_gpio_waitrdy(chip, gpiomtd->rdy, + instr->ctx.waitrdy.timeout_ms); + + default: + return -EINVAL; + } + + return 0; +} + +static int gpio_nand_exec_op(struct nand_chip *chip, + const struct nand_operation *op, + bool check_only) +{ + struct gpiomtd *gpiomtd = gpio_nand_getpriv(nand_to_mtd(chip)); + unsigned int i; + int ret = 0; + + if (check_only) + return 0; + + gpio_nand_dosync(gpiomtd); + gpiod_set_value(gpiomtd->nce, 0); + for (i = 0; i < op->ninstrs; i++) { + ret = gpio_nand_exec_instr(chip, &op->instrs[i]); + if (ret) + break; + + if (op->instrs[i].delay_ns) + ndelay(op->instrs[i].delay_ns); + } + gpio_nand_dosync(gpiomtd); + gpiod_set_value(gpiomtd->nce, 1); + + return ret; +} + +static const struct nand_controller_ops gpio_nand_ops = { + .exec_op = gpio_nand_exec_op, +}; + #ifdef CONFIG_OF static const struct of_device_id gpio_nand_id_table[] = { { .compatible = "gpio-control-nand" }, @@ -226,9 +321,9 @@ static int gpio_nand_probe(struct platform_device *pdev) chip = &gpiomtd->nand_chip; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - chip->legacy.IO_ADDR_R = devm_ioremap_resource(dev, res); - if (IS_ERR(chip->legacy.IO_ADDR_R)) - return PTR_ERR(chip->legacy.IO_ADDR_R); + gpiomtd->io = devm_ioremap_resource(dev, res); + if (IS_ERR(gpiomtd->io)) + return PTR_ERR(gpiomtd->io); res = gpio_nand_get_io_sync(pdev); if (res) { @@ -275,7 +370,10 @@ static int gpio_nand_probe(struct platform_device *pdev) chip->legacy.dev_ready = gpio_nand_devready; nand_controller_init(&gpiomtd->base); + gpiomtd->base.ops = &gpio_nand_ops; + nand_set_flash_node(chip, pdev->dev.of_node); + chip->legacy.IO_ADDR_R = gpiomtd->io; chip->legacy.IO_ADDR_W = chip->legacy.IO_ADDR_R; chip->ecc.mode = NAND_ECC_SOFT; chip->ecc.algo = NAND_ECC_HAMMING; -- cgit v1.2.3 From df66c27101ff279dc2e8cc2ced7191029495f194 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Wed, 3 Jun 2020 17:07:46 +0200 Subject: mtd: rawnand: gpio: Get rid of the legacy interface implementation Now that exec_op() is implemented, we can get rid of the legacy interface implementation. Signed-off-by: Boris Brezillon Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20200603150746.1423257-4-boris.brezillon@collabora.com --- drivers/mtd/nand/raw/gpio.c | 35 ----------------------------------- 1 file changed, 35 deletions(-) (limited to 'drivers/mtd/nand/raw/gpio.c') diff --git a/drivers/mtd/nand/raw/gpio.c b/drivers/mtd/nand/raw/gpio.c index 115998011192..3bd847ccc3f3 100644 --- a/drivers/mtd/nand/raw/gpio.c +++ b/drivers/mtd/nand/raw/gpio.c @@ -72,34 +72,6 @@ static void gpio_nand_dosync(struct gpiomtd *gpiomtd) static inline void gpio_nand_dosync(struct gpiomtd *gpiomtd) {} #endif -static void gpio_nand_cmd_ctrl(struct nand_chip *chip, int cmd, - unsigned int ctrl) -{ - struct gpiomtd *gpiomtd = gpio_nand_getpriv(nand_to_mtd(chip)); - - gpio_nand_dosync(gpiomtd); - - if (ctrl & NAND_CTRL_CHANGE) { - if (gpiomtd->nce) - gpiod_set_value(gpiomtd->nce, !(ctrl & NAND_NCE)); - gpiod_set_value(gpiomtd->cle, !!(ctrl & NAND_CLE)); - gpiod_set_value(gpiomtd->ale, !!(ctrl & NAND_ALE)); - gpio_nand_dosync(gpiomtd); - } - if (cmd == NAND_CMD_NONE) - return; - - writeb(cmd, gpiomtd->nand_chip.legacy.IO_ADDR_W); - gpio_nand_dosync(gpiomtd); -} - -static int gpio_nand_devready(struct nand_chip *chip) -{ - struct gpiomtd *gpiomtd = gpio_nand_getpriv(nand_to_mtd(chip)); - - return gpiod_get_value(gpiomtd->rdy); -} - static int gpio_nand_exec_instr(struct nand_chip *chip, const struct nand_op_instr *instr) { @@ -365,21 +337,14 @@ static int gpio_nand_probe(struct platform_device *pdev) ret = PTR_ERR(gpiomtd->rdy); goto out_ce; } - /* Using RDY pin */ - if (gpiomtd->rdy) - chip->legacy.dev_ready = gpio_nand_devready; nand_controller_init(&gpiomtd->base); gpiomtd->base.ops = &gpio_nand_ops; nand_set_flash_node(chip, pdev->dev.of_node); - chip->legacy.IO_ADDR_R = gpiomtd->io; - chip->legacy.IO_ADDR_W = chip->legacy.IO_ADDR_R; chip->ecc.mode = NAND_ECC_SOFT; chip->ecc.algo = NAND_ECC_HAMMING; chip->options = gpiomtd->plat.options; - chip->legacy.chip_delay = gpiomtd->plat.chip_delay; - chip->legacy.cmd_ctrl = gpio_nand_cmd_ctrl; chip->controller = &gpiomtd->base; mtd = nand_to_mtd(chip); -- cgit v1.2.3