diff options
author | Gabor Juhos <juhosg@openwrt.org> | 2012-01-07 19:36:33 +0000 |
---|---|---|
committer | Gabor Juhos <juhosg@openwrt.org> | 2012-01-07 19:36:33 +0000 |
commit | a56bdeff9d994f6e8e39cd8a0cad571866b27533 (patch) | |
tree | b9485b060efb44c62a76663bab827fec1c13c238 /target/linux/ar71xx/patches-2.6.39/113-mtd-m25p80-allow-to-specify-max-read-size.patch | |
parent | 8b567fb508573e35f1acfce638cdc76617c1f0b8 (diff) | |
download | upstream-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
Diffstat (limited to 'target/linux/ar71xx/patches-2.6.39/113-mtd-m25p80-allow-to-specify-max-read-size.patch')
-rw-r--r-- | target/linux/ar71xx/patches-2.6.39/113-mtd-m25p80-allow-to-specify-max-read-size.patch | 112 |
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 */ + }; + |