From b2be69516662957a9cb1b330d640898f262f7f0e Mon Sep 17 00:00:00 2001
From: Haolin Li
Date: Sun, 5 Sep 2021 22:41:41 +0800
Subject: [PATCH 01/18] mtd: spinand: macronix: Fix ECC Status Read
According to datasheet, the upper four bits are reserved or used for
reflecting the ECC status of the accumulated pages. The error bits
number for the worst segment of the current page is encoded on lower
four bits. Fix it by masking the upper bits.
This same issue has been already fixed in the linux kernel by:
"mtd: spinand: macronix: Fix ECC Status Read"
(sha1: f4cb4d7b46f6409382fd981eec9556e1f3c1dc5d)
Apply the same fix in the U-Boot driver.
Signed-off-by: Haolin Li
Reviewed-by: Jagan Teki
---
drivers/mtd/nand/spi/macronix.c | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/drivers/mtd/nand/spi/macronix.c b/drivers/mtd/nand/spi/macronix.c
index f4a8e81639..6d643a8000 100644
--- a/drivers/mtd/nand/spi/macronix.c
+++ b/drivers/mtd/nand/spi/macronix.c
@@ -14,6 +14,8 @@
#include
#define SPINAND_MFR_MACRONIX 0xC2
+#define MACRONIX_ECCSR_MASK 0x0F
+
static SPINAND_OP_VARIANTS(read_cache_variants,
SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0),
@@ -59,7 +61,13 @@ static int mx35lf1ge4ab_get_eccsr(struct spinand_device *spinand, u8 *eccsr)
SPI_MEM_OP_DUMMY(1, 1),
SPI_MEM_OP_DATA_IN(1, eccsr, 1));
- return spi_mem_exec_op(spinand->slave, &op);
+ int ret = spi_mem_exec_op(spinand->slave, &op);
+
+ if (ret)
+ return ret;
+
+ *eccsr &= MACRONIX_ECCSR_MASK;
+ return 0;
}
static int mx35lf1ge4ab_ecc_get_status(struct spinand_device *spinand,
From e8966138175644545fbd9ed741cbde572dd1ed1c Mon Sep 17 00:00:00 2001
From: Marek Vasut
Date: Tue, 5 Oct 2021 10:58:47 +0200
Subject: [PATCH 02/18] mtd: spi-nor-ids: Reinstate Micron MT25QL02G
This ID disappeared in 5b66fdb29dc ("mtd: spi: Remove unused files"),
add the ID back, since the chip is used on devices supported by U-Boot.
Fixes: 5b66fdb29dc ("mtd: spi: Remove unused files")
Signed-off-by: Marek Vasut
Cc: Horatiu Vultur
Cc: Simon Goldschmidt
Cc: Stefan Roese
Cc: Vignesh R
Reviewed-by: Stefan Roese
Reviewed-by: Jagan Teki
---
drivers/mtd/spi/spi-nor-ids.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/mtd/spi/spi-nor-ids.c b/drivers/mtd/spi/spi-nor-ids.c
index 0bff52d5f2..f7f37f8ec4 100644
--- a/drivers/mtd/spi/spi-nor-ids.c
+++ b/drivers/mtd/spi/spi-nor-ids.c
@@ -195,6 +195,7 @@ const struct flash_info spi_nor_ids[] = {
{ INFO("n25q00a", 0x20bb21, 0, 64 * 1024, 2048, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ | NO_CHIP_ERASE) },
{ INFO("mt25ql01g", 0x21ba20, 0, 64 * 1024, 2048, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ | NO_CHIP_ERASE) },
{ INFO("mt25qu02g", 0x20bb22, 0, 64 * 1024, 4096, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ | NO_CHIP_ERASE) },
+ { INFO("mt25ql02g", 0x20ba22, 0, 64 * 1024, 4096, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ | NO_CHIP_ERASE | SPI_NOR_4B_OPCODES) },
#ifdef CONFIG_SPI_FLASH_MT35XU
{ INFO("mt35xu512aba", 0x2c5b1a, 0, 128 * 1024, 512, USE_FSR | SPI_NOR_OCTAL_READ | SPI_NOR_4B_OPCODES | SPI_NOR_OCTAL_DTR_READ) },
#endif /* CONFIG_SPI_FLASH_MT35XU */
From e4f97f12620e84aef23b836041b298405f18f70d Mon Sep 17 00:00:00 2001
From: Yanhong Wang
Date: Thu, 30 Sep 2021 19:53:01 +0800
Subject: [PATCH 03/18] mtd: spi-nor-ids: Add GD25LQ256D Chip
Add Gigadevice GD25LQ256D SPI NOR chip.
https://www.gigadevice.com/datasheet/gd25lq256d/
Signed-off-by: Yanhong Wang
Reviewed-by: Bin Meng
[jagan: updated commit message]
Signed-off-by: Jagan Teki
Reviewed-by: Jagan Teki
---
drivers/mtd/spi/spi-nor-ids.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/drivers/mtd/spi/spi-nor-ids.c b/drivers/mtd/spi/spi-nor-ids.c
index f7f37f8ec4..08b25712e3 100644
--- a/drivers/mtd/spi/spi-nor-ids.c
+++ b/drivers/mtd/spi/spi-nor-ids.c
@@ -122,6 +122,11 @@ const struct flash_info spi_nor_ids[] = {
SECT_4K | SPI_NOR_DUAL_READ |
SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB)
},
+ {
+ INFO("gd25lq256d", 0xc86019, 0, 64 * 1024, 512,
+ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
+ SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB)
+ },
#endif
#ifdef CONFIG_SPI_FLASH_ISSI /* ISSI */
/* ISSI */
From e66c6f10272cba050068017081b0996a9fa8b786 Mon Sep 17 00:00:00 2001
From: Takahiro Kuwano
Date: Thu, 30 Sep 2021 11:23:37 +0900
Subject: [PATCH 04/18] mtd: spi-nor: Add support for Spansion S25FL256L
The S25FL256L is a part of the S25FL-L family and has the same feature set
as S25FL128L except the density.
The datasheet can be found in the following link.
https://www.cypress.com/file/316171/download
The S25FL256L is 32MB NOR Flash that does not support Bank Address
Register. This fixup is activated if CONFIG_SPI_FLASH_BAR is enabled and
returns ENOTSUPP in setup() hook to avoid further ops.
Tested on Xilinx Zynq-7000 FPGA board.
Signed-off-by: Takahiro Kuwano
---
drivers/mtd/spi/spi-nor-core.c | 19 +++++++++++++++++++
drivers/mtd/spi/spi-nor-ids.c | 1 +
2 files changed, 20 insertions(+)
diff --git a/drivers/mtd/spi/spi-nor-core.c b/drivers/mtd/spi/spi-nor-core.c
index f1b4e5ea8e..7572be5e34 100644
--- a/drivers/mtd/spi/spi-nor-core.c
+++ b/drivers/mtd/spi/spi-nor-core.c
@@ -3224,6 +3224,21 @@ static struct spi_nor_fixups s25hx_t_fixups = {
.post_bfpt = s25hx_t_post_bfpt_fixup,
.post_sfdp = s25hx_t_post_sfdp_fixup,
};
+
+static int s25fl256l_setup(struct spi_nor *nor, const struct flash_info *info,
+ const struct spi_nor_flash_parameter *params)
+{
+ return -ENOTSUPP; /* Bank Address Register is not supported */
+}
+
+static void s25fl256l_default_init(struct spi_nor *nor)
+{
+ nor->setup = s25fl256l_setup;
+}
+
+static struct spi_nor_fixups s25fl256l_fixups = {
+ .default_init = s25fl256l_default_init,
+};
#endif
#ifdef CONFIG_SPI_FLASH_S28HS512T
@@ -3646,6 +3661,10 @@ void spi_nor_set_fixups(struct spi_nor *nor)
break;
}
}
+
+ if (CONFIG_IS_ENABLED(SPI_FLASH_BAR) &&
+ !strcmp(nor->info->name, "s25fl256l"))
+ nor->fixups = &s25fl256l_fixups;
#endif
#ifdef CONFIG_SPI_FLASH_S28HS512T
diff --git a/drivers/mtd/spi/spi-nor-ids.c b/drivers/mtd/spi/spi-nor-ids.c
index 08b25712e3..3e0935e1fb 100644
--- a/drivers/mtd/spi/spi-nor-ids.c
+++ b/drivers/mtd/spi/spi-nor-ids.c
@@ -233,6 +233,7 @@ const struct flash_info spi_nor_ids[] = {
{ INFO("s25fl208k", 0x014014, 0, 64 * 1024, 16, SECT_4K | SPI_NOR_DUAL_READ) },
{ INFO("s25fl064l", 0x016017, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
{ INFO("s25fl128l", 0x016018, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
+ { INFO("s25fl256l", 0x016019, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
{ INFO6("s25hl512t", 0x342a1a, 0x0f0390, 256 * 1024, 256,
SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES |
USE_CLSR) },
From 36384f612da992ab485c4b7cd768a89e8c3fe8cf Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marek=20Beh=C3=BAn?=
Date: Tue, 5 Oct 2021 15:55:57 +0200
Subject: [PATCH 05/18] mtd: spi-nor-core: Try cleaning up in case writing BAR
failed
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Use the cleanup codepath of spi_nor_erase() also in the event of failure
of writing the BAR register.
Signed-off-by: Marek Behún
Reviewed-by: Simon Glass
Reviewed-by: Jagan Teki
Reviewed-by: Pratyush Yadav
Tested-by: Masami Hiramatsu
---
drivers/mtd/spi/spi-nor-core.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/mtd/spi/spi-nor-core.c b/drivers/mtd/spi/spi-nor-core.c
index 7572be5e34..6da7dc3a25 100644
--- a/drivers/mtd/spi/spi-nor-core.c
+++ b/drivers/mtd/spi/spi-nor-core.c
@@ -929,7 +929,7 @@ static int spi_nor_erase(struct mtd_info *mtd, struct erase_info *instr)
#ifdef CONFIG_SPI_FLASH_BAR
ret = write_bar(nor, addr);
if (ret < 0)
- return ret;
+ goto erase_err;
#endif
write_enable(nor);
From 5ea6dccee45ab941cfc78fbbfd9600ef24c5ca60 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marek=20Beh=C3=BAn?=
Date: Tue, 5 Oct 2021 15:55:58 +0200
Subject: [PATCH 06/18] mtd: spi-nor-core: Check return value of write_enable()
in spi_nor_erase()
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The spi_nor_erase() function does not check return value of the
write_enable() call. Fix this.
Signed-off-by: Marek Behún
Reviewed-by: Simon Glass
Reviewed-by: Jagan Teki
Reviewed-by: Pratyush Yadav
Tested-by: Masami Hiramatsu
---
drivers/mtd/spi/spi-nor-core.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/mtd/spi/spi-nor-core.c b/drivers/mtd/spi/spi-nor-core.c
index 6da7dc3a25..6231ec5ce5 100644
--- a/drivers/mtd/spi/spi-nor-core.c
+++ b/drivers/mtd/spi/spi-nor-core.c
@@ -931,7 +931,9 @@ static int spi_nor_erase(struct mtd_info *mtd, struct erase_info *instr)
if (ret < 0)
goto erase_err;
#endif
- write_enable(nor);
+ ret = write_enable(nor);
+ if (ret < 0)
+ goto erase_err;
ret = spi_nor_erase_sector(nor, addr);
if (ret < 0)
From a9d9d412e00e246dbba2076ce3c11b7a5b542a76 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marek=20Beh=C3=BAn?=
Date: Tue, 5 Oct 2021 15:55:59 +0200
Subject: [PATCH 07/18] mtd: spi-nor-core: Don't overwrite return value if it
is non-zero
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The cleanup code of the spi_nor_erase() function overwrites the ret
variable with return value of clean_bar(), even if the ret variable is
already set. Fix this.
Signed-off-by: Marek Behún
Reviewed-by: Simon Glass
Tested-by: Masami Hiramatsu
---
drivers/mtd/spi/spi-nor-core.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/mtd/spi/spi-nor-core.c b/drivers/mtd/spi/spi-nor-core.c
index 6231ec5ce5..d8eed595b7 100644
--- a/drivers/mtd/spi/spi-nor-core.c
+++ b/drivers/mtd/spi/spi-nor-core.c
@@ -909,7 +909,7 @@ static int spi_nor_erase(struct mtd_info *mtd, struct erase_info *instr)
{
struct spi_nor *nor = mtd_to_spi_nor(mtd);
u32 addr, len, rem;
- int ret;
+ int ret, err;
dev_dbg(nor->dev, "at 0x%llx, len %lld\n", (long long)instr->addr,
(long long)instr->len);
@@ -949,7 +949,9 @@ static int spi_nor_erase(struct mtd_info *mtd, struct erase_info *instr)
erase_err:
#ifdef CONFIG_SPI_FLASH_BAR
- ret = clean_bar(nor);
+ err = clean_bar(nor);
+ if (!ret)
+ ret = err;
#endif
write_disable(nor);
From f57277997bd8036d45337ec60b08a025a0473f89 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marek=20Beh=C3=BAn?=
Date: Tue, 5 Oct 2021 15:56:00 +0200
Subject: [PATCH 08/18] mtd: spi-nor-core: Check return value of
write_disable() in spi_nor_erase()
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The cleanup code of spi_nor_erase() function calls write_disable(), but
does not return it's return value even in case of failure. Fix this.
Signed-off-by: Marek Behún
Reviewed-by: Simon Glass
Tested-by: Masami Hiramatsu
---
drivers/mtd/spi/spi-nor-core.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/mtd/spi/spi-nor-core.c b/drivers/mtd/spi/spi-nor-core.c
index d8eed595b7..30c54cd7b9 100644
--- a/drivers/mtd/spi/spi-nor-core.c
+++ b/drivers/mtd/spi/spi-nor-core.c
@@ -953,7 +953,9 @@ erase_err:
if (!ret)
ret = err;
#endif
- write_disable(nor);
+ err = write_disable(nor);
+ if (!ret)
+ ret = err;
return ret;
}
From a67b3719f32673a9890700c72b980acbd2749e49 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marek=20Beh=C3=BAn?=
Date: Tue, 5 Oct 2021 15:56:01 +0200
Subject: [PATCH 09/18] mtd: spi-flash: Check for zero length in legacy
spi_flash_*()
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Check for zero length in the legacy spi_flash_read() /
spi_flash_write() / spi_flash_erase() functions.
On zero length, return 0 immediately, don't call the underlying method.
Rationale:
- these legacy functions call the _read(), _write() and _erase() methods
of struct mtd
- the DM callers of these methods already check for zero length
- making all callers of these methods check for zero length makes it
possible to remove the check from implementations of these _read(),
_write() and _erase() methods
Signed-off-by: Marek Behún
---
include/spi_flash.h | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/include/spi_flash.h b/include/spi_flash.h
index 3d747c925b..4d4ae89c19 100644
--- a/include/spi_flash.h
+++ b/include/spi_flash.h
@@ -165,6 +165,9 @@ static inline int spi_flash_read(struct spi_flash *flash, u32 offset,
struct mtd_info *mtd = &flash->mtd;
size_t retlen;
+ if (!len)
+ return 0;
+
return mtd->_read(mtd, offset, len, &retlen, buf);
}
@@ -174,6 +177,9 @@ static inline int spi_flash_write(struct spi_flash *flash, u32 offset,
struct mtd_info *mtd = &flash->mtd;
size_t retlen;
+ if (!len)
+ return 0;
+
return mtd->_write(mtd, offset, len, &retlen, buf);
}
@@ -188,6 +194,9 @@ static inline int spi_flash_erase(struct spi_flash *flash, u32 offset,
return -EINVAL;
}
+ if (!len)
+ return 0;
+
memset(&instr, 0, sizeof(instr));
instr.addr = offset;
instr.len = len;
From 7398c1b758e70708edc1d0aced2e2b07ded1ed7e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marek=20Beh=C3=BAn?=
Date: Tue, 5 Oct 2021 15:56:02 +0200
Subject: [PATCH 10/18] mtd: spi-nor-core: Don't check for zero length in
spi_nor_write() / spi_nor_erase()
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This check is already done in all callers: mtdcore's mtd_write() /
mtd_erase(), legacy spi_nor_write() / spi_flash_erase(). No reason to do
this here as well.
Signed-off-by: Marek Behún
---
drivers/mtd/spi/spi-nor-core.c | 6 ------
1 file changed, 6 deletions(-)
diff --git a/drivers/mtd/spi/spi-nor-core.c b/drivers/mtd/spi/spi-nor-core.c
index 30c54cd7b9..751172d6c9 100644
--- a/drivers/mtd/spi/spi-nor-core.c
+++ b/drivers/mtd/spi/spi-nor-core.c
@@ -914,9 +914,6 @@ static int spi_nor_erase(struct mtd_info *mtd, struct erase_info *instr)
dev_dbg(nor->dev, "at 0x%llx, len %lld\n", (long long)instr->addr,
(long long)instr->len);
- if (!instr->len)
- return 0;
-
div_u64_rem(instr->len, mtd->erasesize, &rem);
if (rem)
return -EINVAL;
@@ -1671,9 +1668,6 @@ static int spi_nor_write(struct mtd_info *mtd, loff_t to, size_t len,
dev_dbg(nor->dev, "to 0x%08x, len %zd\n", (u32)to, len);
- if (!len)
- return 0;
-
for (i = 0; i < len; ) {
ssize_t written;
loff_t addr = to + i;
From ff0000b47d7945701b2f9d17cc301b54452d499b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marek=20Beh=C3=BAn?=
Date: Tue, 5 Oct 2021 15:56:03 +0200
Subject: [PATCH 11/18] mtd: spi-nor-core: Call mtd_erase_callback() from
spi_nor_erase()
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The spi_nor_erase() function does not call mtd_erase_callback() as it
should.
The mtdpart code currently implements the subtraction of partition
offset in mtd_erase_callback().
This results in partition offset being added prior calling
spi_nor_erase(), but not subtracted back on return. The result is that
the `mtd erase` command does not erase the whole partition, only some of
it's blocks:
=> mtd erase "Rescue system"
Erasing 0x00000000 ... 0x006fffff (1792 eraseblock(s))
jedec_spi_nor spi-nor@0: at 0x100000, len 4096
jedec_spi_nor spi-nor@0: at 0x201000, len 4096
jedec_spi_nor spi-nor@0: at 0x302000, len 4096
jedec_spi_nor spi-nor@0: at 0x403000, len 4096
jedec_spi_nor spi-nor@0: at 0x504000, len 4096
jedec_spi_nor spi-nor@0: at 0x605000, len 4096
jedec_spi_nor spi-nor@0: at 0x706000, len 4096
This is obviously wrong.
Add proper calling of mtd_erase_callback() into the spi_nor_erase()
function.
Signed-off-by: Marek Behún
Reviewed-by: Simon Glass
Reported-by: Masami Hiramatsu
Tested-by: Masami Hiramatsu
---
drivers/mtd/spi/spi-nor-core.c | 20 ++++++++++++++++++--
1 file changed, 18 insertions(+), 2 deletions(-)
diff --git a/drivers/mtd/spi/spi-nor-core.c b/drivers/mtd/spi/spi-nor-core.c
index 751172d6c9..2c71866bca 100644
--- a/drivers/mtd/spi/spi-nor-core.c
+++ b/drivers/mtd/spi/spi-nor-core.c
@@ -908,6 +908,7 @@ static int spi_nor_erase_sector(struct spi_nor *nor, u32 addr)
static int spi_nor_erase(struct mtd_info *mtd, struct erase_info *instr)
{
struct spi_nor *nor = mtd_to_spi_nor(mtd);
+ bool addr_known = false;
u32 addr, len, rem;
int ret, err;
@@ -915,12 +916,17 @@ static int spi_nor_erase(struct mtd_info *mtd, struct erase_info *instr)
(long long)instr->len);
div_u64_rem(instr->len, mtd->erasesize, &rem);
- if (rem)
- return -EINVAL;
+ if (rem) {
+ ret = -EINVAL;
+ goto erase_err_callback;
+ }
addr = instr->addr;
len = instr->len;
+ instr->state = MTD_ERASING;
+ addr_known = true;
+
while (len) {
WATCHDOG_RESET();
#ifdef CONFIG_SPI_FLASH_BAR
@@ -944,6 +950,7 @@ static int spi_nor_erase(struct mtd_info *mtd, struct erase_info *instr)
goto erase_err;
}
+ addr_known = false;
erase_err:
#ifdef CONFIG_SPI_FLASH_BAR
err = clean_bar(nor);
@@ -954,6 +961,15 @@ erase_err:
if (!ret)
ret = err;
+erase_err_callback:
+ if (ret) {
+ instr->fail_addr = addr_known ? addr : MTD_FAIL_ADDR_UNKNOWN;
+ instr->state = MTD_ERASE_FAILED;
+ } else {
+ instr->state = MTD_ERASE_DONE;
+ }
+ mtd_erase_callback(instr);
+
return ret;
}
From 1fd5e67595367126c9f76b3f0c47db21523665c3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marek=20Beh=C3=BAn?=
Date: Tue, 5 Oct 2021 15:56:04 +0200
Subject: [PATCH 12/18] mtd: spi-nor-core: Check for ctrlc() in spi_nor_erase()
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
May it possible to interrupt the spi_nor_erase() function.
Signed-off-by: Marek Behún
Reviewed-by: Simon Glass
Tested-by: Masami Hiramatsu
---
drivers/mtd/spi/spi-nor-core.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/drivers/mtd/spi/spi-nor-core.c b/drivers/mtd/spi/spi-nor-core.c
index 2c71866bca..a85759967b 100644
--- a/drivers/mtd/spi/spi-nor-core.c
+++ b/drivers/mtd/spi/spi-nor-core.c
@@ -929,6 +929,11 @@ static int spi_nor_erase(struct mtd_info *mtd, struct erase_info *instr)
while (len) {
WATCHDOG_RESET();
+ if (ctrlc()) {
+ addr_known = false;
+ ret = -EINTR;
+ goto erase_err;
+ }
#ifdef CONFIG_SPI_FLASH_BAR
ret = write_bar(nor, addr);
if (ret < 0)
From a60397d219c2ddbceedfea4e121e303804d333d0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marek=20Beh=C3=BAn?=
Date: Tue, 5 Oct 2021 15:56:05 +0200
Subject: [PATCH 13/18] mtd: mtdpart: Make mtdpart's _erase method sane
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The _erase() method of the mtdpart driver, part_erase(), currently
implements offset shifting (for given mtdpart partition) in a weird way:
1. part_erase() adds partition offset to block address
2. parent driver's _erase() method is called
3. parent driver's _erase() method calls mtd_erase_callback()
4. mtd_erase_callback() subtracts partition offset from block address
so that the callback function is given correct address
The problem here is that if the parent's driver does not call
mtd_erase_callback() in some scenario (this was recently a case for
spi_nor_erase(), which did not call mtd_erase_callback() at all), the
offset is not shifted back.
Moreover the code would be more readable if part_erase() not only added
partition offset before calling parent's _erase(), but also subtracted
it back afterwards. Currently the mtd_erase_callback() is expected to do
this subtracting since it does have to do it anyway.
Add the more steps to this procedure:
5. mtd_erase_callback() adds partition offset to block address so that
it returns the the erase_info structure members as it received them
6. part_erase() subtracts partition offset from block address
This makes the code more logical and also prevents errors in case
parent's driver does not call mtd_erase_callback() for some reason.
(BTW, the purpose of mtd_erase_callback() in Linux is to inform the
caller that it is done, since in Linux erasing is done asynchronously.
We are abusing the purpose of mtd_erase_callback() in U-Boot for
completely different purpose. The callback function itself has empty
implementation in all cases in U-Boot.)
Signed-off-by: Marek Behún
Reviewed-by: Simon Glass
Tested-by: Masami Hiramatsu
---
drivers/mtd/mtdpart.c | 26 ++++++++++++++++++--------
1 file changed, 18 insertions(+), 8 deletions(-)
diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c
index aa58f722da..6ab481a7b1 100644
--- a/drivers/mtd/mtdpart.c
+++ b/drivers/mtd/mtdpart.c
@@ -446,24 +446,34 @@ static int part_erase(struct mtd_info *mtd, struct erase_info *instr)
int ret;
instr->addr += mtd->offset;
+
ret = mtd->parent->_erase(mtd->parent, instr);
- if (ret) {
- if (instr->fail_addr != MTD_FAIL_ADDR_UNKNOWN)
- instr->fail_addr -= mtd->offset;
- instr->addr -= mtd->offset;
- }
+ if (ret && instr->fail_addr != MTD_FAIL_ADDR_UNKNOWN)
+ instr->fail_addr -= mtd->offset;
+
+ instr->addr -= mtd->offset;
+
return ret;
}
void mtd_erase_callback(struct erase_info *instr)
{
- if (instr->mtd->_erase == part_erase) {
+ if (!instr->callback)
+ return;
+
+ if (instr->mtd->_erase == part_erase && instr->len) {
if (instr->fail_addr != MTD_FAIL_ADDR_UNKNOWN)
instr->fail_addr -= instr->mtd->offset;
instr->addr -= instr->mtd->offset;
}
- if (instr->callback)
- instr->callback(instr);
+
+ instr->callback(instr);
+
+ if (instr->mtd->_erase == part_erase && instr->len) {
+ if (instr->fail_addr != MTD_FAIL_ADDR_UNKNOWN)
+ instr->fail_addr += instr->mtd->offset;
+ instr->addr += instr->mtd->offset;
+ }
}
EXPORT_SYMBOL_GPL(mtd_erase_callback);
From 0d1ecc99cb59c2190257f7738f91db21f174dc02 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marek=20Beh=C3=BAn?=
Date: Tue, 5 Oct 2021 15:56:06 +0200
Subject: [PATCH 14/18] mtd: Remove mtd_erase_callback() entirely
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The original purpose of mtd_erase_callback() in Linux at the time it was
imported to U-Boot, was to inform the caller that erasing is done (since
it was an asynchronous operation).
All supplied callback methods in U-Boot do nothing, but the
mtd_erase_callback() function was (until previous patch) grossly abused
in U-Boot's mtdpart implementation for completely different purpose.
Since we got rid of the abusement, remove the mtd_erase_callback()
function and the .callback member from struct erase_info entirely, in
order to avoid such problems in the future.
Signed-off-by: Marek Behún
---
cmd/onenand.c | 9 ++-------
drivers/mtd/altera_qspi.c | 3 ---
drivers/mtd/cfi_mtd.c | 1 -
drivers/mtd/mtdconcat.c | 11 -----------
drivers/mtd/mtdcore.c | 8 --------
drivers/mtd/mtdpart.c | 21 ---------------------
drivers/mtd/nand/raw/nand_base.c | 4 ----
drivers/mtd/onenand/onenand_base.c | 3 ---
drivers/mtd/spi/sf_mtd.c | 1 -
drivers/mtd/spi/spi-nor-core.c | 5 ++---
drivers/mtd/ubi/io.c | 13 -------------
env/onenand.c | 4 +---
fs/yaffs2/yaffs_mtdif.c | 1 -
include/linux/mtd/mtd.h | 11 -----------
include/nand.h | 1 -
15 files changed, 5 insertions(+), 91 deletions(-)
diff --git a/cmd/onenand.c b/cmd/onenand.c
index 852ed5c7b2..592985a7ee 100644
--- a/cmd/onenand.c
+++ b/cmd/onenand.c
@@ -186,9 +186,7 @@ next:
static int onenand_block_erase(u32 start, u32 size, int force)
{
struct onenand_chip *this = mtd->priv;
- struct erase_info instr = {
- .callback = NULL,
- };
+ struct erase_info instr = {};
loff_t ofs;
int ret;
int blocksize = 1 << this->erase_shift;
@@ -219,10 +217,7 @@ static int onenand_block_erase(u32 start, u32 size, int force)
static int onenand_block_test(u32 start, u32 size)
{
struct onenand_chip *this = mtd->priv;
- struct erase_info instr = {
- .callback = NULL,
- .priv = 0,
- };
+ struct erase_info instr = {};
int blocks;
loff_t ofs;
diff --git a/drivers/mtd/altera_qspi.c b/drivers/mtd/altera_qspi.c
index 7bac599a54..d31391f36a 100644
--- a/drivers/mtd/altera_qspi.c
+++ b/drivers/mtd/altera_qspi.c
@@ -153,7 +153,6 @@ static int altera_qspi_erase(struct mtd_info *mtd, struct erase_info *instr)
putc('\n');
instr->fail_addr = MTD_FAIL_ADDR_UNKNOWN;
instr->state = MTD_ERASE_FAILED;
- mtd_erase_callback(instr);
return -EIO;
}
flash = pdata->base + addr;
@@ -177,7 +176,6 @@ static int altera_qspi_erase(struct mtd_info *mtd, struct erase_info *instr)
writel(stat, ®s->isr); /* clear isr */
instr->fail_addr = addr;
instr->state = MTD_ERASE_FAILED;
- mtd_erase_callback(instr);
return -EIO;
}
if (flash_verbose)
@@ -189,7 +187,6 @@ static int altera_qspi_erase(struct mtd_info *mtd, struct erase_info *instr)
addr += mtd->erasesize;
}
instr->state = MTD_ERASE_DONE;
- mtd_erase_callback(instr);
return 0;
}
diff --git a/drivers/mtd/cfi_mtd.c b/drivers/mtd/cfi_mtd.c
index 78293caa2f..2295bb7220 100644
--- a/drivers/mtd/cfi_mtd.c
+++ b/drivers/mtd/cfi_mtd.c
@@ -58,7 +58,6 @@ static int cfi_mtd_erase(struct mtd_info *mtd, struct erase_info *instr)
}
instr->state = MTD_ERASE_DONE;
- mtd_erase_callback(instr);
return 0;
}
diff --git a/drivers/mtd/mtdconcat.c b/drivers/mtd/mtdconcat.c
index 684bc94998..af3c4765c4 100644
--- a/drivers/mtd/mtdconcat.c
+++ b/drivers/mtd/mtdconcat.c
@@ -338,14 +338,6 @@ concat_write_oob(struct mtd_info *mtd, loff_t to, struct mtd_oob_ops *ops)
return -EINVAL;
}
-static void concat_erase_callback(struct erase_info *instr)
-{
- /* Nothing to do here in U-Boot */
-#ifndef __UBOOT__
- wake_up((wait_queue_head_t *) instr->priv);
-#endif
-}
-
static int concat_dev_erase(struct mtd_info *mtd, struct erase_info *erase)
{
int err;
@@ -358,7 +350,6 @@ static int concat_dev_erase(struct mtd_info *mtd, struct erase_info *erase)
init_waitqueue_head(&waitq);
erase->mtd = mtd;
- erase->callback = concat_erase_callback;
erase->priv = (unsigned long) &waitq;
/*
@@ -498,8 +489,6 @@ static int concat_erase(struct mtd_info *mtd, struct erase_info *instr)
if (err)
return err;
- if (instr->callback)
- instr->callback(instr);
return 0;
}
diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
index 9496903e86..1d45fb55c7 100644
--- a/drivers/mtd/mtdcore.c
+++ b/drivers/mtd/mtdcore.c
@@ -906,13 +906,6 @@ void __put_mtd_device(struct mtd_info *mtd)
}
EXPORT_SYMBOL_GPL(__put_mtd_device);
-/*
- * Erase is an asynchronous operation. Device drivers are supposed
- * to call instr->callback() whenever the operation completes, even
- * if it completes with a failure.
- * Callers are supposed to pass a callback function and wait for it
- * to be called before writing to the block.
- */
int mtd_erase(struct mtd_info *mtd, struct erase_info *instr)
{
if (instr->addr > mtd->size || instr->len > mtd->size - instr->addr)
@@ -922,7 +915,6 @@ int mtd_erase(struct mtd_info *mtd, struct erase_info *instr)
instr->fail_addr = MTD_FAIL_ADDR_UNKNOWN;
if (!instr->len) {
instr->state = MTD_ERASE_DONE;
- mtd_erase_callback(instr);
return 0;
}
return mtd->_erase(mtd, instr);
diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c
index 6ab481a7b1..a435ce6d07 100644
--- a/drivers/mtd/mtdpart.c
+++ b/drivers/mtd/mtdpart.c
@@ -456,27 +456,6 @@ static int part_erase(struct mtd_info *mtd, struct erase_info *instr)
return ret;
}
-void mtd_erase_callback(struct erase_info *instr)
-{
- if (!instr->callback)
- return;
-
- if (instr->mtd->_erase == part_erase && instr->len) {
- if (instr->fail_addr != MTD_FAIL_ADDR_UNKNOWN)
- instr->fail_addr -= instr->mtd->offset;
- instr->addr -= instr->mtd->offset;
- }
-
- instr->callback(instr);
-
- if (instr->mtd->_erase == part_erase && instr->len) {
- if (instr->fail_addr != MTD_FAIL_ADDR_UNKNOWN)
- instr->fail_addr += instr->mtd->offset;
- instr->addr += instr->mtd->offset;
- }
-}
-EXPORT_SYMBOL_GPL(mtd_erase_callback);
-
static int part_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
{
return mtd->parent->_lock(mtd->parent, ofs + mtd->offset, len);
diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
index b533683dfe..f7616985d9 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -3602,10 +3602,6 @@ erase_exit:
chip->select_chip(mtd, -1);
nand_release_device(mtd);
- /* Do call back function */
- if (!ret)
- mtd_erase_callback(instr);
-
/* Return more or less happy */
return ret;
}
diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c
index 46aeef258d..56e1858de4 100644
--- a/drivers/mtd/onenand/onenand_base.c
+++ b/drivers/mtd/onenand/onenand_base.c
@@ -1836,9 +1836,6 @@ int onenand_erase(struct mtd_info *mtd, struct erase_info *instr)
erase_exit:
ret = instr->state == MTD_ERASE_DONE ? 0 : -EIO;
- /* Do call back function */
- if (!ret)
- mtd_erase_callback(instr);
/* Deselect and wake up anyone waiting on the device */
onenand_release_device(mtd);
diff --git a/drivers/mtd/spi/sf_mtd.c b/drivers/mtd/spi/sf_mtd.c
index 04de868080..0aed28a52b 100644
--- a/drivers/mtd/spi/sf_mtd.c
+++ b/drivers/mtd/spi/sf_mtd.c
@@ -46,7 +46,6 @@ static int spi_flash_mtd_erase(struct mtd_info *mtd, struct erase_info *instr)
}
instr->state = MTD_ERASE_DONE;
- mtd_erase_callback(instr);
return 0;
}
diff --git a/drivers/mtd/spi/spi-nor-core.c b/drivers/mtd/spi/spi-nor-core.c
index a85759967b..4388a08a90 100644
--- a/drivers/mtd/spi/spi-nor-core.c
+++ b/drivers/mtd/spi/spi-nor-core.c
@@ -918,7 +918,7 @@ static int spi_nor_erase(struct mtd_info *mtd, struct erase_info *instr)
div_u64_rem(instr->len, mtd->erasesize, &rem);
if (rem) {
ret = -EINVAL;
- goto erase_err_callback;
+ goto err;
}
addr = instr->addr;
@@ -966,14 +966,13 @@ erase_err:
if (!ret)
ret = err;
-erase_err_callback:
+err:
if (ret) {
instr->fail_addr = addr_known ? addr : MTD_FAIL_ADDR_UNKNOWN;
instr->state = MTD_ERASE_FAILED;
} else {
instr->state = MTD_ERASE_DONE;
}
- mtd_erase_callback(instr);
return ret;
}
diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c
index b8b878b918..14be95b74b 100644
--- a/drivers/mtd/ubi/io.c
+++ b/drivers/mtd/ubi/io.c
@@ -304,18 +304,6 @@ int ubi_io_write(struct ubi_device *ubi, const void *buf, int pnum, int offset,
return err;
}
-/**
- * erase_callback - MTD erasure call-back.
- * @ei: MTD erase information object.
- *
- * Note, even though MTD erase interface is asynchronous, all the current
- * implementations are synchronous anyway.
- */
-static void erase_callback(struct erase_info *ei)
-{
- wake_up_interruptible((wait_queue_head_t *)ei->priv);
-}
-
/**
* do_sync_erase - synchronously erase a physical eraseblock.
* @ubi: UBI device description object
@@ -346,7 +334,6 @@ retry:
ei.mtd = ubi->mtd;
ei.addr = (loff_t)pnum * ubi->peb_size;
ei.len = ubi->peb_size;
- ei.callback = erase_callback;
ei.priv = (unsigned long)&wq;
err = mtd_erase(ubi->mtd, &ei);
diff --git a/env/onenand.c b/env/onenand.c
index c8da3ff811..1faa2cb62a 100644
--- a/env/onenand.c
+++ b/env/onenand.c
@@ -73,9 +73,7 @@ static int env_onenand_save(void)
#endif
loff_t env_addr = CONFIG_ENV_ADDR;
size_t retlen;
- struct erase_info instr = {
- .callback = NULL,
- };
+ struct erase_info instr = {};
ret = env_export(&env_new);
if (ret)
diff --git a/fs/yaffs2/yaffs_mtdif.c b/fs/yaffs2/yaffs_mtdif.c
index d338f9aa91..50fed2d4b1 100644
--- a/fs/yaffs2/yaffs_mtdif.c
+++ b/fs/yaffs2/yaffs_mtdif.c
@@ -145,7 +145,6 @@ int nandmtd_EraseBlockInNAND(struct yaffs_dev *dev, int blockNumber)
ei.len = dev->data_bytes_per_chunk * dev->param.chunks_per_block;
ei.time = 1000;
ei.retries = 2;
- ei.callback = NULL;
ei.priv = (u_long) dev;
/* Todo finish off the ei if required */
diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h
index 3b302fb8c3..7455400981 100644
--- a/include/linux/mtd/mtd.h
+++ b/include/linux/mtd/mtd.h
@@ -51,7 +51,6 @@ struct erase_info {
u_long retries;
unsigned dev;
unsigned cell;
- void (*callback) (struct erase_info *self);
u_long priv;
u_char state;
struct erase_info *next;
@@ -535,16 +534,6 @@ extern int unregister_mtd_user (struct mtd_notifier *old);
#endif
void *mtd_kmalloc_up_to(const struct mtd_info *mtd, size_t *size);
-#ifdef CONFIG_MTD_PARTITIONS
-void mtd_erase_callback(struct erase_info *instr);
-#else
-static inline void mtd_erase_callback(struct erase_info *instr)
-{
- if (instr->callback)
- instr->callback(instr);
-}
-#endif
-
static inline int mtd_is_bitflip(int err) {
return err == -EUCLEAN;
}
diff --git a/include/nand.h b/include/nand.h
index 75c605193a..09dbda4e81 100644
--- a/include/nand.h
+++ b/include/nand.h
@@ -69,7 +69,6 @@ static inline int nand_erase(struct mtd_info *info, loff_t off, size_t size)
instr.mtd = info;
instr.addr = off;
instr.len = size;
- instr.callback = 0;
return mtd_erase(info, &instr);
}
From b7a772a3bba6e414234c6c2ed098c92c3fca2db6 Mon Sep 17 00:00:00 2001
From: Kris Chaplin
Date: Mon, 18 Oct 2021 03:26:50 -0700
Subject: [PATCH 15/18] mtd: spi-nor-ids: Add is25lp512 and is25wp512 devices
Add is25lp512 and is25wp512 devices to spi-nor id table
Tested on Intel n5x hardware with QSPI carrier card
Signed-off-by: Kris Chaplin
[jagan: droped Tested-by of patch author]
Signed-off-by: Jagan Teki
Reviewed-by: Jagan Teki
---
drivers/mtd/spi/spi-nor-ids.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/drivers/mtd/spi/spi-nor-ids.c b/drivers/mtd/spi/spi-nor-ids.c
index 3e0935e1fb..105580bbcf 100644
--- a/drivers/mtd/spi/spi-nor-ids.c
+++ b/drivers/mtd/spi/spi-nor-ids.c
@@ -138,6 +138,8 @@ const struct flash_info spi_nor_ids[] = {
SECT_4K | SPI_NOR_DUAL_READ) },
{ INFO("is25lp256", 0x9d6019, 0, 64 * 1024, 512,
SECT_4K | SPI_NOR_DUAL_READ) },
+ { INFO("is25lp512", 0x9d601a, 0, 64 * 1024, 1024,
+ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
{ INFO("is25wp032", 0x9d7016, 0, 64 * 1024, 64,
SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
{ INFO("is25wp064", 0x9d7017, 0, 64 * 1024, 128,
@@ -147,6 +149,8 @@ const struct flash_info spi_nor_ids[] = {
{ INFO("is25wp256", 0x9d7019, 0, 64 * 1024, 512,
SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
SPI_NOR_4B_OPCODES) },
+ { INFO("is25wp512", 0x9d701a, 0, 64 * 1024, 1024,
+ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
#endif
#ifdef CONFIG_SPI_FLASH_MACRONIX /* MACRONIX */
/* Macronix */
From 85886161ef51f1fd8a0bea2518324cf6374bac8f Mon Sep 17 00:00:00 2001
From: Kris Chaplin
Date: Mon, 18 Oct 2021 03:30:18 -0700
Subject: [PATCH 16/18] mtd: spi-nor-ids: Add SECT_4K to mt25qu512a
The mt25qu512a supports 4K or 64K sectors, so adding
SECT_4K to enable 4K sector usage.
Tested on Intel n5x hardware with QSPI carrier card
Signed-off-by: Kris Chaplin
Acked-by: Pratyush Yadav
[jagan: droped Tested-by of patch author and datasheet link]
Signed-off-by: Jagan Teki
Reviewed-by: Jagan Teki
---
drivers/mtd/spi/spi-nor-ids.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/mtd/spi/spi-nor-ids.c b/drivers/mtd/spi/spi-nor-ids.c
index 105580bbcf..3ae7bb1ed7 100644
--- a/drivers/mtd/spi/spi-nor-ids.c
+++ b/drivers/mtd/spi/spi-nor-ids.c
@@ -195,7 +195,7 @@ const struct flash_info spi_nor_ids[] = {
{ INFO6("mt25qu256a", 0x20bb19, 0x104400, 64 * 1024, 512, SECT_4K | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES | USE_FSR) },
{ INFO("n25q256ax1", 0x20bb19, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_QUAD_READ | USE_FSR) },
{ INFO6("mt25qu512a", 0x20bb20, 0x104400, 64 * 1024, 1024,
- SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES |
+ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES |
USE_FSR) },
{ INFO("n25q512a", 0x20bb20, 0, 64 * 1024, 1024, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) },
{ INFO6("mt25ql512a", 0x20ba20, 0x104400, 64 * 1024, 1024, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
From e8751a9387add3fb786828498352103b7188b296 Mon Sep 17 00:00:00 2001
From: Kuldeep Singh
Date: Tue, 3 Aug 2021 14:32:57 +0530
Subject: [PATCH 17/18] spi: nxp-fspi: Add support for IP read only
Add support for disabling AHB bus and read entire flash contents via IP
bus only. Please note, this enables IP bus read using a quirk which can
be enabled directly in device-type data or in existence of an errata
where AHB bus may need to be disabled.
Signed-off-by: Kuldeep Singh
Acked-by: Jagan Teki
---
drivers/spi/nxp_fspi.c | 24 ++++++++++++++++++++----
1 file changed, 20 insertions(+), 4 deletions(-)
diff --git a/drivers/spi/nxp_fspi.c b/drivers/spi/nxp_fspi.c
index bba7a330e0..7715ed9110 100644
--- a/drivers/spi/nxp_fspi.c
+++ b/drivers/spi/nxp_fspi.c
@@ -304,6 +304,9 @@
#define POLL_TOUT 5000
#define NXP_FSPI_MAX_CHIPSELECT 4
+/* Access flash memory using IP bus only */
+#define FSPI_QUIRK_USE_IP_ONLY BIT(0)
+
struct nxp_fspi_devtype_data {
unsigned int rxfifo;
unsigned int txfifo;
@@ -338,6 +341,11 @@ struct nxp_fspi {
const struct nxp_fspi_devtype_data *devtype_data;
};
+static inline int needs_ip_only(struct nxp_fspi *f)
+{
+ return f->devtype_data->quirks & FSPI_QUIRK_USE_IP_ONLY;
+}
+
/*
* R/W functions for big- or little-endian registers:
* The FSPI controller's endianness is independent of
@@ -769,12 +777,14 @@ static int nxp_fspi_exec_op(struct spi_slave *slave,
nxp_fspi_prepare_lut(f, op);
/*
- * If we have large chunks of data, we read them through the AHB bus
- * by accessing the mapped memory. In all other cases we use
- * IP commands to access the flash.
+ * If we have large chunks of data, we read them through the AHB bus by
+ * accessing the mapped memory. In all other cases we use IP commands
+ * to access the flash. Read via AHB bus may be corrupted due to
+ * existence of an errata and therefore discard AHB read in such cases.
*/
if (op->data.nbytes > (f->devtype_data->rxfifo - 4) &&
- op->data.dir == SPI_MEM_DATA_IN) {
+ op->data.dir == SPI_MEM_DATA_IN &&
+ !needs_ip_only(f)) {
nxp_fspi_read_ahb(f, op);
} else {
if (op->data.nbytes && op->data.dir == SPI_MEM_DATA_OUT)
@@ -808,6 +818,12 @@ static int nxp_fspi_adjust_op_size(struct spi_slave *slave,
op->data.nbytes = ALIGN_DOWN(op->data.nbytes, 8);
}
+ /* Limit data bytes to RX FIFO in case of IP read only */
+ if (needs_ip_only(f) &&
+ op->data.dir == SPI_MEM_DATA_IN &&
+ op->data.nbytes > f->devtype_data->rxfifo)
+ op->data.nbytes = f->devtype_data->rxfifo;
+
return 0;
}
From b9cfd8b0911209e2ebec887e497510ee42f9e788 Mon Sep 17 00:00:00 2001
From: Kuldeep Singh
Date: Tue, 3 Aug 2021 14:32:58 +0530
Subject: [PATCH 18/18] spi: nxp_fspi: Implement errata workaround for LS1028A
Errata ERR050568 description says that "Flash access by FlexSPI AHB
command may not work with platform frequency equal to 300 MHz" on
LS1028A.
By default, smaller length reads(equal to RX FIFO size) are done by IP
bus and larger length reads using AHB bus. For adding errata workaround,
use IP bus to read entire flash contents and disable AHB path when
platform frequency is 300Mhz.
Signed-off-by: Kuldeep Singh
Reviewed-by: Jagan Teki
---
drivers/spi/nxp_fspi.c | 53 ++++++++++++++++++++++++++++++++++++++----
1 file changed, 48 insertions(+), 5 deletions(-)
diff --git a/drivers/spi/nxp_fspi.c b/drivers/spi/nxp_fspi.c
index 7715ed9110..b7c922b1df 100644
--- a/drivers/spi/nxp_fspi.c
+++ b/drivers/spi/nxp_fspi.c
@@ -41,6 +41,11 @@
#include
#include
#include
+#ifdef CONFIG_FSL_LAYERSCAPE
+#include
+#include
+#include
+#endif
#include
#include
#include
@@ -315,7 +320,7 @@ struct nxp_fspi_devtype_data {
bool little_endian;
};
-static const struct nxp_fspi_devtype_data lx2160a_data = {
+static struct nxp_fspi_devtype_data lx2160a_data = {
.rxfifo = SZ_512, /* (64 * 64 bits) */
.txfifo = SZ_1K, /* (128 * 64 bits) */
.ahb_buf_size = SZ_2K, /* (256 * 64 bits) */
@@ -323,7 +328,7 @@ static const struct nxp_fspi_devtype_data lx2160a_data = {
.little_endian = true, /* little-endian */
};
-static const struct nxp_fspi_devtype_data imx8mm_data = {
+static struct nxp_fspi_devtype_data imx8mm_data = {
.rxfifo = SZ_512, /* (64 * 64 bits) */
.txfifo = SZ_1K, /* (128 * 64 bits) */
.ahb_buf_size = SZ_2K, /* (256 * 64 bits) */
@@ -338,7 +343,7 @@ struct nxp_fspi {
u32 memmap_phy;
u32 memmap_phy_size;
struct clk clk, clk_en;
- const struct nxp_fspi_devtype_data *devtype_data;
+ struct nxp_fspi_devtype_data *devtype_data;
};
static inline int needs_ip_only(struct nxp_fspi *f)
@@ -529,8 +534,8 @@ static void nxp_fspi_prepare_lut(struct nxp_fspi *f,
for (i = 0; i < ARRAY_SIZE(lutval); i++)
fspi_writel(f, lutval[i], base + FSPI_LUT_REG(i));
- dev_dbg(f->dev, "CMD[%x] lutval[0:%x \t 1:%x \t 2:%x \t 3:%x]\n",
- op->cmd.opcode, lutval[0], lutval[1], lutval[2], lutval[3]);
+ dev_dbg(f->dev, "CMD[%x] lutval[0:%x \t 1:%x \t 2:%x \t 3:%x], size: 0x%08x\n",
+ op->cmd.opcode, lutval[0], lutval[1], lutval[2], lutval[3], op->data.nbytes);
/* lock LUT */
fspi_writel(f, FSPI_LUTKEY_VALUE, f->iobase + FSPI_LUTKEY);
@@ -827,6 +832,33 @@ static int nxp_fspi_adjust_op_size(struct spi_slave *slave,
return 0;
}
+#ifdef CONFIG_FSL_LAYERSCAPE
+static void erratum_err050568(struct nxp_fspi *f)
+{
+ struct sys_info sysinfo;
+ u32 svr = 0, freq = 0;
+
+ /* Check for LS1028A variants */
+ svr = SVR_SOC_VER(get_svr());
+ if (svr != SVR_LS1017A ||
+ svr != SVR_LS1018A ||
+ svr != SVR_LS1027A ||
+ svr != SVR_LS1028A) {
+ dev_dbg(f->dev, "Errata applicable only for LS1028A variants\n");
+ return;
+ }
+
+ /* Read PLL frequency */
+ get_sys_info(&sysinfo);
+ freq = sysinfo.freq_systembus / 1000000; /* Convert to MHz */
+ dev_dbg(f->dev, "svr: %08x, Frequency: %dMhz\n", svr, freq);
+
+ /* Use IP bus only if PLL is 300MHz */
+ if (freq == 300)
+ f->devtype_data->quirks |= FSPI_QUIRK_USE_IP_ONLY;
+}
+#endif
+
static int nxp_fspi_default_setup(struct nxp_fspi *f)
{
void __iomem *base = f->iobase;
@@ -847,6 +879,17 @@ static int nxp_fspi_default_setup(struct nxp_fspi *f)
return ret;
#endif
+#ifdef CONFIG_FSL_LAYERSCAPE
+ /*
+ * ERR050568: Flash access by FlexSPI AHB command may not work with
+ * platform frequency equal to 300 MHz on LS1028A.
+ * LS1028A reuses LX2160A compatible entry. Make errata applicable for
+ * Layerscape LS1028A platform family.
+ */
+ if (device_is_compatible(f->dev, "nxp,lx2160a-fspi"))
+ erratum_err050568(f);
+#endif
+
/* Reset the module */
/* w1c register, wait unit clear */
ret = fspi_readl_poll_tout(f, f->iobase + FSPI_MCR0,