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