diff options
| -rw-r--r-- | drivers/mtd/spi-nor/core.h | 8 | ||||
| -rw-r--r-- | drivers/mtd/spi-nor/debugfs.c | 28 | ||||
| -rw-r--r-- | drivers/mtd/spi-nor/swp.c | 13 |
3 files changed, 45 insertions, 4 deletions
diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h index cd355e94b97e..ce46771ecdc8 100644 --- a/drivers/mtd/spi-nor/core.h +++ b/drivers/mtd/spi-nor/core.h @@ -287,6 +287,9 @@ struct spi_nor_erase_map { * false otherwise. This feedback may be misleading because users * may get an "unlocked" status even though a subpart of the region * is effectively locked. + * + * If in doubt during development, check-out the debugfs output which tries to + * be more user friendly. */ struct spi_nor_locking_ops { int (*lock)(struct spi_nor *nor, loff_t ofs, u64 len); @@ -678,6 +681,7 @@ int spi_nor_post_bfpt_fixups(struct spi_nor *nor, const struct sfdp_bfpt *bfpt); void spi_nor_init_default_locking_ops(struct spi_nor *nor); +bool spi_nor_has_default_locking_ops(struct spi_nor *nor); void spi_nor_try_unlock_all(struct spi_nor *nor); void spi_nor_cache_sr_lock_bits(struct spi_nor *nor, u8 *sr); void spi_nor_set_mtd_locking_ops(struct spi_nor *nor); @@ -712,6 +716,10 @@ static inline bool spi_nor_needs_sfdp(const struct spi_nor *nor) return !nor->info->size; } +u64 spi_nor_get_min_prot_length_sr(struct spi_nor *nor); +void spi_nor_get_locked_range_sr(struct spi_nor *nor, const u8 *sr, loff_t *ofs, u64 *len); +bool spi_nor_is_locked_sr(struct spi_nor *nor, loff_t ofs, u64 len, const u8 *sr); + #ifdef CONFIG_DEBUG_FS void spi_nor_debugfs_register(struct spi_nor *nor); void spi_nor_debugfs_shutdown(void); diff --git a/drivers/mtd/spi-nor/debugfs.c b/drivers/mtd/spi-nor/debugfs.c index d0191eb9f879..82df8ad4176c 100644 --- a/drivers/mtd/spi-nor/debugfs.c +++ b/drivers/mtd/spi-nor/debugfs.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 #include <linux/debugfs.h> +#include <linux/math64.h> #include <linux/mtd/spi-nor.h> #include <linux/spi/spi.h> #include <linux/spi/spi-mem.h> @@ -77,11 +78,14 @@ static void spi_nor_print_flags(struct seq_file *s, unsigned long flags, static int spi_nor_params_show(struct seq_file *s, void *data) { struct spi_nor *nor = s->private; + u64 min_prot_len = spi_nor_get_min_prot_length_sr(nor); struct spi_nor_flash_parameter *params = nor->params; struct spi_nor_erase_map *erase_map = ¶ms->erase_map; struct spi_nor_erase_region *region = erase_map->regions; const struct flash_info *info = nor->info; char buf[16], *str; + loff_t lock_start; + u64 lock_length; unsigned int i; seq_printf(s, "name\t\t%s\n", info->name); @@ -159,6 +163,30 @@ static int spi_nor_params_show(struct seq_file *s, void *data) region[i].overlaid ? "yes" : "no"); } + if (!spi_nor_has_default_locking_ops(nor)) + return 0; + + seq_puts(s, "\nlocked sectors\n"); + seq_puts(s, " region (in hex) | status | #sectors\n"); + seq_puts(s, " ------------------+----------+---------\n"); + + spi_nor_get_locked_range_sr(nor, nor->dfs_sr_cache, &lock_start, &lock_length); + if (!lock_length || lock_length == params->size) { + seq_printf(s, " %08llx-%08llx | %s | %llu\n", 0ULL, params->size - 1, + lock_length ? " locked" : "unlocked", + div_u64(params->size, min_prot_len)); + } else if (!lock_start) { + seq_printf(s, " %08llx-%08llx | %s | %llu\n", 0ULL, lock_length - 1, + " locked", div_u64(lock_length, min_prot_len)); + seq_printf(s, " %08llx-%08llx | %s | %llu\n", lock_length, params->size - 1, + "unlocked", div_u64(params->size - lock_length, min_prot_len)); + } else { + seq_printf(s, " %08llx-%08llx | %s | %llu\n", 0ULL, lock_start - 1, + "unlocked", div_u64(lock_start, min_prot_len)); + seq_printf(s, " %08llx-%08llx | %s | %llu\n", lock_start, params->size - 1, + " locked", div_u64(lock_length, min_prot_len)); + } + return 0; } DEFINE_SHOW_ATTRIBUTE(spi_nor_params); diff --git a/drivers/mtd/spi-nor/swp.c b/drivers/mtd/spi-nor/swp.c index cd37fec08c0e..2411d8f1012d 100644 --- a/drivers/mtd/spi-nor/swp.c +++ b/drivers/mtd/spi-nor/swp.c @@ -34,7 +34,7 @@ static u8 spi_nor_get_sr_tb_mask(struct spi_nor *nor) return 0; } -static u64 spi_nor_get_min_prot_length_sr(struct spi_nor *nor) +u64 spi_nor_get_min_prot_length_sr(struct spi_nor *nor) { unsigned int bp_slots, bp_slots_needed; /* @@ -55,8 +55,8 @@ static u64 spi_nor_get_min_prot_length_sr(struct spi_nor *nor) return sector_size; } -static void spi_nor_get_locked_range_sr(struct spi_nor *nor, const u8 *sr, loff_t *ofs, - u64 *len) +void spi_nor_get_locked_range_sr(struct spi_nor *nor, const u8 *sr, loff_t *ofs, + u64 *len) { u64 min_prot_len; u8 bp_mask = spi_nor_get_sr_bp_mask(nor); @@ -114,7 +114,7 @@ static bool spi_nor_check_lock_status_sr(struct spi_nor *nor, loff_t ofs, return (ofs >= lock_offs_max) || (offs_max <= lock_offs); } -static bool spi_nor_is_locked_sr(struct spi_nor *nor, loff_t ofs, u64 len, const u8 *sr) +bool spi_nor_is_locked_sr(struct spi_nor *nor, loff_t ofs, u64 len, const u8 *sr) { return spi_nor_check_lock_status_sr(nor, ofs, len, sr, true); } @@ -416,6 +416,11 @@ void spi_nor_init_default_locking_ops(struct spi_nor *nor) nor->params->locking_ops = &spi_nor_sr_locking_ops; } +bool spi_nor_has_default_locking_ops(struct spi_nor *nor) +{ + return nor->params->locking_ops == &spi_nor_sr_locking_ops; +} + static int spi_nor_lock(struct mtd_info *mtd, loff_t ofs, u64 len) { struct spi_nor *nor = mtd_to_spi_nor(mtd); |
