static int stm_lock(struct spi_nor *nor, loff_t ofs, uint64_t len)
{
struct mtd_info *mtd = nor->mtd;
uint32_t offset = ofs;
uint8_t status_old, status_new;
int ret = 0;
status_old = read_sr(nor);
if (offset < mtd->size - (mtd->size / 2))
status_new = status_old | SR_BP2 | SR_BP1 | SR_BP0;
else if (offset < mtd->size - (mtd->size / 4))
status_new = (status_old & ~SR_BP0) | SR_BP2 | SR_BP1;
else if (offset < mtd->size - (mtd->size / 8))
status_new = (status_old & ~SR_BP1) | SR_BP2 | SR_BP0;
else if (offset < mtd->size - (mtd->size / 16))
status_new = (status_old & ~(SR_BP0 | SR_BP1)) | SR_BP2;
else if (offset < mtd->size - (mtd->size / 32))
status_new = (status_old & ~SR_BP2) | SR_BP1 | SR_BP0;
else if (offset < mtd->size - (mtd->size / 64))
status_new = (status_old & ~(SR_BP2 | SR_BP0)) | SR_BP1;
else
status_new = (status_old & ~(SR_BP2 | SR_BP1)) | SR_BP0;
/* Only modify protection if it will not unlock other areas */
if ((status_new & (SR_BP2 | SR_BP1 | SR_BP0)) >
(status_old & (SR_BP2 | SR_BP1 | SR_BP0))) {
write_enable(nor);
ret = write_sr(nor, status_new);
}
return ret;
}
static int stm_unlock(struct spi_nor *nor, loff_t ofs, uint64_t len)
{
struct mtd_info *mtd = nor->mtd;
uint32_t offset = ofs;
uint8_t status_old, status_new;
int ret = 0;
status_old = read_sr(nor);
if (offset+len > mtd->size - (mtd->size / 64))
status_new = status_old & ~(SR_BP2 | SR_BP1 | SR_BP0);
else if (offset+len > mtd->size - (mtd->size / 32))
status_new = (status_old & ~(SR_BP2 | SR_BP1)) | SR_BP0;
else if (offset+len > mtd->size - (mtd->size / 16))
status_new = (status_old & ~(SR_BP2 | SR_BP0)) | SR_BP1;
else if (offset+len > mtd->size - (mtd->size / 8))
status_new = (status_old & ~SR_BP2) | SR_BP1 | SR_BP0;
else if (offset+len > mtd->size - (mtd->size / 4))
status_new = (status_old & ~(SR_BP0 | SR_BP1)) | SR_BP2;
else if (offset+len > mtd->size - (mtd->size / 2))
status_new = (status_old & ~SR_BP1) | SR_BP2 | SR_BP0;
else
status_new = (status_old & ~SR_BP0) | SR_BP2 | SR_BP1;
/* Only modify protection if it will not lock other areas */
if ((status_new & (SR_BP2 | SR_BP1 | SR_BP0)) <
(status_old & (SR_BP2 | SR_BP1 | SR_BP0))) {
write_enable(nor);
ret = write_sr(nor, status_new);
}
return ret;
}