Commit 320475fb authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'mtd/fixes-for-6.17-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux

Pull mtd fixes from Miquel Raynal:
 "SPI NAND fix:
   - Wrong OOB layout for Winbond W25N01JW SPI NAND devices

  Raw NAND fixes:
   - Atmel raw NAND controller timings
   - Buffer handling in stm32_fmc2 driver
   - Error handling in Nuvoton's driver

  MTD devices fixes:
   - Wrong depends-on dependencies on the Intel DRM driver

* tag 'mtd/fixes-for-6.17-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux:
  mtd: spinand: winbond: Fix oob_layout for W25N01JW
  mtd: nand: raw: atmel: Respect tAR, tCLR in read setup timing
  mtd: rawnand: stm32_fmc2: fix ECC overwrite
  mtd: rawnand: stm32_fmc2: avoid overlapping mappings on ECC buffer
  mtd: rawnand: nuvoton: Fix an error handling path in ma35_nand_chips_init()
  mtd: MTD_INTEL_DG should depend on DRM_I915 or DRM_XE
parents db87bd2a 4550d33e
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -185,8 +185,8 @@ config MTD_POWERNV_FLASH

config MTD_INTEL_DG
	tristate "Intel Discrete Graphics non-volatile memory driver"
	depends on AUXILIARY_BUS
	depends on MTD
	depends on AUXILIARY_BUS && MTD
	depends on DRM_I915!=n || DRM_XE!=n || COMPILE_TEST
	help
	  This provides an MTD device to access Intel Discrete Graphics
	  non-volatile memory.
