openwrt icon indicating copy to clipboard operation
openwrt copied to clipboard

ath79: fix jffs2 read fail issue for TP-Link TL-WR2543N

Open DragonBluep opened this issue 2 years ago • 2 comments

DragonBluep avatar Jan 18 '24 13:01 DragonBluep

You shouldn't need to modify spi-nor at all, and rather let the spi-ath79 driver set a maximum message length (see the max_message_size() callback) (based on a property).

The spi-nor driver then should do the right thing and split reads automatically.

KanjiMonster avatar Jan 18 '24 16:01 KanjiMonster

You shouldn't need to modify spi-nor at all, and rather let the spi-ath79 driver set a maximum message length (see the max_message_size() callback) (based on a property).

The spi-nor driver then should do the right thing and split reads automatically.

Hi! Thanks for your review. I've tried limit the max_message_size/max_transfer_size on ath79-spi driver today. It does indeed reduce the size of a single read operation, but it cannot fix this issue. This problem seems to be caused by the capacitor taking some time to charge? So it requires some delay time? But strangely, even though I inserted same delay in ath79-spi spi-mem read function, it still couldn't work properly.

I decided not to touch the current patch. In the last attempt, I bricked this device, and recently I don't really want to teardown it to attach TTL.

--- a/drivers/spi/spi-ath79.c
+++ b/drivers/spi/spi-ath79.c
@@ -20,6 +20,8 @@
 #include <linux/bitops.h>
 #include <linux/clk.h>
 #include <linux/err.h>
+#include <linux/limits.h>
+#include <linux/of.h>
 
 #define DRV_NAME	"ath79-spi"
 
@@ -41,6 +43,7 @@ struct ath79_spi {
 	struct spi_bitbang	bitbang;
 	u32			ioc_base;
 	u32			reg_ctrl;
+	u32			max_message_size;
 	void __iomem		*base;
 	struct clk		*clk;
 	unsigned int		rrw_delay;
@@ -105,6 +108,14 @@ static void ath79_spi_disable(struct ath79_spi *sp)
 	ath79_spi_wr(sp, AR71XX_SPI_REG_FS, 0);
 }
 
+static size_t ath79_spi_max_message_size(struct spi_device *spi)
+{
+	struct ath79_spi *sp = ath79_spidev_to_sp(spi);
+
+	WARN_ONCE("max_message_size %u\n", sp->max_message_size);
+	return sp->max_message_size; // ? sp->max_message_size : SIZE_MAX;
+}
+
 static u32 ath79_spi_txrx_mode0(struct spi_device *spi, unsigned int nsecs,
 			       u32 word, u8 bits, unsigned flags)
 {
@@ -151,6 +162,11 @@ static int ath79_exec_mem_op(struct spi_mem *mem,
 	/* disable GPIO mode */
 	ath79_spi_wr(sp, AR71XX_SPI_REG_FS, 0);
 
+	if (sp->max_message_size) {
+		WARN_ONCE(1, "nbytes %u\n", op->data.nbytes);
+		usleep_range(10, 20);
+	}
+
 	memcpy_fromio(op->data.buf.in, sp->base + op->addr.val, op->data.nbytes);
 
 	/* enable GPIO mode */
@@ -188,6 +204,8 @@ static int ath79_spi_probe(struct platform_device *pdev)
 	master->flags = SPI_MASTER_GPIO_SS;
 	master->num_chipselect = 3;
 	master->mem_ops = &ath79_mem_ops;
+	master->max_transfer_size = ath79_spi_max_message_size;
+	master->max_message_size = ath79_spi_max_message_size;
 
 	sp->bitbang.master = master;
 	sp->bitbang.chipselect = ath79_spi_chipselect;
@@ -220,6 +238,12 @@ static int ath79_spi_probe(struct platform_device *pdev)
 	dev_dbg(&pdev->dev, "register read/write delay is %u nsecs\n",
 		sp->rrw_delay);
 
+	sp->max_message_size = 0;
+	if (!of_property_read_u32(pdev->dev.of_node, "max-message-size",
+				  &sp->max_message_size))
+		dev_info(&pdev->dev, "set max spi message size to %u\n",
+			 sp->max_message_size);
+
 	ath79_spi_enable(sp);
 	ret = spi_bitbang_start(&sp->bitbang);
 	if (ret)

DragonBluep avatar Jan 19 '24 11:01 DragonBluep