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

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



SPI NOR core changes:
* Add support for flash reset using the dt reset-gpios property.
* Update hwcaps.mask to include 8D-8D-8D read and page program ops
  when xSPI profile 1.0 table is defined.
* Bypass zero erase size in spi_nor_find_best_erase_type().
* Fix select_uniform_erase to skip 0 erase size
* Add generic flash driver. If a flash is not found in the flash_info
  array, fall back to the generic flash driver which is described solely
  by the flash's SFDP tables.
* Fix the number of bytes for the dummy cycles in
  spi_nor_spimem_check_readop().
* Introduce SPI_NOR_QUAD_PP flag, as PP_1_1_4 is not SFDP discoverable.

SPI NOR manufacturer drivers changes:
* Spansion:
  - use PARSE_SFDP for s28hs512t,
  - add support for s28hl512t, s28hl01gt, and s28hs01gt.
* Gigadevice: Replace default_init() with post_bfpt() for gd25q256.
* Micron - ST: Enable locking for mt25qu256a.
* Winbond: Add support for W25Q512NW-IQ.
* ISSI: Use PARSE_SFDP and SPI_NOR_QUAD_PP.

Fix merge conflict in the jedec,spi-nor bindings.

Signed-off-by: default avatarMiquel Raynal <miquel.raynal@bootlin.com>
parents 1d46f1ae 1799cd85
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -5,6 +5,9 @@ Contact: linux-mtd@lists.infradead.org
Description:	(RO) The JEDEC ID of the SPI NOR flash as reported by the
		flash device.

		The attribute is not present if the flash doesn't support
		the "Read JEDEC ID" command (9Fh). This is the case for
		non-JEDEC compliant flashes.

What:		/sys/bus/spi/devices/.../spi-nor/manufacturer
Date:		April 2021
@@ -12,6 +15,9 @@ KernelVersion: 5.14
Contact:	linux-mtd@lists.infradead.org
Description:	(RO) Manufacturer of the SPI NOR flash.

		The attribute is not present if the flash device isn't
		known to the kernel and is only probed by its SFDP
		tables.

What:		/sys/bus/spi/devices/.../spi-nor/partname
Date:		April 2021
+8 −0
Original line number Diff line number Diff line
@@ -70,10 +70,17 @@ properties:
      be used on such systems, to denote the absence of a reliable reset
      mechanism.

  reset-gpios:
    description:
      A GPIO line connected to the RESET (active low) signal of the device.
      If "broken-flash-reset" is present then having this property does not
      make any difference.

unevaluatedProperties: false

examples:
  - |
    #include <dt-bindings/gpio/gpio.h>
    spi {
        #address-cells = <1>;
        #size-cells = <0>;
@@ -83,6 +90,7 @@ examples:
            reg = <0>;
            spi-max-frequency = <40000000>;
            m25p,fast-read;
            reset-gpios = <&gpio 12 GPIO_ACTIVE_LOW>;
        };
    };
