Lines Matching +full:nand +full:- +full:ecc +full:- +full:algo
1 // SPDX-License-Identifier: GPL-2.0-only
10 * Device driver for NAND flash that uses a memory mapped interface to
11 * read/write the NAND commands and data, and GPIO pins for control signals
12 * (the DT binding refers to this as "GPIO assisted NAND flash")
25 #include <linux/mtd/nand-gpio.h>
52 * Make sure the GPIO state changes occur in-order with writes to NAND
54 * Needed on PXA due to bus-reordering within the SoC itself (see section on
61 if (gpiomtd->io_sync) { in gpio_nand_dosync()
64 * What's required is what's here - a read from a separate in gpio_nand_dosync()
67 tmp = readl(gpiomtd->io_sync); in gpio_nand_dosync()
81 switch (instr->type) { in gpio_nand_exec_instr()
84 gpiod_set_value(gpiomtd->cle, 1); in gpio_nand_exec_instr()
86 writeb(instr->ctx.cmd.opcode, gpiomtd->io); in gpio_nand_exec_instr()
88 gpiod_set_value(gpiomtd->cle, 0); in gpio_nand_exec_instr()
93 gpiod_set_value(gpiomtd->ale, 1); in gpio_nand_exec_instr()
95 for (i = 0; i < instr->ctx.addr.naddrs; i++) in gpio_nand_exec_instr()
96 writeb(instr->ctx.addr.addrs[i], gpiomtd->io); in gpio_nand_exec_instr()
98 gpiod_set_value(gpiomtd->ale, 0); in gpio_nand_exec_instr()
103 if ((chip->options & NAND_BUSWIDTH_16) && in gpio_nand_exec_instr()
104 !instr->ctx.data.force_8bit) in gpio_nand_exec_instr()
105 ioread16_rep(gpiomtd->io, instr->ctx.data.buf.in, in gpio_nand_exec_instr()
106 instr->ctx.data.len / 2); in gpio_nand_exec_instr()
108 ioread8_rep(gpiomtd->io, instr->ctx.data.buf.in, in gpio_nand_exec_instr()
109 instr->ctx.data.len); in gpio_nand_exec_instr()
114 if ((chip->options & NAND_BUSWIDTH_16) && in gpio_nand_exec_instr()
115 !instr->ctx.data.force_8bit) in gpio_nand_exec_instr()
116 iowrite16_rep(gpiomtd->io, instr->ctx.data.buf.out, in gpio_nand_exec_instr()
117 instr->ctx.data.len / 2); in gpio_nand_exec_instr()
119 iowrite8_rep(gpiomtd->io, instr->ctx.data.buf.out, in gpio_nand_exec_instr()
120 instr->ctx.data.len); in gpio_nand_exec_instr()
124 if (!gpiomtd->rdy) in gpio_nand_exec_instr()
125 return nand_soft_waitrdy(chip, instr->ctx.waitrdy.timeout_ms); in gpio_nand_exec_instr()
127 return nand_gpio_waitrdy(chip, gpiomtd->rdy, in gpio_nand_exec_instr()
128 instr->ctx.waitrdy.timeout_ms); in gpio_nand_exec_instr()
131 return -EINVAL; in gpio_nand_exec_instr()
149 gpiod_set_value(gpiomtd->nce, 0); in gpio_nand_exec_op()
150 for (i = 0; i < op->ninstrs; i++) { in gpio_nand_exec_op()
151 ret = gpio_nand_exec_instr(chip, &op->instrs[i]); in gpio_nand_exec_op()
155 if (op->instrs[i].delay_ns) in gpio_nand_exec_op()
156 ndelay(op->instrs[i].delay_ns); in gpio_nand_exec_op()
159 gpiod_set_value(gpiomtd->nce, 1); in gpio_nand_exec_op()
166 chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT; in gpio_nand_attach_chip()
168 if (chip->ecc.algo == NAND_ECC_ALGO_UNKNOWN) in gpio_nand_attach_chip()
169 chip->ecc.algo = NAND_ECC_ALGO_HAMMING; in gpio_nand_attach_chip()
181 { .compatible = "gpio-control-nand" },
191 if (!dev->of_node) in gpio_nand_get_config_of()
192 return -ENODEV; in gpio_nand_get_config_of()
194 if (!of_property_read_u32(dev->of_node, "bank-width", &val)) { in gpio_nand_get_config_of()
196 plat->options |= NAND_BUSWIDTH_16; in gpio_nand_get_config_of()
198 dev_err(dev, "invalid bank-width %u\n", val); in gpio_nand_get_config_of()
199 return -EINVAL; in gpio_nand_get_config_of()
203 if (!of_property_read_u32(dev->of_node, "chip-delay", &val)) in gpio_nand_get_config_of()
204 plat->chip_delay = val; in gpio_nand_get_config_of()
214 if (of_property_read_u64(pdev->dev.of_node, in gpio_nand_get_io_sync_of()
215 "gpio-control-nand,io-sync-reg", &addr)) in gpio_nand_get_io_sync_of()
218 r = devm_kzalloc(&pdev->dev, sizeof(*r), GFP_KERNEL); in gpio_nand_get_io_sync_of()
222 r->start = addr; in gpio_nand_get_io_sync_of()
223 r->end = r->start + 0x3; in gpio_nand_get_io_sync_of()
224 r->flags = IORESOURCE_MEM; in gpio_nand_get_io_sync_of()
232 return -ENOSYS; in gpio_nand_get_config_of()
255 return -EINVAL; in gpio_nand_get_config()
272 struct nand_chip *chip = &gpiomtd->nand_chip; in gpio_nand_remove()
280 if (gpiomtd->nwp && !IS_ERR(gpiomtd->nwp)) in gpio_nand_remove()
281 gpiod_set_value(gpiomtd->nwp, 0); in gpio_nand_remove()
282 if (gpiomtd->nce && !IS_ERR(gpiomtd->nce)) in gpio_nand_remove()
283 gpiod_set_value(gpiomtd->nce, 0); in gpio_nand_remove()
294 struct device *dev = &pdev->dev; in gpio_nand_probe()
297 if (!dev->of_node && !dev_get_platdata(dev)) in gpio_nand_probe()
298 return -EINVAL; in gpio_nand_probe()
302 return -ENOMEM; in gpio_nand_probe()
304 chip = &gpiomtd->nand_chip; in gpio_nand_probe()
307 gpiomtd->io = devm_ioremap_resource(dev, res); in gpio_nand_probe()
308 if (IS_ERR(gpiomtd->io)) in gpio_nand_probe()
309 return PTR_ERR(gpiomtd->io); in gpio_nand_probe()
313 gpiomtd->io_sync = devm_ioremap_resource(dev, res); in gpio_nand_probe()
314 if (IS_ERR(gpiomtd->io_sync)) in gpio_nand_probe()
315 return PTR_ERR(gpiomtd->io_sync); in gpio_nand_probe()
318 ret = gpio_nand_get_config(dev, &gpiomtd->plat); in gpio_nand_probe()
323 gpiomtd->nce = devm_gpiod_get_optional(dev, "nce", GPIOD_OUT_HIGH); in gpio_nand_probe()
324 if (IS_ERR(gpiomtd->nce)) in gpio_nand_probe()
325 return PTR_ERR(gpiomtd->nce); in gpio_nand_probe()
328 gpiomtd->nwp = devm_gpiod_get_optional(dev, "nwp", GPIOD_OUT_LOW); in gpio_nand_probe()
329 if (IS_ERR(gpiomtd->nwp)) { in gpio_nand_probe()
330 ret = PTR_ERR(gpiomtd->nwp); in gpio_nand_probe()
334 gpiomtd->ale = devm_gpiod_get(dev, "ale", GPIOD_OUT_LOW); in gpio_nand_probe()
335 if (IS_ERR(gpiomtd->ale)) { in gpio_nand_probe()
336 ret = PTR_ERR(gpiomtd->ale); in gpio_nand_probe()
340 gpiomtd->cle = devm_gpiod_get(dev, "cle", GPIOD_OUT_LOW); in gpio_nand_probe()
341 if (IS_ERR(gpiomtd->cle)) { in gpio_nand_probe()
342 ret = PTR_ERR(gpiomtd->cle); in gpio_nand_probe()
346 gpiomtd->rdy = devm_gpiod_get_optional(dev, "rdy", GPIOD_IN); in gpio_nand_probe()
347 if (IS_ERR(gpiomtd->rdy)) { in gpio_nand_probe()
348 ret = PTR_ERR(gpiomtd->rdy); in gpio_nand_probe()
352 nand_controller_init(&gpiomtd->base); in gpio_nand_probe()
353 gpiomtd->base.ops = &gpio_nand_ops; in gpio_nand_probe()
355 nand_set_flash_node(chip, pdev->dev.of_node); in gpio_nand_probe()
356 chip->options = gpiomtd->plat.options; in gpio_nand_probe()
357 chip->controller = &gpiomtd->base; in gpio_nand_probe()
360 mtd->dev.parent = dev; in gpio_nand_probe()
365 if (gpiomtd->nwp && !IS_ERR(gpiomtd->nwp)) in gpio_nand_probe()
366 gpiod_direction_output(gpiomtd->nwp, 1); in gpio_nand_probe()
372 if (gpiomtd->plat.adjust_parts) in gpio_nand_probe()
373 gpiomtd->plat.adjust_parts(&gpiomtd->plat, mtd->size); in gpio_nand_probe()
375 ret = mtd_device_register(mtd, gpiomtd->plat.parts, in gpio_nand_probe()
376 gpiomtd->plat.num_parts); in gpio_nand_probe()
381 if (gpiomtd->nwp && !IS_ERR(gpiomtd->nwp)) in gpio_nand_probe()
382 gpiod_set_value(gpiomtd->nwp, 0); in gpio_nand_probe()
384 if (gpiomtd->nce && !IS_ERR(gpiomtd->nce)) in gpio_nand_probe()
385 gpiod_set_value(gpiomtd->nce, 0); in gpio_nand_probe()
394 .name = "gpio-nand",
403 MODULE_DESCRIPTION("GPIO NAND Driver");