Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4553d469 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull MTD updates from Richard Weinberger:
 "MTD core changes:
   - add debugfs nodes for querying the flash name and id
   - mtd parser reorganization

  SPI NOR core changes:
   - always use bounce buffer for register read/writes
   - move m25p80 code in spi-nor.c
   - rework hwcaps selection for the spi-mem case
   - rework the core in order to move the manufacturer specific code out
     of it:
       - regroup flash parameters in 'struct spi_nor_flash_parameter'
       - add default_init() and post_sfdp() hooks to tweak the flash
         parameters
       - introduce the ->set_4byte(), ->convert_addr() and ->setup()
         methods, to deal with manufacturer specific code
       - rework the SPI NOR lock/unlock logic
   - fix an error code in spi_nor_read_raw()
   - fix a memory leak bug
   - enable the debugfs for the partname and partid
   - add support for few flashes

  SPI NOR controller drivers changes:
   - intel-spi:
       - Whitelist 4B read commands
       - Add support for Intel Tiger Lake SPI serial flash
   - aspeed-smc: Add of_node_put()
   - hisi-sfc: add of_node_put()
   - cadence-quadspi: Fix QSPI RCU Schedule Stall

  NAND core:
   - Fixing typos
   - Adding missing of_node_put() in various drivers

  Raw NAND controller drivers:
   - Macronix: new controller driver
   - Omap2: fix the number of bitflips returned
   - Brcmnand: fix a pointer not iterating over all the page chunks
   - W90x900: driver removed
   - Onenand: fix a memory leak
   - Sharpsl: missing include guard
   - STM32: avoid warnings when building with W=1
   - Ingenic: fix a coccinelle warning
   - r852: call a helper to simplify the code

  CFI core:
   - Kill useless initializer in mtd_do_chip_probe()
   - Fix a rare write failure seen on some cfi_cmdset_0002 compliant
     Parallel NORs
   - Bunch of cleanups for cfi_cmdset_0002 driver's write functions by
     Tokunori Ikegami"

* tag 'mtd/for-5.4' of git://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux: (77 commits)
  mtd: pmc551: Remove set but not used variable 'soff_lo'
  mtd: cfi_cmdset_0002: Fix do_erase_chip() to get chip as erasing mode
  mtd: sm_ftl: Fix memory leak in sm_init_zone() error path
  mtd: parsers: Move CMDLINE parser
  mtd: parsers: Move OF parser
  mtd: parsers: Move BCM63xx parser
  mtd: parsers: Move BCM47xx parser
  mtd: parsers: Move TI AR7 parser
  mtd: pismo: Simplify getting the adapter of a client
  mtd: phram: Module parameters add writable permissions
  mtd: pxa2xx: Use ioremap_cache insted of ioremap_cached
  mtd: spi-nor: Rename "n25q512a" to "mt25qu512a (n25q512a)"
  mtd: spi-nor: Add support for mt35xu02g
  mtd: rawnand: omap2: Fix number of bitflips reporting with ELM
  mtd: rawnand: brcmnand: Fix ecc chunk calculation for erased page bitfips
  mtd: spi-nor: remove superfluous pass of nor->info->sector_size
  mtd: spi-nor: enable the debugfs for the partname and partid
  mtd: mtdcore: add debugfs nodes for querying the flash name and id
  mtd: spi-nor: hisi-sfc: Add of_node_put() before break
  mtd: spi-nor: aspeed-smc: Add of_node_put()
  ...
parents 6cb2e9ee 2cfcfadb
Loading
Loading
Loading
Loading
+36 −0
Original line number Diff line number Diff line
Macronix Raw NAND Controller Device Tree Bindings
-------------------------------------------------

Required properties:
- compatible: should be "mxic,multi-itfc-v009-nand-controller"
- reg: should contain 1 entry for the registers
- #address-cells: should be set to 1
- #size-cells: should be set to 0
- interrupts: interrupt line connected to this raw NAND controller
- clock-names: should contain "ps", "send" and "send_dly"
- clocks: should contain 3 phandles for the "ps", "send" and
	 "send_dly" clocks

Children nodes:
- children nodes represent the available NAND chips.

See Documentation/devicetree/bindings/mtd/nand-controller.yaml
for more details on generic bindings.

