aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGabor Juhos <juhosg@openwrt.org>2012-01-07 19:36:33 +0000
committerGabor Juhos <juhosg@openwrt.org>2012-01-07 19:36:33 +0000
commita56bdeff9d994f6e8e39cd8a0cad571866b27533 (patch)
treeb9485b060efb44c62a76663bab827fec1c13c238
parent8b567fb508573e35f1acfce638cdc76617c1f0b8 (diff)
downloadupstream-a56bdeff9d994f6e8e39cd8a0cad571866b27533.tar.gz
upstream-a56bdeff9d994f6e8e39cd8a0cad571866b27533.tar.bz2
upstream-a56bdeff9d994f6e8e39cd8a0cad571866b27533.zip
ar71xx: allow to specify max read size for m25p80
Reading from the flash chip on the TL-WR2543ND seems buggy. If the SPI flash driver tries to read too much data in one SPI transfer, the flash chip returns bogus values. This can be caused by a buggy flash chip on my board, or it can be a bug in our SPI driver. Add a workaround to the m25p80 driver until I find out the root cause of the problem. The patch allows to specify the maximum numner of bytes which can be read safely withint one SPI transfer. SVN-Revision: 29679
-rw-r--r--target/linux/ar71xx/patches-2.6.39/113-mtd-m25p80-allow-to-specify-max-read-size.patch112
1 files changed, 112 insertions, 0 deletions
diff --git a/target/linux/ar71xx/patches-2.6.39/113-mtd-m25p80-allow-to-specify-max-read-size.patch b/target/linux/ar71xx/patches-2.6.39/113-mtd-m25p80-allow-to-specify-max-read-size.patch
new file mode 100644
index 0000000000..8bb69df242
--- /dev/null
+++ b/target/linux/ar71xx/patches-2.6.39/113-mtd-m25p80-allow-to-specify-max-read-size.patch
@@ -0,0 +1,112 @@
+--- a/drivers/mtd/devices/m25p80.c
++++ b/drivers/mtd/devices/m25p80.c
+@@ -94,6 +94,7 @@ struct m25p {
+ u16 addr_width;
+ u8 erase_opcode;
+ u8 *command;
++ size_t max_read_len;
+ };
+
+ static inline struct m25p *mtd_to_m25p(struct mtd_info *mtd)
+@@ -341,6 +342,7 @@ static int m25p80_read(struct mtd_info *
+ struct m25p *flash = mtd_to_m25p(mtd);
+ struct spi_transfer t[2];
+ struct spi_message m;
++ loff_t ofs;
+
+ DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %zd\n",
+ dev_name(&flash->spi->dev), __func__, "from",
+@@ -364,8 +366,6 @@ static int m25p80_read(struct mtd_info *
+ t[0].len = m25p_cmdsz(flash) + FAST_READ_DUMMY_BYTE;
+ spi_message_add_tail(&t[0], &m);
+
+- t[1].rx_buf = buf;
+- t[1].len = len;
+ spi_message_add_tail(&t[1], &m);
+
+ /* Byte count starts at zero. */
+@@ -373,13 +373,6 @@ static int m25p80_read(struct mtd_info *
+
+ mutex_lock(&flash->lock);
+
+- /* Wait till previous write/erase is done. */
+- if (wait_till_ready(flash)) {
+- /* REVISIT status return?? */
+- mutex_unlock(&flash->lock);
+- return 1;
+- }
+-
+ /* FIXME switch to OPCODE_FAST_READ. It's required for higher
+ * clocks; and at this writing, every chip this driver handles
+ * supports that opcode.
+@@ -387,11 +380,44 @@ static int m25p80_read(struct mtd_info *
+
+ /* Set up the write data buffer. */
+ flash->command[0] = OPCODE_READ;
+- m25p_addr2cmd(flash, from, flash->command);
+
+- spi_sync(flash->spi, &m);
++ ofs = 0;
++ while (len) {
++ size_t readlen;
++ size_t done;
++ int ret;
++
++ ret = wait_till_ready(flash);
++ if (ret) {
++ mutex_unlock(&flash->lock);
++ return 1;
++ }
++
++ if (flash->max_read_len > 0 &&
++ flash->max_read_len < len)
++ readlen = flash->max_read_len;
++ else
++ readlen = len;
++
++ t[1].rx_buf = buf + ofs;
++ t[1].len = readlen;
++
++ m25p_addr2cmd(flash, from + ofs, flash->command);
++
++ spi_sync(flash->spi, &m);
+
+- *retlen = m.actual_length - m25p_cmdsz(flash) - FAST_READ_DUMMY_BYTE;
++ done = m.actual_length - m25p_cmdsz(flash) -
++ FAST_READ_DUMMY_BYTE;
++ if (done != readlen) {
++ mutex_unlock(&flash->lock);
++ return 1;
++ }
++
++ ofs += done;
++ len -= done;
++ }
++
++ *retlen = ofs;
+
+ mutex_unlock(&flash->lock);
+
+@@ -901,6 +927,12 @@ static int __devinit m25p_probe(struct s
+ flash->mtd.erase = m25p80_erase;
+ flash->mtd.read = m25p80_read;
+
++ if (data && data->max_read_len) {
++ flash->max_read_len = data->max_read_len;
++ dev_warn(&spi->dev, "max_read_len set to %d bytes\n",
++ flash->max_read_len);
++ }
++
+ /* sst flash chips use AAI word program */
+ if (info->jedec_id >> 16 == 0xbf)
+ flash->mtd.write = sst_write;
+--- a/include/linux/spi/flash.h
++++ b/include/linux/spi/flash.h
+@@ -26,6 +26,7 @@ struct flash_platform_data {
+ char *type;
+ const char **part_probes;
+
++ size_t max_read_len;
+ /* we'll likely add more ... use JEDEC IDs, etc */
+ };
+