修改spif和uboot,加上写保护与解除保护
This commit is contained in:
parent
a10ff1b209
commit
10e6767b22
|
@ -757,6 +757,7 @@ CONFIG_MTD_SPI_NOR=y
|
|||
# CONFIG_MTD_SPI_NOR_USE_4K_SECTORS is not set
|
||||
# CONFIG_SPI_CADENCE_QUADSPI is not set
|
||||
# CONFIG_SPI_FLASH_SR is not set
|
||||
# CONFIG_SPI_FLASH_DEFAULT_LOCK is not set
|
||||
# CONFIG_MTD_UBI is not set
|
||||
CONFIG_DTC=y
|
||||
CONFIG_OF=y
|
||||
|
|
|
@ -757,6 +757,7 @@ CONFIG_MTD_SPI_NOR=y
|
|||
# CONFIG_MTD_SPI_NOR_USE_4K_SECTORS is not set
|
||||
# CONFIG_SPI_CADENCE_QUADSPI is not set
|
||||
# CONFIG_SPI_FLASH_SR is not set
|
||||
# CONFIG_SPI_FLASH_DEFAULT_LOCK is not set
|
||||
# CONFIG_MTD_UBI is not set
|
||||
CONFIG_DTC=y
|
||||
CONFIG_OF=y
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
/*bootargs = "earlyprintk=sunxi-uart,0x02500000 clk_ignore_unused initcall_debug=0 console=ttyS0,115200 loglevel=6 lpj=240000 root=/dev/mtdblock4 rootwait init=/files/pseudo_init rdinit=/rdinit partitions=env@mtdblock1:env-redund@mtdblock2:boot@mtdblock3:rootfs@mtdblock4:extend@mtdblock5:rootfs_data@mtdblock6:UDISK@mtdblock7 coherent_pool=16K androidboot.hardware=sun8iw21p1 boot_type=3 androidboot.boot_type=3 gpt=1 mbr_offset=2080768 bootreason=unknow";*/
|
||||
|
||||
/* for OTA recovery system:(kernel rootfs extend) */
|
||||
bootargs = "earlyprintk=sunxi-uart,0x02500000 clk_ignore_unused initcall_debug=0 console=ttyS0,115200 loglevel=1 lpj=240000 root=/dev/mtdblock4 rootwait init=/files/pseudo_init rdinit=/rdinit partitions=env@mtdblock1:env-redund@mtdblock2:boot@mtdblock3:rootfs@mtdblock4:extend@mtdblock5:recovery@mtdblock6:rootfs_data@mtdblock7:UDISK@mtdblock8 coherent_pool=16K androidboot.hardware=sun8iw21p1 boot_type=3 androidboot.boot_type=3 gpt=1 mbr_offset=2080768 bootreason=unknow";
|
||||
bootargs = "earlyprintk=sunxi-uart,0x02500000 clk_ignore_unused initcall_debug=0 console=ttyS0,115200 loglevel=1 lpj=240000 root=/dev/mtdblock4 rootwait init=/files/pseudo_init rdinit=/rdinit partitions=env@mtdblock1:env-redund@mtdblock2:boot@mtdblock3:rootfs@mtdblock4:extend@mtdblock5:recovery@mtdblock6:UDISK@mtdblock7 coherent_pool=16K androidboot.hardware=sun8iw21p1 boot_type=3 androidboot.boot_type=3 gpt=1 mbr_offset=2080768 bootreason=unknow";
|
||||
|
||||
|
||||
/* for OTA recovery system:(kernel rootfs extend appImg recoveryImg) */
|
||||
|
|
|
@ -762,6 +762,7 @@ CONFIG_MTD_SPI_NOR=y
|
|||
# CONFIG_MTD_SPI_NOR_USE_4K_SECTORS is not set
|
||||
# CONFIG_SPI_CADENCE_QUADSPI is not set
|
||||
# CONFIG_SPI_FLASH_SR is not set
|
||||
CONFIG_SPI_FLASH_DEFAULT_LOCK=y
|
||||
# CONFIG_MTD_UBI is not set
|
||||
CONFIG_DTC=y
|
||||
CONFIG_OF=y
|
||||
|
|
|
@ -765,6 +765,7 @@ CONFIG_MTD_SPI_NOR=y
|
|||
# CONFIG_MTD_SPI_NOR_USE_4K_SECTORS is not set
|
||||
# CONFIG_SPI_CADENCE_QUADSPI is not set
|
||||
# CONFIG_SPI_FLASH_SR is not set
|
||||
# CONFIG_SPI_FLASH_DEFAULT_LOCK is not set
|
||||
# CONFIG_MTD_UBI is not set
|
||||
CONFIG_DTC=y
|
||||
CONFIG_OF=y
|
||||
|
|
|
@ -30,6 +30,7 @@ size = 16
|
|||
; 2、name最大12个字符
|
||||
; 3、size = 0, 将创建一个无大小的空分区
|
||||
; 4、为了安全和效率考虑,分区大小最好保证为16M字节的整数倍
|
||||
; 5、size 128 = 64KB 扇区512byte py_nor_flash
|
||||
;********************************************************************************************************
|
||||
[partition_start]
|
||||
|
||||
|
@ -47,13 +48,13 @@ size = 16
|
|||
|
||||
[partition]
|
||||
name = boot
|
||||
size = 6144
|
||||
size = 9728
|
||||
downloadfile = "boot.fex"
|
||||
user_type = 0x8000
|
||||
|
||||
[partition]
|
||||
name = rootfs
|
||||
size = 20480
|
||||
size = 24064
|
||||
downloadfile = "rootfs.fex"
|
||||
user_type = 0x8000
|
||||
|
||||
|
@ -81,10 +82,10 @@ size = 16
|
|||
; downloadfile = "recoveryimg.fex"
|
||||
; user_type = 0x8000
|
||||
|
||||
[partition]
|
||||
name = rootfs_data
|
||||
size = 2048
|
||||
user_type = 0x8000
|
||||
;[partition]
|
||||
; name = rootfs_data
|
||||
; size = 2048
|
||||
; user_type = 0x8000
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -3873,6 +3873,9 @@ static int spi_nor_setup(struct spi_nor *nor, const struct flash_info *info,
|
|||
|
||||
static int sunxi_lock_init(struct spi_nor *nor)
|
||||
{
|
||||
uint8_t mask = 0;
|
||||
uint8_t status1 = 0;
|
||||
uint8_t status2 = 0;
|
||||
struct mtd_info *mtd = &nor->mtd;
|
||||
const struct flash_info *info = nor->info;
|
||||
|
||||
|
@ -3884,6 +3887,67 @@ static int sunxi_lock_init(struct spi_nor *nor)
|
|||
if (sunxi_individual_lock_is_enable(nor))
|
||||
sunxi_individual_unlock_global(nor);
|
||||
|
||||
|
||||
if (JEDEC_MFR(nor->info) == SNOR_MFR_PUYA)
|
||||
{
|
||||
if (nor->info->id[2] == 0x19) // py25q256hb id:0x852019
|
||||
{
|
||||
status1 = (uint8_t)read_sr(nor);
|
||||
/* check cmp first */
|
||||
status2 = (uint8_t)read_sr2(nor);
|
||||
// if ((status2 < 0) || (status1 < 0))
|
||||
// {
|
||||
// printf("read err!:%x %x\n", status1, status2);
|
||||
// }
|
||||
if (status2 & (SR2_CMP_GD)) // cmp=1
|
||||
{
|
||||
mask = (SR_BP2 | SR_BP3);
|
||||
status1 |= mask;
|
||||
printf("cmp=1\n");
|
||||
}
|
||||
else // cmp=0
|
||||
{
|
||||
printf("cmp=0\n");
|
||||
mask = (uint8_t) ~(SR_BP0 | SR_BP1 | SR_BP2 | SR_BP3);
|
||||
status1 &= mask;
|
||||
}
|
||||
if (write_sr_and_check(nor, status1, mask) != 0)
|
||||
{
|
||||
printf("py_unlock sr err!:%x\n", status1);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
else if (nor->info->id[2] == 0x18) // py25q128ha id:0x852018
|
||||
{
|
||||
status1 = (uint8_t)read_sr(nor);
|
||||
/* check cmp first */
|
||||
status2 = (uint8_t)read_sr2(nor);
|
||||
// if ((status2 < 0) || (status1 < 0))
|
||||
// {
|
||||
// printf("read err!:%x %x\n", status1, status2);
|
||||
// }
|
||||
if (status2 & (SR2_CMP_GD)) // cmp=1
|
||||
{
|
||||
mask = (SR_BP0 | SR_BP1 | SR_BP2);
|
||||
status1 |= mask;
|
||||
printf("cmp=1\n");
|
||||
}
|
||||
else // cmp=0
|
||||
{
|
||||
printf("cmp=0\n");
|
||||
mask = (uint8_t) ~(SR_BP0 | SR_BP1 | SR_BP2);
|
||||
status1 &= mask;
|
||||
}
|
||||
if (write_sr_and_check(nor, status1, mask) != 0)
|
||||
{
|
||||
printf("py_unlock sr err!:%x\n", status1);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (JEDEC_MFR(info) == SNOR_MFR_ST ||
|
||||
JEDEC_MFR(info) == SNOR_MFR_MICRON ||
|
||||
JEDEC_MFR(info) == SNOR_MFR_SST)
|
||||
|
|
|
@ -81,4 +81,10 @@ config SPI_FLASH_SR
|
|||
help
|
||||
when set, enable security register write, read, earse functions.
|
||||
|
||||
config SPI_FLASH_DEFAULT_LOCK
|
||||
bool "SPI FLASH default lock"
|
||||
default n
|
||||
help
|
||||
when set, norflash will be protected after kernel run
|
||||
|
||||
endif # MTD_SPI_NOR
|
||||
|
|
|
@ -507,6 +507,42 @@ static int read_sr(struct spi_nor *nor)
|
|||
return nor->bouncebuf[0];
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the PUYA status register 2, returning its value in the location
|
||||
* Return the status register value.
|
||||
* Returns negative if error occurred.
|
||||
*/
|
||||
static int read_puya_sr2(struct spi_nor *nor)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = nor->read_reg(nor, SPINOR_OP_RDSR2, nor->bouncebuf, 1);
|
||||
if (ret < 0) {
|
||||
pr_err("error %d reading SR\n", (int) ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return nor->bouncebuf[0];
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the PUYA configuration register, returning its value in the location
|
||||
* Return the status register value.
|
||||
* Returns negative if error occurred.
|
||||
*/
|
||||
static int read_puya_cr(struct spi_nor *nor)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = nor->read_reg(nor, SPINOR_OP_RDSR3, nor->bouncebuf, 1);
|
||||
if (ret < 0) {
|
||||
pr_err("error %d reading SR\n", (int) ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return nor->bouncebuf[0];
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the flag status register, returning its value in the location
|
||||
* Return the status register value.
|
||||
|
@ -553,6 +589,26 @@ static int write_sr(struct spi_nor *nor, u8 val)
|
|||
return nor->write_reg(nor, SPINOR_OP_WRSR, nor->bouncebuf, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Write status register2 1 byte
|
||||
* Returns negative if error occurred.
|
||||
*/
|
||||
static int write_puya_sr2(struct spi_nor *nor, u8 val)
|
||||
{
|
||||
nor->bouncebuf[0] = val;
|
||||
return nor->write_reg(nor, SPINOR_OP_WRSR2, nor->bouncebuf, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Write configuration register 1 byte
|
||||
* Returns negative if error occurred.
|
||||
*/
|
||||
static int write_puya_cr(struct spi_nor *nor, u8 val)
|
||||
{
|
||||
nor->bouncebuf[0] = val;
|
||||
return nor->write_reg(nor, SPINOR_OP_WRSR3, nor->bouncebuf, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set write enable latch with Write Enable command.
|
||||
* Returns negative if error occurred.
|
||||
|
@ -1401,6 +1457,48 @@ static int write_sr_and_check(struct spi_nor *nor, u8 status_new, u8 mask)
|
|||
return ((ret & mask) != (status_new & mask)) ? -EIO : 0;
|
||||
}
|
||||
|
||||
/* Write status register2 and ensure bits in mask match written values */
|
||||
static int write_sr2_and_check(struct spi_nor *nor, u8 status_new, u8 mask)
|
||||
{
|
||||
int ret;
|
||||
|
||||
write_enable(nor);
|
||||
ret = write_puya_sr2(nor, status_new);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = spi_nor_wait_till_ready(nor);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = read_puya_sr2(nor);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return ((ret & status_new) != (status_new & status_new)) ? -EIO : 0;
|
||||
}
|
||||
|
||||
/* Write configuration register and ensure bits in mask match written values */
|
||||
static int write_cr_and_check(struct spi_nor *nor, u8 status_new, u8 mask)
|
||||
{
|
||||
int ret;
|
||||
|
||||
write_enable(nor);
|
||||
ret = write_puya_cr(nor, status_new);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = spi_nor_wait_till_ready(nor);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = read_puya_cr(nor);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return ((ret & mask) != (status_new & mask)) ? -EIO : 0;
|
||||
}
|
||||
|
||||
static void stm_get_locked_range(struct spi_nor *nor, u8 sr, loff_t *ofs,
|
||||
uint64_t *len)
|
||||
{
|
||||
|
@ -1672,6 +1770,175 @@ static const struct spi_nor_locking_ops stm_locking_ops = {
|
|||
.is_locked = stm_is_locked,
|
||||
};
|
||||
|
||||
/* unlock except UDISK */
|
||||
/* 解锁先判断CMP位,再决定sr2应该写什么 */
|
||||
static int py_unlock(struct spi_nor *nor, loff_t ofs, uint64_t len)
|
||||
{
|
||||
uint8_t mask = 0;
|
||||
uint8_t status1 = 0;
|
||||
uint8_t status2 = 0;
|
||||
|
||||
if (nor->info->id[2] == 0x19) // py25q256hb id:0x852019
|
||||
{
|
||||
status1 = (uint8_t)read_sr(nor);
|
||||
/* check cmp first */
|
||||
status2 = (uint8_t)read_puya_sr2(nor);
|
||||
// if ((status2 < 0) || (status1 < 0))
|
||||
// {
|
||||
// pr_emerg("py_lock read err!:%x %x\n", status1, status2);
|
||||
// return -1;
|
||||
// }
|
||||
if (status2 & (SR2_CMP_GD)) // cmp=1
|
||||
{
|
||||
mask = (SR_BP2 | SR_BP3);
|
||||
status1 |= mask;
|
||||
}
|
||||
else // cmp=0
|
||||
{
|
||||
mask = (uint8_t) ~(SR_BP0 | SR_BP1 | SR_BP2 | SR_BP3);
|
||||
status1 &= mask;
|
||||
}
|
||||
if (write_sr_and_check(nor, status1, mask) != 0)
|
||||
{
|
||||
pr_emerg("py_unlock sr err!:%x\n", status1);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
else if (nor->info->id[2] == 0x18) // py25q128ha id:0x852018
|
||||
{
|
||||
pr_emerg("not support py25q128ha yet\n");
|
||||
return -1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* lock except UDISK */
|
||||
/* 上锁先判断CMP位,然后配置CMP位确保为1(cmp default值需要改变)再写sr2 */
|
||||
/* 第一次上电会调用这个函数更改CMP位,只要上电过一次,flash就会改成CMP=1 */
|
||||
static int py_lock(struct spi_nor *nor, loff_t ofs, uint64_t len)
|
||||
{
|
||||
uint8_t status1 = 0;
|
||||
uint8_t status2 = 0;
|
||||
uint8_t status_cr = 0;
|
||||
uint8_t mask = 0;
|
||||
if (nor->info->id[2] == 0x19) // py25q256hb id:0x852019
|
||||
{
|
||||
/* read old sr1 and sr2 */
|
||||
status2 = (uint8_t)read_puya_sr2(nor);
|
||||
status1 = (uint8_t)read_sr(nor);
|
||||
status_cr = (uint8_t)read_puya_cr(nor);
|
||||
// if ((status2 < 0) || (status1 < 0) || (status_cr < 0))
|
||||
// {
|
||||
// pr_emerg("py_lock read err!:%x %x %x\n", status1, status2, status_cr);
|
||||
// return -1;
|
||||
// }
|
||||
|
||||
if ((status2 & SR2_CMP_GD) == 0) // set cmp=1 if it's not 1
|
||||
{
|
||||
/* first write sr2 CMP=1 */
|
||||
status2 |= (SR2_CMP_GD);
|
||||
if (write_sr2_and_check(nor, status2, status2) != 0)
|
||||
{
|
||||
pr_emerg("py_lock sr2 err!:%x\n", status2);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if ((status_cr & SR_WPS_EN_WINBOND) != 0) // set wps=0 if it's not 0
|
||||
{
|
||||
/* first write CR WPS=0 */
|
||||
status_cr &= ~(SR_WPS_EN_WINBOND);
|
||||
if (write_cr_and_check(nor, status_cr, status_cr) != 0)
|
||||
{
|
||||
pr_emerg("py_lock cr err!:%x\n", status_cr);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* sr1 lower 3/4 24MB except UDISK */
|
||||
mask |= (SR_BP3);
|
||||
mask &= ~(SR_BP0 | SR_BP1 | SR_BP2 | SR_BP4);
|
||||
// 0x7c 0111 1100 Status Register BP0~BP4,只判断这几位
|
||||
if ((status1 & 0x7c) != mask)
|
||||
{
|
||||
status1 |= (SR_BP3);
|
||||
status1 &= ~(SR_BP0 | SR_BP1 | SR_BP2 | SR_BP4);
|
||||
if (write_sr_and_check(nor, status1, mask) != 0)
|
||||
{
|
||||
pr_emerg("py_lock sr err!:%x\n", status1);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
else if (nor->info->id[2] == 0x18) // py25q128ha id:0x852018
|
||||
{
|
||||
// pr_emerg("not support py25q128ha yet\n");
|
||||
return -1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if the flash is locked. py_is_locked for
|
||||
* more info.
|
||||
*
|
||||
* Returns 1 if entire region is locked, 0 is unlocked, and
|
||||
* negative on errors.
|
||||
*/
|
||||
static int py_is_locked(struct spi_nor *nor, loff_t ofs, uint64_t len)
|
||||
{
|
||||
uint8_t mask = 0;
|
||||
uint8_t status1 = 0;
|
||||
uint8_t status2 = 0;
|
||||
if (nor->info->id[2] == 0x19) // py25q256hb id:0x852019
|
||||
{
|
||||
status1 = (uint8_t)read_sr(nor);
|
||||
/* check cmp first */
|
||||
status2 = (uint8_t)read_puya_sr2(nor);
|
||||
// if ((status2 < 0) || (status1 < 0))
|
||||
// {
|
||||
// pr_emerg("py_lock read err!:%x %x\n", status1, status2);
|
||||
// return -1;
|
||||
// }
|
||||
/* unlock status mask */
|
||||
if (status2 & (SR2_CMP_GD)) // cmp=1
|
||||
{
|
||||
mask = (SR_BP2 | SR_BP3);
|
||||
/* TODO:还有一种情况也算unlock,但是暂时未使用 */
|
||||
}
|
||||
else // cmp=0
|
||||
{
|
||||
mask &= ~(SR_BP0 | SR_BP1 | SR_BP2 | SR_BP3);
|
||||
}
|
||||
|
||||
if ((status1 & 0x7c) != mask)
|
||||
{
|
||||
// printk(KERN_EMERG "lock\n");
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// printk(KERN_EMERG "unlock\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else if (nor->info->id[2] == 0x18) // py25q128ha id:0x852018
|
||||
{
|
||||
pr_emerg("not support py25q128ha yet\n");
|
||||
return -1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static const struct spi_nor_locking_ops puya_locking_ops = {
|
||||
.lock = py_lock,
|
||||
.unlock = py_unlock,
|
||||
.is_locked = py_is_locked,
|
||||
};
|
||||
|
||||
static int spi_nor_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
|
||||
{
|
||||
struct spi_nor *nor = mtd_to_spi_nor(mtd);
|
||||
|
@ -2091,6 +2358,78 @@ static int spi_nor_spansion_clear_sr_bp(struct spi_nor *nor)
|
|||
return spi_nor_clear_sr_bp(nor);
|
||||
}
|
||||
|
||||
/**
|
||||
* HAS : spi_nor_puya_clear_sr_bp() - clear the Status Register Block Protection
|
||||
* bits on puya flashes.
|
||||
* @nor: pointer to a 'struct spi_nor'
|
||||
* 前提WPS=0,根据sr寄存器CMP位,判断应该写什么解锁
|
||||
*
|
||||
*
|
||||
* Return: 0 on success, -errno otherwise.
|
||||
*/
|
||||
static int spi_nor_puya_clear_sr_bp(struct spi_nor *nor)
|
||||
{
|
||||
uint8_t mask = 0;
|
||||
uint8_t status1 = 0;
|
||||
uint8_t status2 = 0;
|
||||
|
||||
if (nor->info->id[2] == 0x19) // py25q256hb id:0x852019
|
||||
{
|
||||
status1 = (uint8_t)read_sr(nor);
|
||||
/* check cmp first */
|
||||
status2 = (uint8_t)read_puya_sr2(nor);
|
||||
// if ((status1 < 0) || (status2 < 0))
|
||||
// {
|
||||
// pr_emerg("clear_sr_bp read err!:%x %x\n", status1, status2);
|
||||
// return -1;
|
||||
// }
|
||||
if (status2 & (SR2_CMP_GD)) // cmp=1
|
||||
{
|
||||
mask = (SR_BP2 | SR_BP3);
|
||||
status1 |= mask;
|
||||
}
|
||||
else // cmp=0
|
||||
{
|
||||
mask = (uint8_t) ~(SR_BP0 | SR_BP1 | SR_BP2 | SR_BP3);
|
||||
status1 &= mask;
|
||||
}
|
||||
if (write_sr_and_check(nor, status1, status1) != 0)
|
||||
{
|
||||
pr_emerg("clear_sr_bp sr err!:%x\n", status1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
else if (nor->info->id[2] == 0x18) // py25q128ha id:0x852018
|
||||
{
|
||||
status1 = (uint8_t)read_sr(nor);
|
||||
/* check cmp first */
|
||||
status2 = (uint8_t)read_puya_sr2(nor);
|
||||
// if ((status2 < 0) || (status1 < 0))
|
||||
// {
|
||||
// printf("clear_sr_bp err!:%x %x\n", status1, status2);
|
||||
// }
|
||||
if (status2 & (SR2_CMP_GD)) // cmp=1
|
||||
{
|
||||
mask = (SR_BP0 | SR_BP1 | SR_BP2);
|
||||
status1 |= mask;
|
||||
}
|
||||
else // cmp=0
|
||||
{
|
||||
mask = (uint8_t) ~(SR_BP0 | SR_BP1 | SR_BP2);
|
||||
status1 &= mask;
|
||||
}
|
||||
if (write_sr_and_check(nor, status1, mask) != 0)
|
||||
{
|
||||
pr_emerg("clear_sr_bp sr err!:%x\n", status1);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Used when the "_ext_id" is two bytes at most */
|
||||
#define INFO(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags) \
|
||||
.id = { \
|
||||
|
@ -2575,11 +2914,11 @@ static const struct flash_info spi_nor_ids[] = {
|
|||
{ "XM25QH128C", INFO(0x204018, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
|
||||
|
||||
/* PUYA */
|
||||
{ "py25q128ha", INFO(0x852018, 0, 64 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_IO_MODE | USE_RX_DTR) },
|
||||
{ "py25q128ha", INFO(0x852018, 0, 64 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_IO_MODE | USE_RX_DTR | SPI_NOR_HAS_LOCK) },
|
||||
{ "p25q128", INFO(0x856018, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
|
||||
{ "p25q64h", INFO(0x856017, 0x0, 64 * 1024, 128, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
|
||||
{ "p25q32h", INFO(0x856016, 0x0, 64 * 1024, 64, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
|
||||
{ "py25q256hb", INFO(0x852019, 0x0, 64 * 1024, 512, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES | USE_IO_MODE | USE_RX_DTR) },
|
||||
{ "py25q256hb", INFO(0x852019, 0x0, 64 * 1024, 512, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES | USE_IO_MODE | USE_RX_DTR | SPI_NOR_HAS_LOCK) },
|
||||
|
||||
/*Zetta*/
|
||||
{ "zd25q64b", INFO(0xba3217, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
|
||||
|
@ -4696,7 +5035,16 @@ static void spi_nor_late_init_params(struct spi_nor *nor)
|
|||
* the default ones.
|
||||
*/
|
||||
if (nor->flags & SNOR_F_HAS_LOCK && !nor->params.locking_ops)
|
||||
nor->params.locking_ops = &stm_locking_ops;
|
||||
{
|
||||
if (JEDEC_MFR(nor->info) == SNOR_MFR_PUYA)
|
||||
{
|
||||
nor->params.locking_ops = &puya_locking_ops;
|
||||
}
|
||||
else // use default
|
||||
{
|
||||
nor->params.locking_ops = &stm_locking_ops;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -4773,6 +5121,7 @@ static int spi_nor_init(struct spi_nor *nor)
|
|||
{
|
||||
int err;
|
||||
|
||||
#ifndef CONFIG_SPI_FLASH_DEFAULT_LOCK
|
||||
if (nor->clear_sr_bp) {
|
||||
if (nor->params.quad_enable == spansion_quad_enable)
|
||||
nor->clear_sr_bp = spi_nor_spansion_clear_sr_bp;
|
||||
|
@ -4784,12 +5133,17 @@ static int spi_nor_init(struct spi_nor *nor)
|
|||
return err;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
err = spi_nor_quad_enable(nor);
|
||||
if (err) {
|
||||
dev_err(nor->dev, "quad mode not supported\n");
|
||||
return err;
|
||||
}
|
||||
#if defined(CONFIG_SPI_FLASH_DEFAULT_LOCK)
|
||||
/* 上电就给flash特定区域上锁 */
|
||||
nor->mtd._lock(&nor->mtd, 0, 0);
|
||||
#endif
|
||||
|
||||
if (nor->addr_width == 4 && !(nor->flags & SNOR_F_4B_OPCODES)) {
|
||||
/*
|
||||
|
@ -5419,11 +5773,23 @@ int spif_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode)
|
|||
* Atmel, SST, Intel/Numonyx, and others serial NOR tend to power up
|
||||
* with the software protection bits set.
|
||||
*/
|
||||
if (JEDEC_MFR(nor->info) == SNOR_MFR_ATMEL ||
|
||||
JEDEC_MFR(nor->info) == SNOR_MFR_INTEL ||
|
||||
JEDEC_MFR(nor->info) == SNOR_MFR_SST ||
|
||||
nor->info->flags & SPI_NOR_HAS_LOCK)
|
||||
nor->clear_sr_bp = spi_nor_clear_sr_bp;
|
||||
if (nor->info->flags & SPI_NOR_HAS_LOCK)
|
||||
{
|
||||
if (JEDEC_MFR(nor->info) == SNOR_MFR_ATMEL ||
|
||||
JEDEC_MFR(nor->info) == SNOR_MFR_INTEL ||
|
||||
JEDEC_MFR(nor->info) == SNOR_MFR_SST)
|
||||
{
|
||||
nor->clear_sr_bp = spi_nor_clear_sr_bp;
|
||||
}
|
||||
else if (JEDEC_MFR(nor->info) == SNOR_MFR_PUYA)
|
||||
{
|
||||
nor->clear_sr_bp = spi_nor_puya_clear_sr_bp;
|
||||
}
|
||||
else
|
||||
{
|
||||
nor->clear_sr_bp = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Init flash parameters based on flash_info struct and SFDP */
|
||||
spi_nor_init_params(nor);
|
||||
|
|
Binary file not shown.
Loading…
Reference in New Issue