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