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