1 // SPDX-License-Identifier: GPL-2.0 2 3 #include <linux/array_size.h> 4 #include <linux/debugfs.h> 5 #include <linux/mtd/spi-nor.h> 6 #include <linux/spi/spi.h> 7 #include <linux/spi/spi-mem.h> 8 9 #include "core.h" 10 11 #define SPI_NOR_DEBUGFS_ROOT "spi-nor" 12 13 #define SNOR_F_NAME(name) [ilog2(SNOR_F_##name)] = #name 14 static const char *const snor_f_names[] = { 15 SNOR_F_NAME(HAS_SR_TB), 16 SNOR_F_NAME(NO_OP_CHIP_ERASE), 17 SNOR_F_NAME(BROKEN_RESET), 18 SNOR_F_NAME(4B_OPCODES), 19 SNOR_F_NAME(HAS_4BAIT), 20 SNOR_F_NAME(HAS_LOCK), 21 SNOR_F_NAME(HAS_16BIT_SR), 22 SNOR_F_NAME(NO_READ_CR), 23 SNOR_F_NAME(HAS_SR_TB_BIT6), 24 SNOR_F_NAME(HAS_4BIT_BP), 25 SNOR_F_NAME(HAS_SR_BP3_BIT6), 26 SNOR_F_NAME(IO_MODE_EN_VOLATILE), 27 SNOR_F_NAME(SOFT_RESET), 28 SNOR_F_NAME(SWP_IS_VOLATILE), 29 SNOR_F_NAME(RWW), 30 SNOR_F_NAME(ECC), 31 SNOR_F_NAME(NO_WP), 32 }; 33 #undef SNOR_F_NAME 34 35 static const char *spi_nor_protocol_name(enum spi_nor_protocol proto) 36 { 37 switch (proto) { 38 case SNOR_PROTO_1_1_1: return "1S-1S-1S"; 39 case SNOR_PROTO_1_1_2: return "1S-1S-2S"; 40 case SNOR_PROTO_1_1_4: return "1S-1S-4S"; 41 case SNOR_PROTO_1_1_8: return "1S-1S-8S"; 42 case SNOR_PROTO_1_2_2: return "1S-2S-2S"; 43 case SNOR_PROTO_1_4_4: return "1S-4S-4S"; 44 case SNOR_PROTO_1_8_8: return "1S-8S-8S"; 45 case SNOR_PROTO_2_2_2: return "2S-2S-2S"; 46 case SNOR_PROTO_4_4_4: return "4S-4S-4S"; 47 case SNOR_PROTO_8_8_8: return "8S-8S-8S"; 48 case SNOR_PROTO_1_1_1_DTR: return "1D-1D-1D"; 49 case SNOR_PROTO_1_2_2_DTR: return "1D-2D-2D"; 50 case SNOR_PROTO_1_4_4_DTR: return "1D-4D-4D"; 51 case SNOR_PROTO_1_8_8_DTR: return "1D-8D-8D"; 52 case SNOR_PROTO_8_8_8_DTR: return "8D-8D-8D"; 53 } 54 55 return "<unknown>"; 56 } 57 58 static void spi_nor_print_flags(struct seq_file *s, unsigned long flags, 59 const char *const *names, int names_len) 60 { 61 bool sep = false; 62 int i; 63 64 for (i = 0; i < sizeof(flags) * BITS_PER_BYTE; i++) { 65 if (!(flags & BIT(i))) 66 continue; 67 if (sep) 68 seq_puts(s, " | "); 69 sep = true; 70 if (i < names_len && names[i]) 71 seq_puts(s, names[i]); 72 else 73 seq_printf(s, "1<<%d", i); 74 } 75 } 76 77 static int spi_nor_params_show(struct seq_file *s, void *data) 78 { 79 struct spi_nor *nor = s->private; 80 struct spi_nor_flash_parameter *params = nor->params; 81 struct spi_nor_erase_map *erase_map = ¶ms->erase_map; 82 struct spi_nor_erase_region *region = erase_map->regions; 83 const struct flash_info *info = nor->info; 84 char buf[16], *str; 85 unsigned int i; 86 87 seq_printf(s, "name\t\t%s\n", info->name); 88 seq_printf(s, "id\t\t%*ph\n", SPI_NOR_MAX_ID_LEN, nor->id); 89 string_get_size(params->size, 1, STRING_UNITS_2, buf, sizeof(buf)); 90 seq_printf(s, "size\t\t%s\n", buf); 91 seq_printf(s, "write size\t%u\n", params->writesize); 92 seq_printf(s, "page size\t%u\n", params->page_size); 93 seq_printf(s, "address nbytes\t%u\n", nor->addr_nbytes); 94 95 seq_puts(s, "flags\t\t"); 96 spi_nor_print_flags(s, nor->flags, snor_f_names, 97 ARRAY_SIZE(snor_f_names)); 98 seq_puts(s, "\n"); 99 100 seq_puts(s, "\nopcodes\n"); 101 seq_printf(s, " read\t\t0x%02x\n", nor->read_opcode); 102 seq_printf(s, " dummy cycles\t%u\n", nor->read_dummy); 103 seq_printf(s, " erase\t\t0x%02x\n", nor->erase_opcode); 104 seq_printf(s, " program\t0x%02x\n", nor->program_opcode); 105 106 switch (nor->cmd_ext_type) { 107 case SPI_NOR_EXT_NONE: 108 str = "none"; 109 break; 110 case SPI_NOR_EXT_REPEAT: 111 str = "repeat"; 112 break; 113 case SPI_NOR_EXT_INVERT: 114 str = "invert"; 115 break; 116 default: 117 str = "<unknown>"; 118 break; 119 } 120 seq_printf(s, " 8D extension\t%s\n", str); 121 122 seq_puts(s, "\nprotocols\n"); 123 seq_printf(s, " read\t\t%s\n", 124 spi_nor_protocol_name(nor->read_proto)); 125 seq_printf(s, " write\t\t%s\n", 126 spi_nor_protocol_name(nor->write_proto)); 127 seq_printf(s, " register\t%s\n", 128 spi_nor_protocol_name(nor->reg_proto)); 129 130 seq_puts(s, "\nerase commands\n"); 131 for (i = 0; i < SNOR_ERASE_TYPE_MAX; i++) { 132 struct spi_nor_erase_type *et = &erase_map->erase_type[i]; 133 134 if (et->size) { 135 string_get_size(et->size, 1, STRING_UNITS_2, buf, 136 sizeof(buf)); 137 seq_printf(s, " %02x (%s) [%d]\n", et->opcode, buf, i); 138 } 139 } 140 141 if (!(nor->flags & SNOR_F_NO_OP_CHIP_ERASE)) { 142 string_get_size(params->size, 1, STRING_UNITS_2, buf, sizeof(buf)); 143 seq_printf(s, " %02x (%s)\n", nor->params->die_erase_opcode, buf); 144 } 145 146 seq_puts(s, "\nsector map\n"); 147 seq_puts(s, " region (in hex) | erase mask | overlaid\n"); 148 seq_puts(s, " ------------------+------------+----------\n"); 149 for (i = 0; i < erase_map->n_regions; i++) { 150 u64 start = region[i].offset; 151 u64 end = start + region[i].size - 1; 152 u8 erase_mask = region[i].erase_mask; 153 154 seq_printf(s, " %08llx-%08llx | [%c%c%c%c] | %s\n", 155 start, end, 156 erase_mask & BIT(0) ? '0' : ' ', 157 erase_mask & BIT(1) ? '1' : ' ', 158 erase_mask & BIT(2) ? '2' : ' ', 159 erase_mask & BIT(3) ? '3' : ' ', 160 region[i].overlaid ? "yes" : "no"); 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