Lines Matching +full:nand +full:- +full:controller
1 // SPDX-License-Identifier: GPL-2.0
3 * Ingenic JZ47xx NAND driver
24 #include <linux/jz4780-nemc.h>
28 #define DRV_NAME "ingenic-nand"
46 struct nand_controller controller; member
68 return container_of(ctrl, struct ingenic_nfc, controller); in to_ingenic_nfc()
75 struct nand_ecc_ctrl *ecc = &chip->ecc; in qi_lb60_ooblayout_ecc()
77 if (section || !ecc->total) in qi_lb60_ooblayout_ecc()
78 return -ERANGE; in qi_lb60_ooblayout_ecc()
80 oobregion->length = ecc->total; in qi_lb60_ooblayout_ecc()
81 oobregion->offset = 12; in qi_lb60_ooblayout_ecc()
90 struct nand_ecc_ctrl *ecc = &chip->ecc; in qi_lb60_ooblayout_free()
93 return -ERANGE; in qi_lb60_ooblayout_free()
95 oobregion->length = mtd->oobsize - ecc->total - 12; in qi_lb60_ooblayout_free()
96 oobregion->offset = 12 + ecc->total; in qi_lb60_ooblayout_free()
110 struct nand_ecc_ctrl *ecc = &chip->ecc; in jz4725b_ooblayout_ecc()
112 if (section || !ecc->total) in jz4725b_ooblayout_ecc()
113 return -ERANGE; in jz4725b_ooblayout_ecc()
115 oobregion->length = ecc->total; in jz4725b_ooblayout_ecc()
116 oobregion->offset = 3; in jz4725b_ooblayout_ecc()
125 struct nand_ecc_ctrl *ecc = &chip->ecc; in jz4725b_ooblayout_free()
128 return -ERANGE; in jz4725b_ooblayout_free()
130 oobregion->length = mtd->oobsize - ecc->total - 3; in jz4725b_ooblayout_free()
131 oobregion->offset = 3 + ecc->total; in jz4725b_ooblayout_free()
143 struct ingenic_nand *nand = to_ingenic_nand(nand_to_mtd(chip)); in ingenic_nand_ecc_hwctl() local
145 nand->reading = (mode == NAND_ECC_READ); in ingenic_nand_ecc_hwctl()
151 struct ingenic_nand *nand = to_ingenic_nand(nand_to_mtd(chip)); in ingenic_nand_ecc_calculate() local
152 struct ingenic_nfc *nfc = to_ingenic_nfc(nand->chip.controller); in ingenic_nand_ecc_calculate()
159 if (nand->reading) in ingenic_nand_ecc_calculate()
162 params.size = nand->chip.ecc.size; in ingenic_nand_ecc_calculate()
163 params.bytes = nand->chip.ecc.bytes; in ingenic_nand_ecc_calculate()
164 params.strength = nand->chip.ecc.strength; in ingenic_nand_ecc_calculate()
166 return ingenic_ecc_calculate(nfc->ecc, ¶ms, dat, ecc_code); in ingenic_nand_ecc_calculate()
172 struct ingenic_nand *nand = to_ingenic_nand(nand_to_mtd(chip)); in ingenic_nand_ecc_correct() local
173 struct ingenic_nfc *nfc = to_ingenic_nfc(nand->chip.controller); in ingenic_nand_ecc_correct()
176 params.size = nand->chip.ecc.size; in ingenic_nand_ecc_correct()
177 params.bytes = nand->chip.ecc.bytes; in ingenic_nand_ecc_correct()
178 params.strength = nand->chip.ecc.strength; in ingenic_nand_ecc_correct()
180 return ingenic_ecc_correct(nfc->ecc, ¶ms, dat, read_ecc); in ingenic_nand_ecc_correct()
186 struct ingenic_nfc *nfc = to_ingenic_nfc(chip->controller); in ingenic_nand_attach_chip()
189 if (chip->ecc.strength == 4) { in ingenic_nand_attach_chip()
191 chip->ecc.bytes = 9; in ingenic_nand_attach_chip()
193 chip->ecc.bytes = fls((1 + 8) * chip->ecc.size) * in ingenic_nand_attach_chip()
194 (chip->ecc.strength / 8); in ingenic_nand_attach_chip()
197 switch (chip->ecc.engine_type) { in ingenic_nand_attach_chip()
199 if (!nfc->ecc) { in ingenic_nand_attach_chip()
200 dev_err(nfc->dev, "HW ECC selected, but ECC controller not found\n"); in ingenic_nand_attach_chip()
201 return -ENODEV; in ingenic_nand_attach_chip()
204 chip->ecc.hwctl = ingenic_nand_ecc_hwctl; in ingenic_nand_attach_chip()
205 chip->ecc.calculate = ingenic_nand_ecc_calculate; in ingenic_nand_attach_chip()
206 chip->ecc.correct = ingenic_nand_ecc_correct; in ingenic_nand_attach_chip()
209 dev_info(nfc->dev, "using %s (strength %d, size %d, bytes %d)\n", in ingenic_nand_attach_chip()
210 (nfc->ecc) ? "hardware ECC" : "software ECC", in ingenic_nand_attach_chip()
211 chip->ecc.strength, chip->ecc.size, chip->ecc.bytes); in ingenic_nand_attach_chip()
214 dev_info(nfc->dev, "not using ECC\n"); in ingenic_nand_attach_chip()
217 dev_err(nfc->dev, "ECC mode %d not supported\n", in ingenic_nand_attach_chip()
218 chip->ecc.engine_type); in ingenic_nand_attach_chip()
219 return -EINVAL; in ingenic_nand_attach_chip()
222 /* The NAND core will generate the ECC layout for SW ECC */ in ingenic_nand_attach_chip()
223 if (chip->ecc.engine_type != NAND_ECC_ENGINE_TYPE_ON_HOST) in ingenic_nand_attach_chip()
227 eccbytes = mtd->writesize / chip->ecc.size * chip->ecc.bytes; in ingenic_nand_attach_chip()
229 if (eccbytes > mtd->oobsize - 2) { in ingenic_nand_attach_chip()
230 dev_err(nfc->dev, in ingenic_nand_attach_chip()
232 eccbytes, mtd->oobsize - 2); in ingenic_nand_attach_chip()
233 return -EINVAL; in ingenic_nand_attach_chip()
240 if (chip->bbt_options & NAND_BBT_USE_FLASH) in ingenic_nand_attach_chip()
241 chip->bbt_options |= NAND_BBT_NO_OOB; in ingenic_nand_attach_chip()
246 else if (nfc->soc_info->oob_layout) in ingenic_nand_attach_chip()
247 mtd_set_ooblayout(mtd, nfc->soc_info->oob_layout); in ingenic_nand_attach_chip()
258 struct ingenic_nand *nand = to_ingenic_nand(nand_to_mtd(chip)); in ingenic_nand_exec_instr() local
259 struct ingenic_nfc *nfc = to_ingenic_nfc(chip->controller); in ingenic_nand_exec_instr()
262 switch (instr->type) { in ingenic_nand_exec_instr()
264 writeb(instr->ctx.cmd.opcode, in ingenic_nand_exec_instr()
265 cs->base + nfc->soc_info->cmd_offset); in ingenic_nand_exec_instr()
268 for (i = 0; i < instr->ctx.addr.naddrs; i++) in ingenic_nand_exec_instr()
269 writeb(instr->ctx.addr.addrs[i], in ingenic_nand_exec_instr()
270 cs->base + nfc->soc_info->addr_offset); in ingenic_nand_exec_instr()
273 if (instr->ctx.data.force_8bit || in ingenic_nand_exec_instr()
274 !(chip->options & NAND_BUSWIDTH_16)) in ingenic_nand_exec_instr()
275 ioread8_rep(cs->base + nfc->soc_info->data_offset, in ingenic_nand_exec_instr()
276 instr->ctx.data.buf.in, in ingenic_nand_exec_instr()
277 instr->ctx.data.len); in ingenic_nand_exec_instr()
279 ioread16_rep(cs->base + nfc->soc_info->data_offset, in ingenic_nand_exec_instr()
280 instr->ctx.data.buf.in, in ingenic_nand_exec_instr()
281 instr->ctx.data.len); in ingenic_nand_exec_instr()
284 if (instr->ctx.data.force_8bit || in ingenic_nand_exec_instr()
285 !(chip->options & NAND_BUSWIDTH_16)) in ingenic_nand_exec_instr()
286 iowrite8_rep(cs->base + nfc->soc_info->data_offset, in ingenic_nand_exec_instr()
287 instr->ctx.data.buf.out, in ingenic_nand_exec_instr()
288 instr->ctx.data.len); in ingenic_nand_exec_instr()
290 iowrite16_rep(cs->base + nfc->soc_info->data_offset, in ingenic_nand_exec_instr()
291 instr->ctx.data.buf.out, in ingenic_nand_exec_instr()
292 instr->ctx.data.len); in ingenic_nand_exec_instr()
295 if (!nand->busy_gpio) in ingenic_nand_exec_instr()
297 instr->ctx.waitrdy.timeout_ms); in ingenic_nand_exec_instr()
299 return nand_gpio_waitrdy(chip, nand->busy_gpio, in ingenic_nand_exec_instr()
300 instr->ctx.waitrdy.timeout_ms); in ingenic_nand_exec_instr()
305 return -EINVAL; in ingenic_nand_exec_instr()
312 struct ingenic_nand *nand = to_ingenic_nand(nand_to_mtd(chip)); in ingenic_nand_exec_op() local
313 struct ingenic_nfc *nfc = to_ingenic_nfc(nand->chip.controller); in ingenic_nand_exec_op()
321 cs = &nfc->cs[op->cs]; in ingenic_nand_exec_op()
322 jz4780_nemc_assert(nfc->dev, cs->bank, true); in ingenic_nand_exec_op()
323 for (i = 0; i < op->ninstrs; i++) { in ingenic_nand_exec_op()
324 ret = ingenic_nand_exec_instr(chip, cs, &op->instrs[i]); in ingenic_nand_exec_op()
328 if (op->instrs[i].delay_ns) in ingenic_nand_exec_op()
329 ndelay(op->instrs[i].delay_ns); in ingenic_nand_exec_op()
331 jz4780_nemc_assert(nfc->dev, cs->bank, false); in ingenic_nand_exec_op()
346 struct device *dev = &pdev->dev; in ingenic_nand_init_chip()
347 struct ingenic_nand *nand; in ingenic_nand_init_chip() local
354 cs = &nfc->cs[chipnr]; in ingenic_nand_init_chip()
358 return -EINVAL; in ingenic_nand_init_chip()
360 cs->bank = be32_to_cpu(*reg); in ingenic_nand_init_chip()
362 jz4780_nemc_set_type(nfc->dev, cs->bank, JZ4780_NEMC_BANK_NAND); in ingenic_nand_init_chip()
364 cs->base = devm_platform_ioremap_resource(pdev, chipnr); in ingenic_nand_init_chip()
365 if (IS_ERR(cs->base)) in ingenic_nand_init_chip()
366 return PTR_ERR(cs->base); in ingenic_nand_init_chip()
368 nand = devm_kzalloc(dev, sizeof(*nand), GFP_KERNEL); in ingenic_nand_init_chip()
369 if (!nand) in ingenic_nand_init_chip()
370 return -ENOMEM; in ingenic_nand_init_chip()
372 nand->busy_gpio = devm_gpiod_get_optional(dev, "rb", GPIOD_IN); in ingenic_nand_init_chip()
374 if (IS_ERR(nand->busy_gpio)) { in ingenic_nand_init_chip()
375 ret = PTR_ERR(nand->busy_gpio); in ingenic_nand_init_chip()
381 * The rb-gpios semantics was undocumented and qi,lb60 (along with in ingenic_nand_init_chip()
383 * NAND ready state, which is high level. Since there's no signal in ingenic_nand_init_chip()
384 * inverter on this board, it should be active-high. Let's fix that in ingenic_nand_init_chip()
385 * here for older DTs so we can re-use the generic nand_gpio_waitrdy() in ingenic_nand_init_chip()
389 gpiod_is_active_low(nand->busy_gpio)) in ingenic_nand_init_chip()
390 gpiod_toggle_active_low(nand->busy_gpio); in ingenic_nand_init_chip()
392 nand->wp_gpio = devm_gpiod_get_optional(dev, "wp", GPIOD_OUT_LOW); in ingenic_nand_init_chip()
394 if (IS_ERR(nand->wp_gpio)) { in ingenic_nand_init_chip()
395 ret = PTR_ERR(nand->wp_gpio); in ingenic_nand_init_chip()
400 chip = &nand->chip; in ingenic_nand_init_chip()
402 mtd->name = devm_kasprintf(dev, GFP_KERNEL, "%s.%d", dev_name(dev), in ingenic_nand_init_chip()
403 cs->bank); in ingenic_nand_init_chip()
404 if (!mtd->name) in ingenic_nand_init_chip()
405 return -ENOMEM; in ingenic_nand_init_chip()
406 mtd->dev.parent = dev; in ingenic_nand_init_chip()
408 chip->options = NAND_NO_SUBPAGE_WRITE; in ingenic_nand_init_chip()
409 chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_ON_HOST; in ingenic_nand_init_chip()
410 chip->controller = &nfc->controller; in ingenic_nand_init_chip()
413 chip->controller->ops = &ingenic_nand_controller_ops; in ingenic_nand_init_chip()
424 list_add_tail(&nand->chip_list, &nfc->chips); in ingenic_nand_init_chip()
435 while (!list_empty(&nfc->chips)) { in ingenic_nand_cleanup_chips()
436 ingenic_chip = list_first_entry(&nfc->chips, in ingenic_nand_cleanup_chips()
438 chip = &ingenic_chip->chip; in ingenic_nand_cleanup_chips()
442 list_del(&ingenic_chip->chip_list); in ingenic_nand_cleanup_chips()
449 struct device *dev = &pdev->dev; in ingenic_nand_init_chips()
453 int num_chips = of_get_child_count(dev->of_node); in ingenic_nand_init_chips()
455 if (num_chips > nfc->num_banks) { in ingenic_nand_init_chips()
457 num_chips, nfc->num_banks); in ingenic_nand_init_chips()
458 return -EINVAL; in ingenic_nand_init_chips()
461 for_each_child_of_node(dev->of_node, np) { in ingenic_nand_init_chips()
477 struct device *dev = &pdev->dev; in ingenic_nand_probe()
485 return -ENODEV; in ingenic_nand_probe()
490 return -ENOMEM; in ingenic_nand_probe()
492 nfc->soc_info = device_get_match_data(dev); in ingenic_nand_probe()
493 if (!nfc->soc_info) in ingenic_nand_probe()
494 return -EINVAL; in ingenic_nand_probe()
498 * having to call it again if the ECC driver returns -EPROBE_DEFER. in ingenic_nand_probe()
500 nfc->ecc = of_ingenic_ecc_get(dev->of_node); in ingenic_nand_probe()
501 if (IS_ERR(nfc->ecc)) in ingenic_nand_probe()
502 return PTR_ERR(nfc->ecc); in ingenic_nand_probe()
504 nfc->dev = dev; in ingenic_nand_probe()
505 nfc->num_banks = num_banks; in ingenic_nand_probe()
507 nand_controller_init(&nfc->controller); in ingenic_nand_probe()
508 INIT_LIST_HEAD(&nfc->chips); in ingenic_nand_probe()
512 if (nfc->ecc) in ingenic_nand_probe()
513 ingenic_ecc_release(nfc->ecc); in ingenic_nand_probe()
525 if (nfc->ecc) in ingenic_nand_remove()
526 ingenic_ecc_release(nfc->ecc); in ingenic_nand_remove()
553 { .compatible = "ingenic,jz4740-nand", .data = &jz4740_soc_info },
554 { .compatible = "ingenic,jz4725b-nand", .data = &jz4725b_soc_info },
555 { .compatible = "ingenic,jz4780-nand", .data = &jz4780_soc_info },
570 MODULE_AUTHOR("Alex Smith <alex@alex-smith.me.uk>");
572 MODULE_DESCRIPTION("Ingenic JZ47xx NAND driver");