Commit f7091fb7 authored by Miquel Raynal's avatar Miquel Raynal
Browse files

Merge tag 'spi-nor/for-6.6' into mtd/next



SPI NOR core changes:
* fix assumption on enabling quad mode in
  spi_nor_write_16bit_sr_and_check()
* avoid setting SRWD bit in SR if WP# signal not connected as it will
  configure the SR permanently as read only. Add "no-wp" dt property.
* clarify the need for spi-nor compatibles in dt-bindings

SPI NOR manufacturer drivers changes:
* spansion:
  - add support for S28HS02GT
  - switch methods to use vreg_offset from SFDP instead of hardcoding
    the register value
* microchip/sst:
  - add support for sst26vf032b flash
* winbond:
  - correct flags for Winbond w25q128

Signed-off-by: default avatarMiquel Raynal <miquel.raynal@bootlin.com>
parents a417ab33 69d50d04
Loading
Loading
Loading
Loading
+19 −2
Original line number Diff line number Diff line
@@ -43,8 +43,10 @@ properties:
          - const: jedec,spi-nor
      - const: jedec,spi-nor
    description:
      Must also include "jedec,spi-nor" for any SPI NOR flash that can be
      identified by the JEDEC READ ID opcode (0x9F).
      SPI NOR flashes compatible with the JEDEC SFDP standard or which may be
      identified with the READ ID opcode (0x9F) do not deserve a specific
      compatible. They should instead only be matched against the generic
      "jedec,spi-nor" compatible.

  reg:
    minItems: 1
@@ -70,6 +72,21 @@ properties:
      be used on such systems, to denote the absence of a reliable reset
      mechanism.

  no-wp:
    type: boolean
    description:
      The status register write disable (SRWD) bit in status register, combined
      with the WP# signal, provides hardware data protection for the device. When
      the SRWD bit is set to 1, and the WP# signal is either driven LOW or hard
      strapped to LOW, the status register nonvolatile bits become read-only and
      the WRITE STATUS REGISTER operation will not execute. The only way to exit
      this hardware-protected mode is to drive WP# HIGH. If the WP# signal of the
      flash device is not connected or is wrongly tied to GND (that includes internal
      pull-downs) then status register permanently becomes read-only as the SRWD bit
      cannot be reset. This boolean flag can be used on such systems to avoid setting
      the SRWD bit while writing the status register. WP# signal hard strapped to GND
      can be a valid use case.

  reset-gpios:
    description:
      A GPIO line connected to the RESET (active low) signal of the device.
+6 −2
Original line number Diff line number Diff line
@@ -48,9 +48,11 @@ static const struct spi_nor_locking_ops at25fs_nor_locking_ops = {
	.is_locked = at25fs_nor_is_locked,
};

static void at25fs_nor_late_init(struct spi_nor *nor)
static int at25fs_nor_late_init(struct spi_nor *nor)
{
	nor->params->locking_ops = &at25fs_nor_locking_ops;

	return 0;
}

