From 76998cb5ed11f35a9623219ad7186fc8432f44c3 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Tue, 20 Jun 2017 11:04:01 +0200 Subject: [PATCH] generic: mtd: backport unlock support and asserted fixes for certain Winbond/Spansion flash chips This patch got lost in the OpenWrt -> LEDE transition and fixes flash writes on new UBNT PicoStations. --- ...certain-Winbond-Spansion-flash-chips.patch | 139 ++++++++++++++++++ 1 file changed, 139 insertions(+) create mode 100644 patches/lede/0031-generic-mtd-backport-unlock-support-and-asserted-fixes-for-certain-Winbond-Spansion-flash-chips.patch diff --git a/patches/lede/0031-generic-mtd-backport-unlock-support-and-asserted-fixes-for-certain-Winbond-Spansion-flash-chips.patch b/patches/lede/0031-generic-mtd-backport-unlock-support-and-asserted-fixes-for-certain-Winbond-Spansion-flash-chips.patch new file mode 100644 index 00000000..55193310 --- /dev/null +++ b/patches/lede/0031-generic-mtd-backport-unlock-support-and-asserted-fixes-for-certain-Winbond-Spansion-flash-chips.patch @@ -0,0 +1,139 @@ +From: Matthias Schiffer +Date: Tue, 20 Jun 2017 11:01:27 +0200 +Subject: generic: mtd: backport unlock support and asserted fixes for certain Winbond/Spansion flash chips + +diff --git a/target/linux/generic/patches-4.4/049-0001-mtd-spi-nor-wait-until-lock-unlock-operations-are-re.patch b/target/linux/generic/patches-4.4/049-0001-mtd-spi-nor-wait-until-lock-unlock-operations-are-re.patch +new file mode 100644 +index 0000000000000000000000000000000000000000..c8aafe2ebbf7368f47e8f4d7a24dd5e45583a136 +--- /dev/null ++++ b/target/linux/generic/patches-4.4/049-0001-mtd-spi-nor-wait-until-lock-unlock-operations-are-re.patch +@@ -0,0 +1,66 @@ ++From 32321e950d8a237d7e8f3a9b76220007dfa87544 Mon Sep 17 00:00:00 2001 ++Message-Id: <32321e950d8a237d7e8f3a9b76220007dfa87544.1462572686.git.mschiffer@universe-factory.net> ++From: =?UTF-8?q?Ezequiel=20Garc=C3=ADa?= ++Date: Mon, 28 Dec 2015 17:54:51 -0300 ++Subject: [PATCH] mtd: spi-nor: wait until lock/unlock operations are ready ++ ++On Micron and Numonyx devices, the status register write command ++(WRSR), raises a work-in-progress bit (WIP) on the status register. ++The datasheets for these devices specify that while the status ++register write is in progress, the status register WIP bit can still ++be read to check the end of the operation. ++ ++This commit adds a wait_till_ready call on lock/unlock operations, ++which is required for Micron and Numonyx but should be harmless for ++others. This is needed to prevent applications from issuing erase or ++program operations before the unlock operation is completed. ++ ++Reported-by: Stas Sergeev ++Signed-off-by: Ezequiel Garcia ++Signed-off-by: Brian Norris ++--- ++ drivers/mtd/spi-nor/spi-nor.c | 12 ++++++++++-- ++ 1 file changed, 10 insertions(+), 2 deletions(-) ++ ++--- a/drivers/mtd/spi-nor/spi-nor.c +++++ b/drivers/mtd/spi-nor/spi-nor.c ++@@ -463,6 +463,7 @@ static int stm_lock(struct spi_nor *nor, ++ u8 status_old, status_new; ++ u8 mask = SR_BP2 | SR_BP1 | SR_BP0; ++ u8 shift = ffs(mask) - 1, pow, val; +++ int ret; ++ ++ status_old = read_sr(nor); ++ ++@@ -499,7 +500,10 @@ static int stm_lock(struct spi_nor *nor, ++ return -EINVAL; ++ ++ write_enable(nor); ++- return write_sr(nor, status_new); +++ ret = write_sr(nor, status_new); +++ if (ret) +++ return ret; +++ return spi_nor_wait_till_ready(nor); ++ } ++ ++ /* ++@@ -513,6 +517,7 @@ static int stm_unlock(struct spi_nor *no ++ uint8_t status_old, status_new; ++ u8 mask = SR_BP2 | SR_BP1 | SR_BP0; ++ u8 shift = ffs(mask) - 1, pow, val; +++ int ret; ++ ++ status_old = read_sr(nor); ++ ++@@ -547,7 +552,10 @@ static int stm_unlock(struct spi_nor *no ++ return -EINVAL; ++ ++ write_enable(nor); ++- return write_sr(nor, status_new); +++ ret = write_sr(nor, status_new); +++ if (ret) +++ return ret; +++ return spi_nor_wait_till_ready(nor); ++ } ++ ++ /* +diff --git a/target/linux/generic/patches-4.4/049-0002-mtd-spi-nor-wait-for-SR_WIP-to-clear-on-initial-unlo.patch b/target/linux/generic/patches-4.4/049-0002-mtd-spi-nor-wait-for-SR_WIP-to-clear-on-initial-unlo.patch +new file mode 100644 +index 0000000000000000000000000000000000000000..0541c95594ec14f62b5db787f4d52d5a42777cdc +--- /dev/null ++++ b/target/linux/generic/patches-4.4/049-0002-mtd-spi-nor-wait-for-SR_WIP-to-clear-on-initial-unlo.patch +@@ -0,0 +1,33 @@ ++From edf891ef9ab773363f8e58022a26d7d31604aed6 Mon Sep 17 00:00:00 2001 ++Message-Id: ++From: Brian Norris ++Date: Fri, 29 Jan 2016 11:25:30 -0800 ++Subject: [PATCH] mtd: spi-nor: wait for SR_WIP to clear on initial unlock ++ ++Fixup a piece leftover by commit 32321e950d8a ("mtd: spi-nor: wait until ++lock/unlock operations are ready"). That commit made us wait for the WIP ++bit to settle after lock/unlock operations, but it missed the open-coded ++"unlock" that happens at probe() time. ++ ++We should probably have this code utilize the unlock() routines in the ++future, to avoid duplication, but unfortunately, flash which need to be ++unlocked don't all have a proper ->flash_unlock() callback. ++ ++Signed-off-by: Brian Norris ++Cc: Stas Sergeev ++Reviewed-by: Ezequiel Garcia ++Tested-by: Ezequiel Garcia ++--- ++ drivers/mtd/spi-nor/spi-nor.c | 1 + ++ 1 file changed, 1 insertion(+) ++ ++--- a/drivers/mtd/spi-nor/spi-nor.c +++++ b/drivers/mtd/spi-nor/spi-nor.c ++@@ -1169,6 +1169,7 @@ int spi_nor_scan(struct spi_nor *nor, co ++ info->flags & SPI_NOR_HAS_LOCK) { ++ write_enable(nor); ++ write_sr(nor, 0); +++ spi_nor_wait_till_ready(nor); ++ } ++ ++ if (!mtd->name) +diff --git a/target/linux/generic/patches-4.4/466-revert-mtd-spi-nor-fix-Spansion-regressions-aliased-.patch b/target/linux/generic/patches-4.4/466-revert-mtd-spi-nor-fix-Spansion-regressions-aliased-.patch +new file mode 100644 +index 0000000000000000000000000000000000000000..7c6530a5e0e8bc144e1d4497428e3c3691c2ef22 +--- /dev/null ++++ b/target/linux/generic/patches-4.4/466-revert-mtd-spi-nor-fix-Spansion-regressions-aliased-.patch +@@ -0,0 +1,18 @@ ++--- a/drivers/mtd/spi-nor/spi-nor.c +++++ b/drivers/mtd/spi-nor/spi-nor.c ++@@ -1161,6 +1161,7 @@ int spi_nor_scan(struct spi_nor *nor, co ++ JEDEC_MFR(info) == SNOR_MFR_INTEL || ++ JEDEC_MFR(info) == SNOR_MFR_MACRONIX || ++ JEDEC_MFR(info) == SNOR_MFR_SST || +++ JEDEC_MFR(info) == SNOR_MFR_WINBOND || ++ info->flags & SPI_NOR_HAS_LOCK) { ++ write_enable(nor); ++ write_sr(nor, 0); ++@@ -1178,6 +1179,7 @@ int spi_nor_scan(struct spi_nor *nor, co ++ ++ /* NOR protection support for STmicro/Micron chips and similar */ ++ if (JEDEC_MFR(info) == SNOR_MFR_MICRON || +++ JEDEC_MFR(info) == SNOR_MFR_WINBOND || ++ info->flags & SPI_NOR_HAS_LOCK) { ++ nor->flash_lock = stm_lock; ++ nor->flash_unlock = stm_unlock;