Example:

	nand: nand-controller@43c30000 {
		compatible = "mxic,multi-itfc-v009-nand-controller";
		reg = <0x43c30000 0x10000>;
		#address-cells = <1>;
		#size-cells = <0>;
		interrupts = <GIC_SPI 0x1d IRQ_TYPE_EDGE_RISING>;
		clocks = <&clkwizard 0>, <&clkwizard 1>, <&clkc 15>;
		clock-names = "send", "send_dly", "ps";

		nand@0 {
			reg = <0>;
			nand-ecc-mode = "soft";
			nand-ecc-algo = "bch";
		};
	};
+0 −67
Original line number Diff line number Diff line
@@ -23,73 +23,6 @@ config MTD_TESTS
	  WARNING: some of the tests will ERASE entire MTD device which they
	  test. Do not use these tests unless you really know what you do.

config MTD_CMDLINE_PARTS
	tristate "Command line partition table parsing"
	depends on MTD
	help
	  Allow generic configuration of the MTD partition tables via the kernel
	  command line. Multiple flash resources are supported for hardware where
	  different kinds of flash memory are available.

	  You will still need the parsing functions to be called by the driver
	  for your particular device. It won't happen automatically. The
	  SA1100 map driver (CONFIG_MTD_SA1100) has an option for this, for
	  example.

	  The format for the command line is as follows:

	  mtdparts=<mtddef>[;<mtddef]
	  <mtddef>  := <mtd-id>:<partdef>[,<partdef>]
	  <partdef> := <size>[@offset][<name>][ro]
	  <mtd-id>  := unique id used in mapping driver/device
	  <size>    := standard linux memsize OR "-" to denote all
	  remaining space
	  <name>    := (NAME)

	  Due to the way Linux handles the command line, no spaces are
	  allowed in the partition definition, including mtd id's and partition
	  names.

	  Examples:

	  1 flash resource (mtd-id "sa1100"), with 1 single writable partition:
	  mtdparts=sa1100:-

	  Same flash, but 2 named partitions, the first one being read-only:
	  mtdparts=sa1100:256k(ARMboot)ro,-(root)

	  If unsure, say 'N'.

config MTD_OF_PARTS
	tristate "OpenFirmware partitioning information support"
	default y
	depends on OF
	help
	  This provides a partition parsing function which derives
	  the partition map from the children of the flash node,
	  as described in Documentation/devicetree/bindings/mtd/partition.txt.

config MTD_AR7_PARTS
	tristate "TI AR7 partitioning support"
	help
	  TI AR7 partitioning support

config MTD_BCM63XX_PARTS
	tristate "BCM63XX CFE partitioning support"
	depends on BCM63XX || BMIPS_GENERIC || COMPILE_TEST
	select CRC32
	select MTD_PARSER_IMAGETAG
	help
	  This provides partition parsing for BCM63xx devices with CFE
	  bootloaders.

config MTD_BCM47XX_PARTS
	tristate "BCM47XX partitioning support"
	depends on BCM47XX || ARCH_BCM_5301X
	help
	  This provides partitions parser for devices based on BCM47xx
	  boards.

menu "Partition parsers"
source "drivers/mtd/parsers/Kconfig"
endmenu
+0 −5
Original line number Diff line number Diff line
@@ -7,11 +7,6 @@
obj-$(CONFIG_MTD)		+= mtd.o
mtd-y				:= mtdcore.o mtdsuper.o mtdconcat.o mtdpart.o mtdchar.o

obj-$(CONFIG_MTD_OF_PARTS)	+= ofpart.o
obj-$(CONFIG_MTD_CMDLINE_PARTS) += cmdlinepart.o
obj-$(CONFIG_MTD_AR7_PARTS)	+= ar7part.o
obj-$(CONFIG_MTD_BCM63XX_PARTS)	+= bcm63xxpart.o
obj-$(CONFIG_MTD_BCM47XX_PARTS)	+= bcm47xxpart.o
obj-y				+= parsers/

# 'Users' - code which presents functionality to userspace.
+186 −113
Original line number Diff line number Diff line
@@ -61,7 +61,9 @@

static int cfi_amdstd_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *);
static int cfi_amdstd_write_words(struct mtd_info *, loff_t, size_t, size_t *, const u_char *);
#if !FORCE_WORD_WRITE
static int cfi_amdstd_write_buffers(struct mtd_info *, loff_t, size_t, size_t *, const u_char *);
#endif
static int cfi_amdstd_erase_chip(struct mtd_info *, struct erase_info *);
static int cfi_amdstd_erase_varsize(struct mtd_info *, struct erase_info *);
static void cfi_amdstd_sync (struct mtd_info *);
@@ -256,6 +258,7 @@ static void fixup_amd_bootblock(struct mtd_info *mtd)
}
#endif

