[PATCH] mtd: spi-nor: add support for BoyaMicro BY25Q128AS

Michael Walle mwalle at kernel.org
Mon Feb 2 02:39:56 PST 2026


Hi,

On Sat Jan 31, 2026 at 4:10 AM CET, Shiji Yang wrote:
> Add new SPI NOR flash vendor BoyaMicro and flash chip BY25Q128AS.
> This chip has 16MB of total capacity, divided into a total of 256
> sectors, each 64KB sized. The chip also supports 4KB sectors.
> Additionally, it supports dual and quad read modes. This chip does
> not support 16 bit SR writing, so we have to introduce a fixup for
> it to handle quad_enable mode correctly. SFDP dump:
> 00000000  53 46 44 50 00 01 01 ff  00 00 01 09 30 00 00 ff  |SFDP........0...|
> 00000010  68 00 01 03 60 00 00 ff  ff ff ff ff ff ff ff ff  |h...`...........|
> 00000020  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
> 00000030  e5 20 f1 ff ff ff ff 07  44 eb 08 6b 08 3b 42 bb  |. ......D..k.;B.|
> 00000040  ee ff ff ff ff ff 00 ff  ff ff 44 eb 0c 20 0f 52  |..........D.. .R|
> 00000050  10 d8 00 ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
> 00000060  00 36 00 27 9e f9 77 64  fc eb ff ff              |.6.'..wd....|

Thanks. This need to go below the "---" line. Also, you'll also need
to provide some basic tests, see
Documentation/driver-api/mtd/spi-nor.rst

> Co-authored-by: David Bauer <mail at david-bauer.net>

What is that? There is Co-developed-by:, but you'd need the SoB tag
from David, see Documentation/process/submitting-patches.rst

> Signed-off-by: Shiji Yang <yangshiji66 at outlook.com>
> ---
>  drivers/mtd/spi-nor/Makefile    |   1 +
>  drivers/mtd/spi-nor/boyamicro.c | 110 ++++++++++++++++++++++++++++++++
>  drivers/mtd/spi-nor/core.c      |   1 +
>  drivers/mtd/spi-nor/core.h      |   1 +
>  4 files changed, 113 insertions(+)
>  create mode 100644 drivers/mtd/spi-nor/boyamicro.c
>
> diff --git a/drivers/mtd/spi-nor/Makefile b/drivers/mtd/spi-nor/Makefile
> index 5dd9c35f6..0024ea03f 100644
> --- a/drivers/mtd/spi-nor/Makefile
> +++ b/drivers/mtd/spi-nor/Makefile
> @@ -2,6 +2,7 @@
>  
>  spi-nor-objs			:= core.o sfdp.o swp.o otp.o sysfs.o
>  spi-nor-objs			+= atmel.o
> +spi-nor-objs			+= boyamicro.o
>  spi-nor-objs			+= eon.o
>  spi-nor-objs			+= esmt.o
>  spi-nor-objs			+= everspin.o
> diff --git a/drivers/mtd/spi-nor/boyamicro.c b/drivers/mtd/spi-nor/boyamicro.c
> new file mode 100644
> index 000000000..059eccb3d
> --- /dev/null
> +++ b/drivers/mtd/spi-nor/boyamicro.c
> @@ -0,0 +1,110 @@
> +// SPDX-License-Identifier: GPL-2.0
> +
> +#include <linux/mtd/spi-nor.h>
> +
> +#include "core.h"
> +
> +#define BOYA_SPINOR_OP_WRSR2		0x31
> +
> +#define BOYA_SPI_NOR_WRSR2_OP(buf)					\
> +	SPI_MEM_OP(SPI_MEM_OP_CMD(BOYA_SPINOR_OP_WRSR2, 0),		\
> +		   SPI_MEM_OP_NO_ADDR,					\
> +		   SPI_MEM_OP_NO_DUMMY,					\
> +		   SPI_MEM_OP_DATA_OUT(1, buf, 0))
> +
> +static int boya_spi_nor_write_sr2(struct spi_nor *nor, const u8 *sr2)
> +{
> +	int ret;
> +
> +	ret = spi_nor_write_enable(nor);
> +	if (ret)
> +		return ret;
> +
> +	if (nor->spimem) {
> +		struct spi_mem_op op = BOYA_SPI_NOR_WRSR2_OP(sr2);
> +
> +		spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
> +
> +		ret = spi_mem_exec_op(nor->spimem, &op);
> +	} else {
> +		ret = spi_nor_controller_ops_write_reg(nor, BOYA_SPINOR_OP_WRSR2,
> +						       sr2, 1);
> +	}
> +
> +	if (ret) {
> +		dev_dbg(nor->dev, "error %d writing SR2\n", ret);
> +		return ret;
> +	}
> +
> +	return spi_nor_wait_till_ready(nor);
> +}

Are you sure, the chip doesn't support writing two status bytes for
the 01h instruction?

In any case, the 31h instruction isn't specific to boya, so that
should go into core.c. I.e. SFDP already describes this .quad_enable
(15th DWORD, bits 22:20, value 6) but we doesn't support it yet.
Also, this flash doesn't contain that info in the SFDP, a pity. But
it's described in the JESD214 standard, so it should go into core.c
not into a manufacturer specific module.

What you'll probably have to do is, to add a special casing in
spi_nor_sr2_bit1_quad_enable() or spi_nor_write_16bit_cr_and_check()
and check whether the flash supports the 01h command with 2 bytes
(SNOR_F_HAS_16BIT_SR).

> +
> +static int by25q128_sr2_bit1_quad_enable(struct spi_nor *nor)
> +{
> +	int ret;
> +	u8 sr2_written;
> +	u8 *sr2 = nor->bouncebuf;
> +
> +	/* Check current Quad Enable bit value. */
> +	ret = spi_nor_read_cr(nor, sr2);
> +	if (ret)
> +		return ret;
> +	if (*sr2 & SR2_QUAD_EN_BIT1)
> +		return 0;
> +
> +	/* Update the Quad Enable bit. */
> +	*sr2 |= SR2_QUAD_EN_BIT1;
> +
> +	ret = boya_spi_nor_write_sr2(nor, sr2);
> +	if (ret)
> +		return ret;
> +
> +	sr2_written = *sr2;
> +
> +	/* Read back and check it. */
> +	ret = spi_nor_read_cr(nor, sr2);
> +	if (ret)
> +		return ret;
> +
> +	if (*sr2 != sr2_written) {
> +		dev_dbg(nor->dev, "SR2: Read back test failed\n");
> +		return -EIO;
> +	}
> +
> +	return 0;
> +}

This will then be the same as spi_nor_sr2_bit1_quad_enable().

> +
> +static int
> +by25q128_post_bfpt(struct spi_nor *nor,
> +		   const struct sfdp_parameter_header *bfpt_header,
> +		   const struct sfdp_bfpt *bfpt)
> +{
> +	/**
> +	 * BY25Q128xS series SFDP table does not define the Quad
> +	 * Enable methods. Overwrite the default Quad Enable method.
> +	 */
> +	nor->params->quad_enable = by25q128_sr2_bit1_quad_enable;
> +
> +	/* The 01H command can only be used to write SR1 */
> +	nor->flags &= ~SNOR_F_HAS_16BIT_SR;

That should probably go into the manufacturer default_init.

> +
> +	return 0;
> +}
> +
> +static const struct spi_nor_fixups by25q128_fixups = {
> +	.post_bfpt = by25q128_post_bfpt,
> +};
> +
> +static const struct flash_info boyamicro_parts[] = {
> +	{
> +		/* BY25Q128AS, BY25Q128ES */
> +		.id = SNOR_ID(0x68, 0x40, 0x18),

And here we are again. 0x68 isn't the boya manufacturer id. They are
missing continuation codes.
I'm really not sure, what we can do about that. We'll have to pick
between
 (1) reject patches like this and just don't support vendors who
     doesn't play by the rules
 (2) only offer bindings via a device tree, so there will be no auto
     probing
 (3) merge it as is, hoping that the real 0x68 vendor won't ever
     produce any flash chips. Or we have to deal with that later and
     facing the possibility that this vendor will be at a
     disadvantage because someone already hijacked their ID and
     they'd need to come up with special handling.

-michael

> +		.fixups = &by25q128_fixups,
> +	},
> +};
> +
> +const struct spi_nor_manufacturer spi_nor_boyamicro = {
> +	.name = "boyamicro",
> +	.parts = boyamicro_parts,
> +	.nparts = ARRAY_SIZE(boyamicro_parts),
> +};
> diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
> index d3f8a78ef..b9adf5ca1 100644
> --- a/drivers/mtd/spi-nor/core.c
> +++ b/drivers/mtd/spi-nor/core.c
> @@ -1941,6 +1941,7 @@ int spi_nor_sr2_bit7_quad_enable(struct spi_nor *nor)
>  
>  static const struct spi_nor_manufacturer *manufacturers[] = {
>  	&spi_nor_atmel,
> +	&spi_nor_boyamicro,
>  	&spi_nor_eon,
>  	&spi_nor_esmt,
>  	&spi_nor_everspin,
> diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
> index 16b382d4f..b1667a08c 100644
> --- a/drivers/mtd/spi-nor/core.h
> +++ b/drivers/mtd/spi-nor/core.h
> @@ -591,6 +591,7 @@ struct sfdp {
>  
>  /* Manufacturer drivers. */
>  extern const struct spi_nor_manufacturer spi_nor_atmel;
> +extern const struct spi_nor_manufacturer spi_nor_boyamicro;
>  extern const struct spi_nor_manufacturer spi_nor_eon;
>  extern const struct spi_nor_manufacturer spi_nor_esmt;
>  extern const struct spi_nor_manufacturer spi_nor_everspin;

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 297 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-mtd/attachments/20260202/023ba4b3/attachment.sig>


More information about the linux-mtd mailing list