Merge branch 'master' of https://source.denx.de/u-boot/custodians/u-boot-spi

- cadence-quadspi fixes (Apurva Nandan, Dhruva Gole)
- CHIP_ERASE optimization (Marek Vasut)
- fixups for s25fs512s (Takahiro Kuwano)
diff --git a/drivers/mtd/spi/spi-nor-core.c b/drivers/mtd/spi/spi-nor-core.c
index 2c3116e..6093277 100644
--- a/drivers/mtd/spi/spi-nor-core.c
+++ b/drivers/mtd/spi/spi-nor-core.c
@@ -669,6 +669,7 @@
 	case SNOR_MFR_MICRON:
 		/* Some Micron need WREN command; all will accept it */
 		need_wren = true;
+		fallthrough;
 	case SNOR_MFR_ISSI:
 	case SNOR_MFR_MACRONIX:
 	case SNOR_MFR_WINBOND:
@@ -903,6 +904,30 @@
 }
 #endif
 
+/**
+ * spi_nor_erase_chip() - Erase the entire flash memory.
+ * @nor:	pointer to 'struct spi_nor'.
+ *
+ * Return: 0 on success, -errno otherwise.
+ */
+static int spi_nor_erase_chip(struct spi_nor *nor)
+{
+	struct spi_mem_op op =
+		SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_CHIP_ERASE, 0),
+			   SPI_MEM_OP_NO_ADDR,
+			   SPI_MEM_OP_NO_DUMMY,
+			   SPI_MEM_OP_NO_DATA);
+	int ret;
+
+	spi_nor_setup_op(nor, &op, nor->write_proto);
+
+	ret = spi_mem_exec_op(nor->spi, &op);
+	if (ret)
+		return ret;
+
+	return nor->mtd.size;
+}
+
 /*
  * Initiate the erasure of a single sector. Returns the number of bytes erased
  * on success, a negative error code on error.
@@ -974,7 +999,12 @@
 		if (ret < 0)
 			goto erase_err;
 
-		ret = spi_nor_erase_sector(nor, addr);
+		if (len == mtd->size &&
+		    !(nor->flags & SNOR_F_NO_OP_CHIP_ERASE)) {
+			ret = spi_nor_erase_chip(nor);
+		} else {
+			ret = spi_nor_erase_sector(nor, addr);
+		}
 		if (ret < 0)
 			goto erase_err;
 
@@ -3199,6 +3229,87 @@
 /* Use ID byte 4 to distinguish S25FS256T and S25Hx-T */
 #define S25FS256T_ID4	(0x08)
 
