[PATCH 13/19] mtd: spi-nor: Add support for cross die read in dual flash configuration
Tejas Bhumkar
tejas.arvind.bhumkar at amd.com
Mon Mar 11 18:22:43 CET 2024
From: Ashok Reddy Soma <ashok.reddy.soma at xilinx.com>
In a dual parallel configuration, halve the read offset.
Determine whether the read offset points to the lower or
upper flash in a dual stacked configuration and set the
corresponding flags accordingly.
Include support for cases where the read involves an odd
number of bytes.
Extend support for cross-die reads in flash memory devices
that contain multiple dies within them.
Signed-off-by: Ashok Reddy Soma <ashok.reddy.soma at xilinx.com>
Signed-off-by: Michal Simek <michal.simek at xilinx.com>
Signed-off-by: Tejas Bhumkar <tejas.arvind.bhumkar at amd.com>
---
drivers/mtd/spi/spi-nor-core.c | 42 ++++++++++++++++++++++++++++++----
include/spi.h | 3 ++-
2 files changed, 39 insertions(+), 6 deletions(-)
diff --git a/drivers/mtd/spi/spi-nor-core.c b/drivers/mtd/spi/spi-nor-core.c
index e0398a7a29..ffb9a48316 100644
--- a/drivers/mtd/spi/spi-nor-core.c
+++ b/drivers/mtd/spi/spi-nor-core.c
@@ -1528,11 +1528,9 @@ static int spi_nor_read(struct mtd_info *mtd, loff_t from, size_t len,
{
struct spi_nor *nor = mtd_to_spi_nor(mtd);
int ret;
- loff_t offset = from;
- u32 read_len = 0;
- u32 rem_bank_len = 0;
- u8 bank;
- bool is_ofst_odd = false;
+ u32 offset = from;
+ u32 bank_size, stack_shift = 0, read_len = 0, rem_bank_len = 0;
+ u8 bank, cur_bank, nxt_bank, is_ofst_odd = 0;
dev_dbg(nor->dev, "from 0x%08x, len %zd\n", (u32)from, len);
@@ -1565,6 +1563,40 @@ static int spi_nor_read(struct mtd_info *mtd, loff_t from, size_t len,
}
}
+ if (nor->addr_width == 4) {
+ /*
+ * Some flash devices like N25Q512 have multiple dies
+ * in it. Read operation in these devices is bounded
+ * by its die segment. In a continuous read, across
+ * multiple dies, when the last byte of the selected
+ * die segment is read, the next byte read is the
+ * first byte of the same die segment. This is Die
+ * cross over issue. So to handle this issue, split
+ * a read transaction, that spans across multiple
+ * banks, into one read per bank. Bank size is 16MB
+ * for single and dual stacked mode and 32MB for dual
+ * parallel mode.
+ */
+ if (nor->spi && nor->spi->multi_die) {
+ bank_size = SZ_16M;
+ if (nor->flags & SNOR_F_HAS_PARALLEL)
+ bank_size <<= 1;
+ cur_bank = offset / bank_size;
+ nxt_bank = (offset + len) / bank_size;
+ if (cur_bank != nxt_bank)
+ rem_bank_len = (bank_size *
+ (cur_bank + 1)) -
+ offset;
+ else
+ rem_bank_len = (mtd->size >>
+ stack_shift) -
+ offset;
+ } else {
+ rem_bank_len = (mtd->size >> stack_shift) -
+ offset;
+ }
+ }
+
if (nor->flags & SNOR_F_HAS_PARALLEL)
offset /= 2;
diff --git a/include/spi.h b/include/spi.h
index ade30fab73..7b6c49cfc5 100644
--- a/include/spi.h
+++ b/include/spi.h
@@ -166,7 +166,7 @@ struct spi_slave {
unsigned int max_write_size;
void *memory_map;
- u8 flags;
+ u32 flags;
#define SPI_XFER_BEGIN BIT(0) /* Assert CS before transfer */
#define SPI_XFER_END BIT(1) /* Deassert CS after transfer */
#define SPI_XFER_ONCE (SPI_XFER_BEGIN | SPI_XFER_END)
@@ -180,6 +180,7 @@ struct spi_slave {
*/
bool multi_cs_cap;
u32 bytemode;
+ bool multi_die; /* flash with multiple dies */
};
/**
--
2.27.0
More information about the U-Boot
mailing list