#if !FORCE_WORD_WRITE
static void fixup_use_write_buffers(struct mtd_info *mtd)
{
	struct map_info *map = mtd->priv;
@@ -265,6 +268,7 @@ static void fixup_use_write_buffers(struct mtd_info *mtd)
		mtd->_write = cfi_amdstd_write_buffers;
	}
}
#endif /* !FORCE_WORD_WRITE */

/* Atmel chips don't use the same PRI format as AMD chips */
static void fixup_convert_atmel_pri(struct mtd_info *mtd)
@@ -1637,11 +1641,11 @@ static int cfi_amdstd_lock_user_prot_reg(struct mtd_info *mtd, loff_t from,
				   do_otp_lock, 1);
}

static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip,
static int __xipram do_write_oneword_once(struct map_info *map,
					  struct flchip *chip,
					  unsigned long adr, map_word datum,
				     int mode)
					  int mode, struct cfi_private *cfi)
{
	struct cfi_private *cfi = map->fldrv_priv;
	unsigned long timeo = jiffies + HZ;
	/*
	 * We use a 1ms + 1 jiffies generic timeout for writes (most devices
@@ -1654,42 +1658,7 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip,
	 */
	unsigned long uWriteTimeout = (HZ / 1000) + 1;
	int ret = 0;
	map_word oldd;
	int retry_cnt = 0;

	adr += chip->start;

	mutex_lock(&chip->mutex);
	ret = get_chip(map, chip, adr, mode);
	if (ret) {
		mutex_unlock(&chip->mutex);
		return ret;
	}

	pr_debug("MTD %s(): WRITE 0x%.8lx(0x%.8lx)\n",
		 __func__, adr, datum.x[0]);

	if (mode == FL_OTP_WRITE)
		otp_enter(map, chip, adr, map_bankwidth(map));

	/*
	 * Check for a NOP for the case when the datum to write is already
	 * present - it saves time and works around buggy chips that corrupt
	 * data at other locations when 0xff is written to a location that
	 * already contains 0xff.
	 */
	oldd = map_read(map, adr);
	if (map_word_equal(map, oldd, datum)) {
		pr_debug("MTD %s(): NOP\n",
		       __func__);
		goto op_done;
	}

	XIP_INVAL_CACHED_RANGE(map, adr, map_bankwidth(map));
	ENABLE_VPP(map);
	xip_disable(map, chip, adr);

 retry:
	cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
	cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL);
	cfi_send_gen_cmd(0xA0, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
@@ -1717,40 +1686,125 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip,
			continue;
		}

		/*
		 * We check "time_after" and "!chip_good" before checking
		 * "chip_good" to avoid the failure due to scheduling.
		 */
		if (time_after(jiffies, timeo) &&
		    !chip_ready(map, chip, adr)) {
		    !chip_good(map, chip, adr, datum)) {
			xip_enable(map, chip, adr);
			printk(KERN_WARNING "MTD %s(): software timeout\n", __func__);
			xip_disable(map, chip, adr);
			ret = -EIO;
			break;
		}

		if (chip_ready(map, chip, adr))
		if (chip_good(map, chip, adr, datum))
			break;

		/* Latency issues. Drop the lock, wait a while and retry */
		UDELAY(map, chip, adr, 1);
	}
	/* Did we succeed? */
	if (!chip_good(map, chip, adr, datum)) {
		/* reset on all failures. */
		cfi_check_err_status(map, chip, adr);
		map_write(map, CMD(0xF0), chip->start);
		/* FIXME - should have reset delay before continuing */

		if (++retry_cnt <= MAX_RETRIES)
			goto retry;
	return ret;
}

		ret = -EIO;
static int __xipram do_write_oneword_start(struct map_info *map,
					   struct flchip *chip,
					   unsigned long adr, int mode)
{
	int ret = 0;

	mutex_lock(&chip->mutex);

	ret = get_chip(map, chip, adr, mode);
	if (ret) {
		mutex_unlock(&chip->mutex);
		return ret;
	}
	xip_enable(map, chip, adr);
 op_done:

	if (mode == FL_OTP_WRITE)
		otp_enter(map, chip, adr, map_bankwidth(map));

	return ret;
}

