[PATCH v6 10/15] nand: spi: add basic blocks for infrastructure

Boris Brezillon boris.brezillon at free-electrons.com
Mon May 29 14:51:18 PDT 2017


On Wed, 24 May 2017 15:07:06 +0800
Peter Pan <peterpandong at micron.com> wrote:

> This is the first commit for spi nand framkework.

					^ framework

> This commit is to add add basic building blocks

	      is adding basic ...

> for the SPI NAND infrastructure.
> 
> Signed-off-by: Peter Pan <peterpandong at micron.com>
> ---

[...]

> +
> +/**
> + * devm_spinand_alloc - [SPI NAND Interface] allocate SPI NAND device instance

Let's drop those [SPI NAND Interface] specifier. It's pretty obvious
that this is part of the spi-nand API, since those symbols are exported.

> + * @dev: pointer to device model structure
> + */
> +struct spinand_device *devm_spinand_alloc(struct device *dev)

You can pass a pointer to the nand_controller object driving the
nand_device here.

> +{
> +	struct spinand_device *spinand;
> +	struct mtd_info *mtd;
> +
> +	spinand = devm_kzalloc(dev, sizeof(*spinand), GFP_KERNEL);
> +	if (!spinand)
> +		return ERR_PTR(-ENOMEM);
> +
> +	spinand_set_of_node(spinand, dev->of_node);
> +	mutex_init(&spinand->lock);
> +	spinand->dev = dev;

Hm, I don't think this is correct. The device here is likely to
represent the controller not the SPI NAND device. For the generic spi
nand controller, I agree, it's the same, but, in case you have one
controller that is attached several spi devices, it's not.

How about putting the struct device pointer in nand_controller and then
pass the controller to this spinand_alloc() function.

> +	mtd = spinand_to_mtd(spinand);
> +	mtd->dev.parent = dev;
> +
> +	return spinand;
> +}
> +EXPORT_SYMBOL_GPL(devm_spinand_alloc);
> +
> +/**
> + * spinand_init - [SPI NAND Interface] initialize the SPI NAND device
> + * @spinand: SPI NAND device structure
> + */
> +int spinand_init(struct spinand_device *spinand)
> +{
> +	struct mtd_info *mtd = spinand_to_mtd(spinand);
> +	struct nand_device *nand = mtd_to_nand(mtd);
> +	int ret;
> +
> +	ret = spinand_detect(spinand);
> +	if (ret) {
> +		dev_err(spinand->dev,
> +			"Detect SPI NAND failed with error %d.\n", ret);
> +		goto err_out;

		return ret;


> +	}

I'd still prefer to move the detection step out of this _init()
function even if this implies duplicating the _detect()+_init()
sequence in all drivers. Maybe you can provide a wrapper called
spinand_detect_and_init() to do both in one go.

> +
> +	spinand_set_rd_wr_op(spinand);
> +
> +	/*
> +	 * Use kzalloc() instead of devm_kzalloc() here, beacause some drivers
> +	 * may use this buffer for DMA access.
> +	 * Memory allocated by devm_ does not guarantee DMA-safe alignment.
> +	 */
> +	spinand->buf = kzalloc(nand_page_size(nand) +
> +			       nand_per_page_oobsize(nand),
> +			       GFP_KERNEL);
> +	if (!spinand->buf) {
> +		ret = -ENOMEM;
> +		goto err_out;

		return -ENOMEM;

> +	}
> +
> +	spinand->oobbuf = spinand->buf + nand_page_size(nand);
> +
> +	ret = spinand_manufacturer_init(spinand);
> +	if (ret) {
> +		dev_err(spinand->dev,
> +			"Manufacurer init SPI NAND failed with err %d.\n",
> +			ret);
> +		goto err_free_buf;
> +	}
> +
> +	mtd->name = spinand->name;
> +	mtd->size = nand_size(nand);
> +	mtd->erasesize = nand_eraseblock_size(nand);
> +	mtd->writesize = nand_page_size(nand);
> +	mtd->writebufsize = mtd->writesize;
> +	mtd->owner = THIS_MODULE;
> +	mtd->type = MTD_NANDFLASH;
> +	mtd->flags = MTD_CAP_NANDFLASH;
> +	mtd->oobsize = nand_per_page_oobsize(nand);
> +	/*
> +	 * Right now, we don't support ECC, so let the whole oob
> +	 * area is available for user.
> +	 */
> +	mtd->oobavail = mtd->oobsize;
> +
> +	/* After power up, all blocks are locked, so unlock it here. */
> +	spinand_lock_block(spinand, BL_ALL_UNLOCKED);
> +
> +	return 0;
> +
> +err_free_buf:
> +	kfree(spinand->buf);
> +err_out:

You can get rid of err_out.

> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(spinand_init);
> +




More information about the linux-mtd mailing list