#ifdef CONFIG_ARM /* gpio_nand_dosync() * * Make sure the GPIO state changes occur in-order with writes to NAND * memory region. * Needed on PXA due to bus-reordering within the SoC itself (see section on * I/O ordering in PXA manual (section 2.3, p35)
*/ staticvoid gpio_nand_dosync(struct gpiomtd *gpiomtd)
{ unsignedlong tmp;
if (gpiomtd->io_sync) { /* * Linux memory barriers don't cater for what's required here. * What's required is what's here - a read from a separate * region with a dependency on that read.
*/
tmp = readl(gpiomtd->io_sync); asmvolatile("mov %1, %0\n" : "=r" (tmp) : "r" (tmp));
}
} #else staticinlinevoid gpio_nand_dosync(struct gpiomtd *gpiomtd) {} #endif
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);
if (!dev->of_node && !dev_get_platdata(dev)) return -EINVAL;
gpiomtd = devm_kzalloc(dev, sizeof(*gpiomtd), GFP_KERNEL); if (!gpiomtd) return -ENOMEM;
chip = &gpiomtd->nand_chip;
gpiomtd->io = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(gpiomtd->io)) return PTR_ERR(gpiomtd->io);
res = gpio_nand_get_io_sync(pdev); if (res) {
gpiomtd->io_sync = devm_ioremap_resource(dev, res); if (IS_ERR(gpiomtd->io_sync)) return PTR_ERR(gpiomtd->io_sync);
}
ret = gpio_nand_get_config(dev, &gpiomtd->plat); if (ret) return ret;
/* Just enable the chip */
gpiomtd->nce = devm_gpiod_get_optional(dev, "nce", GPIOD_OUT_HIGH); if (IS_ERR(gpiomtd->nce)) return PTR_ERR(gpiomtd->nce);
/* We disable write protection once we know probe() will succeed */
gpiomtd->nwp = devm_gpiod_get_optional(dev, "nwp", GPIOD_OUT_LOW); if (IS_ERR(gpiomtd->nwp)) {
ret = PTR_ERR(gpiomtd->nwp); goto out_ce;
}
gpiomtd->ale = devm_gpiod_get(dev, "ale", GPIOD_OUT_LOW); if (IS_ERR(gpiomtd->ale)) {
ret = PTR_ERR(gpiomtd->ale); goto out_ce;
}
gpiomtd->cle = devm_gpiod_get(dev, "cle", GPIOD_OUT_LOW); if (IS_ERR(gpiomtd->cle)) {
ret = PTR_ERR(gpiomtd->cle); goto out_ce;
}
gpiomtd->rdy = devm_gpiod_get_optional(dev, "rdy", GPIOD_IN); if (IS_ERR(gpiomtd->rdy)) {
ret = PTR_ERR(gpiomtd->rdy); goto out_ce;
}
/* Disable write protection, if wired up */ if (gpiomtd->nwp && !IS_ERR(gpiomtd->nwp))
gpiod_direction_output(gpiomtd->nwp, 1);
/* * This driver assumes that the default ECC engine should be TYPE_SOFT. * Set ->engine_type before registering the NAND devices in order to * provide a driver specific default value.
*/
chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT;
ret = nand_scan(chip, 1); if (ret) goto err_wp;
if (gpiomtd->plat.adjust_parts)
gpiomtd->plat.adjust_parts(&gpiomtd->plat, mtd->size);
ret = mtd_device_register(mtd, gpiomtd->plat.parts,
gpiomtd->plat.num_parts); if (!ret) return 0;
err_wp: if (gpiomtd->nwp && !IS_ERR(gpiomtd->nwp))
gpiod_set_value(gpiomtd->nwp, 0);
out_ce: if (gpiomtd->nce && !IS_ERR(gpiomtd->nce))
gpiod_set_value(gpiomtd->nce, 0);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.