Skip to content

Commit

Permalink
mtd: spi-nor: Fixed die crossover issue
Browse files Browse the repository at this point in the history
Read operation in multi die flash devices is bounded by its
die segment. In a continuous read, that spans across multiple
die, 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 crossover issue.

This patch fixes this issue by splitting a read transaction,
that spans across multiple banks, into one read per bank. Bank
size for single and dual stacked connection is 16MB and for
dual parallel connection its 32MB.

Signed-off-by: Amit Kumar Mahapatra <amit.kumar-mahapatra@xilinx.com>
Reviewed-by: Naga Sureshkumar Relli <naga.sureshkumar.relli@xilinx.com>
Signed-off-by: Radhey Shyam Pandey <radhey.shyam.pandey@xilinx.com>
  • Loading branch information
Amit Kumar Mahapatra authored and radheyxilinx committed Aug 1, 2019
1 parent 9de6a1e commit c8ca26b
Showing 1 changed file with 32 additions and 3 deletions.
35 changes: 32 additions & 3 deletions drivers/mtd/spi-nor/spi-nor.c
Expand Up @@ -1719,6 +1719,9 @@ static int spi_nor_read(struct mtd_info *mtd, loff_t from, size_t len,
u8 bank;
u8 is_ofst_odd = 0;
loff_t addr = 0;
u8 cur_bank;
u8 nxt_bank;
u32 bank_size;

#define OFFSET_16_MB 0x1000000

Expand Down Expand Up @@ -1756,10 +1759,36 @@ static int spi_nor_read(struct mtd_info *mtd, loff_t from, size_t len,
}
}

/* Die cross over issue is not handled */
if (nor->addr_width == 4) {
rem_bank_len = (mtd->size >> stack_shift) -
(offset << nor->shift);
/*
* 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->multi_die) {
bank_size = (OFFSET_16_MB << nor->shift);
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 << nor->shift);
} else {
rem_bank_len = (mtd->size >> stack_shift) -
(offset << nor->shift);
}
}
if (nor->addr_width == 3)
write_ear(nor, offset);
Expand Down

0 comments on commit c8ca26b

Please sign in to comment.