[PATCH v3 1/3] mtd: nand: add asm9260 NFC driver

Boris Brezillon boris.brezillon at free-electrons.com
Thu Jan 1 13:14:33 PST 2015


On Wed, 31 Dec 2014 13:58:51 +0100
Oleksij Rempel <linux at rempel-privat.de> wrote:

> Add driver for Nand Flash Controller used on Alphascales ASM9260 chips.
> The IP core of this controller has some similarities with
> Evatronix NANDFLASH-CTRL IP (unknown revision), so probably it can be reused
> by some other SoCs.
> 
> Signed-off-by: Oleksij Rempel <linux at rempel-privat.de>
> ---
>  drivers/mtd/nand/Kconfig        |   7 +
>  drivers/mtd/nand/Makefile       |   1 +
>  drivers/mtd/nand/asm9260_nand.c | 989 ++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 997 insertions(+)
>  create mode 100644 drivers/mtd/nand/asm9260_nand.c
> 
> diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
> index dd10646..580a608 100644
> --- a/drivers/mtd/nand/Kconfig
> +++ b/drivers/mtd/nand/Kconfig
> @@ -41,6 +41,13 @@ config MTD_SM_COMMON
>  	tristate
>  	default n

[...]

> +
> +static void asm9260_nand_command_lp(struct mtd_info *mtd,
> +		unsigned int command, int column, int page_addr)
> +{
> +	struct asm9260_nand_priv *priv = mtd_to_priv(mtd);
> +
> +	switch (command) {
> +	case NAND_CMD_RESET:
> +		asm9260_nand_cmd_prep(priv, NAND_CMD_RESET, 0, 0, SEQ0);
> +		asm9260_nand_cmd_comp(mtd, 0);
> +		break;
> +
> +	case NAND_CMD_READID:
> +		iowrite32(1, priv->base + HW_FIFO_INIT);
> +		iowrite32((ADDR_CYCLE_1 << BM_CTRL_ADDR_CYCLE1_S)
> +			| BM_CTRL_CUSTOM_PAGE_SIZE
> +			| (PAGE_SIZE_4096B << BM_CTRL_PAGE_SIZE_S)
> +			| (BLOCK_SIZE_32P << BM_CTRL_BLOCK_SIZE_S)
> +			| BM_CTRL_INT_EN
> +			| (ADDR_CYCLE_1 << BM_CTRL_ADDR_CYCLE0_S),
> +			priv->base + HW_CTRL);
> +
> +		iowrite32(8, priv->base + HW_DATA_SIZE);
> +		iowrite32(column, priv->base + HW_ADDR0_0);
> +		asm9260_nand_cmd_prep(priv, NAND_CMD_READID, 0, 0, SEQ1);
> +
> +		priv->read_cache_cnt = 0;
> +		break;
> +
> +	case NAND_CMD_READOOB:
> +		column += mtd->writesize;
> +		command = NAND_CMD_READ0;
> +	case NAND_CMD_READ0:
> +		iowrite32(1, priv->base + HW_FIFO_INIT);
> +
> +		if (column == 0) {
> +			asm9260_nand_ctrl(priv, 0);
> +			iowrite32(priv->spare_size, priv->base + HW_SPARE_SIZE);
> +		} else if (column == mtd->writesize) {
> +			asm9260_nand_ctrl(priv, BM_CTRL_CUSTOM_PAGE_SIZE);
> +			iowrite32(mtd->oobsize, priv->base + HW_SPARE_SIZE);
> +			iowrite32(mtd->oobsize, priv->base + HW_DATA_SIZE);
> +		} else {
> +			dev_err(priv->dev, "Couldn't support the column\n");
> +			break;
> +		}
> +
> +		asm9260_nand_set_addr(priv, page_addr, column);
> +
> +		asm9260_nand_cmd_prep(priv, NAND_CMD_READ0,
> +				NAND_CMD_READSTART, 0, SEQ10);
> +
> +		priv->read_cache_cnt = 0;
> +		break;
> +	case NAND_CMD_SEQIN:
> +		iowrite32(1, priv->base + HW_FIFO_INIT);
> +
> +		if (column == 0) {
> +			priv->page_cache = page_addr;
> +			asm9260_nand_ctrl(priv, 0);
> +			iowrite32(priv->spare_size, priv->base + HW_SPARE_SIZE);
> +		} else if (column == mtd->writesize) {
> +			asm9260_nand_ctrl(priv, BM_CTRL_CUSTOM_PAGE_SIZE);
> +			iowrite32(mtd->oobsize, priv->base + HW_DATA_SIZE);
> +		}
> +
> +		asm9260_nand_set_addr(priv, page_addr, column);
> +
> +		asm9260_nand_cmd_prep(priv, NAND_CMD_SEQIN, NAND_CMD_PAGEPROG,
> +			0, SEQ12);
> +
> +		break;
> +	case NAND_CMD_STATUS:
> +		iowrite32(1, priv->base + HW_FIFO_INIT);
> +		asm9260_nand_ctrl(priv, BM_CTRL_CUSTOM_PAGE_SIZE);
> +
> +		/*
> +		 * Workaround for status bug.
> +		 * Instead of SEQ4 we need to use SEQ1 here, which will
> +		 * send cmd with address. For this case we need to make sure
> +		 * ADDR == 0.
> +		 */
> +		asm9260_nand_set_addr(priv, 0, 0);
> +		iowrite32(4, priv->base + HW_DATA_SIZE);
> +		asm9260_nand_cmd_prep(priv, NAND_CMD_STATUS, 0, 0, SEQ1);
> +
> +		priv->read_cache_cnt = 0;
> +		break;
> +
> +	case NAND_CMD_ERASE1:
> +		priv->wait_time = 400;
> +		asm9260_nand_set_addr(priv, page_addr, column);
> +
> +		asm9260_nand_ctrl(priv, 0);
> +
> +		/*
> +		 * Prepare and send command now. We don't need to split it in
> +		 * two stages.
> +		 */
> +		asm9260_nand_cmd_prep(priv, NAND_CMD_ERASE1, NAND_CMD_ERASE2,
> +				0, SEQ14);
> +		asm9260_nand_cmd_comp(mtd, 0);
> +		break;
> +	default:
> +		break;

You should support other NAND commands (like the ONFI related ones)
instead of silently ignoring them.


-- 
Boris Brezillon, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com



More information about the linux-mtd mailing list