static const struct spi_nor_fixups at25fs_nor_fixups = {
@@ -149,9 +151,11 @@ static const struct spi_nor_locking_ops atmel_nor_global_protection_ops = {
	.is_locked = atmel_nor_is_global_protected,
};

static void atmel_nor_global_protection_late_init(struct spi_nor *nor)
static int atmel_nor_global_protection_late_init(struct spi_nor *nor)
{
	nor->params->locking_ops = &atmel_nor_global_protection_ops;

	return 0;
}

static const struct spi_nor_fixups atmel_nor_global_protection_fixups = {
+6 −27
Original line number Diff line number Diff line
@@ -394,30 +394,18 @@ static int nxp_spifi_probe(struct platform_device *pdev)
	if (IS_ERR(spifi->flash_base))
		return PTR_ERR(spifi->flash_base);

	spifi->clk_spifi = devm_clk_get(&pdev->dev, "spifi");
	spifi->clk_spifi = devm_clk_get_enabled(&pdev->dev, "spifi");
	if (IS_ERR(spifi->clk_spifi)) {
		dev_err(&pdev->dev, "spifi clock not found\n");
		dev_err(&pdev->dev, "spifi clock not found or unable to enable\n");
		return PTR_ERR(spifi->clk_spifi);
	}

	spifi->clk_reg = devm_clk_get(&pdev->dev, "reg");
	spifi->clk_reg = devm_clk_get_enabled(&pdev->dev, "reg");
	if (IS_ERR(spifi->clk_reg)) {
		dev_err(&pdev->dev, "reg clock not found\n");
		dev_err(&pdev->dev, "reg clock not found or unable to enable\n");
		return PTR_ERR(spifi->clk_reg);
	}

	ret = clk_prepare_enable(spifi->clk_reg);
	if (ret) {
		dev_err(&pdev->dev, "unable to enable reg clock\n");
		return ret;
	}

	ret = clk_prepare_enable(spifi->clk_spifi);
	if (ret) {
		dev_err(&pdev->dev, "unable to enable spifi clock\n");
		goto dis_clk_reg;
	}

	spifi->dev = &pdev->dev;
	platform_set_drvdata(pdev, spifi);

@@ -430,24 +418,17 @@ static int nxp_spifi_probe(struct platform_device *pdev)
	flash_np = of_get_next_available_child(pdev->dev.of_node, NULL);
	if (!flash_np) {
		dev_err(&pdev->dev, "no SPI flash device to configure\n");
		ret = -ENODEV;
		goto dis_clks;
		return -ENODEV;
	}

	ret = nxp_spifi_setup_flash(spifi, flash_np);
	of_node_put(flash_np);
	if (ret) {
		dev_err(&pdev->dev, "unable to setup flash chip\n");
		goto dis_clks;
		return ret;
	}

	return 0;

dis_clks:
	clk_disable_unprepare(spifi->clk_spifi);
dis_clk_reg:
	clk_disable_unprepare(spifi->clk_reg);
	return ret;
}

static int nxp_spifi_remove(struct platform_device *pdev)
@@ -455,8 +436,6 @@ static int nxp_spifi_remove(struct platform_device *pdev)
	struct nxp_spifi *spifi = platform_get_drvdata(pdev);

	mtd_device_unregister(&spifi->nor.mtd);
	clk_disable_unprepare(spifi->clk_spifi);
	clk_disable_unprepare(spifi->clk_reg);

	return 0;
}
+34 −23
Original line number Diff line number Diff line
@@ -870,21 +870,22 @@ static int spi_nor_write_16bit_sr_and_check(struct spi_nor *nor, u8 sr1)
		ret = spi_nor_read_cr(nor, &sr_cr[1]);
		if (ret)
			return ret;
	} else if (nor->params->quad_enable) {
	} else if (spi_nor_get_protocol_width(nor->read_proto) == 4 &&
		   spi_nor_get_protocol_width(nor->write_proto) == 4 &&
		   nor->params->quad_enable) {
		/*
		 * If the Status Register 2 Read command (35h) is not
		 * supported, we should at least be sure we don't
		 * change the value of the SR2 Quad Enable bit.
		 *
		 * We can safely assume that when the Quad Enable method is
		 * set, the value of the QE bit is one, as a consequence of the
		 * nor->params->quad_enable() call.
		 * When the Quad Enable method is set and the buswidth is 4, we
		 * can safely assume that the value of the QE bit is one, as a
		 * consequence of the nor->params->quad_enable() call.
		 *
		 * We can safely assume that the Quad Enable bit is present in
		 * the Status Register 2 at BIT(1). According to the JESD216
		 * revB standard, BFPT DWORDS[15], bits 22:20, the 16-bit
		 * Write Status (01h) command is available just for the cases
		 * in which the QE bit is described in SR2 at BIT(1).
		 * According to the JESD216 revB standard, BFPT DWORDS[15],
		 * bits 22:20, the 16-bit Write Status (01h) command is
		 * available just for the cases in which the QE bit is
		 * described in SR2 at BIT(1).
		 */
		sr_cr[1] = SR2_QUAD_EN_BIT1;
	} else {
@@ -2844,6 +2845,9 @@ static void spi_nor_init_flags(struct spi_nor *nor)
	if (of_property_read_bool(np, "broken-flash-reset"))
		nor->flags |= SNOR_F_BROKEN_RESET;

	if (of_property_read_bool(np, "no-wp"))
		nor->flags |= SNOR_F_NO_WP;

	if (flags & SPI_NOR_SWP_IS_VOLATILE)
		nor->flags |= SNOR_F_SWP_IS_VOLATILE;

@@ -2897,16 +2901,23 @@ static void spi_nor_init_fixup_flags(struct spi_nor *nor)
 * SFDP standard, or where SFDP tables are not defined at all.
 * Will replace the spi_nor_manufacturer_init_params() method.
 */
static void spi_nor_late_init_params(struct spi_nor *nor)
static int spi_nor_late_init_params(struct spi_nor *nor)
{
	struct spi_nor_flash_parameter *params = nor->params;
	int ret;

	if (nor->manufacturer && nor->manufacturer->fixups &&
	    nor->manufacturer->fixups->late_init)
		nor->manufacturer->fixups->late_init(nor);
	    nor->manufacturer->fixups->late_init) {
		ret = nor->manufacturer->fixups->late_init(nor);
		if (ret)
			return ret;
	}

	if (nor->info->fixups && nor->info->fixups->late_init)
		nor->info->fixups->late_init(nor);
	if (nor->info->fixups && nor->info->fixups->late_init) {
		ret = nor->info->fixups->late_init(nor);
		if (ret)
			return ret;
	}

	/* Default method kept for backward compatibility. */
	if (!params->set_4byte_addr_mode)
@@ -2924,6 +2935,8 @@ static void spi_nor_late_init_params(struct spi_nor *nor)

	if (nor->info->n_banks > 1)
		params->bank_size = div64_u64(params->size, nor->info->n_banks);

	return 0;
}

