[PATCH v5 5/6] nand: spi: Add generic SPI controller support

Marek Vasut marex at denx.de
Fri Apr 14 06:26:24 PDT 2017


On 04/10/2017 09:51 AM, Peter Pan wrote:
> This commit supports to use generic spi controller
> as spi nand controller.
> 
> Signed-off-by: Peter Pan <peterpandong at micron.com>
> ---
>  drivers/mtd/nand/spi/Kconfig                   |   2 +
>  drivers/mtd/nand/spi/Makefile                  |   1 +
>  drivers/mtd/nand/spi/controllers/Kconfig       |   5 +
>  drivers/mtd/nand/spi/controllers/Makefile      |   1 +
>  drivers/mtd/nand/spi/controllers/generic-spi.c | 159 +++++++++++++++++++++++++
>  5 files changed, 168 insertions(+)
>  create mode 100644 drivers/mtd/nand/spi/controllers/Kconfig
>  create mode 100644 drivers/mtd/nand/spi/controllers/Makefile
>  create mode 100644 drivers/mtd/nand/spi/controllers/generic-spi.c

[...]

> +static int gen_spi_spinand_probe(struct spi_device *spi)
> +{
> +	struct spinand_device *chip;
> +	struct gen_spi_spinand_controller *controller;
> +	struct spinand_controller *spinand_controller;
> +	struct device *dev = &spi->dev;
> +	u16 mode = spi->mode;
> +	int ret;
> +
> +	chip = spinand_alloc(dev);
> +	if (IS_ERR(chip)) {
> +		ret = PTR_ERR(chip);
> +		goto err1;
> +	}

Would it make sense to embed the struct spinand_device into struct
gen_spi_nand_controller , so you'd get rid of one allocation ?

> +	controller = devm_kzalloc(dev, sizeof(*controller), GFP_KERNEL);
> +	if (!controller) {
> +		ret = -ENOMEM;
> +		goto err2;
> +	}
> +	controller->spi = spi;
> +	spinand_controller = &controller->ctrl;
> +	spinand_controller->ops = &gen_spi_spinand_ops;
> +	spinand_controller->caps = SPINAND_CAP_RD_X1 | SPINAND_CAP_WR_X1;
> +
> +	if ((mode & SPI_RX_QUAD) && (mode & SPI_TX_QUAD))
> +		spinand_controller->caps |= SPINAND_CAP_RD_QUAD;
> +	if ((mode & SPI_RX_DUAL) && (mode & SPI_TX_DUAL))
> +		spinand_controller->caps |= SPINAND_CAP_RD_DUAL;
> +	if (mode & SPI_RX_QUAD)
> +		spinand_controller->caps |= SPINAND_CAP_RD_X4;
> +	if (mode & SPI_RX_DUAL)
> +		spinand_controller->caps |= SPINAND_CAP_RD_X2;
> +	if (mode & SPI_TX_QUAD)
> +		spinand_controller->caps |= SPINAND_CAP_WR_QUAD |
> +					    SPINAND_CAP_WR_X4;
> +	if (mode & SPI_TX_DUAL)
> +		spinand_controller->caps |= SPINAND_CAP_WR_DUAL |
> +					    SPINAND_CAP_WR_X2;
> +	chip->controller.controller = spinand_controller;
> +	/*
> +	 * generic spi controller doesn't have ecc capability,
> +	 * so use on-die ecc.
> +	 */
> +	chip->ecc.type = SPINAND_ECC_ONDIE;
> +	spi_set_drvdata(spi, chip);
> +
> +	ret = spinand_register(chip);
> +	if (ret)
> +		goto err3;
> +
> +	return 0;
> +
> +err3:
> +	devm_kfree(dev, controller);
> +err2:
> +	spinand_free(chip);
> +err1:
> +	return ret;
> +}
> +
> +static int gen_spi_spinand_remove(struct spi_device *spi)
> +{
> +	struct spinand_device *chip = spi_get_drvdata(spi);
> +	struct spinand_controller *scontroller = chip->controller.controller;
> +	struct gen_spi_spinand_controller *controller;
> +
> +	spinand_unregister(chip);
> +	controller = to_gen_spi_spinand_controller(scontroller);
> +	devm_kfree(&spi->dev, controller);
> +	spinand_free(chip);
> +
> +	return 0;
> +}
> +
> +static struct spi_driver gen_spi_spinand_driver = {
> +	.driver = {
> +		.name	= "generic_spinand",
> +		.owner	= THIS_MODULE,
> +	},
> +	.probe	= gen_spi_spinand_probe,
> +	.remove	= gen_spi_spinand_remove,
> +};
> +module_spi_driver(gen_spi_spinand_driver);
> +
> +MODULE_DESCRIPTION("Generic SPI controller to support SPI NAND");
> +MODULE_AUTHOR("Peter Pan<peterpandong at micron.com>");
> +MODULE_LICENSE("GPL v2");
> 


-- 
Best regards,
Marek Vasut



More information about the linux-mtd mailing list