+/* Number of dummy cycle for Read Any Register (RDAR) op. */
+#define S25FS_S_RDAR_DUMMY	8
+
+static int s25fs_s_quad_enable(struct spi_nor *nor)
+{
+	return spansion_quad_enable_volatile(nor, 0, S25FS_S_RDAR_DUMMY);
+}
+
+static int s25fs_s_erase_non_uniform(struct spi_nor *nor, loff_t addr)
+{
+	/* Support 8 x 4KB sectors at bottom */
+	return spansion_erase_non_uniform(nor, addr, SPINOR_OP_BE_4K_4B, 0, SZ_32K);
+}
+
+static int s25fs_s_setup(struct spi_nor *nor, const struct flash_info *info,
+			 const struct spi_nor_flash_parameter *params)
+{
+	int ret;
+	u8 cfr3v;
+
+	/* Bank Address Register is not supported */
+	if (CONFIG_IS_ENABLED(SPI_FLASH_BAR))
+		return -EOPNOTSUPP;
+
+	/*
+	 * Read CR3V to check if uniform sector is selected. If not, assign an
+	 * erase hook that supports non-uniform erase.
+	 */
+	ret = spansion_read_any_reg(nor, SPINOR_REG_ADDR_CFR3V,
+				    S25FS_S_RDAR_DUMMY, &cfr3v);
+	if (ret)
+		return ret;
+	if (!(cfr3v & CFR3V_UNHYSA))
+		nor->erase = s25fs_s_erase_non_uniform;
+
+	return spi_nor_default_setup(nor, info, params);
+}
+
+static void s25fs_s_default_init(struct spi_nor *nor)
+{
+	nor->setup = s25fs_s_setup;
+}
+
+static int s25fs_s_post_bfpt_fixup(struct spi_nor *nor,
+				   const struct sfdp_parameter_header *header,
+				   const struct sfdp_bfpt *bfpt,
+				   struct spi_nor_flash_parameter *params)
+{
+	/* The erase size is set to 4K from BFPT, but it's wrong. Fix it. */
+	nor->erase_opcode = SPINOR_OP_SE;
+	nor->mtd.erasesize = nor->info->sector_size;
+
+	/* The S25FS-S chip family reports 512-byte pages in BFPT but
+	 * in reality the write buffer still wraps at the safe default
+	 * of 256 bytes.  Overwrite the page size advertised by BFPT
+	 * to get the writes working.
+	 */
+	params->page_size = 256;
+
+	return 0;
+}
+
+static void s25fs_s_post_sfdp_fixup(struct spi_nor *nor,
+				    struct spi_nor_flash_parameter *params)
+{
+	/* READ_1_1_2 is not supported */
+	params->hwcaps.mask &= ~SNOR_HWCAPS_READ_1_1_2;
+	/* READ_1_1_4 is not supported */
+	params->hwcaps.mask &= ~SNOR_HWCAPS_READ_1_1_4;
+	/* PP_1_1_4 is not supported */
+	params->hwcaps.mask &= ~SNOR_HWCAPS_PP_1_1_4;
+	/* Use volatile register to enable quad */
+	params->quad_enable = s25fs_s_quad_enable;
+}
+
+static struct spi_nor_fixups s25fs_s_fixups = {
+	.default_init = s25fs_s_default_init,
+	.post_bfpt = s25fs_s_post_bfpt_fixup,
+	.post_sfdp = s25fs_s_post_sfdp_fixup,
+};
+
 static int s25_mdp_ready(struct spi_nor *nor)
 {
 	u32 addr;
@@ -3897,6 +4008,10 @@
 	if (CONFIG_IS_ENABLED(SPI_FLASH_BAR) &&
 	    !strcmp(nor->info->name, "s25fl256l"))
 		nor->fixups = &s25fl256l_fixups;
+
+	/* For FS-S (family ID = 0x81)  */
+	if (JEDEC_MFR(nor->info) == SNOR_MFR_SPANSION && nor->info->id[5] == 0x81)
+		nor->fixups = &s25fs_s_fixups;
 #endif
 
 #ifdef CONFIG_SPI_FLASH_MT35XU
diff --git a/drivers/spi/cadence_qspi.c b/drivers/spi/cadence_qspi.c
index c7f10c5..f931e4c 100644
--- a/drivers/spi/cadence_qspi.c
+++ b/drivers/spi/cadence_qspi.c
@@ -312,13 +312,12 @@
 		 * which is unsupported on some flash devices during register
 		 * reads, prefer STIG mode for such small reads.
 		 */
-		if (!op->addr.nbytes ||
-		    op->data.nbytes <= CQSPI_STIG_DATA_LEN_MAX)
+		if (op->data.nbytes <= CQSPI_STIG_DATA_LEN_MAX)
 			mode = CQSPI_STIG_READ;
 		else
 			mode = CQSPI_READ;
 	} else {
-		if (!op->addr.nbytes || !op->data.buf.out)
+		if (op->data.nbytes <= CQSPI_STIG_DATA_LEN_MAX)
 			mode = CQSPI_STIG_WRITE;
 		else
 			mode = CQSPI_WRITE;
@@ -362,8 +361,15 @@
 {
 	bool all_true, all_false;
 
-	all_true = op->cmd.dtr && op->addr.dtr && op->dummy.dtr &&
-		   op->data.dtr;
+	/*
+	 * op->dummy.dtr is required for converting nbytes into ncycles.
+	 * Also, don't check the dtr field of the op phase having zero nbytes.
+	 */
+	all_true = op->cmd.dtr &&
+		   (!op->addr.nbytes || op->addr.dtr) &&
+		   (!op->dummy.nbytes || op->dummy.dtr) &&
+		   (!op->data.nbytes || op->data.dtr);
+
 	all_false = !op->cmd.dtr && !op->addr.dtr && !op->dummy.dtr &&
 		    !op->data.dtr;
 
diff --git a/drivers/spi/cadence_qspi_apb.c b/drivers/spi/cadence_qspi_apb.c
index 21fe2e6..9ce2c0f 100644
--- a/drivers/spi/cadence_qspi_apb.c
+++ b/drivers/spi/cadence_qspi_apb.c
@@ -120,7 +120,16 @@
 {
 	int ret;
 
-	priv->dtr = op->data.dtr && op->cmd.dtr && op->addr.dtr;
+	/*
+	 * For an op to be DTR, cmd phase along with every other non-empty
+	 * phase should have dtr field set to 1. If an op phase has zero
+	 * nbytes, ignore its dtr field; otherwise, check its dtr field.
+	 * Also, dummy checks not performed here Since supports_op()
+	 * already checks that all or none of the fields are DTR.
+	 */
+	priv->dtr = op->cmd.dtr &&
+		    (!op->addr.nbytes || op->addr.dtr) &&
+		    (!op->data.nbytes || op->data.dtr);
 
 	ret = cadence_qspi_buswidth_to_inst_type(op->cmd.buswidth);
 	if (ret < 0)
@@ -367,6 +376,9 @@
 	if (!cadence_qspi_wait_idle(reg_base))
 		return -EIO;
 
+	/* Flush the CMDCTRL reg after the execution */
+	writel(0, reg_base + CQSPI_REG_CMDCTRL);
+
 	return 0;
 }
 
@@ -453,11 +465,6 @@
 	unsigned int dummy_clk;
 	u8 opcode;
 
-	if (rxlen > CQSPI_STIG_DATA_LEN_MAX || !rxbuf) {
-		printf("QSPI: Invalid input arguments rxlen %u\n", rxlen);
-		return -EINVAL;
-	}
-
 	if (priv->dtr)
 		opcode = op->cmd.opcode >> 8;
 	else
@@ -540,26 +547,12 @@
 	unsigned int reg = 0;
 	unsigned int wr_data;
 	unsigned int wr_len;
+	unsigned int dummy_clk;
 	unsigned int txlen = op->data.nbytes;
 	const void *txbuf = op->data.buf.out;
 	void *reg_base = priv->regbase;
-	u32 addr;
 	u8 opcode;
 
-	/* Reorder address to SPI bus order if only transferring address */
-	if (!txlen) {
-		addr = cpu_to_be32(op->addr.val);
-		if (op->addr.nbytes == 3)
-			addr >>= 8;
-		txbuf = &addr;
-		txlen = op->addr.nbytes;
-	}
-
-	if (txlen > CQSPI_STIG_DATA_LEN_MAX) {
-		printf("QSPI: Invalid input arguments txlen %u\n", txlen);
-		return -EINVAL;
-	}
-
 	if (priv->dtr)
 		opcode = op->cmd.opcode >> 8;
 	else
@@ -567,6 +560,27 @@
 
 	reg |= opcode << CQSPI_REG_CMDCTRL_OPCODE_LSB;
 
+	/* setup ADDR BIT field */
+	if (op->addr.nbytes) {
+		writel(op->addr.val, priv->regbase + CQSPI_REG_CMDADDRESS);
+		/*
+		 * address bytes are zero indexed
+		 */
+		reg |= (((op->addr.nbytes - 1) &
+			  CQSPI_REG_CMDCTRL_ADD_BYTES_MASK) <<
+			  CQSPI_REG_CMDCTRL_ADD_BYTES_LSB);
+		reg |= (0x1 << CQSPI_REG_CMDCTRL_ADDR_EN_LSB);
+	}
+
+	/* Set up dummy cycles. */
+	dummy_clk = cadence_qspi_calc_dummy(op, priv->dtr);
+	if (dummy_clk > CQSPI_DUMMY_CLKS_MAX)
+		return -EOPNOTSUPP;
+
+	if (dummy_clk)
+		reg |= (dummy_clk & CQSPI_REG_CMDCTRL_DUMMY_MASK)
+		     << CQSPI_REG_CMDCTRL_DUMMY_LSB;
+
 	if (txlen) {
 		/* writing data = yes */
 		reg |= (0x1 << CQSPI_REG_CMDCTRL_WR_EN_LSB);
diff --git a/drivers/spi/npcm_fiu_spi.c b/drivers/spi/npcm_fiu_spi.c
index 7000fe5..73c5064 100644
--- a/drivers/spi/npcm_fiu_spi.c
+++ b/drivers/spi/npcm_fiu_spi.c
@@ -11,6 +11,7 @@
 #include <linux/bitfield.h>
 #include <linux/log2.h>
 #include <linux/iopoll.h>
+#include <power/regulator.h>
 
 #define DW_SIZE			4
 #define CHUNK_SIZE		16
@@ -34,6 +35,34 @@
 #define UMA_CTS_RDYST		BIT(24)
 #define UMA_CTS_DEV_NUM_MASK	GENMASK(9, 8)
 
+/* Direct Write Configuration Register */
+#define DWR_CFG_WBURST_MASK	GENMASK(25, 24)
+#define DWR_CFG_ADDSIZ_MASK	GENMASK(17, 16)
+#define DWR_CFG_ABPCK_MASK	GENMASK(11, 10)
+#define DRW_CFG_DBPCK_MASK	GENMASK(9, 8)
+#define DRW_CFG_WRCMD		2
+enum {
+	DWR_WBURST_1_BYTE,
+	DWR_WBURST_16_BYTE = 3,
+};
+
+enum {
+	DWR_ADDSIZ_24_BIT,
+	DWR_ADDSIZ_32_BIT,
+};
+
+enum {
+	DWR_ABPCK_BIT_PER_CLK,
+	DWR_ABPCK_2_BIT_PER_CLK,
+	DWR_ABPCK_4_BIT_PER_CLK,
+};
+
+enum {
+	DWR_DBPCK_BIT_PER_CLK,
+	DWR_DBPCK_2_BIT_PER_CLK,
+	DWR_DBPCK_4_BIT_PER_CLK,
+};
+
 struct npcm_fiu_regs {
 	unsigned int    drd_cfg;
 	unsigned int    dwr_cfg;
@@ -67,19 +96,10 @@
 
 struct npcm_fiu_priv {
 	struct npcm_fiu_regs *regs;
-	struct clk clk;
 };
 
 static int npcm_fiu_spi_set_speed(struct udevice *bus, uint speed)
 {
-	struct npcm_fiu_priv *priv = dev_get_priv(bus);
-	int ret;
-
-	debug("%s: set speed %u\n", bus->name, speed);
-	ret = clk_set_rate(&priv->clk, speed);
-	if (ret < 0)
-		return ret;
-
 	return 0;
 }
 
@@ -349,13 +369,38 @@
 static int npcm_fiu_spi_probe(struct udevice *bus)
 {
 	struct npcm_fiu_priv *priv = dev_get_priv(bus);
-	int ret;
+	struct udevice *vqspi_supply;
+	int vqspi_uv;
 
 	priv->regs = (struct npcm_fiu_regs *)dev_read_addr_ptr(bus);
 
-	ret = clk_get_by_index(bus, 0, &priv->clk);
-	if (ret < 0)
-		return ret;
+	if (IS_ENABLED(CONFIG_DM_REGULATOR)) {
+		device_get_supply_regulator(bus, "vqspi-supply", &vqspi_supply);
+		vqspi_uv = dev_read_u32_default(bus, "vqspi-microvolt", 0);
+		/* Set IO voltage */
+		if (vqspi_supply && vqspi_uv)
+			regulator_set_value(vqspi_supply, vqspi_uv);
+	}
+
+	return 0;
+}
+
+static int npcm_fiu_spi_bind(struct udevice *bus)
+{
+	struct npcm_fiu_regs *regs;
+
+	if (dev_read_bool(bus, "nuvoton,spix-mode")) {
+		regs = dev_read_addr_ptr(bus);
+		if (!regs)
+			return -EINVAL;
+
+		/* Setup direct write cfg for SPIX */
+		writel(FIELD_PREP(DWR_CFG_WBURST_MASK, DWR_WBURST_16_BYTE) |
+		       FIELD_PREP(DWR_CFG_ADDSIZ_MASK, DWR_ADDSIZ_24_BIT) |
+		       FIELD_PREP(DWR_CFG_ABPCK_MASK, DWR_ABPCK_4_BIT_PER_CLK) |
+		       FIELD_PREP(DRW_CFG_DBPCK_MASK, DWR_DBPCK_4_BIT_PER_CLK) |
+		       DRW_CFG_WRCMD, &regs->dwr_cfg);
+	}
 
 	return 0;
 }
@@ -384,4 +429,5 @@
 	.ops    = &npcm_fiu_spi_ops,
 	.priv_auto = sizeof(struct npcm_fiu_priv),
 	.probe  = npcm_fiu_spi_probe,
+	.bind = npcm_fiu_spi_bind,
 };
diff --git a/drivers/spi/spi-mem.c b/drivers/spi/spi-mem.c
index 8e8995f..b7eca58 100644
--- a/drivers/spi/spi-mem.c
+++ b/drivers/spi/spi-mem.c
@@ -181,8 +181,12 @@
 	if (op->dummy.nbytes && op->dummy.buswidth == 8 && op->dummy.nbytes % 2)
 		return false;
 
-	if (op->data.dir != SPI_MEM_NO_DATA &&
-	    op->dummy.buswidth == 8 && op->data.nbytes % 2)
+	/*
+	 * Transactions of odd length do not make sense for 8D-8D-8D mode
+	 * because a byte is transferred in just half a cycle.
+	 */
+	if (op->data.dir != SPI_MEM_NO_DATA && op->data.dir != SPI_MEM_DATA_IN &&
+	    op->data.buswidth == 8 && op->data.nbytes % 2)
 		return false;
 
 	return spi_mem_check_buswidth(slave, op);
diff --git a/drivers/spi/spi-sn-f-ospi.c b/drivers/spi/spi-sn-f-ospi.c
index ebf2903..e3633a5 100644
--- a/drivers/spi/spi-sn-f-ospi.c
+++ b/drivers/spi/spi-sn-f-ospi.c
@@ -556,7 +556,7 @@
 	if (!f_ospi_supports_op_width(op))
 		return false;
 
-	return true;
+	return spi_mem_default_supports_op(slave, op);
 }
 
 static int f_ospi_adjust_op_size(struct spi_slave *slave, struct spi_mem_op *op)
diff --git a/drivers/spi/spi-synquacer.c b/drivers/spi/spi-synquacer.c
index 0cae3df..0f5d0a3 100644
--- a/drivers/spi/spi-synquacer.c
+++ b/drivers/spi/spi-synquacer.c
@@ -186,7 +186,7 @@
 	struct udevice *bus = dev->parent;
 	struct synquacer_spi_priv *priv = dev_get_priv(bus);
 	struct dm_spi_slave_plat *slave_plat = dev_get_parent_plat(dev);
-	u32 val, div, bus_width;
+	u32 val, div, bus_width = 1;
 	int rwflag;
 
 	rwflag = (rx ? 1 : 0) | (tx ? 2 : 0);
@@ -211,6 +211,8 @@
 		bus_width = 4;
 	else if (priv->mode & SPI_TX_OCTAL)
 		bus_width = 8;
+	else
+		log_warning("SPI mode not configured, setting to byte mode\n");
 
 	div = DIV_ROUND_UP(125000000, priv->speed);