+13 −3
Original line number Diff line number Diff line
@@ -1377,14 +1377,24 @@ static int atmel_smc_nand_prepare_smcconf(struct atmel_nand *nand,
	if (ret)
		return ret;

	/*
	 * Read setup timing depends on the operation done on the NAND:
	 *
	 * NRD_SETUP = max(tAR, tCLR)
	 */
	timeps = max(conf->timings.sdr.tAR_min, conf->timings.sdr.tCLR_min);
	ncycles = DIV_ROUND_UP(timeps, mckperiodps);
	totalcycles += ncycles;
	ret = atmel_smc_cs_conf_set_setup(smcconf, ATMEL_SMC_NRD_SHIFT, ncycles);
	if (ret)
		return ret;

	/*
	 * The read cycle timing is directly matching tRC, but is also
	 * dependent on the setup and hold timings we calculated earlier,
	 * which gives:
	 *
	 * NRD_CYCLE = max(tRC, NRD_PULSE + NRD_HOLD)
	 *
	 * NRD_SETUP is always 0.
	 * NRD_CYCLE = max(tRC, NRD_SETUP + NRD_PULSE + NRD_HOLD)
	 */
	ncycles = DIV_ROUND_UP(conf->timings.sdr.tRC_min, mckperiodps);
	ncycles = max(totalcycles, ncycles);
+2 −2
Original line number Diff line number Diff line
@@ -935,10 +935,10 @@ static void ma35_chips_cleanup(struct ma35_nand_info *nand)

static int ma35_nand_chips_init(struct device *dev, struct ma35_nand_info *nand)
{
	struct device_node *np = dev->of_node, *nand_np;
	struct device_node *np = dev->of_node;
	int ret;

	for_each_child_of_node(np, nand_np) {
	for_each_child_of_node_scoped(np, nand_np) {
		ret = ma35_nand_chip_init(dev, nand, nand_np);
		if (ret) {
			ma35_chips_cleanup(nand);
+24 −22
Original line number Diff line number Diff line
@@ -272,6 +272,7 @@ struct stm32_fmc2_nfc {
	struct sg_table dma_data_sg;
	struct sg_table dma_ecc_sg;
	u8 *ecc_buf;
	dma_addr_t dma_ecc_addr;
	int dma_ecc_len;
	u32 tx_dma_max_burst;
	u32 rx_dma_max_burst;
@@ -902,17 +903,10 @@ static int stm32_fmc2_nfc_xfer(struct nand_chip *chip, const u8 *buf,

	if (!write_data && !raw) {
		/* Configure DMA ECC status */
		p = nfc->ecc_buf;
		for_each_sg(nfc->dma_ecc_sg.sgl, sg, eccsteps, s) {
			sg_set_buf(sg, p, nfc->dma_ecc_len);
			p += nfc->dma_ecc_len;
		}

		ret = dma_map_sg(nfc->dev, nfc->dma_ecc_sg.sgl,
				 eccsteps, dma_data_dir);
		if (!ret) {
			ret = -EIO;
			goto err_unmap_data;
			sg_dma_address(sg) = nfc->dma_ecc_addr +
					     s * nfc->dma_ecc_len;
			sg_dma_len(sg) = nfc->dma_ecc_len;
		}

		desc_ecc = dmaengine_prep_slave_sg(nfc->dma_ecc_ch,
@@ -921,7 +915,7 @@ static int stm32_fmc2_nfc_xfer(struct nand_chip *chip, const u8 *buf,
						   DMA_PREP_INTERRUPT);
		if (!desc_ecc) {
			ret = -ENOMEM;
			goto err_unmap_ecc;
			goto err_unmap_data;
		}

		reinit_completion(&nfc->dma_ecc_complete);
@@ -929,7 +923,7 @@ static int stm32_fmc2_nfc_xfer(struct nand_chip *chip, const u8 *buf,
		desc_ecc->callback_param = &nfc->dma_ecc_complete;
		ret = dma_submit_error(dmaengine_submit(desc_ecc));
		if (ret)
			goto err_unmap_ecc;
			goto err_unmap_data;

		dma_async_issue_pending(nfc->dma_ecc_ch);
	}
@@ -949,7 +943,7 @@ static int stm32_fmc2_nfc_xfer(struct nand_chip *chip, const u8 *buf,
		if (!write_data && !raw)
			dmaengine_terminate_all(nfc->dma_ecc_ch);
		ret = -ETIMEDOUT;
		goto err_unmap_ecc;
		goto err_unmap_data;
	}

	/* Wait DMA data transfer completion */
@@ -969,11 +963,6 @@ static int stm32_fmc2_nfc_xfer(struct nand_chip *chip, const u8 *buf,
		}
	}

err_unmap_ecc:
	if (!write_data && !raw)
		dma_unmap_sg(nfc->dev, nfc->dma_ecc_sg.sgl,
			     eccsteps, dma_data_dir);

err_unmap_data:
	dma_unmap_sg(nfc->dev, nfc->dma_data_sg.sgl, eccsteps, dma_data_dir);

@@ -996,9 +985,21 @@ static int stm32_fmc2_nfc_seq_write(struct nand_chip *chip, const u8 *buf,

	/* Write oob */
	if (oob_required) {
		ret = nand_change_write_column_op(chip, mtd->writesize,
						  chip->oob_poi, mtd->oobsize,
						  false);
		unsigned int offset_in_page = mtd->writesize;
		const void *buf = chip->oob_poi;
		unsigned int len = mtd->oobsize;

		if (!raw) {
			struct mtd_oob_region oob_free;

			mtd_ooblayout_free(mtd, 0, &oob_free);
			offset_in_page += oob_free.offset;
			buf += oob_free.offset;
			len = oob_free.length;
		}

		ret = nand_change_write_column_op(chip, offset_in_page,
						  buf, len, false);
		if (ret)
			return ret;
	}
@@ -1610,7 +1611,8 @@ static int stm32_fmc2_nfc_dma_setup(struct stm32_fmc2_nfc *nfc)
		return ret;

	/* Allocate a buffer to store ECC status registers */
	nfc->ecc_buf = devm_kzalloc(nfc->dev, FMC2_MAX_ECC_BUF_LEN, GFP_KERNEL);
	nfc->ecc_buf = dmam_alloc_coherent(nfc->dev, FMC2_MAX_ECC_BUF_LEN,
					   &nfc->dma_ecc_addr, GFP_KERNEL);
	if (!nfc->ecc_buf)
		return -ENOMEM;

+36 −1
Original line number Diff line number Diff line
@@ -176,6 +176,36 @@ static const struct mtd_ooblayout_ops w25n02kv_ooblayout = {
	.free = w25n02kv_ooblayout_free,
};

static int w25n01jw_ooblayout_ecc(struct mtd_info *mtd, int section,
				  struct mtd_oob_region *region)
{
	if (section > 3)
		return -ERANGE;

	region->offset = (16 * section) + 12;
	region->length = 4;

	return 0;
}

static int w25n01jw_ooblayout_free(struct mtd_info *mtd, int section,
				   struct mtd_oob_region *region)
{
	if (section > 3)
		return -ERANGE;

	region->offset = (16 * section);
	region->length = 12;

	/* Extract BBM */
	if (!section) {
		region->offset += 2;
		region->length -= 2;
	}

	return 0;
}

static int w35n01jw_ooblayout_ecc(struct mtd_info *mtd, int section,
				  struct mtd_oob_region *region)
{
@@ -206,6 +236,11 @@ static int w35n01jw_ooblayout_free(struct mtd_info *mtd, int section,
	return 0;
}

static const struct mtd_ooblayout_ops w25n01jw_ooblayout = {
	.ecc = w25n01jw_ooblayout_ecc,
	.free = w25n01jw_ooblayout_free,
};

static const struct mtd_ooblayout_ops w35n01jw_ooblayout = {
	.ecc = w35n01jw_ooblayout_ecc,
	.free = w35n01jw_ooblayout_free,
@@ -394,7 +429,7 @@ static const struct spinand_info winbond_spinand_table[] = {
					      &write_cache_variants,
					      &update_cache_variants),
		     0,
		     SPINAND_ECCINFO(&w25m02gv_ooblayout, NULL),
		     SPINAND_ECCINFO(&w25n01jw_ooblayout, NULL),
		     SPINAND_CONFIGURE_CHIP(w25n0xjw_hs_cfg)),
	SPINAND_INFO("W25N01KV", /* 3.3V */
		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xae, 0x21),