static void __xipram do_write_oneword_done(struct map_info *map,
					   struct flchip *chip,
					   unsigned long adr, int mode)
{
	if (mode == FL_OTP_WRITE)
		otp_exit(map, chip, adr, map_bankwidth(map));

	chip->state = FL_READY;
	DISABLE_VPP(map);
	put_chip(map, chip, adr);

	mutex_unlock(&chip->mutex);
}

static int __xipram do_write_oneword_retry(struct map_info *map,
					   struct flchip *chip,
					   unsigned long adr, map_word datum,
					   int mode)
{
	struct cfi_private *cfi = map->fldrv_priv;
	int ret = 0;
	map_word oldd;
	int retry_cnt = 0;

	/*
	 * Check for a NOP for the case when the datum to write is already
	 * present - it saves time and works around buggy chips that corrupt
	 * data at other locations when 0xff is written to a location that
	 * already contains 0xff.
	 */
	oldd = map_read(map, adr);
	if (map_word_equal(map, oldd, datum)) {
		pr_debug("MTD %s(): NOP\n", __func__);
		return ret;
	}

	XIP_INVAL_CACHED_RANGE(map, adr, map_bankwidth(map));
	ENABLE_VPP(map);
	xip_disable(map, chip, adr);

 retry:
	ret = do_write_oneword_once(map, chip, adr, datum, mode, cfi);
	if (ret) {
		/* reset on all failures. */
		cfi_check_err_status(map, chip, adr);
		map_write(map, CMD(0xF0), chip->start);
		/* FIXME - should have reset delay before continuing */

		if (++retry_cnt <= MAX_RETRIES) {
			ret = 0;
			goto retry;
		}
	}
	xip_enable(map, chip, adr);

	return ret;
}

static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip,
				     unsigned long adr, map_word datum,
				     int mode)
{
	int ret = 0;

	adr += chip->start;

	pr_debug("MTD %s(): WRITE 0x%.8lx(0x%.8lx)\n", __func__, adr,
		 datum.x[0]);

	ret = do_write_oneword_start(map, chip, adr, mode);
	if (ret)
		return ret;

	ret = do_write_oneword_retry(map, chip, adr, datum, mode);

	do_write_oneword_done(map, chip, adr, mode);

	return ret;
}
@@ -1879,6 +1933,78 @@ static int cfi_amdstd_write_words(struct mtd_info *mtd, loff_t to, size_t len,
	return 0;
}

#if !FORCE_WORD_WRITE
static int __xipram do_write_buffer_wait(struct map_info *map,
					 struct flchip *chip, unsigned long adr,
					 map_word datum)
{
	unsigned long timeo;
	unsigned long u_write_timeout;
	int ret = 0;

	/*
	 * Timeout is calculated according to CFI data, if available.
	 * See more comments in cfi_cmdset_0002().
	 */
	u_write_timeout = usecs_to_jiffies(chip->buffer_write_time_max);
	timeo = jiffies + u_write_timeout;

	for (;;) {
		if (chip->state != FL_WRITING) {
			/* Someone's suspended the write. Sleep */
			DECLARE_WAITQUEUE(wait, current);

			set_current_state(TASK_UNINTERRUPTIBLE);
			add_wait_queue(&chip->wq, &wait);
			mutex_unlock(&chip->mutex);
			schedule();
			remove_wait_queue(&chip->wq, &wait);
			timeo = jiffies + (HZ / 2); /* FIXME */
			mutex_lock(&chip->mutex);
			continue;
		}

		/*
		 * We check "time_after" and "!chip_good" before checking
		 * "chip_good" to avoid the failure due to scheduling.
		 */
		if (time_after(jiffies, timeo) &&
		    !chip_good(map, chip, adr, datum)) {
			ret = -EIO;
			break;
		}

		if (chip_good(map, chip, adr, datum))
			break;

		/* Latency issues. Drop the lock, wait a while and retry */
		UDELAY(map, chip, adr, 1);
	}

	return ret;
}

static void __xipram do_write_buffer_reset(struct map_info *map,
					   struct flchip *chip,
					   struct cfi_private *cfi)
{
	/*
	 * Recovery from write-buffer programming failures requires
	 * the write-to-buffer-reset sequence.  Since the last part
	 * of the sequence also works as a normal reset, we can run
	 * the same commands regardless of why we are here.
	 * See e.g.
	 * http://www.spansion.com/Support/Application%20Notes/MirrorBit_Write_Buffer_Prog_Page_Buffer_Read_AN.pdf
	 */
	cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi,
			 cfi->device_type, NULL);
	cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi,
			 cfi->device_type, NULL);
	cfi_send_gen_cmd(0xF0, cfi->addr_unlock1, chip->start, map, cfi,
			 cfi->device_type, NULL);

	/* FIXME - should have reset delay before continuing */
}

