From fb57f360f63ca108cbb0fe0aaccf6f293bacad8f Mon Sep 17 00:00:00 2001 From: Dmitry Ermakov Date: Sun, 26 Feb 2023 07:57:48 +0300 Subject: [PATCH] [Gk7205v200] SPI NOR force global unlock and SR clear (#649) --- .../patches/14-spi-nor-global-unlock.patch | 211 ++++++++++++++++++ 1 file changed, 211 insertions(+) create mode 100644 br-ext-chip-goke/board/gk7205v200/kernel/patches/14-spi-nor-global-unlock.patch diff --git a/br-ext-chip-goke/board/gk7205v200/kernel/patches/14-spi-nor-global-unlock.patch b/br-ext-chip-goke/board/gk7205v200/kernel/patches/14-spi-nor-global-unlock.patch new file mode 100644 index 00000000..911f2d76 --- /dev/null +++ b/br-ext-chip-goke/board/gk7205v200/kernel/patches/14-spi-nor-global-unlock.patch @@ -0,0 +1,211 @@ +--- a/drivers/mtd/spi-nor/spi-nor.c ++++ b/drivers/mtd/spi-nor/spi-nor.c +@@ -107,6 +107,34 @@ + return val; + } + ++static int read_sr2(struct spi_nor *nor) ++{ ++ int ret; ++ u8 val; ++ ++ ret = nor->read_reg(nor, SPINOR_OP_RDSR2, &val, 1); ++ if (ret < 0) { ++ pr_err("error %d reading SR2\n", (int) ret); ++ return ret; ++ } ++ ++ return val; ++} ++ ++static int read_sr3(struct spi_nor *nor) ++{ ++ int ret; ++ u8 val; ++ ++ ret = nor->read_reg(nor, SPINOR_OP_RDSR3, &val, 1); ++ if (ret < 0) { ++ pr_err("error %d reading SR3\n", (int) ret); ++ return ret; ++ } ++ ++ return val; ++} ++ + /* + * Read the flag status register, returning its value in the location + * Return the status register value. +@@ -166,6 +194,12 @@ + return nor->write_reg(nor, SPINOR_OP_WRSR2, nor->cmd_buf, 1); + } + ++static inline int write_sr3(struct spi_nor *nor, u8 val) ++{ ++ nor->cmd_buf[0] = val; ++ return nor->write_reg(nor, SPINOR_OP_WRSR3, nor->cmd_buf, 1); ++} ++ + /* + * Set write enable latch with Write Enable command. + * Returns negative if error occurred. +@@ -2178,7 +2212,7 @@ + + if (!nor->level) { + nor->end_addr = 0; +- dev_warn(nor->dev, "all blocks is unlocked.\n"); ++ dev_warn(nor->dev, "all blocks are unlocked.\n"); + return; + } + +@@ -2261,6 +2295,48 @@ + return level; + } + ++static void bsp_global_unlock(struct spi_nor *nor) { ++ int val; ++ ++ dev_info(nor->dev, "Force global unlock\n"); ++ write_enable(nor); ++ /* Global Block/Sector Unlock, ++ * see 8.2.42 Global Block/Sector Unlock (98h) */ ++ nor->write_reg(nor, 0x98, NULL, 0); ++ spi_nor_wait_till_ready(nor); ++ ++ val = read_sr(nor); ++ if (val){ ++ dev_info(nor->dev, "SR1:[%02x]->[00] ", val); ++ val=0; ++ write_enable(nor); ++ write_sr(nor, val); ++ if(spi_nor_wait_till_ready(nor)) ++ dev_err(nor->dev, "error while writing SR1.\n"); ++ } ++ ++ val = read_sr2(nor); ++ if (val){ ++ dev_info(nor->dev, "SR2:[%02x]->[00]", val); ++ val = 0; ++ write_enable(nor); ++ write_sr2(nor, val); ++ if(spi_nor_wait_till_ready(nor)) ++ dev_err(nor->dev, "error while writing SR2.\n"); ++ } ++ ++ val = read_sr3(nor); ++ if (val & 4){ ++ dev_info(nor->dev, "SR3:[%02x]->[%02x]", val, val ^ 4); ++ val ^= 4; // Remove SR3_WPS ++ write_enable(nor); ++ write_sr3(nor, val); ++ if(spi_nor_wait_till_ready(nor)) ++ dev_err(nor->dev, "error while writing SR3.\n"); ++ } ++ ++} ++ + static void bsp_get_spi_lock_info(struct spi_nor *nor, const struct flash_info *info) + { + unsigned int chipsize; +@@ -2275,18 +2351,12 @@ + case SNOR_MFR_ESMT: + case SNOR_MFR_EON: + case SNOR_MFR_SPANSION: ++ bsp_global_unlock(nor); + /* BP bit convert to lock level */ + nor->level = bsp_bp_to_level(nor, info, BP_NUM_3); + break; + case SNOR_MFR_WINBOND: +- if (!strcmp("w25q128(b/f)v", info->name)) { +- dev_info(nor->dev, "Force global unlock\n"); +- write_enable(nor); +- /* Global Block/Sector Unlock, +- * see 8.2.42 Global Block/Sector Unlock (98h) */ +- nor->write_reg(nor, 0x98, NULL, 0); +- write_disable(nor); +- } ++ bsp_global_unlock(nor); + /* BP bit convert to lock level */ + if (chipsize <= _16M) + nor->level = bsp_bp_to_level(nor, info, BP_NUM_3); +@@ -2294,7 +2364,8 @@ + nor->level = bsp_bp_to_level(nor, info, BP_NUM_4); + break; + case SNOR_MFR_MACRONIX: +- ++ case SNOR_MFR_XMC: ++ bsp_global_unlock(nor); + /* BP bit convert to lock level */ + if (chipsize <= _8M) + nor->level = bsp_bp_to_level(nor, info, BP_NUM_3); +@@ -2302,6 +2373,7 @@ + nor->level = bsp_bp_to_level(nor, info, BP_NUM_4); + break; + case SNOR_MFR_XTX: ++ bsp_global_unlock(nor); + /* BP bit convert to lock level */ + nor->level = bsp_bp_to_level(nor, info, BP_NUM_4); + break; +@@ -2562,6 +2634,8 @@ + { + int ret; + unsigned char cval,val; ++ unsigned char sr1, sr2, sr3; ++ char sr1txt[256] = {0}, sr2txt[256] = {0}, sr3txt[256] = {0}; + + if (JEDEC_MFR(info) == SNOR_MFR_MACRONIX){ + val = read_sr(nor); +@@ -2583,26 +2657,24 @@ + nor->cmd_buf[1]=(cval & (~CR_DUMMY_CYCLE)); + ret = nor->write_reg(nor, SPINOR_OP_WRSR, nor->cmd_buf, 2); + } +- } else if (JEDEC_MFR(info) == SNOR_MFR_WINBOND) { +- unsigned char sr1, sr2, sr3; +- char sr1txt[256] = {0}, sr2txt[256] = {0}, sr3txt[256] = {0}; +- +- sr1 = read_sr(nor); +- if (sr1 < 0) +- return sr1; +- ret = nor->read_reg(nor, SPINOR_OP_RDSR2, &sr2, 1); +- if(ret < 0){ +- dev_err(nor->dev, "error %d reading config Reg.\n", ret); +- return ret; +- } +- ret = nor->read_reg(nor, SPINOR_OP_RDSR3, &sr3, 1); +- if(ret < 0){ +- dev_err(nor->dev, "error %d reading config Reg.\n", ret); +- return ret; +- } +- dev_info(nor->dev, "Winbond: SR1 [%s], SR2 [%s], SR3 [%s]\n", +- winbond_sr1txt(sr1txt, sr1), winbond_sr2txt(sr2txt, sr2), +- winbond_sr3txt(sr3txt, sr3)); ++ } ++ ++ sr1 = read_sr(nor); ++ if (sr1 < 0) ++ return sr1; ++ sr2 = read_sr2(nor); ++ if (sr2 < 0) ++ return sr2; ++ sr3 = read_sr3(nor); ++ if (sr3 < 0) ++ return sr3; ++ if (JEDEC_MFR(info) == SNOR_MFR_WINBOND) { ++ dev_info(nor->dev, "Winbond: SR1 [%s], SR2 [%s], SR3 [%s]\n", ++ winbond_sr1txt(sr1txt, sr1), winbond_sr2txt(sr2txt, sr2), ++ winbond_sr3txt(sr3txt, sr3)); ++ } else { ++ dev_info(nor->dev, "SR1 [%02x], SR2 [%02x], SR3 [%02x]\n", ++ sr1, sr2, sr3); + } + + if (params) { +--- a/include/linux/mtd/spi-nor.h ++++ b/include/linux/mtd/spi-nor.h +@@ -30,6 +30,7 @@ + #define SNOR_MFR_ESMT 0x8c + #define SNOR_MFR_GD 0xc8 + #define SNOR_MFR_XTX 0x0b ++#define SNOR_MFR_XMC 0x20 + #define SNOR_MFR_PUYA 0x85 + #define SNOR_MFR_FM 0xa1 + #define SNOR_MFR_ISSI 0x9d