Skip to content

Commit

Permalink
mtd: spi-nor: intel-spi: Avoid crossing 4K address boundary on read/w…
Browse files Browse the repository at this point in the history
…rite

commit 2b75ebe upstream.

It was observed that reads crossing 4K address boundary are failing.

This limitation is mentioned in Intel documents:

Intel(R) 9 Series Chipset Family Platform Controller Hub (PCH) Datasheet:

"5.26.3 Flash Access
Program Register Access:
* Program Register Accesses are not allowed to cross a 4 KB boundary..."

Enhanced Serial Peripheral Interface (eSPI)
Interface Base Specification (for Client and Server Platforms):

"5.1.4 Address
For other memory transactions, the address may start or end at any byte
boundary. However, the address and payload length combination must not
cross the naturally aligned address boundary of the corresponding Maximum
Payload Size. It must not cross a 4 KB address boundary."

Avoid this by splitting an operation crossing the boundary into two
operations.

Fixes: 8afda8b ("spi-nor: Add support for Intel SPI serial flash controller")
Cc: [email protected]
Reported-by: Romain Porte <[email protected]>
Tested-by: Pascal Fabreges <[email protected]>
Signed-off-by: Alexander Sverdlin <[email protected]>
Reviewed-by: Tudor Ambarus <[email protected]>
Acked-by: Mika Westerberg <[email protected]>
Signed-off-by: Miquel Raynal <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
  • Loading branch information
asverdlin authored and gregkh committed May 22, 2019
1 parent ed824ff commit 8a2c343
Showing 1 changed file with 8 additions and 0 deletions.
8 changes: 8 additions & 0 deletions drivers/mtd/spi-nor/intel-spi.c
Original file line number Diff line number Diff line change
Expand Up @@ -632,6 +632,10 @@ static ssize_t intel_spi_read(struct spi_nor *nor, loff_t from, size_t len,
while (len > 0) {
block_size = min_t(size_t, len, INTEL_SPI_FIFO_SZ);

/* Read cannot cross 4K boundary */
block_size = min_t(loff_t, from + block_size,
round_up(from + 1, SZ_4K)) - from;

writel(from, ispi->base + FADDR);

val = readl(ispi->base + HSFSTS_CTL);
Expand Down Expand Up @@ -685,6 +689,10 @@ static ssize_t intel_spi_write(struct spi_nor *nor, loff_t to, size_t len,
while (len > 0) {
block_size = min_t(size_t, len, INTEL_SPI_FIFO_SZ);

/* Write cannot cross 4K boundary */
block_size = min_t(loff_t, to + block_size,
round_up(to + 1, SZ_4K)) - to;

writel(to, ispi->base + FADDR);

val = readl(ispi->base + HSFSTS_CTL);
Expand Down

0 comments on commit 8a2c343

Please sign in to comment.