1 // SPDX-License-Identifier: GPL-2.0 2 3 #include <linux/array_size.h> 4 #include <linux/debugfs.h> 5 #include <linux/math64.h> 6 #include <linux/mtd/spi-nor.h> 7 #include <linux/spi/spi.h> 8 #include <linux/spi/spi-mem.h> 9 10 #include "core.h" 11 12 #define SPI_NOR_DEBUGFS_ROOT "spi-nor" 13 14 #define SNOR_F_NAME(name) [ilog2(SNOR_F_##name)] = #name 15 static const char *const snor_f_names[] = { 16 SNOR_F_NAME(HAS_SR_TB), 17 SNOR_F_NAME(NO_OP_CHIP_ERASE), 18 SNOR_F_NAME(BROKEN_RESET), 19 SNOR_F_NAME(4B_OPCODES), 20 SNOR_F_NAME(HAS_4BAIT), 21 SNOR_F_NAME(HAS_LOCK), 22 SNOR_F_NAME(HAS_16BIT_SR), 23 SNOR_F_NAME(NO_READ_CR), 24 SNOR_F_NAME(HAS_SR_TB_BIT6), 25 SNOR_F_NAME(HAS_4BIT_BP), 26 SNOR_F_NAME(HAS_SR_BP3_BIT6), 27 SNOR_F_NAME(IO_MODE_EN_VOLATILE), 28 SNOR_F_NAME(SOFT_RESET), 29 SNOR_F_NAME(SWP_IS_VOLATILE), 30 SNOR_F_NAME(RWW), 31 SNOR_F_NAME(ECC), 32 SNOR_F_NAME(NO_WP), 33 SNOR_F_NAME(SWAP16), 34 SNOR_F_NAME(HAS_SR2_CMP_BIT6), 35 }; 36 #undef SNOR_F_NAME 37 38 static const char *spi_nor_protocol_name(enum spi_nor_protocol proto) 39 { 40 switch (proto) { 41 case SNOR_PROTO_1_1_1: return "1S-1S-1S"; 42 case SNOR_PROTO_1_1_2: return "1S-1S-2S"; 43 case SNOR_PROTO_1_1_4: return "1S-1S-4S"; 44 case SNOR_PROTO_1_1_8: return "1S-1S-8S"; 45 case SNOR_PROTO_1_2_2: return "1S-2S-2S"; 46 case SNOR_PROTO_1_4_4: return "1S-4S-4S"; 47 case SNOR_PROTO_1_8_8: return "1S-8S-8S"; 48 case SNOR_PROTO_2_2_2: return "2S-2S-2S"; 49 case SNOR_PROTO_4_4_4: return "4S-4S-4S"; 50 case SNOR_PROTO_8_8_8: return "8S-8S-8S"; 51 case SNOR_PROTO_1_1_1_DTR: return "1D-1D-1D"; 52 case SNOR_PROTO_1_2_2_DTR: return "1D-2D-2D"; 53 case SNOR_PROTO_1_4_4_DTR: return "1D-4D-4D"; 54 case SNOR_PROTO_1_8_8_DTR: return "1D-8D-8D"; 55 case SNOR_PROTO_8_8_8_DTR: return "8D-8D-8D"; 56 } 57 58 return "<unknown>"; 59 } 60 61 static void spi_nor_print_flags(struct seq_file *s, unsigned long flags, 62 const char *const *names, int names_len) 63 { 64 bool sep = false; 65 int i; 66 67 for (i = 0; i < sizeof(flags) * BITS_PER_BYTE; i++) { 68 if (!(flags & BIT(i))) 69 continue; 70 if (sep) 71 seq_puts(s, " | "); 72 sep = true; 73 if (i < names_len && names[i]) 74 seq_puts(s, names[i]); 75 else 76 seq_printf(s, "1<<%d", i); 77 } 78 } 79 80 static int spi_nor_params_show(struct seq_file *s, void *data) 81 { 82 struct spi_nor *nor = s->private; 83 u64 min_prot_len = spi_nor_get_min_prot_length_sr(nor); 84 struct spi_nor_flash_parameter *params = nor->params; 85 struct spi_nor_erase_map *erase_map = ¶ms->erase_map; 86 struct spi_nor_erase_region *region = erase_map->regions; 87 const struct flash_info *info = nor->info; 88 char buf[16], *str; 89 loff_t lock_start; 90 u64 lock_length; 91 unsigned int i; 92 93 seq_printf(s, "name\t\t%s\n", info->name); 94 seq_printf(s, "id\t\t%*ph\n", SPI_NOR_MAX_ID_LEN, nor->id); 95 string_get_size(params->size, 1, STRING_UNITS_2, buf, sizeof(buf)); 96 seq_printf(s, "size\t\t%s\n", buf); 97 seq_printf(s, "write size\t%u\n", params->writesize); 98 seq_printf(s, "page size\t%u\n", params->page_size); 99 seq_printf(s, "address nbytes\t%u\n", nor->addr_nbytes); 100 101 seq_puts(s, "flags\t\t"); 102 spi_nor_print_flags(s, nor->flags, snor_f_names, 103 ARRAY_SIZE(snor_f_names)); 104 seq_puts(s, "\n"); 105 106 seq_puts(s, "\nopcodes\n"); 107 seq_printf(s, " read\t\t0x%02x\n", nor->read_opcode); 108 seq_printf(s, " dummy cycles\t%u\n", nor->read_dummy); 109 seq_printf(s, " erase\t\t0x%02x\n", nor->erase_opcode); 110 seq_printf(s, " program\t0x%02x\n", nor->program_opcode); 111 112 switch (nor->cmd_ext_type) { 113 case SPI_NOR_EXT_NONE: 114 str = "none"; 115 break; 116 case SPI_NOR_EXT_REPEAT: 117 str = "repeat"; 118 break; 119 case SPI_NOR_EXT_INVERT: 120 str = "invert"; 121 break; 122 default: 123 str = "<unknown>"; 124 break; 125 } 126 seq_printf(s, " 8D extension\t%s\n", str); 127 128 seq_puts(s, "\nprotocols\n"); 129 seq_printf(s, " read\t\t%s\n", 130 spi_nor_protocol_name(nor->read_proto)); 131 seq_printf(s, " write\t\t%s\n", 132 spi_nor_protocol_name(nor->write_proto)); 133 seq_printf(s, " register\t%s\n", 134 spi_nor_protocol_name(nor->reg_proto)); 135 136 seq_puts(s, "\nerase commands\n"); 137 for (i = 0; i < SNOR_ERASE_TYPE_MAX; i++) { 138 struct spi_nor_erase_type *et = &erase_map->erase_type[i]; 139 140 if (et->size) { 141 string_get_size(et->size, 1, STRING_UNITS_2, buf, 142 sizeof(buf)); 143 seq_printf(s, " %02x (%s) [%d]\n", et->opcode, buf, i); 144 } 145 } 146 147 if (!(nor->flags & SNOR_F_NO_OP_CHIP_ERASE)) { 148 string_get_size(params->size, 1, STRING_UNITS_2, buf, sizeof(buf)); 149 seq_printf(s, " %02x (%s)\n", params->die_erase_opcode, buf); 150 } 151 152 seq_puts(s, "\nsector map\n"); 153 seq_puts(s, " region (in hex) | erase mask | overlaid\n"); 154 seq_puts(s, " ------------------+------------+---------\n"); 155 for (i = 0; i < erase_map->n_regions; i++) { 156 u64 start = region[i].offset; 157 u64 end = start + region[i].size - 1; 158 u8 erase_mask = region[i].erase_mask; 159 160 seq_printf(s, " %08llx-%08llx | [%c%c%c%c] | %s\n", 161 start, end, 162 erase_mask & BIT(0) ? '0' : ' ', 163 erase_mask & BIT(1) ? '1' : ' ', 164 erase_mask & BIT(2) ? '2' : ' ', 165 erase_mask & BIT(3) ? '3' : ' ', 166 region[i].overlaid ? "yes" : "no"); 167 } 168 169 if (!spi_nor_has_default_locking_ops(nor)) 170 return 0; 171 172 seq_puts(s, "\nlocked sectors\n"); 173 seq_puts(s, " region (in hex) | status | #sectors\n"); 174 seq_puts(s, " ------------------+----------+---------\n"); 175 176 spi_nor_get_locked_range_sr(nor, nor->dfs_sr_cache, &lock_start, &lock_length); 177 if (!lock_length || lock_length == params->size) { 178 seq_printf(s, " %08llx-%08llx | %s | %llu\n", 0ULL, params->size - 1, 179 lock_length ? " locked" : "unlocked", 180 div_u64(params->size, min_prot_len)); 181 } else if (!lock_start) { 182 seq_printf(s, " %08llx-%08llx | %s | %llu\n", 0ULL, lock_length - 1, 183 " locked", div_u64(lock_length, min_prot_len)); 184 seq_printf(s, " %08llx-%08llx | %s | %llu\n", lock_length, params->size - 1, 185 "unlocked", div_u64(params->size - lock_length, min_prot_len)); 186 } else { 187 seq_printf(s, " %08llx-%08llx | %s | %llu\n", 0ULL, lock_start - 1, 188 "unlocked", div_u64(lock_start, min_prot_len)); 189 seq_printf(s, " %08llx-%08llx | %s | %llu\n", lock_start, params->size - 1, 190 " locked", div_u64(lock_length, min_prot_len)); 191 } 192 193 return 0; 194 } 195 DEFINE_SHOW_ATTRIBUTE(spi_nor_params); 196 197 static int spi_nor_locked_sectors_map_show(struct seq_file *s, void *data) 198 { 199 struct spi_nor *nor = s->private; 200 struct spi_nor_flash_parameter *params = nor->params; 201 u64 min_prot_len = spi_nor_get_min_prot_length_sr(nor); 202 unsigned int sector = 0; 203 u64 offset = 0; 204 bool locked; 205 int i; 206 207 seq_printf(s, "Locked sectors map (x: locked, .: unlocked, unit: %lldkiB)\n", 208 min_prot_len / 1024); 209 while (offset < params->size) { 210 seq_printf(s, " 0x%08llx (#%5d): ", offset, sector); 211 for (i = 0; i < 64 && offset < params->size; i++) { 212 locked = spi_nor_is_locked_sr(nor, offset, min_prot_len, 213 nor->dfs_sr_cache); 214 if (locked) 215 seq_puts(s, "x"); 216 else 217 seq_puts(s, "."); 218 219 if (((i + 1) % 16) == 0) 220 seq_puts(s, " "); 221 222 offset += min_prot_len; 223 sector++; 224 } 225 seq_puts(s, "\n"); 226 } 227 228 return 0; 229 } 230 DEFINE_SHOW_ATTRIBUTE(spi_nor_locked_sectors_map); 231 232 static void spi_nor_print_read_cmd(struct seq_file *s, u32 cap, 233 struct spi_nor_read_command *cmd) 234 { 235 seq_printf(s, " %s%s\n", spi_nor_protocol_name(cmd->proto), 236 cap == SNOR_HWCAPS_READ_FAST ? " (fast read)" : ""); 237 seq_printf(s, " opcode\t0x%02x\n", cmd->opcode); 238 seq_printf(s, " mode cycles\t%u\n", cmd->num_mode_clocks); 239 seq_printf(s, " dummy cycles\t%u\n", cmd->num_wait_states); 240 } 241 242 static void spi_nor_print_pp_cmd(struct seq_file *s, 243 struct spi_nor_pp_command *cmd) 244 { 245 seq_printf(s, " %s\n", spi_nor_protocol_name(cmd->proto)); 246 seq_printf(s, " opcode\t0x%02x\n", cmd->opcode); 247 } 248 249 static int spi_nor_capabilities_show(struct seq_file *s, void *data) 250 { 251 struct spi_nor *nor = s->private; 252 struct spi_nor_flash_parameter *params = nor->params; 253 u32 hwcaps = params->hwcaps.mask; 254 int i, cmd; 255 256 seq_puts(s, "Supported read modes by the flash\n"); 257 for (i = 0; i < sizeof(hwcaps) * BITS_PER_BYTE; i++) { 258 if (!(hwcaps & BIT(i))) 259 continue; 260 261 cmd = spi_nor_hwcaps_read2cmd(BIT(i)); 262 if (cmd < 0) 263 continue; 264 265 spi_nor_print_read_cmd(s, BIT(i), ¶ms->reads[cmd]); 266 hwcaps &= ~BIT(i); 267 } 268 269 seq_puts(s, "\nSupported page program modes by the flash\n"); 270 for (i = 0; i < sizeof(hwcaps) * BITS_PER_BYTE; i++) { 271 if (!(hwcaps & BIT(i))) 272 continue; 273 274 cmd = spi_nor_hwcaps_pp2cmd(BIT(i)); 275 if (cmd < 0) 276 continue; 277 278 spi_nor_print_pp_cmd(s, ¶ms->page_programs[cmd]); 279 hwcaps &= ~BIT(i); 280 } 281 282 if (hwcaps) 283 seq_printf(s, "\nunknown hwcaps 0x%x\n", hwcaps); 284 285 return 0; 286 } 287 DEFINE_SHOW_ATTRIBUTE(spi_nor_capabilities); 288 289 static void spi_nor_debugfs_unregister(void *data) 290 { 291 struct spi_nor *nor = data; 292 293 debugfs_remove(nor->debugfs_root); 294 nor->debugfs_root = NULL; 295 } 296 297 static struct dentry *rootdir; 298 299 void spi_nor_debugfs_register(struct spi_nor *nor) 300 { 301 struct dentry *d; 302 int ret; 303 304 if (!rootdir) 305 rootdir = debugfs_create_dir(SPI_NOR_DEBUGFS_ROOT, NULL); 306 307 ret = devm_add_action(nor->dev, spi_nor_debugfs_unregister, nor); 308 if (ret) 309 return; 310 311 d = debugfs_create_dir(dev_name(nor->dev), rootdir); 312 nor->debugfs_root = d; 313 314 debugfs_create_file("params", 0444, d, nor, &spi_nor_params_fops); 315 debugfs_create_file("capabilities", 0444, d, nor, 316 &spi_nor_capabilities_fops); 317 if (spi_nor_has_default_locking_ops(nor)) 318 debugfs_create_file("locked-sectors-map", 0444, d, nor, 319 &spi_nor_locked_sectors_map_fops); 320 } 321 322 void spi_nor_debugfs_shutdown(void) 323 { 324 debugfs_remove(rootdir); 325 } 326