Commit 26fd6bff authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'mtd/fixes-for-7.1-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux

Pull mtd fixes from Miquel Raynal:
 "Besides an out-of-bound bug, this is about properly supporting Winbond
  octal SPI NAND chips which use a specific pattern for stuffing more
  address bits in some operations. This uses the spi-mem flag in SPI
  NAND that was added to the spi-mem layer just before the merge window
  through the spi tree"

* tag 'mtd/fixes-for-7.1-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux:
  mtd: spinand: winbond: Fix ODTR write VCR on W35NxxJW
  mtd: spinand: winbond: Set the packed page read flag to W35N02/04JW
  mtd: spinand: Add support for packed read data ODTR commands
  mtd: spi-nor: debugfs: fix out-of-bounds read in spi_nor_params_show()
parents cae4ef6f 135ac3b8
Loading
Loading
Loading
Loading
+21 −3
Original line number Diff line number Diff line
@@ -100,6 +100,17 @@ spinand_fill_page_read_op(struct spinand_device *spinand, u64 addr)
	return op;
}

static struct spi_mem_op
spinand_fill_page_read_packed_op(struct spinand_device *spinand, u64 addr)
{
	struct spi_mem_op op = spinand->op_templates->page_read;

	op.cmd.opcode |= addr >> 16;
	op.addr.val = addr & 0xFFFF;

	return op;
}

struct spi_mem_op
spinand_fill_prog_exec_op(struct spinand_device *spinand, u64 addr)
{
@@ -453,7 +464,10 @@ static int spinand_load_page_op(struct spinand_device *spinand,
{
	struct nand_device *nand = spinand_to_nand(spinand);
	unsigned int row = nanddev_pos_to_row(nand, &req->pos);
	struct spi_mem_op op = SPINAND_OP(spinand, page_read, row);
	bool packed = spinand->flags & SPINAND_ODTR_PACKED_PAGE_READ;
	struct spi_mem_op op = packed ?
		SPINAND_OP(spinand, page_read_packed, row) :
		SPINAND_OP(spinand, page_read, row);

	return spi_mem_exec_op(spinand->spimem, &op);
}
@@ -1489,9 +1503,13 @@ static int spinand_init_odtr_instruction_set(struct spinand_device *spinand)
	if (!spi_mem_supports_op(spinand->spimem, &tmpl->blk_erase))
		return -EOPNOTSUPP;

	if (spinand->flags & SPINAND_ODTR_PACKED_PAGE_READ)
		tmpl->page_read = (struct spi_mem_op)SPINAND_PAGE_READ_PACKED_8D_8D_0_OP(0);
	else
		tmpl->page_read = (struct spi_mem_op)SPINAND_PAGE_READ_8D_8D_0_OP(0);
	if (!spi_mem_supports_op(spinand->spimem, &tmpl->page_read))
	if (!spi_mem_supports_op(spinand->spimem, &tmpl->page_read)) {
		return -EOPNOTSUPP;
	}

	tmpl->prog_exec = (struct spi_mem_op)SPINAND_PROG_EXEC_8D_8D_0_OP(0);
	if (!spi_mem_supports_op(spinand->spimem, &tmpl->prog_exec))
+3 −3
Original line number Diff line number Diff line
@@ -99,7 +99,7 @@ static SPINAND_OP_VARIANTS(update_cache_variants,

#define SPINAND_WINBOND_WRITE_VCR_8D_8D_8D(reg, buf)			\
	SPI_MEM_OP(SPI_MEM_DTR_OP_RPT_CMD(0x81, 8),			\
		   SPI_MEM_DTR_OP_ADDR(4, reg, 8),			\
		   SPI_MEM_DTR_OP_ADDR(4, reg << 8, 8),			\
		   SPI_MEM_OP_NO_DUMMY,					\
		   SPI_MEM_DTR_OP_DATA_OUT(2, buf, 8))

@@ -518,7 +518,7 @@ static const struct spinand_info winbond_spinand_table[] = {
		     SPINAND_INFO_OP_VARIANTS(&read_cache_octal_variants,
					      &write_cache_octal_variants,
					      &update_cache_octal_variants),
		     0,
		     SPINAND_ODTR_PACKED_PAGE_READ,
		     SPINAND_INFO_VENDOR_OPS(&winbond_w35_ops),
		     SPINAND_ECCINFO(&w35n01jw_ooblayout, NULL),
		     SPINAND_CONFIGURE_CHIP(w35n0xjw_vcr_cfg)),
@@ -529,7 +529,7 @@ static const struct spinand_info winbond_spinand_table[] = {
		     SPINAND_INFO_OP_VARIANTS(&read_cache_octal_variants,
					      &write_cache_octal_variants,
					      &update_cache_octal_variants),
		     0,
		     SPINAND_ODTR_PACKED_PAGE_READ,
		     SPINAND_INFO_VENDOR_OPS(&winbond_w35_ops),
		     SPINAND_ECCINFO(&w35n01jw_ooblayout, NULL),
		     SPINAND_CONFIGURE_CHIP(w35n0xjw_vcr_cfg)),
+3 −1
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0

#include <linux/array_size.h>
#include <linux/debugfs.h>
#include <linux/mtd/spi-nor.h>
#include <linux/spi/spi.h>
@@ -92,7 +93,8 @@ static int spi_nor_params_show(struct seq_file *s, void *data)
	seq_printf(s, "address nbytes\t%u\n", nor->addr_nbytes);

	seq_puts(s, "flags\t\t");
	spi_nor_print_flags(s, nor->flags, snor_f_names, sizeof(snor_f_names));
	spi_nor_print_flags(s, nor->flags, snor_f_names,
			    ARRAY_SIZE(snor_f_names));
	seq_puts(s, "\n");

	seq_puts(s, "\nopcodes\n");
+7 −0
Original line number Diff line number Diff line
@@ -290,6 +290,12 @@
		   SPI_MEM_OP_NO_DUMMY,					\
		   SPI_MEM_OP_NO_DATA)

#define SPINAND_PAGE_READ_PACKED_8D_8D_0_OP(addr)			\
	SPI_MEM_OP(SPI_MEM_DTR_OP_PACKED_CMD(0x13, addr >> 16, 8),	\
		   SPI_MEM_DTR_OP_ADDR(2, addr & 0xffff, 8),		\
		   SPI_MEM_OP_NO_DUMMY,					\
		   SPI_MEM_OP_NO_DATA)

#define SPINAND_PAGE_READ_FROM_CACHE_8D_8D_8D_OP(addr, ndummy, buf, len, freq) \
	SPI_MEM_OP(SPI_MEM_DTR_OP_RPT_CMD(0x9d, 8),			\
		   SPI_MEM_DTR_OP_ADDR(2, addr, 8),			\
@@ -483,6 +489,7 @@ struct spinand_ecc_info {
#define SPINAND_HAS_PROG_PLANE_SELECT_BIT		BIT(2)
#define SPINAND_HAS_READ_PLANE_SELECT_BIT		BIT(3)
#define SPINAND_NO_RAW_ACCESS				BIT(4)
#define SPINAND_ODTR_PACKED_PAGE_READ			BIT(5)

/**
 * struct spinand_ondie_ecc_conf - private SPI-NAND on-die ECC engine structure