From bda58d294189963dbe26c851d348cc714ffee63f Mon Sep 17 00:00:00 2001 From: Jon Lin Date: Tue, 8 Nov 2022 16:43:54 +0800 Subject: [PATCH] mtd: spi-nor: normem: Add code Support NM25Q128EVB. Change-Id: Id781d499407b1d4db448db1cfff71b43bf6e8e93 Signed-off-by: Jon Lin --- drivers/mtd/spi-nor/Makefile | 1 + drivers/mtd/spi-nor/core.c | 83 ++++++++++++++++++++++++++++++++++++ drivers/mtd/spi-nor/core.h | 2 + drivers/mtd/spi-nor/normem.c | 28 ++++++++++++ include/linux/mtd/spi-nor.h | 2 + 5 files changed, 116 insertions(+) create mode 100644 drivers/mtd/spi-nor/normem.c diff --git a/drivers/mtd/spi-nor/Makefile b/drivers/mtd/spi-nor/Makefile index 0e98dd6bd07d..ef4e92bb5f68 100644 --- a/drivers/mtd/spi-nor/Makefile +++ b/drivers/mtd/spi-nor/Makefile @@ -11,6 +11,7 @@ spi-nor-objs += everspin.o spi-nor-objs += fmsh.o spi-nor-objs += fujitsu.o spi-nor-objs += gigadevice.o +spi-nor-objs += normem.o spi-nor-objs += intel.o spi-nor-objs += issi.o spi-nor-objs += macronix.o diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c index 10d7b74ef9ed..2f38ca1e5568 100644 --- a/drivers/mtd/spi-nor/core.c +++ b/drivers/mtd/spi-nor/core.c @@ -891,6 +891,45 @@ static int spi_nor_write_16bit_sr_and_check(struct spi_nor *nor, u8 sr1) return 0; } +/** + * spi_nor_write_cr() - Write the Configure Register. + * @nor: pointer to 'struct spi_nor'. + * @sr: pointer to DMA-able buffer to write to the Status Register. + * @len: number of bytes to write to the Status Register. + * + * Return: 0 on success, -errno otherwise. + */ +static int spi_nor_write_8bit_cr(struct spi_nor *nor, u8 cr) +{ + int ret; + u8 *sr_cr = nor->bouncebuf; + + ret = spi_nor_write_enable(nor); + if (ret) + return ret; + + sr_cr[0] = cr; + + if (nor->spimem) { + struct spi_mem_op op = + SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WRCR, 1), + SPI_MEM_OP_NO_ADDR, + SPI_MEM_OP_NO_DUMMY, + SPI_MEM_OP_DATA_OUT(1, sr_cr, 1)); + + ret = spi_mem_exec_op(nor->spimem, &op); + } else { + ret = nor->controller_ops->write_reg(nor, SPINOR_OP_WRCR, sr_cr, 1); + } + + if (ret) { + dev_dbg(nor->dev, "error %d writing SR\n", ret); + return ret; + } + + return spi_nor_wait_till_ready(nor); +} + /** * spi_nor_write_16bit_cr_and_check() - Write the Status Register 1 and the * Configuration Register in one shot. Ensure that the byte written in the @@ -2055,6 +2094,49 @@ int spi_nor_sr2_bit7_quad_enable(struct spi_nor *nor) return 0; } +/** + * spi_nor_sr2_bit2_quad_enable() - set QE bit in Status Register 2. + * @nor: pointer to a 'struct spi_nor' + * + * Set the Quad Enable (QE) bit in the Status Register 2. + * + * Return: 0 on success, -errno otherwise. + */ +int spi_nor_sr2_bit2_quad_enable(struct spi_nor *nor) +{ + u8 *cr = nor->bouncebuf; + int ret; + u8 cr_written; + + /* Check current Quad Enable bit value. */ + ret = spi_nor_read_cr(nor, cr); + if (ret) + return ret; + if (*cr & SR2_QUAD_EN_BIT2) + return 0; + + /* Update the Quad Enable bit. */ + *cr |= SR2_QUAD_EN_BIT2; + + ret = spi_nor_write_8bit_cr(nor, *cr); + if (ret) + return ret; + + cr_written = *cr; + + /* Read back and check it. */ + ret = spi_nor_read_cr(nor, cr); + if (ret) + return ret; + + if (*cr != cr_written) { + dev_dbg(nor->dev, "CR: Read back test failed\n"); + return -EIO; + } + + return 0; +} + static const struct spi_nor_manufacturer *manufacturers[] = { &spi_nor_atmel, &spi_nor_boya, @@ -2066,6 +2148,7 @@ static const struct spi_nor_manufacturer *manufacturers[] = { &spi_nor_fmsh, &spi_nor_fujitsu, &spi_nor_gigadevice, + &spi_nor_normem, &spi_nor_intel, &spi_nor_issi, &spi_nor_macronix, diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h index 56fb9c963e06..f0aee9508c77 100644 --- a/drivers/mtd/spi-nor/core.h +++ b/drivers/mtd/spi-nor/core.h @@ -391,6 +391,7 @@ extern const struct spi_nor_manufacturer spi_nor_everspin; extern const struct spi_nor_manufacturer spi_nor_fmsh; extern const struct spi_nor_manufacturer spi_nor_fujitsu; extern const struct spi_nor_manufacturer spi_nor_gigadevice; +extern const struct spi_nor_manufacturer spi_nor_normem; extern const struct spi_nor_manufacturer spi_nor_intel; extern const struct spi_nor_manufacturer spi_nor_issi; extern const struct spi_nor_manufacturer spi_nor_macronix; @@ -414,6 +415,7 @@ void spi_nor_unlock_and_unprep(struct spi_nor *nor); int spi_nor_sr1_bit6_quad_enable(struct spi_nor *nor); int spi_nor_sr2_bit1_quad_enable(struct spi_nor *nor); int spi_nor_sr2_bit7_quad_enable(struct spi_nor *nor); +int spi_nor_sr2_bit2_quad_enable(struct spi_nor *nor); int spi_nor_write_sr_and_check(struct spi_nor *nor, u8 sr1); int spi_nor_xread_sr(struct spi_nor *nor, u8 *sr); diff --git a/drivers/mtd/spi-nor/normem.c b/drivers/mtd/spi-nor/normem.c new file mode 100644 index 000000000000..c181ead1ae70 --- /dev/null +++ b/drivers/mtd/spi-nor/normem.c @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2022 Rockchip Electronics Co., Ltd. + */ + +#include + +#include "core.h" + +static const struct flash_info normem_parts[] = { + { "NM25Q128EVB", INFO(0x522118, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, +}; + +static void normem_default_init(struct spi_nor *nor) +{ + nor->params->quad_enable = spi_nor_sr1_bit6_quad_enable; +} + +static const struct spi_nor_fixups normem_fixups = { + .default_init = normem_default_init, +}; + +const struct spi_nor_manufacturer spi_nor_normem = { + .name = "normem", + .parts = normem_parts, + .nparts = ARRAY_SIZE(normem_parts), + .fixups = &normem_fixups, +}; diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h index 60bac2c0ec45..bfe4d492c6bf 100644 --- a/include/linux/mtd/spi-nor.h +++ b/include/linux/mtd/spi-nor.h @@ -47,6 +47,7 @@ #define SPINOR_OP_RDID 0x9f /* Read JEDEC ID */ #define SPINOR_OP_RDSFDP 0x5a /* Read SFDP */ #define SPINOR_OP_RDCR 0x35 /* Read configuration register */ +#define SPINOR_OP_WRCR 0x31 /* Write configure register */ #define SPINOR_OP_RDFSR 0x70 /* Read flag status register */ #define SPINOR_OP_CLFSR 0x50 /* Clear flag status register */ #define SPINOR_OP_RDEAR 0xc8 /* Read Extended Address Register */ @@ -135,6 +136,7 @@ /* Status Register 2 bits. */ #define SR2_QUAD_EN_BIT1 BIT(1) +#define SR2_QUAD_EN_BIT2 BIT(2) #define SR2_QUAD_EN_BIT7 BIT(7) /* Supported SPI protocols */