Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d03af162 authored by Miquel Raynal's avatar Miquel Raynal
Browse files

mtd: rawnand: denali: convert to nand_scan()



Two helpers have been added to the core to do all kind of controller
side configuration/initialization between the detection phase and the
final NAND scan. Implement these hooks so that we can convert the driver
to just use nand_scan() instead of the nand_scan_ident() +
nand_scan_tail() pair.

Signed-off-by: default avatarMiquel Raynal <miquel.raynal@bootlin.com>
Reviewed-by: default avatarBoris Brezillon <boris.brezillon@bootlin.com>
Acked-by: default avatarMasahiro Yamada <yamada.masahiro@socionext.com>
parent b2342c1c
Loading
Loading
Loading
Loading
+77 −62
Original line number Diff line number Diff line
@@ -1205,62 +1205,12 @@ static int denali_multidev_fixup(struct denali_nand_info *denali)
	return 0;
}

int denali_init(struct denali_nand_info *denali)
static int denali_attach_chip(struct nand_chip *chip)
{
	struct nand_chip *chip = &denali->nand;
	struct mtd_info *mtd = nand_to_mtd(chip);
	u32 features = ioread32(denali->reg + FEATURES);
	struct denali_nand_info *denali = mtd_to_denali(mtd);
	int ret;

	mtd->dev.parent = denali->dev;
	denali_hw_init(denali);

	init_completion(&denali->complete);
	spin_lock_init(&denali->irq_lock);

	denali_clear_irq_all(denali);

	ret = devm_request_irq(denali->dev, denali->irq, denali_isr,
			       IRQF_SHARED, DENALI_NAND_NAME, denali);
	if (ret) {
		dev_err(denali->dev, "Unable to request IRQ\n");
		return ret;
	}

	denali_enable_irq(denali);
	denali_reset_banks(denali);

	denali->active_bank = DENALI_INVALID_BANK;

	nand_set_flash_node(chip, denali->dev->of_node);
	/* Fallback to the default name if DT did not give "label" property */
	if (!mtd->name)
		mtd->name = "denali-nand";

	chip->select_chip = denali_select_chip;
	chip->read_byte = denali_read_byte;
	chip->write_byte = denali_write_byte;
	chip->read_word = denali_read_word;
	chip->cmd_ctrl = denali_cmd_ctrl;
	chip->dev_ready = denali_dev_ready;
	chip->waitfunc = denali_waitfunc;

	if (features & FEATURES__INDEX_ADDR) {
		denali->host_read = denali_indexed_read;
		denali->host_write = denali_indexed_write;
	} else {
		denali->host_read = denali_direct_read;
		denali->host_write = denali_direct_write;
	}

	/* clk rate info is needed for setup_data_interface */
	if (denali->clk_rate && denali->clk_x_rate)
		chip->setup_data_interface = denali_setup_data_interface;

	ret = nand_scan_ident(mtd, denali->max_banks, NULL);
	if (ret)
		goto disable_irq;

	if (ioread32(denali->reg + FEATURES) & FEATURES__DMA)
		denali->dma_avail = 1;

@@ -1293,7 +1243,7 @@ int denali_init(struct denali_nand_info *denali)
				   mtd->oobsize - denali->oob_skip_bytes);
	if (ret) {
		dev_err(denali->dev, "Failed to setup ECC settings.\n");
		goto disable_irq;
		return ret;
	}

	dev_dbg(denali->dev,
@@ -1337,7 +1287,7 @@ int denali_init(struct denali_nand_info *denali)

	ret = denali_multidev_fixup(denali);
	if (ret)
		goto disable_irq;
		return ret;

	/*
	 * This buffer is DMA-mapped by denali_{read,write}_page_raw.  Do not
@@ -1345,26 +1295,92 @@ int denali_init(struct denali_nand_info *denali)
	 * guarantee DMA-safe alignment.
	 */
	denali->buf = kmalloc(mtd->writesize + mtd->oobsize, GFP_KERNEL);
	if (!denali->buf) {
		ret = -ENOMEM;
		goto disable_irq;
	if (!denali->buf)
		return -ENOMEM;

	return 0;
}

static void denali_detach_chip(struct nand_chip *chip)
{
	struct mtd_info *mtd = nand_to_mtd(chip);
	struct denali_nand_info *denali = mtd_to_denali(mtd);

	kfree(denali->buf);
}

static const struct nand_controller_ops denali_controller_ops = {
	.attach_chip = denali_attach_chip,
	.detach_chip = denali_detach_chip,
};

int denali_init(struct denali_nand_info *denali)
{
	struct nand_chip *chip = &denali->nand;
	struct mtd_info *mtd = nand_to_mtd(chip);
	u32 features = ioread32(denali->reg + FEATURES);
	int ret;

	mtd->dev.parent = denali->dev;
	denali_hw_init(denali);

	init_completion(&denali->complete);
	spin_lock_init(&denali->irq_lock);

	denali_clear_irq_all(denali);

	ret = devm_request_irq(denali->dev, denali->irq, denali_isr,
			       IRQF_SHARED, DENALI_NAND_NAME, denali);
	if (ret) {
		dev_err(denali->dev, "Unable to request IRQ\n");
		return ret;
	}

	denali_enable_irq(denali);
	denali_reset_banks(denali);

	denali->active_bank = DENALI_INVALID_BANK;

	nand_set_flash_node(chip, denali->dev->of_node);
	/* Fallback to the default name if DT did not give "label" property */
	if (!mtd->name)
		mtd->name = "denali-nand";

	chip->select_chip = denali_select_chip;
	chip->read_byte = denali_read_byte;
	chip->write_byte = denali_write_byte;
	chip->read_word = denali_read_word;
	chip->cmd_ctrl = denali_cmd_ctrl;
	chip->dev_ready = denali_dev_ready;
	chip->waitfunc = denali_waitfunc;

	if (features & FEATURES__INDEX_ADDR) {
		denali->host_read = denali_indexed_read;
		denali->host_write = denali_indexed_write;
	} else {
		denali->host_read = denali_direct_read;
		denali->host_write = denali_direct_write;
	}

	ret = nand_scan_tail(mtd);
	/* clk rate info is needed for setup_data_interface */
	if (denali->clk_rate && denali->clk_x_rate)
		chip->setup_data_interface = denali_setup_data_interface;

	chip->dummy_controller.ops = &denali_controller_ops;
	ret = nand_scan(mtd, denali->max_banks);
	if (ret)
		goto free_buf;
		goto disable_irq;

	ret = mtd_device_register(mtd, NULL, 0);
	if (ret) {
		dev_err(denali->dev, "Failed to register MTD: %d\n", ret);
		goto cleanup_nand;
	}

	return 0;

cleanup_nand:
	nand_cleanup(chip);
free_buf:
	kfree(denali->buf);
disable_irq:
	denali_disable_irq(denali);

@@ -1377,7 +1393,6 @@ void denali_remove(struct denali_nand_info *denali)
	struct mtd_info *mtd = nand_to_mtd(&denali->nand);

	nand_release(mtd);
	kfree(denali->buf);
	denali_disable_irq(denali);
}
EXPORT_SYMBOL(denali_remove);