mirror of https://github.com/OpenIPC/firmware.git
[Gk7205v200] SPI NOR force global unlock and SR clear (#649)
parent
cee839f5b1
commit
fb57f360f6
|
@ -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
|
Loading…
Reference in New Issue