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 | --- a/drivers/mtd/spi-nor/spi-nor.c | ||||||
| +++ b/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 || |  	if (JEDEC_MFR(info) == SNOR_MFR_ATMEL || | ||||||
|  	    JEDEC_MFR(info) == SNOR_MFR_INTEL || |  	    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 | --- a/drivers/mtd/spi-nor/spi-nor.c | ||||||
| +++ b/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_INTEL || | ||||||
|  	    JEDEC_MFR(info) == SNOR_MFR_MACRONIX || |  	    JEDEC_MFR(info) == SNOR_MFR_MACRONIX || | ||||||
|  	    JEDEC_MFR(info) == SNOR_MFR_SST || |  	    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) { |  	    info->flags & SPI_NOR_HAS_LOCK) { | ||||||
|  		write_enable(nor); |  		write_enable(nor); | ||||||
|  		write_sr(nor, 0); |  		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 */ |  	/* NOR protection support for STmicro/Micron chips and similar */ | ||||||
|  	if (JEDEC_MFR(info) == SNOR_MFR_MICRON || |  	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) |  	depends on ARCH_AT91 || (ARM && COMPILE_TEST) | ||||||
| --- a/drivers/mtd/spi-nor/spi-nor.c | --- a/drivers/mtd/spi-nor/spi-nor.c | ||||||
| +++ b/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 |  #ifdef CONFIG_MTD_SPI_NOR_USE_4K_SECTORS | ||||||
|  	/* prefer "small sector" erase if possible */ |  	/* 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 |  obj-$(CONFIG_SPI_OC_TINY)		+= spi-oc-tiny.o | ||||||
| --- /dev/null | --- /dev/null | ||||||
| +++ b/drivers/spi/spi-mt7621.c | +++ b/drivers/spi/spi-mt7621.c | ||||||
| @@ -0,0 +1,483 @@ | @@ -0,0 +1,491 @@ | ||||||
| +/* | +/* | ||||||
| + * spi-mt7621.c -- MediaTek MT7621 SPI controller driver | + * 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) | +		if (t->speed_hz < speed) | ||||||
| +			speed = t->speed_hz; | +			speed = t->speed_hz; | ||||||
| + | + | ||||||
| +		if (WARN_ON(len + t->len > 36)) { | +		/* | ||||||
| +			status = -EIO; | +		 * m25p80 might attempt to write more data than we can handle. | ||||||
| +			goto msg_done; | +		 * 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++) | +		for (i = 0; i < t->len; i++, len++) | ||||||
| +			data[len / 4] |= buf[i] << (8 * (len & 3)); | +			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); | +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) | +static int mt7621_spi_probe(struct platform_device *pdev) | ||||||
| +{ | +{ | ||||||
| +	const struct of_device_id *match; | +	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->bits_per_word_mask = SPI_BPW_MASK(8); | ||||||
| +	master->dev.of_node = pdev->dev.of_node; | +	master->dev.of_node = pdev->dev.of_node; | ||||||
| +	master->num_chipselect = 2; | +	master->num_chipselect = 2; | ||||||
|  | +	master->max_transfer_size = mt7621_max_transfer_size; | ||||||
| + | + | ||||||
| +	dev_set_drvdata(&pdev->dev, master); | +	dev_set_drvdata(&pdev->dev, master); | ||||||
| + | + | ||||||
|   | |||||||
| @@ -165,7 +165,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name> | |||||||
|  	for (i = 0; i < len; ) { |  	for (i = 0; i < len; ) { | ||||||
|  		ssize_t written; |  		ssize_t written; | ||||||
|  		loff_t addr = to + i; |  		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: |  write_err: | ||||||
| @@ -173,7 +173,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name> | |||||||
|  	spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_WRITE); |  	spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_WRITE); | ||||||
|  	return ret; |  	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) { |  	} else if (mtd->size > 0x1000000) { | ||||||
|  		/* enable 4-byte addressing if the device exceeds 16MiB */ |  		/* enable 4-byte addressing if the device exceeds 16MiB */ | ||||||
|  		nor->addr_width = 4; |  		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) }, |  	{ "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) }, |  	{ "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) }, |  	{ "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
	 Felix Fietkau
					Felix Fietkau