Commit edd2b983 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull mtd updates from Miquel Raynal:
 "Core MTD changes:

   - We must ignore error -ENOENT from parsers on subpartitions which is
     a legitimate return value

   - PM support is added to the intel-dg driver

  Raw NAND changes:

   - The major change in this is the support for the Allwinner H616 NAND
     controller, which lead to numerous changes and cleanups in the
     driver.

   - Another notable change in this driver is the use of field_get() and
     field_prep(), but since the global support for this helpers is
     going to be merged in the same release as we start using these
     helpers, we undefine them in the first place to avoid warnings.

   - Marvell drivers layout handling changes have also landed, they fix
     previous definitions and abuses that have been made previously,
     which implied to relax the ECC parameters validation in the core a
     bit.

   - The Cadence NAND controller driver gets NV-DDR interface support.

  SPI NAND changes:

   - Support for FudanMicro FM25S01BI3 and ESMT F50L1G41LC is added.

  SPI NOR changes:

   - Fix SMPT parsing for S25FS-S flash family. They report variable
     dummy cycles for reads. This results in the default of 0 being
     used. This works for other Infineon chips, but not for the S25FS-S
     family. They need 8 dummy cycles. Add fixup hooks to specify that.
     Also add fixup hooks to fix incorrect map ID data in SFDP.

   - Add support for a bunch of Winbond flashes. Their block protection
     information is not discoverable, so they need to have an entry in
     the flash tables to describe that.

   - Some cleanups for Micron flash support.

   - Add support for Micron mt35xu01gbba.

   - Some SPI controllers like the Intel one on the PCI bus do not
     support the read CR opcode (0x35). Do not use the opcode if the
     controller does not support it.

  Aside from these main changes, there is the usual load of API updates,
  kdoc fixes, potential memory leaks fixes, etc"

* tag 'mtd/for-6.19' of git://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux: (51 commits)
  mtd: sm_ftl: Fix typo in comment in sm_read_lba
  mtd: sm_ftl: Replace deprecated strncpy with sysfs_emit in sm_attr_show
  mtd: lpddr_cmds: fix signed shifts in lpddr_cmds
  mtd: docg3: fix kernel-doc warnings
  mtd: spinand: add support for FudanMicro FM25S01BI3
  mtd: rawnand: renesas: Handle devm_pm_runtime_enable() errors
  mtd: nand: realtek-ecc: Fix Kconfig dependencies
  mtd: rawnand: sunxi: #undef field_{get,prep}() before local definition
  mailmap: update Pratyush Yadav's email address
  mtd: spi-nor: core: Check read CR support
  mtd: spi-nor: micron-st: add TODO for fixing mt35xu02gcba
  mtd: spi-nor: micron-st: add mt35xu01gbba support
  mtd: spi-nor: micron-st: use SFDP of mt35xu512aba
  mtd: spi-nor: micron-st: move set_octal_dtr to late_init()
  mtd: spi-nor: micron-st: rename the die_late_init functions
  mtd: spinand: esmt: add support for F50L1G41LC
  mtd: rawnand: lpc32xx_slc: Convert to use devm_gpiod_get_optional()
  mtd: mtdpart: ignore error -ENOENT from parsers on subpartitions
  mtd: maps: pcmciamtd: fix potential memory leak in pcmciamtd_detach()
  mtd: spi-nor: spansion: SMPT fixups for S25FS-S
  ...
parents 77956cf3 801b0840
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -638,6 +638,7 @@ Peter Oruba <peter.oruba@amd.com>
Peter Oruba <peter@oruba.de>
Pierre-Louis Bossart <pierre-louis.bossart@linux.dev> <pierre-louis.bossart@linux.intel.com>
Pratyush Anand <pratyush.anand@gmail.com> <pratyush.anand@st.com>
Pratyush Yadav <pratyush@kernel.org> <ptyadav@amazon.de>
Praveen BP <praveenbp@ti.com>
Pradeep Kumar Chitrapu <quic_pradeepc@quicinc.com> <pradeepc@codeaurora.org>
Prasad Sodagudi <quic_psodagud@quicinc.com> <psodagud@codeaurora.org>
+38 −3
Original line number Diff line number Diff line
@@ -6,9 +6,6 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#

title: Allwinner A10 NAND Controller

allOf:
  - $ref: nand-controller.yaml

