ramips: remove chunked-io patch and set spi->max_transfer_size instead
Signed-off-by: Felix Fietkau <nbd@nbd.name>
This commit is contained in:
		@@ -0,0 +1,36 @@
 | 
			
		||||
From: Felix Fietkau <nbd@nbd.name>
 | 
			
		||||
Date: Thu, 22 Feb 2018 11:11:57 +0100
 | 
			
		||||
Subject: [PATCH] mtd: spi-nor: allow NOR driver to write fewer bytes than
 | 
			
		||||
 requested
 | 
			
		||||
 | 
			
		||||
The write size can be constrained by the maximum message/transfer size
 | 
			
		||||
of the SPI controller. Only check for ret = 0 to avoid an infinite loop.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Felix Fietkau <nbd@nbd.name>
 | 
			
		||||
---
 | 
			
		||||
 | 
			
		||||
--- a/drivers/mtd/spi-nor/spi-nor.c
 | 
			
		||||
+++ b/drivers/mtd/spi-nor/spi-nor.c
 | 
			
		||||
@@ -1371,7 +1371,7 @@ static int spi_nor_write(struct mtd_info
 | 
			
		||||
 
 | 
			
		||||
 		write_enable(nor);
 | 
			
		||||
 		ret = nor->write(nor, addr, page_remain, buf + i);
 | 
			
		||||
-		if (ret < 0)
 | 
			
		||||
+		if (ret <= 0)
 | 
			
		||||
 			goto write_err;
 | 
			
		||||
 		written = ret;
 | 
			
		||||
 
 | 
			
		||||
@@ -1380,13 +1380,6 @@ static int spi_nor_write(struct mtd_info
 | 
			
		||||
 			goto write_err;
 | 
			
		||||
 		*retlen += written;
 | 
			
		||||
 		i += written;
 | 
			
		||||
-		if (written != page_remain) {
 | 
			
		||||
-			dev_err(nor->dev,
 | 
			
		||||
-				"While writing %zu bytes written %zd bytes\n",
 | 
			
		||||
-				page_remain, written);
 | 
			
		||||
-			ret = -EIO;
 | 
			
		||||
-			goto write_err;
 | 
			
		||||
-		}
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
 write_err:
 | 
			
		||||
@@ -8,7 +8,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
 | 
			
		||||
 | 
			
		||||
--- a/drivers/mtd/spi-nor/spi-nor.c
 | 
			
		||||
+++ b/drivers/mtd/spi-nor/spi-nor.c
 | 
			
		||||
@@ -2715,6 +2715,7 @@ int spi_nor_scan(struct spi_nor *nor, co
 | 
			
		||||
@@ -2708,6 +2708,7 @@ int spi_nor_scan(struct spi_nor *nor, co
 | 
			
		||||
 
 | 
			
		||||
 	if (JEDEC_MFR(info) == SNOR_MFR_ATMEL ||
 | 
			
		||||
 	    JEDEC_MFR(info) == SNOR_MFR_INTEL ||
 | 
			
		||||
 
 | 
			
		||||
@@ -17,7 +17,7 @@ Signed-off-by: Matthias Schiffer <mschiffer@universe-factory.net>
 | 
			
		||||
 | 
			
		||||
--- a/drivers/mtd/spi-nor/spi-nor.c
 | 
			
		||||
+++ b/drivers/mtd/spi-nor/spi-nor.c
 | 
			
		||||
@@ -2717,6 +2717,7 @@ int spi_nor_scan(struct spi_nor *nor, co
 | 
			
		||||
@@ -2710,6 +2710,7 @@ int spi_nor_scan(struct spi_nor *nor, co
 | 
			
		||||
 	    JEDEC_MFR(info) == SNOR_MFR_INTEL ||
 | 
			
		||||
 	    JEDEC_MFR(info) == SNOR_MFR_MACRONIX ||
 | 
			
		||||
 	    JEDEC_MFR(info) == SNOR_MFR_SST ||
 | 
			
		||||
@@ -25,7 +25,7 @@ Signed-off-by: Matthias Schiffer <mschiffer@universe-factory.net>
 | 
			
		||||
 	    info->flags & SPI_NOR_HAS_LOCK) {
 | 
			
		||||
 		write_enable(nor);
 | 
			
		||||
 		write_sr(nor, 0);
 | 
			
		||||
@@ -2735,7 +2736,8 @@ int spi_nor_scan(struct spi_nor *nor, co
 | 
			
		||||
@@ -2728,7 +2729,8 @@ int spi_nor_scan(struct spi_nor *nor, co
 | 
			
		||||
 
 | 
			
		||||
 	/* NOR protection support for STmicro/Micron chips and similar */
 | 
			
		||||
 	if (JEDEC_MFR(info) == SNOR_MFR_MICRON ||
 | 
			
		||||
 
 | 
			
		||||
@@ -39,7 +39,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
 | 
			
		||||
 	depends on ARCH_AT91 || (ARM && COMPILE_TEST)
 | 
			
		||||
--- a/drivers/mtd/spi-nor/spi-nor.c
 | 
			
		||||
+++ b/drivers/mtd/spi-nor/spi-nor.c
 | 
			
		||||
@@ -2562,10 +2562,12 @@ static int spi_nor_select_erase(struct s
 | 
			
		||||
@@ -2555,10 +2555,12 @@ static int spi_nor_select_erase(struct s
 | 
			
		||||
 
 | 
			
		||||
 #ifdef CONFIG_MTD_SPI_NOR_USE_4K_SECTORS
 | 
			
		||||
 	/* prefer "small sector" erase if possible */
 | 
			
		||||
 
 | 
			
		||||
@@ -38,7 +38,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
 | 
			
		||||
 obj-$(CONFIG_SPI_OC_TINY)		+= spi-oc-tiny.o
 | 
			
		||||
--- /dev/null
 | 
			
		||||
+++ b/drivers/spi/spi-mt7621.c
 | 
			
		||||
@@ -0,0 +1,483 @@
 | 
			
		||||
@@ -0,0 +1,491 @@
 | 
			
		||||
+/*
 | 
			
		||||
+ * spi-mt7621.c -- MediaTek MT7621 SPI controller driver
 | 
			
		||||
+ *
 | 
			
		||||
@@ -243,10 +243,12 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
 | 
			
		||||
+		if (t->speed_hz < speed)
 | 
			
		||||
+			speed = t->speed_hz;
 | 
			
		||||
+
 | 
			
		||||
+		if (WARN_ON(len + t->len > 36)) {
 | 
			
		||||
+			status = -EIO;
 | 
			
		||||
+			goto msg_done;
 | 
			
		||||
+		}
 | 
			
		||||
+		/*
 | 
			
		||||
+		 * m25p80 might attempt to write more data than we can handle.
 | 
			
		||||
+		 * truncate the message to what we can fit into the registers
 | 
			
		||||
+		 */
 | 
			
		||||
+		if (len + t->len > 36)
 | 
			
		||||
+			t->len = 36 - len;
 | 
			
		||||
+
 | 
			
		||||
+		for (i = 0; i < t->len; i++, len++)
 | 
			
		||||
+			data[len / 4] |= buf[i] << (8 * (len & 3));
 | 
			
		||||
@@ -426,6 +428,11 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
 | 
			
		||||
+};
 | 
			
		||||
+MODULE_DEVICE_TABLE(of, mt7621_spi_match);
 | 
			
		||||
+
 | 
			
		||||
+static size_t mt7621_max_transfer_size(struct spi_device *spi)
 | 
			
		||||
+{
 | 
			
		||||
+	return 32;
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+static int mt7621_spi_probe(struct platform_device *pdev)
 | 
			
		||||
+{
 | 
			
		||||
+	const struct of_device_id *match;
 | 
			
		||||
@@ -472,6 +479,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
 | 
			
		||||
+	master->bits_per_word_mask = SPI_BPW_MASK(8);
 | 
			
		||||
+	master->dev.of_node = pdev->dev.of_node;
 | 
			
		||||
+	master->num_chipselect = 2;
 | 
			
		||||
+	master->max_transfer_size = mt7621_max_transfer_size;
 | 
			
		||||
+
 | 
			
		||||
+	dev_set_drvdata(&pdev->dev, master);
 | 
			
		||||
+
 | 
			
		||||
 
 | 
			
		||||
@@ -165,7 +165,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
 | 
			
		||||
 	for (i = 0; i < len; ) {
 | 
			
		||||
 		ssize_t written;
 | 
			
		||||
 		loff_t addr = to + i;
 | 
			
		||||
@@ -1392,6 +1463,7 @@ static int spi_nor_write(struct mtd_info
 | 
			
		||||
@@ -1385,6 +1456,7 @@ static int spi_nor_write(struct mtd_info
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
 write_err:
 | 
			
		||||
@@ -173,7 +173,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
 | 
			
		||||
 	spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_WRITE);
 | 
			
		||||
 	return ret;
 | 
			
		||||
 }
 | 
			
		||||
@@ -2808,8 +2880,10 @@ int spi_nor_scan(struct spi_nor *nor, co
 | 
			
		||||
@@ -2801,8 +2873,10 @@ int spi_nor_scan(struct spi_nor *nor, co
 | 
			
		||||
 	} else if (mtd->size > 0x1000000) {
 | 
			
		||||
 		/* enable 4-byte addressing if the device exceeds 16MiB */
 | 
			
		||||
 		nor->addr_width = 4;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,124 +0,0 @@
 | 
			
		||||
--- a/drivers/mtd/spi-nor/spi-nor.c
 | 
			
		||||
+++ b/drivers/mtd/spi-nor/spi-nor.c
 | 
			
		||||
@@ -1468,6 +1468,67 @@ write_err:
 | 
			
		||||
 	return ret;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
+static int spi_nor_chunked_write(struct mtd_info *mtd, loff_t _to, size_t _len,
 | 
			
		||||
+				 size_t *_retlen, const u_char *_buf)
 | 
			
		||||
+{
 | 
			
		||||
+	struct spi_nor *nor = mtd_to_spi_nor(mtd);
 | 
			
		||||
+	u32 addr_width = nor->addr_width + !!(nor->flags & SNOR_F_4B_EXT_ADDR);
 | 
			
		||||
+	int chunk_size;
 | 
			
		||||
+	int retlen = 0;
 | 
			
		||||
+	int ret;
 | 
			
		||||
+
 | 
			
		||||
+	chunk_size = nor->chunk_size;
 | 
			
		||||
+	if (!chunk_size)
 | 
			
		||||
+		chunk_size = _len;
 | 
			
		||||
+
 | 
			
		||||
+	if (addr_width > 3)
 | 
			
		||||
+		chunk_size -= addr_width - 3;
 | 
			
		||||
+
 | 
			
		||||
+	while (retlen < _len) {
 | 
			
		||||
+		size_t len = min_t(int, chunk_size, _len - retlen);
 | 
			
		||||
+		const u_char *buf = _buf + retlen;
 | 
			
		||||
+		loff_t to = _to + retlen;
 | 
			
		||||
+
 | 
			
		||||
+		if (nor->flags & SNOR_F_SST)
 | 
			
		||||
+			ret = sst_write(mtd, to, len, &retlen, buf);
 | 
			
		||||
+		else
 | 
			
		||||
+			ret = spi_nor_write(mtd, to, len, &retlen, buf);
 | 
			
		||||
+		if (ret)
 | 
			
		||||
+			return ret;
 | 
			
		||||
+	}
 | 
			
		||||
+
 | 
			
		||||
+	*_retlen += retlen;
 | 
			
		||||
+	return 0;
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+static int spi_nor_chunked_read(struct mtd_info *mtd, loff_t _from, size_t _len,
 | 
			
		||||
+				size_t *_retlen, u_char *_buf)
 | 
			
		||||
+{
 | 
			
		||||
+	struct spi_nor *nor = mtd_to_spi_nor(mtd);
 | 
			
		||||
+	int chunk_size;
 | 
			
		||||
+	int ret;
 | 
			
		||||
+
 | 
			
		||||
+	chunk_size = nor->chunk_size;
 | 
			
		||||
+	if (!chunk_size)
 | 
			
		||||
+		chunk_size = _len;
 | 
			
		||||
+
 | 
			
		||||
+	*_retlen = 0;
 | 
			
		||||
+	while (*_retlen < _len) {
 | 
			
		||||
+		size_t len = min_t(int, chunk_size, _len - *_retlen);
 | 
			
		||||
+		u_char *buf = _buf + *_retlen;
 | 
			
		||||
+		loff_t from = _from + *_retlen;
 | 
			
		||||
+		int retlen = 0;
 | 
			
		||||
+
 | 
			
		||||
+		ret = spi_nor_read(mtd, from, len, &retlen, buf);
 | 
			
		||||
+		if (ret)
 | 
			
		||||
+			return ret;
 | 
			
		||||
+
 | 
			
		||||
+		*_retlen += retlen;
 | 
			
		||||
+	}
 | 
			
		||||
+
 | 
			
		||||
+	return 0;
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
 /**
 | 
			
		||||
  * macronix_quad_enable() - set QE bit in Status Register.
 | 
			
		||||
  * @nor:	pointer to a 'struct spi_nor'
 | 
			
		||||
@@ -2826,10 +2887,12 @@ int spi_nor_scan(struct spi_nor *nor, co
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
 	/* sst nor chips use AAI word program */
 | 
			
		||||
-	if (info->flags & SST_WRITE)
 | 
			
		||||
+	if (info->flags & SST_WRITE) {
 | 
			
		||||
 		mtd->_write = sst_write;
 | 
			
		||||
-	else
 | 
			
		||||
+		nor->flags |= SNOR_F_SST;
 | 
			
		||||
+	} else {
 | 
			
		||||
 		mtd->_write = spi_nor_write;
 | 
			
		||||
+	}
 | 
			
		||||
 
 | 
			
		||||
 	if (info->flags & USE_FSR)
 | 
			
		||||
 		nor->flags |= SNOR_F_USE_FSR;
 | 
			
		||||
@@ -2848,11 +2911,20 @@ int spi_nor_scan(struct spi_nor *nor, co
 | 
			
		||||
 	mtd->writebufsize = nor->page_size;
 | 
			
		||||
 
 | 
			
		||||
 	if (np) {
 | 
			
		||||
+		u32 val;
 | 
			
		||||
+
 | 
			
		||||
 		/* If we were instantiated by DT, use it */
 | 
			
		||||
 		if (of_property_read_bool(np, "m25p,fast-read"))
 | 
			
		||||
 			params.hwcaps.mask |= SNOR_HWCAPS_READ_FAST;
 | 
			
		||||
 		else
 | 
			
		||||
 			params.hwcaps.mask &= ~SNOR_HWCAPS_READ_FAST;
 | 
			
		||||
+
 | 
			
		||||
+		if (!of_property_read_u32(np, "m25p,chunked-io", &val)) {
 | 
			
		||||
+			dev_info(dev, "using chunked io (size=%d)\n", val);
 | 
			
		||||
+			mtd->_read = spi_nor_chunked_read;
 | 
			
		||||
+			mtd->_write = spi_nor_chunked_write;
 | 
			
		||||
+			nor->chunk_size = val;
 | 
			
		||||
+		}
 | 
			
		||||
 	} else {
 | 
			
		||||
 		/* If we weren't instantiated by DT, default to fast-read */
 | 
			
		||||
 		params.hwcaps.mask |= SNOR_HWCAPS_READ_FAST;
 | 
			
		||||
--- a/include/linux/mtd/spi-nor.h
 | 
			
		||||
+++ b/include/linux/mtd/spi-nor.h
 | 
			
		||||
@@ -231,6 +231,7 @@ enum spi_nor_option_flags {
 | 
			
		||||
 	SNOR_F_READY_XSR_RDY	= BIT(4),
 | 
			
		||||
 	SNOR_F_USE_CLSR		= BIT(5),
 | 
			
		||||
 	SNOR_F_4B_EXT_ADDR	= BIT(6),
 | 
			
		||||
+	SNOR_F_SST		= BIT(7),
 | 
			
		||||
 };
 | 
			
		||||
 
 | 
			
		||||
 /**
 | 
			
		||||
@@ -272,6 +273,7 @@ struct spi_nor {
 | 
			
		||||
 	struct mutex		lock;
 | 
			
		||||
 	struct device		*dev;
 | 
			
		||||
 	u32			page_size;
 | 
			
		||||
+	size_t			chunk_size;
 | 
			
		||||
 	u8			addr_width;
 | 
			
		||||
 	u8			erase_opcode;
 | 
			
		||||
 	u8			read_opcode;
 | 
			
		||||
@@ -9,56 +9,3 @@
 | 
			
		||||
 	{ "mx66u51235f", INFO(0xc2253a, 0, 64 * 1024, 1024, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
 | 
			
		||||
 	{ "mx66l1g45g",  INFO(0xc2201b, 0, 64 * 1024, 2048, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
 | 
			
		||||
 	{ "mx66l1g55g",  INFO(0xc2261b, 0, 64 * 1024, 2048, SPI_NOR_QUAD_READ) },
 | 
			
		||||
@@ -1947,7 +1947,11 @@ static int spi_nor_read_sfdp(struct spi_
 | 
			
		||||
 	nor->read_dummy = 8;
 | 
			
		||||
 
 | 
			
		||||
 	while (len) {
 | 
			
		||||
-		ret = nor->read(nor, addr, len, (u8 *)buf);
 | 
			
		||||
+		size_t _len = len;
 | 
			
		||||
+
 | 
			
		||||
+		if (nor->chunk_size)
 | 
			
		||||
+			_len = min(len, nor->chunk_size);
 | 
			
		||||
+		ret = nor->read(nor, addr, _len, (u8 *)buf);
 | 
			
		||||
 		if (!ret || ret > len) {
 | 
			
		||||
 			ret = -EIO;
 | 
			
		||||
 			goto read_err;
 | 
			
		||||
@@ -2791,6 +2795,7 @@ int spi_nor_scan(struct spi_nor *nor, co
 | 
			
		||||
 	struct device *dev = nor->dev;
 | 
			
		||||
 	struct mtd_info *mtd = &nor->mtd;
 | 
			
		||||
 	struct device_node *np = spi_nor_get_flash_node(nor);
 | 
			
		||||
+	u32 val;
 | 
			
		||||
 	int ret;
 | 
			
		||||
 	int i;
 | 
			
		||||
 
 | 
			
		||||
@@ -2803,6 +2808,9 @@ int spi_nor_scan(struct spi_nor *nor, co
 | 
			
		||||
 	nor->read_proto = SNOR_PROTO_1_1_1;
 | 
			
		||||
 	nor->write_proto = SNOR_PROTO_1_1_1;
 | 
			
		||||
 
 | 
			
		||||
+	if (np && !of_property_read_u32(np, "m25p,chunked-io", &val))
 | 
			
		||||
+		nor->chunk_size = val;
 | 
			
		||||
+
 | 
			
		||||
 	if (name)
 | 
			
		||||
 		info = spi_nor_match_id(name);
 | 
			
		||||
 	/* Try to auto-detect if chip name wasn't specified or not found */
 | 
			
		||||
@@ -2916,19 +2924,16 @@ int spi_nor_scan(struct spi_nor *nor, co
 | 
			
		||||
 	mtd->writebufsize = nor->page_size;
 | 
			
		||||
 
 | 
			
		||||
 	if (np) {
 | 
			
		||||
-		u32 val;
 | 
			
		||||
-
 | 
			
		||||
 		/* If we were instantiated by DT, use it */
 | 
			
		||||
 		if (of_property_read_bool(np, "m25p,fast-read"))
 | 
			
		||||
 			params.hwcaps.mask |= SNOR_HWCAPS_READ_FAST;
 | 
			
		||||
 		else
 | 
			
		||||
 			params.hwcaps.mask &= ~SNOR_HWCAPS_READ_FAST;
 | 
			
		||||
 
 | 
			
		||||
-		if (!of_property_read_u32(np, "m25p,chunked-io", &val)) {
 | 
			
		||||
-			dev_info(dev, "using chunked io (size=%d)\n", val);
 | 
			
		||||
+		if (nor->chunk_size) {
 | 
			
		||||
+			dev_info(dev, "using chunked io (size=%d)\n", nor->chunk_size);
 | 
			
		||||
 			mtd->_read = spi_nor_chunked_read;
 | 
			
		||||
 			mtd->_write = spi_nor_chunked_write;
 | 
			
		||||
-			nor->chunk_size = val;
 | 
			
		||||
 		}
 | 
			
		||||
 	} else {
 | 
			
		||||
 		/* If we weren't instantiated by DT, default to fast-read */
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user