diff options
Diffstat (limited to 'target/linux/ramips/patches-4.14/0054-mtd-add-chunked-read-io-to-m25p80.patch')
-rw-r--r-- | target/linux/ramips/patches-4.14/0054-mtd-add-chunked-read-io-to-m25p80.patch | 124 |
1 files changed, 124 insertions, 0 deletions
diff --git a/target/linux/ramips/patches-4.14/0054-mtd-add-chunked-read-io-to-m25p80.patch b/target/linux/ramips/patches-4.14/0054-mtd-add-chunked-read-io-to-m25p80.patch new file mode 100644 index 0000000000..b20f081afe --- /dev/null +++ b/target/linux/ramips/patches-4.14/0054-mtd-add-chunked-read-io-to-m25p80.patch @@ -0,0 +1,124 @@ +--- 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; |