Skip to content

Commit 22b27a6

Browse files
bbrezillonmiquelraynal
authored andcommitted
mtd: rawnand: gpio: Implement exec_op()
Implement exec_op() so we can get rid of the legacy interface implementation. Signed-off-by: Boris Brezillon <[email protected]> Signed-off-by: Miquel Raynal <[email protected]> Link: https://lore.kernel.org/linux-mtd/[email protected]
1 parent b4c7196 commit 22b27a6

File tree

1 file changed

+101
-3
lines changed

1 file changed

+101
-3
lines changed

drivers/mtd/nand/raw/gpio.c

Lines changed: 101 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,11 @@
2525
#include <linux/mtd/nand-gpio.h>
2626
#include <linux/of.h>
2727
#include <linux/of_address.h>
28+
#include <linux/delay.h>
2829

2930
struct gpiomtd {
3031
struct nand_controller base;
32+
void __iomem *io;
3133
void __iomem *io_sync;
3234
struct nand_chip nand_chip;
3335
struct gpio_nand_platdata plat;
@@ -98,6 +100,99 @@ static int gpio_nand_devready(struct nand_chip *chip)
98100
return gpiod_get_value(gpiomtd->rdy);
99101
}
100102

103+
static int gpio_nand_exec_instr(struct nand_chip *chip,
104+
const struct nand_op_instr *instr)
105+
{
106+
struct gpiomtd *gpiomtd = gpio_nand_getpriv(nand_to_mtd(chip));
107+
unsigned int i;
108+
109+
switch (instr->type) {
110+
case NAND_OP_CMD_INSTR:
111+
gpio_nand_dosync(gpiomtd);
112+
gpiod_set_value(gpiomtd->cle, 1);
113+
gpio_nand_dosync(gpiomtd);
114+
writeb(instr->ctx.cmd.opcode, gpiomtd->io);
115+
gpio_nand_dosync(gpiomtd);
116+
gpiod_set_value(gpiomtd->cle, 0);
117+
return 0;
118+
119+
case NAND_OP_ADDR_INSTR:
120+
gpio_nand_dosync(gpiomtd);
121+
gpiod_set_value(gpiomtd->ale, 1);
122+
gpio_nand_dosync(gpiomtd);
123+
for (i = 0; i < instr->ctx.addr.naddrs; i++)
124+
writeb(instr->ctx.addr.addrs[i], gpiomtd->io);
125+
gpio_nand_dosync(gpiomtd);
126+
gpiod_set_value(gpiomtd->ale, 0);
127+
return 0;
128+
129+
case NAND_OP_DATA_IN_INSTR:
130+
gpio_nand_dosync(gpiomtd);
131+
if ((chip->options & NAND_BUSWIDTH_16) &&
132+
!instr->ctx.data.force_8bit)
133+
ioread16_rep(gpiomtd->io, instr->ctx.data.buf.in,
134+
instr->ctx.data.len / 2);
135+
else
136+
ioread8_rep(gpiomtd->io, instr->ctx.data.buf.in,
137+
instr->ctx.data.len);
138+
return 0;
139+
140+
case NAND_OP_DATA_OUT_INSTR:
141+
gpio_nand_dosync(gpiomtd);
142+
if ((chip->options & NAND_BUSWIDTH_16) &&
143+
!instr->ctx.data.force_8bit)
144+
iowrite16_rep(gpiomtd->io, instr->ctx.data.buf.out,
145+
instr->ctx.data.len / 2);
146+
else
147+
iowrite8_rep(gpiomtd->io, instr->ctx.data.buf.out,
148+
instr->ctx.data.len);
149+
return 0;
150+
151+
case NAND_OP_WAITRDY_INSTR:
152+
if (!gpiomtd->rdy)
153+
return nand_soft_waitrdy(chip, instr->ctx.waitrdy.timeout_ms);
154+
155+
return nand_gpio_waitrdy(chip, gpiomtd->rdy,
156+
instr->ctx.waitrdy.timeout_ms);
157+
158+
default:
159+
return -EINVAL;
160+
}
161+
162+
return 0;
163+
}
164+
165+
static int gpio_nand_exec_op(struct nand_chip *chip,
166+
const struct nand_operation *op,
167+
bool check_only)
168+
{
169+
struct gpiomtd *gpiomtd = gpio_nand_getpriv(nand_to_mtd(chip));
170+
unsigned int i;
171+
int ret = 0;
172+
173+
if (check_only)
174+
return 0;
175+
176+
gpio_nand_dosync(gpiomtd);
177+
gpiod_set_value(gpiomtd->nce, 0);
178+
for (i = 0; i < op->ninstrs; i++) {
179+
ret = gpio_nand_exec_instr(chip, &op->instrs[i]);
180+
if (ret)
181+
break;
182+
183+
if (op->instrs[i].delay_ns)
184+
ndelay(op->instrs[i].delay_ns);
185+
}
186+
gpio_nand_dosync(gpiomtd);
187+
gpiod_set_value(gpiomtd->nce, 1);
188+
189+
return ret;
190+
}
191+
192+
static const struct nand_controller_ops gpio_nand_ops = {
193+
.exec_op = gpio_nand_exec_op,
194+
};
195+
101196
#ifdef CONFIG_OF
102197
static const struct of_device_id gpio_nand_id_table[] = {
103198
{ .compatible = "gpio-control-nand" },
@@ -226,9 +321,9 @@ static int gpio_nand_probe(struct platform_device *pdev)
226321
chip = &gpiomtd->nand_chip;
227322

228323
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
229-
chip->legacy.IO_ADDR_R = devm_ioremap_resource(dev, res);
230-
if (IS_ERR(chip->legacy.IO_ADDR_R))
231-
return PTR_ERR(chip->legacy.IO_ADDR_R);
324+
gpiomtd->io = devm_ioremap_resource(dev, res);
325+
if (IS_ERR(gpiomtd->io))
326+
return PTR_ERR(gpiomtd->io);
232327

233328
res = gpio_nand_get_io_sync(pdev);
234329
if (res) {
@@ -275,7 +370,10 @@ static int gpio_nand_probe(struct platform_device *pdev)
275370
chip->legacy.dev_ready = gpio_nand_devready;
276371

277372
nand_controller_init(&gpiomtd->base);
373+
gpiomtd->base.ops = &gpio_nand_ops;
374+
278375
nand_set_flash_node(chip, pdev->dev.of_node);
376+
chip->legacy.IO_ADDR_R = gpiomtd->io;
279377
chip->legacy.IO_ADDR_W = chip->legacy.IO_ADDR_R;
280378
chip->ecc.mode = NAND_ECC_SOFT;
281379
chip->ecc.algo = NAND_ECC_HAMMING;

0 commit comments

Comments
 (0)