maintainers:
  - Chen-Yu Tsai <wens@csie.org>
  - Maxime Ripard <mripard@kernel.org>
@@ -18,6 +15,8 @@ properties:
    enum:
      - allwinner,sun4i-a10-nand
      - allwinner,sun8i-a23-nand-controller
      - allwinner,sun50i-h616-nand-controller

  reg:
    maxItems: 1

@@ -25,14 +24,20 @@ properties:
    maxItems: 1

  clocks:
    minItems: 2
    items:
      - description: Bus Clock
      - description: Module Clock
      - description: ECC Clock
      - description: MBus Clock

  clock-names:
    minItems: 2
    items:
      - const: ahb
      - const: mod
      - const: ecc
      - const: mbus

  resets:
    maxItems: 1
@@ -85,6 +90,36 @@ required:

unevaluatedProperties: false

allOf:
  - $ref: nand-controller.yaml

  - if:
      properties:
        compatible:
          contains:
            enum:
              - allwinner,sun4i-a10-nand
              - allwinner,sun8i-a23-nand-controller
    then:
      properties:
        clocks:
          maxItems: 2
        clock-names:
          maxItems: 2

  - if:
      properties:
        compatible:
          contains:
            enum:
              - allwinner,sun50i-h616-nand-controller
    then:
      properties:
        clocks:
          minItems: 4
        clock-names:
          minItems: 4

examples:
  - |
    #include <dt-bindings/interrupt-controller/arm-gic.h>
+10 −0
Original line number Diff line number Diff line
@@ -69,6 +69,16 @@ properties:
    minItems: 1
    maxItems: 8

  clocks:
    description: |
      Chips may need clocks to be enabled for themselves or for transparent
      bridges.

  power-domains:
    description: |
      Chips may need power domains to be enabled for themselves or for
      transparent bridges.

  bank-width:
    description: Width (in bytes) of the bank.  Equal to the device width times
      the number of interleaved chips.
