1 /* 2 * Simulate a SPI flash 3 * 4 * Copyright (c) 2011-2013 The Chromium OS Authors. 5 * See file CREDITS for list of people who contributed to this 6 * project. 7 * 8 * Licensed under the GPL-2 or later. 9 */ 10 11 #include <common.h> 12 #include <malloc.h> 13 #include <spi.h> 14 #include <os.h> 15 16 #include <spi_flash.h> 17 #include "sf_internal.h" 18 19 #include <asm/getopt.h> 20 #include <asm/spi.h> 21 #include <asm/state.h> 22 23 /* 24 * The different states that our SPI flash transitions between. 25 * We need to keep track of this across multiple xfer calls since 26 * the SPI bus could possibly call down into us multiple times. 27 */ 28 enum sandbox_sf_state { 29 SF_CMD, /* default state -- we're awaiting a command */ 30 SF_ID, /* read the flash's (jedec) ID code */ 31 SF_ADDR, /* processing the offset in the flash to read/etc... */ 32 SF_READ, /* reading data from the flash */ 33 SF_WRITE, /* writing data to the flash, i.e. page programming */ 34 SF_ERASE, /* erase the flash */ 35 SF_READ_STATUS, /* read the flash's status register */ 36 SF_READ_STATUS1, /* read the flash's status register upper 8 bits*/ 37 }; 38 39 static const char *sandbox_sf_state_name(enum sandbox_sf_state state) 40 { 41 static const char * const states[] = { 42 "CMD", "ID", "ADDR", "READ", "WRITE", "ERASE", "READ_STATUS", 43 }; 44 return states[state]; 45 } 46 47 /* Bits for the status register */ 48 #define STAT_WIP (1 << 0) 49 #define STAT_WEL (1 << 1) 50 51 /* Assume all SPI flashes have 3 byte addresses since they do atm */ 52 #define SF_ADDR_LEN 3 53 54 #define IDCODE_LEN 3 55 56 /* Used to quickly bulk erase backing store */ 57 static u8 sandbox_sf_0xff[0x1000]; 58 59 /* Internal state data for each SPI flash */ 60 struct sandbox_spi_flash { 61 /* 62 * As we receive data over the SPI bus, our flash transitions 63 * between states. For example, we start off in the SF_CMD 64 * state where the first byte tells us what operation to perform 65 * (such as read or write the flash). But the operation itself 66 * can go through a few states such as first reading in the 67 * offset in the flash to perform the requested operation. 68 * Thus "state" stores the exact state that our machine is in 69 * while "cmd" stores the overall command we're processing. 70 */ 71 enum sandbox_sf_state state; 72 uint cmd; 73 /* Erase size of current erase command */ 74 uint erase_size; 75 /* Current position in the flash; used when reading/writing/etc... */ 76 uint off; 77 /* How many address bytes we've consumed */ 78 uint addr_bytes, pad_addr_bytes; 79 /* The current flash status (see STAT_XXX defines above) */ 80 u16 status; 81 /* Data describing the flash we're emulating */ 82 const struct spi_flash_params *data; 83 /* The file on disk to serv up data from */ 84 int fd; 85 }; 86 87 static int sandbox_sf_setup(void **priv, const char *spec) 88 { 89 /* spec = idcode:file */ 90 struct sandbox_spi_flash *sbsf; 91 const char *file; 92 size_t len, idname_len; 93 const struct spi_flash_params *data; 94 95 file = strchr(spec, ':'); 96 if (!file) { 97 printf("sandbox_sf: unable to parse file\n"); 98 goto error; 99 } 100 idname_len = file - spec; 101 ++file; 102 103 for (data = spi_flash_params_table; data->name; data++) { 104 len = strlen(data->name); 105 if (idname_len != len) 106 continue; 107 if (!memcmp(spec, data->name, len)) 108 break; 109 } 110 if (!data->name) { 111 printf("sandbox_sf: unknown flash '%*s'\n", (int)idname_len, 112 spec); 113 goto error; 114 } 115 116 if (sandbox_sf_0xff[0] == 0x00) 117 memset(sandbox_sf_0xff, 0xff, sizeof(sandbox_sf_0xff)); 118 119 sbsf = calloc(sizeof(*sbsf), 1); 120 if (!sbsf) { 121 printf("sandbox_sf: out of memory\n"); 122 goto error; 123 } 124 125 sbsf->fd = os_open(file, 02); 126 if (sbsf->fd == -1) { 127 free(sbsf); 128 printf("sandbox_sf: unable to open file '%s'\n", file); 129 goto error; 130 } 131 132 sbsf->data = data; 133 134 *priv = sbsf; 135 return 0; 136 137 error: 138 return 1; 139 } 140 141 static void sandbox_sf_free(void *priv) 142 { 143 struct sandbox_spi_flash *sbsf = priv; 144 145 os_close(sbsf->fd); 146 free(sbsf); 147 } 148 149 static void sandbox_sf_cs_activate(void *priv) 150 { 151 struct sandbox_spi_flash *sbsf = priv; 152 153 debug("sandbox_sf: CS activated; state is fresh!\n"); 154 155 /* CS is asserted, so reset state */ 156 sbsf->off = 0; 157 sbsf->addr_bytes = 0; 158 sbsf->pad_addr_bytes = 0; 159 sbsf->state = SF_CMD; 160 sbsf->cmd = SF_CMD; 161 } 162 163 static void sandbox_sf_cs_deactivate(void *priv) 164 { 165 debug("sandbox_sf: CS deactivated; cmd done processing!\n"); 166 } 167 168 /* Figure out what command this stream is telling us to do */ 169 static int sandbox_sf_process_cmd(struct sandbox_spi_flash *sbsf, const u8 *rx, 170 u8 *tx) 171 { 172 enum sandbox_sf_state oldstate = sbsf->state; 173 174 /* We need to output a byte for the cmd byte we just ate */ 175 sandbox_spi_tristate(tx, 1); 176 177 sbsf->cmd = rx[0]; 178 switch (sbsf->cmd) { 179 case CMD_READ_ID: 180 sbsf->state = SF_ID; 181 sbsf->cmd = SF_ID; 182 break; 183 case CMD_READ_ARRAY_FAST: 184 sbsf->pad_addr_bytes = 1; 185 case CMD_READ_ARRAY_SLOW: 186 case CMD_PAGE_PROGRAM: 187 sbsf->state = SF_ADDR; 188 break; 189 case CMD_WRITE_DISABLE: 190 debug(" write disabled\n"); 191 sbsf->status &= ~STAT_WEL; 192 break; 193 case CMD_READ_STATUS: 194 sbsf->state = SF_READ_STATUS; 195 break; 196 case CMD_READ_STATUS1: 197 sbsf->state = SF_READ_STATUS1; 198 break; 199 case CMD_WRITE_ENABLE: 200 debug(" write enabled\n"); 201 sbsf->status |= STAT_WEL; 202 break; 203 default: { 204 int flags = sbsf->data->flags; 205 206 /* we only support erase here */ 207 if (sbsf->cmd == CMD_ERASE_CHIP) { 208 sbsf->erase_size = sbsf->data->sector_size * 209 sbsf->data->nr_sectors; 210 } else if (sbsf->cmd == CMD_ERASE_4K && (flags & SECT_4K)) { 211 sbsf->erase_size = 4 << 10; 212 } else if (sbsf->cmd == CMD_ERASE_32K && (flags & SECT_32K)) { 213 sbsf->erase_size = 32 << 10; 214 } else if (sbsf->cmd == CMD_ERASE_64K && 215 !(flags & (SECT_4K | SECT_32K))) { 216 sbsf->erase_size = 64 << 10; 217 } else { 218 debug(" cmd unknown: %#x\n", sbsf->cmd); 219 return 1; 220 } 221 sbsf->state = SF_ADDR; 222 break; 223 } 224 } 225 226 if (oldstate != sbsf->state) 227 debug(" cmd: transition to %s state\n", 228 sandbox_sf_state_name(sbsf->state)); 229 230 return 0; 231 } 232 233 int sandbox_erase_part(struct sandbox_spi_flash *sbsf, int size) 234 { 235 int todo; 236 int ret; 237 238 while (size > 0) { 239 todo = min(size, sizeof(sandbox_sf_0xff)); 240 ret = os_write(sbsf->fd, sandbox_sf_0xff, todo); 241 if (ret != todo) 242 return ret; 243 size -= todo; 244 } 245 246 return 0; 247 } 248 249 static int sandbox_sf_xfer(void *priv, const u8 *rx, u8 *tx, 250 uint bytes) 251 { 252 struct sandbox_spi_flash *sbsf = priv; 253 uint cnt, pos = 0; 254 int ret; 255 256 debug("sandbox_sf: state:%x(%s) bytes:%u\n", sbsf->state, 257 sandbox_sf_state_name(sbsf->state), bytes); 258 259 if (sbsf->state == SF_CMD) { 260 /* Figure out the initial state */ 261 if (sandbox_sf_process_cmd(sbsf, rx, tx)) 262 return 1; 263 ++pos; 264 } 265 266 /* Process the remaining data */ 267 while (pos < bytes) { 268 switch (sbsf->state) { 269 case SF_ID: { 270 u8 id; 271 272 debug(" id: off:%u tx:", sbsf->off); 273 if (sbsf->off < IDCODE_LEN) { 274 /* Extract correct byte from ID 0x00aabbcc */ 275 id = sbsf->data->jedec >> 276 (8 * (IDCODE_LEN - 1 - sbsf->off)); 277 } else { 278 id = 0; 279 } 280 debug("%d %02x\n", sbsf->off, id); 281 tx[pos++] = id; 282 ++sbsf->off; 283 break; 284 } 285 case SF_ADDR: 286 debug(" addr: bytes:%u rx:%02x ", sbsf->addr_bytes, 287 rx[pos]); 288 289 if (sbsf->addr_bytes++ < SF_ADDR_LEN) 290 sbsf->off = (sbsf->off << 8) | rx[pos]; 291 debug("addr:%06x\n", sbsf->off); 292 293 sandbox_spi_tristate(&tx[pos++], 1); 294 295 /* See if we're done processing */ 296 if (sbsf->addr_bytes < 297 SF_ADDR_LEN + sbsf->pad_addr_bytes) 298 break; 299 300 /* Next state! */ 301 if (os_lseek(sbsf->fd, sbsf->off, OS_SEEK_SET) < 0) { 302 puts("sandbox_sf: os_lseek() failed"); 303 return 1; 304 } 305 switch (sbsf->cmd) { 306 case CMD_READ_ARRAY_FAST: 307 case CMD_READ_ARRAY_SLOW: 308 sbsf->state = SF_READ; 309 break; 310 case CMD_PAGE_PROGRAM: 311 sbsf->state = SF_WRITE; 312 break; 313 default: 314 /* assume erase state ... */ 315 sbsf->state = SF_ERASE; 316 goto case_sf_erase; 317 } 318 debug(" cmd: transition to %s state\n", 319 sandbox_sf_state_name(sbsf->state)); 320 break; 321 case SF_READ: 322 /* 323 * XXX: need to handle exotic behavior: 324 * - reading past end of device 325 */ 326 327 cnt = bytes - pos; 328 debug(" tx: read(%u)\n", cnt); 329 ret = os_read(sbsf->fd, tx + pos, cnt); 330 if (ret < 0) { 331 puts("sandbox_spi: os_read() failed\n"); 332 return 1; 333 } 334 pos += ret; 335 break; 336 case SF_READ_STATUS: 337 debug(" read status: %#x\n", sbsf->status); 338 cnt = bytes - pos; 339 memset(tx + pos, sbsf->status, cnt); 340 pos += cnt; 341 break; 342 case SF_READ_STATUS1: 343 debug(" read status: %#x\n", sbsf->status); 344 cnt = bytes - pos; 345 memset(tx + pos, sbsf->status >> 8, cnt); 346 pos += cnt; 347 break; 348 case SF_WRITE: 349 /* 350 * XXX: need to handle exotic behavior: 351 * - unaligned addresses 352 * - more than a page (256) worth of data 353 * - reading past end of device 354 */ 355 if (!(sbsf->status & STAT_WEL)) { 356 puts("sandbox_sf: write enable not set before write\n"); 357 goto done; 358 } 359 360 cnt = bytes - pos; 361 debug(" rx: write(%u)\n", cnt); 362 sandbox_spi_tristate(&tx[pos], cnt); 363 ret = os_write(sbsf->fd, rx + pos, cnt); 364 if (ret < 0) { 365 puts("sandbox_spi: os_write() failed\n"); 366 return 1; 367 } 368 pos += ret; 369 sbsf->status &= ~STAT_WEL; 370 break; 371 case SF_ERASE: 372 case_sf_erase: { 373 if (!(sbsf->status & STAT_WEL)) { 374 puts("sandbox_sf: write enable not set before erase\n"); 375 goto done; 376 } 377 378 /* verify address is aligned */ 379 if (sbsf->off & (sbsf->erase_size - 1)) { 380 debug(" sector erase: cmd:%#x needs align:%#x, but we got %#x\n", 381 sbsf->cmd, sbsf->erase_size, 382 sbsf->off); 383 sbsf->status &= ~STAT_WEL; 384 goto done; 385 } 386 387 debug(" sector erase addr: %u, size: %u\n", sbsf->off, 388 sbsf->erase_size); 389 390 cnt = bytes - pos; 391 sandbox_spi_tristate(&tx[pos], cnt); 392 pos += cnt; 393 394 /* 395 * TODO(vapier@gentoo.org): latch WIP in status, and 396 * delay before clearing it ? 397 */ 398 ret = sandbox_erase_part(sbsf, sbsf->erase_size); 399 sbsf->status &= ~STAT_WEL; 400 if (ret) { 401 debug("sandbox_sf: Erase failed\n"); 402 goto done; 403 } 404 goto done; 405 } 406 default: 407 debug(" ??? no idea what to do ???\n"); 408 goto done; 409 } 410 } 411 412 done: 413 return pos == bytes ? 0 : 1; 414 } 415 416 static const struct sandbox_spi_emu_ops sandbox_sf_ops = { 417 .setup = sandbox_sf_setup, 418 .free = sandbox_sf_free, 419 .cs_activate = sandbox_sf_cs_activate, 420 .cs_deactivate = sandbox_sf_cs_deactivate, 421 .xfer = sandbox_sf_xfer, 422 }; 423 424 static int sandbox_cmdline_cb_spi_sf(struct sandbox_state *state, 425 const char *arg) 426 { 427 unsigned long bus, cs; 428 const char *spec = sandbox_spi_parse_spec(arg, &bus, &cs); 429 430 if (!spec) 431 return 1; 432 433 /* 434 * It is safe to not make a copy of 'spec' because it comes from the 435 * command line. 436 * 437 * TODO(sjg@chromium.org): It would be nice if we could parse the 438 * spec here, but the problem is that no U-Boot init has been done 439 * yet. Perhaps we can figure something out. 440 */ 441 state->spi[bus][cs].ops = &sandbox_sf_ops; 442 state->spi[bus][cs].spec = spec; 443 return 0; 444 } 445 SANDBOX_CMDLINE_OPT(spi_sf, 1, "connect a SPI flash: <bus>:<cs>:<id>:<file>"); 446