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 = erase_map->regions; 82 const struct flash_info *info = nor->info; 83 char buf[16], *str; 84 unsigned 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 | overlaid\n"); 146 seq_puts(s, " ------------------+------------+----------\n"); 147 for (i = 0; i < erase_map->n_regions; i++) { 148 u64 start = region[i].offset; 149 u64 end = start + region[i].size - 1; 150 u8 erase_mask = region[i].erase_mask; 151 152 seq_printf(s, " %08llx-%08llx | [%c%c%c%c] | %s\n", 153 start, end, 154 erase_mask & BIT(0) ? '0' : ' ', 155 erase_mask & BIT(1) ? '1' : ' ', 156 erase_mask & BIT(2) ? '2' : ' ', 157 erase_mask & BIT(3) ? '3' : ' ', 158 region[i].overlaid ? "yes" : "no"); 159 } 160 161 return 0; 162 } 163 DEFINE_SHOW_ATTRIBUTE(spi_nor_params); 164 165 static void spi_nor_print_read_cmd(struct seq_file *s, u32 cap, 166 struct spi_nor_read_command *cmd) 167 { 168 seq_printf(s, " %s%s\n", spi_nor_protocol_name(cmd->proto), 169 cap == SNOR_HWCAPS_READ_FAST ? " (fast read)" : ""); 170 seq_printf(s, " opcode\t0x%02x\n", cmd->opcode); 171 seq_printf(s, " mode cycles\t%u\n", cmd->num_mode_clocks); 172 seq_printf(s, " dummy cycles\t%u\n", cmd->num_wait_states); 173 } 174 175 static void spi_nor_print_pp_cmd(struct seq_file *s, 176 struct spi_nor_pp_command *cmd) 177 { 178 seq_printf(s, " %s\n", spi_nor_protocol_name(cmd->proto)); 179 seq_printf(s, " opcode\t0x%02x\n", cmd->opcode); 180 } 181 182 static int spi_nor_capabilities_show(struct seq_file *s, void *data) 183 { 184 struct spi_nor *nor = s->private; 185 struct spi_nor_flash_parameter *params = nor->params; 186 u32 hwcaps = params->hwcaps.mask; 187 int i, cmd; 188 189 seq_puts(s, "Supported read modes by the flash\n"); 190 for (i = 0; i < sizeof(hwcaps) * BITS_PER_BYTE; i++) { 191 if (!(hwcaps & BIT(i))) 192 continue; 193 194 cmd = spi_nor_hwcaps_read2cmd(BIT(i)); 195 if (cmd < 0) 196 continue; 197 198 spi_nor_print_read_cmd(s, BIT(i), ¶ms->reads[cmd]); 199 hwcaps &= ~BIT(i); 200 } 201 202 seq_puts(s, "\nSupported page program modes by the flash\n"); 203 for (i = 0; i < sizeof(hwcaps) * BITS_PER_BYTE; i++) { 204 if (!(hwcaps & BIT(i))) 205 continue; 206 207 cmd = spi_nor_hwcaps_pp2cmd(BIT(i)); 208 if (cmd < 0) 209 continue; 210 211 spi_nor_print_pp_cmd(s, ¶ms->page_programs[cmd]); 212 hwcaps &= ~BIT(i); 213 } 214 215 if (hwcaps) 216 seq_printf(s, "\nunknown hwcaps 0x%x\n", hwcaps); 217 218 return 0; 219 } 220 DEFINE_SHOW_ATTRIBUTE(spi_nor_capabilities); 221 222 static void spi_nor_debugfs_unregister(void *data) 223 { 224 struct spi_nor *nor = data; 225 226 debugfs_remove(nor->debugfs_root); 227 nor->debugfs_root = NULL; 228 } 229 230 static struct dentry *rootdir; 231 232 void spi_nor_debugfs_register(struct spi_nor *nor) 233 { 234 struct dentry *d; 235 int ret; 236 237 if (!rootdir) 238 rootdir = debugfs_create_dir(SPI_NOR_DEBUGFS_ROOT, NULL); 239 240 ret = devm_add_action(nor->dev, spi_nor_debugfs_unregister, nor); 241 if (ret) 242 return; 243 244 d = debugfs_create_dir(dev_name(nor->dev), rootdir); 245 nor->debugfs_root = d; 246 247 debugfs_create_file("params", 0444, d, nor, &spi_nor_params_fops); 248 debugfs_create_file("capabilities", 0444, d, nor, 249 &spi_nor_capabilities_fops); 250 } 251 252 void spi_nor_debugfs_shutdown(void) 253 { 254 debugfs_remove(rootdir); 255 } 256