/*
 * FIXME: interleaved mode not tested, and probably not supported!
@@ -1888,13 +2014,6 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip,
				    int len)
{
	struct cfi_private *cfi = map->fldrv_priv;
	unsigned long timeo = jiffies + HZ;
	/*
	 * Timeout is calculated according to CFI data, if available.
	 * See more comments in cfi_cmdset_0002().
	 */
	unsigned long uWriteTimeout =
				usecs_to_jiffies(chip->buffer_write_time_max);
	int ret = -EIO;
	unsigned long cmd_adr;
	int z, words;
@@ -1951,63 +2070,16 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip,
				adr, map_bankwidth(map),
				chip->word_write_time);

	timeo = jiffies + uWriteTimeout;

	for (;;) {
		if (chip->state != FL_WRITING) {
			/* Someone's suspended the write. Sleep */
			DECLARE_WAITQUEUE(wait, current);

			set_current_state(TASK_UNINTERRUPTIBLE);
			add_wait_queue(&chip->wq, &wait);
			mutex_unlock(&chip->mutex);
			schedule();
			remove_wait_queue(&chip->wq, &wait);
			timeo = jiffies + (HZ / 2); /* FIXME */
			mutex_lock(&chip->mutex);
			continue;
		}

		/*
		 * We check "time_after" and "!chip_good" before checking "chip_good" to avoid
		 * the failure due to scheduling.
		 */
		if (time_after(jiffies, timeo) &&
		    !chip_good(map, chip, adr, datum))
			break;

		if (chip_good(map, chip, adr, datum)) {
			xip_enable(map, chip, adr);
			goto op_done;
		}

		/* Latency issues. Drop the lock, wait a while and retry */
		UDELAY(map, chip, adr, 1);
	ret = do_write_buffer_wait(map, chip, adr, datum);
	if (ret) {
		cfi_check_err_status(map, chip, adr);
		do_write_buffer_reset(map, chip, cfi);
		pr_err("MTD %s(): software timeout, address:0x%.8lx.\n",
		       __func__, adr);
	}

	/*
	 * Recovery from write-buffer programming failures requires
	 * the write-to-buffer-reset sequence.  Since the last part
	 * of the sequence also works as a normal reset, we can run
	 * the same commands regardless of why we are here.
	 * See e.g.
	 * http://www.spansion.com/Support/Application%20Notes/MirrorBit_Write_Buffer_Prog_Page_Buffer_Read_AN.pdf
	 */
	cfi_check_err_status(map, chip, adr);
	cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi,
			 cfi->device_type, NULL);
	cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi,
			 cfi->device_type, NULL);
	cfi_send_gen_cmd(0xF0, cfi->addr_unlock1, chip->start, map, cfi,
			 cfi->device_type, NULL);
	xip_enable(map, chip, adr);
	/* FIXME - should have reset delay before continuing */

	printk(KERN_WARNING "MTD %s(): software timeout, address:0x%.8lx.\n",
	       __func__, adr);

	ret = -EIO;
 op_done:
	chip->state = FL_READY;
	DISABLE_VPP(map);
	put_chip(map, chip, adr);
@@ -2091,6 +2163,7 @@ static int cfi_amdstd_write_buffers(struct mtd_info *mtd, loff_t to, size_t len,

	return 0;
}
#endif /* !FORCE_WORD_WRITE */

/*
 * Wait for the flash chip to become ready to write data
@@ -2344,7 +2417,7 @@ static int __xipram do_erase_chip(struct map_info *map, struct flchip *chip)
	adr = cfi->addr_unlock1;

	mutex_lock(&chip->mutex);
	ret = get_chip(map, chip, adr, FL_WRITING);
	ret = get_chip(map, chip, adr, FL_ERASING);
	if (ret) {
		mutex_unlock(&chip->mutex);
		return ret;
+1 −1
Original line number Diff line number Diff line
@@ -20,7 +20,7 @@ static int genprobe_new_chip(struct map_info *map, struct chip_probe *cp,

struct mtd_info *mtd_do_chip_probe(struct map_info *map, struct chip_probe *cp)
{
	struct mtd_info *mtd = NULL;
	struct mtd_info *mtd;
	struct cfi_private *cfi;

	/* First probe the map to see if we have CFI stuff there. */
Loading