u64 min_prot_len;
int ret;
u8 status_old[1] = {}, status_new[1] = {};
- u8 bp_mask = spi_nor_get_sr_bp_mask(nor);
+ loff_t ofs_old, ofs_new;
+ u64 len_old, len_new;
loff_t lock_len;
bool can_be_top = true, can_be_bottom = nor->flags & SNOR_F_HAS_SR_TB;
bool use_top;
if (ret)
return ret;
- /* Don't "lock" with no region! */
- if (!(status_new[0] & bp_mask))
- return -EINVAL;
-
/*
* Disallow further writes if WP# pin is neither left floating nor
* wrongly tied to GND (that includes internal pull-downs).
if (!(nor->flags & SNOR_F_NO_WP))
status_new[0] |= SR_SRWD;
+ spi_nor_get_locked_range_sr(nor, status_old, &ofs_old, &len_old);
+ spi_nor_get_locked_range_sr(nor, status_new, &ofs_new, &len_new);
+
+ /* Don't "lock" with no region! */
+ if (!len_new)
+ return -EINVAL;
+
/* Don't bother if they're the same */
if (status_new[0] == status_old[0])
return 0;
/* Only modify protection if it will not unlock other areas */
- if ((status_new[0] & bp_mask) < (status_old[0] & bp_mask))
+ if (len_old &&
+ (ofs_old < ofs_new || (ofs_new + len_new) < (ofs_old + len_old)))
return -EINVAL;
return spi_nor_write_sr_and_check(nor, status_new[0]);
u64 min_prot_len;
int ret;
u8 status_old[1], status_new[1];
- u8 bp_mask = spi_nor_get_sr_bp_mask(nor);
+ loff_t ofs_old, ofs_new;
+ u64 len_old, len_new;
loff_t lock_len;
bool can_be_top = true, can_be_bottom = nor->flags & SNOR_F_HAS_SR_TB;
bool use_top;
return 0;
/* Only modify protection if it will not lock other areas */
- if ((status_new[0] & bp_mask) > (status_old[0] & bp_mask))
+ spi_nor_get_locked_range_sr(nor, status_old, &ofs_old, &len_old);
+ spi_nor_get_locked_range_sr(nor, status_new, &ofs_new, &len_new);
+ if (len_old && len_new &&
+ (ofs_new < ofs_old || (ofs_old + len_old) < (ofs_new + len_new)))
return -EINVAL;
return spi_nor_write_sr_and_check(nor, status_new[0]);