+1 −1
Original line number Diff line number Diff line
@@ -274,11 +274,11 @@ struct docg3_cascade {
 * @cascade: the cascade this device belongs to
 * @device_id: number of the cascaded DoCG3 device (0, 1, 2 or 3)
 * @if_cfg: if true, reads are on 16bits, else reads are on 8bits

 * @reliable: if 0, docg3 in normal mode, if 1 docg3 in fast mode, if 2 in
 *            reliable mode
 *            Fast mode implies more errors than normal mode.
 *            Reliable mode implies that page 2*n and 2*n+1 are clones.
 * @max_block: maximum block number for this device
 * @bbt: bad block table cache
 * @oob_write_ofs: offset of the MTD where this OOB should belong (ie. in next
 *                 page_write)
+62 −12
Original line number Diff line number Diff line
@@ -15,14 +15,18 @@
#include <linux/module.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
#include <linux/pm_runtime.h>
#include <linux/string.h>
#include <linux/slab.h>
#include <linux/sizes.h>
#include <linux/types.h>

#define INTEL_DG_NVM_RPM_TIMEOUT_MS 500

struct intel_dg_nvm {
	struct kref refcnt;
	struct mtd_info mtd;
	struct device *dev;
	struct mutex lock; /* region access lock */
	void __iomem *base;
	void __iomem *base2;
@@ -421,6 +425,8 @@ static int intel_dg_nvm_init(struct intel_dg_nvm *nvm, struct device *device,
	unsigned int i, n;
	int ret;

	nvm->dev = device;

	/* clean error register, previous errors are ignored */
	idg_nvm_error(nvm);

@@ -498,6 +504,7 @@ static int intel_dg_mtd_erase(struct mtd_info *mtd, struct erase_info *info)
	size_t len;
	u8 region;
	u64 addr;
	int ret;

	if (WARN_ON(!nvm))
		return -EINVAL;
@@ -512,20 +519,29 @@ static int intel_dg_mtd_erase(struct mtd_info *mtd, struct erase_info *info)
	total_len = info->len;
	addr = info->addr;

	ret = pm_runtime_resume_and_get(nvm->dev);
	if (ret < 0) {
		dev_err(&mtd->dev, "rpm: get failed %d\n", ret);
		return ret;
	}

	ret = 0;
	guard(mutex)(&nvm->lock);

	while (total_len > 0) {
		if (!IS_ALIGNED(addr, SZ_4K) || !IS_ALIGNED(total_len, SZ_4K)) {
			dev_err(&mtd->dev, "unaligned erase %llx %zx\n", addr, total_len);
			info->fail_addr = addr;
			return -ERANGE;
			ret = -ERANGE;
			break;
		}

		idx = idg_nvm_get_region(nvm, addr);
		if (idx >= nvm->nregions) {
			dev_err(&mtd->dev, "out of range");
			info->fail_addr = MTD_FAIL_ADDR_UNKNOWN;
			return -ERANGE;
			ret = -ERANGE;
			break;
		}

		from = addr - nvm->regions[idx].offset;
@@ -541,14 +557,16 @@ static int intel_dg_mtd_erase(struct mtd_info *mtd, struct erase_info *info)
		if (bytes < 0) {
			dev_dbg(&mtd->dev, "erase failed with %zd\n", bytes);
			info->fail_addr += nvm->regions[idx].offset;
			return bytes;
			ret = bytes;
			break;
		}

		addr += len;
		total_len -= len;
	}

	return 0;
	pm_runtime_put_autosuspend(nvm->dev);
	return ret;
}

static int intel_dg_mtd_read(struct mtd_info *mtd, loff_t from, size_t len,
@@ -577,17 +595,24 @@ static int intel_dg_mtd_read(struct mtd_info *mtd, loff_t from, size_t len,
	if (len > nvm->regions[idx].size - from)
		len = nvm->regions[idx].size - from;

	ret = pm_runtime_resume_and_get(nvm->dev);
	if (ret < 0) {
		dev_err(&mtd->dev, "rpm: get failed %zd\n", ret);
		return ret;
	}

	guard(mutex)(&nvm->lock);

	ret = idg_read(nvm, region, from, len, buf);
	if (ret < 0) {
		dev_dbg(&mtd->dev, "read failed with %zd\n", ret);
		return ret;
	}

	} else {
		*retlen = ret;
		ret = 0;
	}

	return 0;
	pm_runtime_put_autosuspend(nvm->dev);
	return ret;
}

static int intel_dg_mtd_write(struct mtd_info *mtd, loff_t to, size_t len,
@@ -616,17 +641,24 @@ static int intel_dg_mtd_write(struct mtd_info *mtd, loff_t to, size_t len,
	if (len > nvm->regions[idx].size - to)
		len = nvm->regions[idx].size - to;

	ret = pm_runtime_resume_and_get(nvm->dev);
	if (ret < 0) {
		dev_err(&mtd->dev, "rpm: get failed %zd\n", ret);
		return ret;
	}

	guard(mutex)(&nvm->lock);

	ret = idg_write(nvm, region, to, len, buf);
	if (ret < 0) {
		dev_dbg(&mtd->dev, "write failed with %zd\n", ret);
		return ret;
	}

	} else {
		*retlen = ret;
		ret = 0;
	}

	return 0;
	pm_runtime_put_autosuspend(nvm->dev);
	return ret;
}

static void intel_dg_nvm_release(struct kref *kref)
@@ -753,6 +785,21 @@ static int intel_dg_mtd_probe(struct auxiliary_device *aux_dev,
	}
	nvm->nregions = n; /* in case where kasprintf fail */

	ret = devm_pm_runtime_enable(device);
	if (ret < 0) {
		dev_err(device, "rpm: enable failed %d\n", ret);
		goto err_norpm;
	}

	pm_runtime_set_autosuspend_delay(device, INTEL_DG_NVM_RPM_TIMEOUT_MS);
	pm_runtime_use_autosuspend(device);

	ret = pm_runtime_resume_and_get(device);
	if (ret < 0) {
		dev_err(device, "rpm: get failed %d\n", ret);
		goto err_norpm;
	}

	nvm->base = devm_ioremap_resource(device, &invm->bar);
	if (IS_ERR(nvm->base)) {
		ret = PTR_ERR(nvm->base);
@@ -781,9 +828,12 @@ static int intel_dg_mtd_probe(struct auxiliary_device *aux_dev,

	dev_set_drvdata(&aux_dev->dev, nvm);

	pm_runtime_put(device);
	return 0;

err:
	pm_runtime_put(device);
err_norpm:
	kref_put(&nvm->refcnt, intel_dg_nvm_release);
	return ret;
}
Loading