...
+80 −5
Original line number Diff line number Diff line
@@ -1184,6 +1184,8 @@ spi_nor_find_best_erase_type(const struct spi_nor_erase_map *map,
			continue;

		erase = &map->erase_type[i];
		if (!erase->size)
			continue;

		/* Alignment is not mandatory for overlaid regions */
		if (region->offset & SNOR_OVERLAID_REGION &&
@@ -1632,6 +1634,16 @@ static const struct spi_nor_manufacturer *manufacturers[] = {
	&spi_nor_xmc,
};

static const struct flash_info spi_nor_generic_flash = {
	.name = "spi-nor-generic",
	/*
	 * JESD216 rev A doesn't specify the page size, therefore we need a
	 * sane default.
	 */
	.page_size = 256,
	.parse_sfdp = true,
};

static const struct flash_info *spi_nor_match_id(struct spi_nor *nor,
						 const u8 *id)
{
@@ -1664,7 +1676,20 @@ static const struct flash_info *spi_nor_detect(struct spi_nor *nor)
		return ERR_PTR(ret);
	}

	/* Cache the complete flash ID. */
	nor->id = devm_kmemdup(nor->dev, id, SPI_NOR_MAX_ID_LEN, GFP_KERNEL);
	if (!nor->id)
		return ERR_PTR(-ENOMEM);

	info = spi_nor_match_id(nor, id);

	/* Fallback to a generic flash described only by its SFDP data. */
	if (!info) {
		ret = spi_nor_check_sfdp_signature(nor);
		if (!ret)
			info = &spi_nor_generic_flash;
	}

	if (!info) {
		dev_err(nor->dev, "unrecognized JEDEC id bytes: %*ph\n",
			SPI_NOR_MAX_ID_LEN, id);
@@ -1914,7 +1939,8 @@ static int spi_nor_spimem_check_readop(struct spi_nor *nor,
	spi_nor_spimem_setup_op(nor, &op, read->proto);

	/* convert the dummy cycles to the number of bytes */
	op.dummy.nbytes = (nor->read_dummy * op.dummy.buswidth) / 8;
	op.dummy.nbytes = (read->num_mode_clocks + read->num_wait_states) *
			  op.dummy.buswidth / 8;
	if (spi_nor_protocol_is_dtr(nor->read_proto))
		op.dummy.nbytes *= 2;

@@ -2091,8 +2117,12 @@ static int spi_nor_select_pp(struct spi_nor *nor,
 * spi_nor_select_uniform_erase() - select optimum uniform erase type
 * @map:		the erase map of the SPI NOR
 * @wanted_size:	the erase type size to search for. Contains the value of
 *			info->sector_size or of the "small sector" size in case
 *			CONFIG_MTD_SPI_NOR_USE_4K_SECTORS is defined.
 *			info->sector_size, the "small sector" size in case
 *			CONFIG_MTD_SPI_NOR_USE_4K_SECTORS is defined or 0 if
 *			there is no information about the sector size. The
 *			latter is the case if the flash parameters are parsed
 *			solely by SFDP, then the largest supported erase type
 *			is selected.
 *
 * Once the optimum uniform sector erase command is found, disable all the
 * other.
@@ -2113,6 +2143,10 @@ spi_nor_select_uniform_erase(struct spi_nor_erase_map *map,

		tested_erase = &map->erase_type[i];

		/* Skip masked erase types. */
		if (!tested_erase->size)
			continue;

		/*
		 * If the current erase size is the one, stop here:
		 * we have found the right uniform Sector Erase command.
@@ -2565,6 +2599,12 @@ static void spi_nor_init_default_params(struct spi_nor *nor)
	params->hwcaps.mask |= SNOR_HWCAPS_PP;
	spi_nor_set_pp_settings(&params->page_programs[SNOR_CMD_PP],
				SPINOR_OP_PP, SNOR_PROTO_1_1_1);

	if (info->flags & SPI_NOR_QUAD_PP) {
		params->hwcaps.mask |= SNOR_HWCAPS_PP_1_1_4;
		spi_nor_set_pp_settings(&params->page_programs[SNOR_CMD_PP_1_1_4],
					SPINOR_OP_PP_1_1_4, SNOR_PROTO_1_1_4);
	}
}

/**
@@ -2840,10 +2880,20 @@ static void spi_nor_put_device(struct mtd_info *mtd)

void spi_nor_restore(struct spi_nor *nor)
{
	int ret;

	/* restore the addressing mode */
	if (nor->addr_nbytes == 4 && !(nor->flags & SNOR_F_4B_OPCODES) &&
	    nor->flags & SNOR_F_BROKEN_RESET)
		nor->params->set_4byte_addr_mode(nor, false);
	    nor->flags & SNOR_F_BROKEN_RESET) {
		ret = nor->params->set_4byte_addr_mode(nor, false);
		if (ret)
			/*
			 * Do not stop the execution in the hope that the flash
			 * will default to the 3-byte address mode after the
			 * software reset.
			 */
			dev_err(nor->dev, "Failed to exit 4-byte address mode, err = %d\n", ret);
	}

	if (nor->flags & SNOR_F_SOFT_RESET)
		spi_nor_soft_reset(nor);
@@ -2935,6 +2985,27 @@ static void spi_nor_set_mtd_info(struct spi_nor *nor)
	mtd->_put_device = spi_nor_put_device;
}

static int spi_nor_hw_reset(struct spi_nor *nor)
{
	struct gpio_desc *reset;

	reset = devm_gpiod_get_optional(nor->dev, "reset", GPIOD_OUT_LOW);
	if (IS_ERR_OR_NULL(reset))
		return PTR_ERR_OR_ZERO(reset);

	/*
	 * Experimental delay values by looking at different flash device
	 * vendors datasheets.
	 */
	usleep_range(1, 5);
	gpiod_set_value_cansleep(reset, 1);
	usleep_range(100, 150);
	gpiod_set_value_cansleep(reset, 0);
	usleep_range(1000, 1200);

	return 0;
}

int spi_nor_scan(struct spi_nor *nor, const char *name,
		 const struct spi_nor_hwcaps *hwcaps)
{
@@ -2967,6 +3038,10 @@ int spi_nor_scan(struct spi_nor *nor, const char *name,
	if (!nor->bouncebuf)
		return -ENOMEM;

	ret = spi_nor_hw_reset(nor);
	if (ret)
		return ret;

	info = spi_nor_get_flash_info(nor, name);
	if (IS_ERR(info))
		return PTR_ERR(info);
+5 −0
Original line number Diff line number Diff line
@@ -458,6 +458,7 @@ struct spi_nor_fixups {
 *   SPI_NOR_NO_ERASE:        no erase command needed.
 *   NO_CHIP_ERASE:           chip does not support chip erase.
 *   SPI_NOR_NO_FR:           can't do fastread.
 *   SPI_NOR_QUAD_PP:         flash supports Quad Input Page Program.
 *
 * @no_sfdp_flags:  flags that indicate support that can be discovered via SFDP.
 *                  Used when SFDP tables are not defined in the flash. These
@@ -507,6 +508,7 @@ struct flash_info {
#define SPI_NOR_NO_ERASE		BIT(6)
#define NO_CHIP_ERASE			BIT(7)
#define SPI_NOR_NO_FR			BIT(8)
#define SPI_NOR_QUAD_PP			BIT(9)

	u8 no_sfdp_flags;
#define SPI_NOR_SKIP_SFDP		BIT(0)
@@ -701,6 +703,9 @@ int spi_nor_controller_ops_read_reg(struct spi_nor *nor, u8 opcode,
int spi_nor_controller_ops_write_reg(struct spi_nor *nor, u8 opcode,
				     const u8 *buf, size_t len);

int spi_nor_check_sfdp_signature(struct spi_nor *nor);
int spi_nor_parse_sfdp(struct spi_nor *nor);

static inline struct spi_nor *mtd_to_spi_nor(struct mtd_info *mtd)
{
	return container_of(mtd, struct spi_nor, mtd);
+1 −1
Original line number Diff line number Diff line
@@ -81,7 +81,7 @@ static int spi_nor_params_show(struct seq_file *s, void *data)
	int i;

	seq_printf(s, "name\t\t%s\n", info->name);
	seq_printf(s, "id\t\t%*ph\n", info->id_len, info->id);
	seq_printf(s, "id\t\t%*ph\n", SPI_NOR_MAX_ID_LEN, nor->id);
	string_get_size(params->size, 1, STRING_UNITS_2, buf, sizeof(buf));
	seq_printf(s, "size\t\t%s\n", buf);
	seq_printf(s, "write size\t%u\n", params->writesize);
Loading