/**
@@ -3082,22 +3095,20 @@ static int spi_nor_init_params(struct spi_nor *nor)
		spi_nor_init_params_deprecated(nor);
	}

	spi_nor_late_init_params(nor);

	return 0;
	return spi_nor_late_init_params(nor);
}

/** spi_nor_octal_dtr_enable() - enable Octal DTR I/O if needed
/** spi_nor_set_octal_dtr() - enable or disable Octal DTR I/O.
 * @nor:                 pointer to a 'struct spi_nor'
 * @enable:              whether to enable or disable Octal DTR
 *
 * Return: 0 on success, -errno otherwise.
 */
static int spi_nor_octal_dtr_enable(struct spi_nor *nor, bool enable)
static int spi_nor_set_octal_dtr(struct spi_nor *nor, bool enable)
{
	int ret;

	if (!nor->params->octal_dtr_enable)
	if (!nor->params->set_octal_dtr)
		return 0;

	if (!(nor->read_proto == SNOR_PROTO_8_8_8_DTR &&
@@ -3107,7 +3118,7 @@ static int spi_nor_octal_dtr_enable(struct spi_nor *nor, bool enable)
	if (!(nor->flags & SNOR_F_IO_MODE_EN_VOLATILE))
		return 0;

	ret = nor->params->octal_dtr_enable(nor, enable);
	ret = nor->params->set_octal_dtr(nor, enable);
	if (ret)
		return ret;

@@ -3168,7 +3179,7 @@ static int spi_nor_init(struct spi_nor *nor)
{
	int err;

	err = spi_nor_octal_dtr_enable(nor, true);
	err = spi_nor_set_octal_dtr(nor, true);
	if (err) {
		dev_dbg(nor->dev, "octal mode not supported\n");
		return err;
@@ -3270,7 +3281,7 @@ static int spi_nor_suspend(struct mtd_info *mtd)
	int ret;

	/* Disable octal DTR mode if we enabled it. */
	ret = spi_nor_octal_dtr_enable(nor, false);
	ret = spi_nor_set_octal_dtr(nor, false);
	if (ret)
		dev_err(nor->dev, "suspend() failed\n");

+6 −3
Original line number Diff line number Diff line
@@ -132,6 +132,7 @@ enum spi_nor_option_flags {
	SNOR_F_SWP_IS_VOLATILE	= BIT(13),
	SNOR_F_RWW		= BIT(14),
	SNOR_F_ECC		= BIT(15),
	SNOR_F_NO_WP		= BIT(16),
};

struct spi_nor_read_command {
@@ -363,7 +364,7 @@ struct spi_nor_otp {
 * @erase_map:		the erase map parsed from the SFDP Sector Map Parameter
 *                      Table.
 * @otp:		SPI NOR OTP info.
 * @octal_dtr_enable:	enables SPI NOR octal DTR mode.
 * @set_octal_dtr:	enables or disables SPI NOR octal DTR mode.
 * @quad_enable:	enables SPI NOR quad mode.
 * @set_4byte_addr_mode: puts the SPI NOR in 4 byte addressing mode.
 * @convert_addr:	converts an absolute address into something the flash
@@ -377,6 +378,7 @@ struct spi_nor_otp {
 *			than reading the status register to indicate they
 *			are ready for a new command
 * @locking_ops:	SPI NOR locking methods.
 * @priv:		flash's private data.
 */
struct spi_nor_flash_parameter {
	u64				bank_size;
@@ -397,7 +399,7 @@ struct spi_nor_flash_parameter {
	struct spi_nor_erase_map        erase_map;
	struct spi_nor_otp		otp;

	int (*octal_dtr_enable)(struct spi_nor *nor, bool enable);
	int (*set_octal_dtr)(struct spi_nor *nor, bool enable);
	int (*quad_enable)(struct spi_nor *nor);
	int (*set_4byte_addr_mode)(struct spi_nor *nor, bool enable);
	u32 (*convert_addr)(struct spi_nor *nor, u32 addr);
@@ -405,6 +407,7 @@ struct spi_nor_flash_parameter {
	int (*ready)(struct spi_nor *nor);

	const struct spi_nor_locking_ops *locking_ops;
	void *priv;
};

/**
@@ -431,7 +434,7 @@ struct spi_nor_fixups {
			 const struct sfdp_parameter_header *bfpt_header,
			 const struct sfdp_bfpt *bfpt);
	int (*post_sfdp)(struct spi_nor *nor);
	void (*late_init)(struct spi_nor *nor);
	int (*late_init)(struct spi_nor *nor);
};

/**
Loading