1ffdb20beSMike Frysinger /* 2ffdb20beSMike Frysinger * Simulate a SPI flash 3ffdb20beSMike Frysinger * 4ffdb20beSMike Frysinger * Copyright (c) 2011-2013 The Chromium OS Authors. 5ffdb20beSMike Frysinger * See file CREDITS for list of people who contributed to this 6ffdb20beSMike Frysinger * project. 7ffdb20beSMike Frysinger * 8ffdb20beSMike Frysinger * Licensed under the GPL-2 or later. 9ffdb20beSMike Frysinger */ 10ffdb20beSMike Frysinger 11ffdb20beSMike Frysinger #include <common.h> 12b6c2956dSSimon Glass #include <dm.h> 13ffdb20beSMike Frysinger #include <malloc.h> 14ffdb20beSMike Frysinger #include <spi.h> 15ffdb20beSMike Frysinger #include <os.h> 16ffdb20beSMike Frysinger 17ffdb20beSMike Frysinger #include <spi_flash.h> 18ffdb20beSMike Frysinger #include "sf_internal.h" 19ffdb20beSMike Frysinger 20ffdb20beSMike Frysinger #include <asm/getopt.h> 21ffdb20beSMike Frysinger #include <asm/spi.h> 22ffdb20beSMike Frysinger #include <asm/state.h> 23b6c2956dSSimon Glass #include <dm/device-internal.h> 24b6c2956dSSimon Glass #include <dm/lists.h> 25b6c2956dSSimon Glass #include <dm/uclass-internal.h> 26b6c2956dSSimon Glass 27b6c2956dSSimon Glass DECLARE_GLOBAL_DATA_PTR; 28ffdb20beSMike Frysinger 29ffdb20beSMike Frysinger /* 30ffdb20beSMike Frysinger * The different states that our SPI flash transitions between. 31ffdb20beSMike Frysinger * We need to keep track of this across multiple xfer calls since 32ffdb20beSMike Frysinger * the SPI bus could possibly call down into us multiple times. 33ffdb20beSMike Frysinger */ 34ffdb20beSMike Frysinger enum sandbox_sf_state { 35ffdb20beSMike Frysinger SF_CMD, /* default state -- we're awaiting a command */ 36ffdb20beSMike Frysinger SF_ID, /* read the flash's (jedec) ID code */ 37ffdb20beSMike Frysinger SF_ADDR, /* processing the offset in the flash to read/etc... */ 38ffdb20beSMike Frysinger SF_READ, /* reading data from the flash */ 39ffdb20beSMike Frysinger SF_WRITE, /* writing data to the flash, i.e. page programming */ 40ffdb20beSMike Frysinger SF_ERASE, /* erase the flash */ 41ffdb20beSMike Frysinger SF_READ_STATUS, /* read the flash's status register */ 42ffdb20beSMike Frysinger SF_READ_STATUS1, /* read the flash's status register upper 8 bits*/ 43b6c2956dSSimon Glass SF_WRITE_STATUS, /* write the flash's status register */ 44ffdb20beSMike Frysinger }; 45ffdb20beSMike Frysinger 46ffdb20beSMike Frysinger static const char *sandbox_sf_state_name(enum sandbox_sf_state state) 47ffdb20beSMike Frysinger { 48ffdb20beSMike Frysinger static const char * const states[] = { 49ffdb20beSMike Frysinger "CMD", "ID", "ADDR", "READ", "WRITE", "ERASE", "READ_STATUS", 50b6c2956dSSimon Glass "READ_STATUS1", "WRITE_STATUS", 51ffdb20beSMike Frysinger }; 52ffdb20beSMike Frysinger return states[state]; 53ffdb20beSMike Frysinger } 54ffdb20beSMike Frysinger 55ffdb20beSMike Frysinger /* Bits for the status register */ 56ffdb20beSMike Frysinger #define STAT_WIP (1 << 0) 57ffdb20beSMike Frysinger #define STAT_WEL (1 << 1) 58ffdb20beSMike Frysinger 59ffdb20beSMike Frysinger /* Assume all SPI flashes have 3 byte addresses since they do atm */ 60ffdb20beSMike Frysinger #define SF_ADDR_LEN 3 61ffdb20beSMike Frysinger 62110bdee0SSimon Glass #define IDCODE_LEN 3 63ffdb20beSMike Frysinger 64ffdb20beSMike Frysinger /* Used to quickly bulk erase backing store */ 65ffdb20beSMike Frysinger static u8 sandbox_sf_0xff[0x1000]; 66ffdb20beSMike Frysinger 67ffdb20beSMike Frysinger /* Internal state data for each SPI flash */ 68ffdb20beSMike Frysinger struct sandbox_spi_flash { 69b6c2956dSSimon Glass unsigned int cs; /* Chip select we are attached to */ 70ffdb20beSMike Frysinger /* 71ffdb20beSMike Frysinger * As we receive data over the SPI bus, our flash transitions 72ffdb20beSMike Frysinger * between states. For example, we start off in the SF_CMD 73ffdb20beSMike Frysinger * state where the first byte tells us what operation to perform 74ffdb20beSMike Frysinger * (such as read or write the flash). But the operation itself 75ffdb20beSMike Frysinger * can go through a few states such as first reading in the 76ffdb20beSMike Frysinger * offset in the flash to perform the requested operation. 77ffdb20beSMike Frysinger * Thus "state" stores the exact state that our machine is in 78ffdb20beSMike Frysinger * while "cmd" stores the overall command we're processing. 79ffdb20beSMike Frysinger */ 80ffdb20beSMike Frysinger enum sandbox_sf_state state; 81ffdb20beSMike Frysinger uint cmd; 82110bdee0SSimon Glass /* Erase size of current erase command */ 83110bdee0SSimon Glass uint erase_size; 84ffdb20beSMike Frysinger /* Current position in the flash; used when reading/writing/etc... */ 85ffdb20beSMike Frysinger uint off; 86ffdb20beSMike Frysinger /* How many address bytes we've consumed */ 87ffdb20beSMike Frysinger uint addr_bytes, pad_addr_bytes; 88ffdb20beSMike Frysinger /* The current flash status (see STAT_XXX defines above) */ 89ffdb20beSMike Frysinger u16 status; 90ffdb20beSMike Frysinger /* Data describing the flash we're emulating */ 91*f790ca7cSJagan Teki const struct spi_flash_info *data; 92ffdb20beSMike Frysinger /* The file on disk to serv up data from */ 93ffdb20beSMike Frysinger int fd; 94ffdb20beSMike Frysinger }; 95ffdb20beSMike Frysinger 96b6c2956dSSimon Glass struct sandbox_spi_flash_plat_data { 97b6c2956dSSimon Glass const char *filename; 98b6c2956dSSimon Glass const char *device_name; 99b6c2956dSSimon Glass int bus; 100b6c2956dSSimon Glass int cs; 101b6c2956dSSimon Glass }; 102b6c2956dSSimon Glass 103b6c2956dSSimon Glass /** 104b6c2956dSSimon Glass * This is a very strange probe function. If it has platform data (which may 105b6c2956dSSimon Glass * have come from the device tree) then this function gets the filename and 106b6c2956dSSimon Glass * device type from there. Failing that it looks at the command line 107b6c2956dSSimon Glass * parameter. 108b6c2956dSSimon Glass */ 109b6c2956dSSimon Glass static int sandbox_sf_probe(struct udevice *dev) 110ffdb20beSMike Frysinger { 111ffdb20beSMike Frysinger /* spec = idcode:file */ 112b6c2956dSSimon Glass struct sandbox_spi_flash *sbsf = dev_get_priv(dev); 113ffdb20beSMike Frysinger const char *file; 114110bdee0SSimon Glass size_t len, idname_len; 115*f790ca7cSJagan Teki const struct spi_flash_info *data; 116b6c2956dSSimon Glass struct sandbox_spi_flash_plat_data *pdata = dev_get_platdata(dev); 117b6c2956dSSimon Glass struct sandbox_state *state = state_get_current(); 118b6c2956dSSimon Glass struct udevice *bus = dev->parent; 119b6c2956dSSimon Glass const char *spec = NULL; 120b6c2956dSSimon Glass int ret = 0; 121b6c2956dSSimon Glass int cs = -1; 122b6c2956dSSimon Glass int i; 123b6c2956dSSimon Glass 124b6c2956dSSimon Glass debug("%s: bus %d, looking for emul=%p: ", __func__, bus->seq, dev); 125b6c2956dSSimon Glass if (bus->seq >= 0 && bus->seq < CONFIG_SANDBOX_SPI_MAX_BUS) { 126b6c2956dSSimon Glass for (i = 0; i < CONFIG_SANDBOX_SPI_MAX_CS; i++) { 127b6c2956dSSimon Glass if (state->spi[bus->seq][i].emul == dev) 128b6c2956dSSimon Glass cs = i; 129b6c2956dSSimon Glass } 130b6c2956dSSimon Glass } 131b6c2956dSSimon Glass if (cs == -1) { 132832adb21SSimon Glass printf("Error: Unknown chip select for device '%s'\n", 133b6c2956dSSimon Glass dev->name); 134b6c2956dSSimon Glass return -EINVAL; 135b6c2956dSSimon Glass } 136b6c2956dSSimon Glass debug("found at cs %d\n", cs); 137b6c2956dSSimon Glass 138b6c2956dSSimon Glass if (!pdata->filename) { 139b6c2956dSSimon Glass struct sandbox_state *state = state_get_current(); 140b6c2956dSSimon Glass 141b6c2956dSSimon Glass assert(bus->seq != -1); 142b6c2956dSSimon Glass if (bus->seq < CONFIG_SANDBOX_SPI_MAX_BUS) 143b6c2956dSSimon Glass spec = state->spi[bus->seq][cs].spec; 1441603bf3cSSimon Glass if (!spec) { 14520f655daSSimon Glass debug("%s: No spec found for bus %d, cs %d\n", 14620f655daSSimon Glass __func__, bus->seq, cs); 1471603bf3cSSimon Glass ret = -ENOENT; 1481603bf3cSSimon Glass goto error; 1491603bf3cSSimon Glass } 150ffdb20beSMike Frysinger 151ffdb20beSMike Frysinger file = strchr(spec, ':'); 152ffdb20beSMike Frysinger if (!file) { 15320f655daSSimon Glass printf("%s: unable to parse file\n", __func__); 154b6c2956dSSimon Glass ret = -EINVAL; 155ffdb20beSMike Frysinger goto error; 156ffdb20beSMike Frysinger } 157ffdb20beSMike Frysinger idname_len = file - spec; 158b6c2956dSSimon Glass pdata->filename = file + 1; 159b6c2956dSSimon Glass pdata->device_name = spec; 160ffdb20beSMike Frysinger ++file; 161b6c2956dSSimon Glass } else { 162b6c2956dSSimon Glass spec = strchr(pdata->device_name, ','); 163b6c2956dSSimon Glass if (spec) 164b6c2956dSSimon Glass spec++; 165b6c2956dSSimon Glass else 166b6c2956dSSimon Glass spec = pdata->device_name; 167b6c2956dSSimon Glass idname_len = strlen(spec); 168b6c2956dSSimon Glass } 169b6c2956dSSimon Glass debug("%s: device='%s'\n", __func__, spec); 170ffdb20beSMike Frysinger 171*f790ca7cSJagan Teki for (data = spi_flash_ids; data->name; data++) { 172ffdb20beSMike Frysinger len = strlen(data->name); 173ffdb20beSMike Frysinger if (idname_len != len) 174ffdb20beSMike Frysinger continue; 175b6c2956dSSimon Glass if (!strncasecmp(spec, data->name, len)) 176ffdb20beSMike Frysinger break; 177ffdb20beSMike Frysinger } 178110bdee0SSimon Glass if (!data->name) { 17920f655daSSimon Glass printf("%s: unknown flash '%*s'\n", __func__, (int)idname_len, 180ffdb20beSMike Frysinger spec); 181b6c2956dSSimon Glass ret = -EINVAL; 182ffdb20beSMike Frysinger goto error; 183ffdb20beSMike Frysinger } 184ffdb20beSMike Frysinger 185ffdb20beSMike Frysinger if (sandbox_sf_0xff[0] == 0x00) 186ffdb20beSMike Frysinger memset(sandbox_sf_0xff, 0xff, sizeof(sandbox_sf_0xff)); 187ffdb20beSMike Frysinger 188b6c2956dSSimon Glass sbsf->fd = os_open(pdata->filename, 02); 189ffdb20beSMike Frysinger if (sbsf->fd == -1) { 19020f655daSSimon Glass printf("%s: unable to open file '%s'\n", __func__, 191b6c2956dSSimon Glass pdata->filename); 192b6c2956dSSimon Glass ret = -EIO; 193ffdb20beSMike Frysinger goto error; 194ffdb20beSMike Frysinger } 195ffdb20beSMike Frysinger 196ffdb20beSMike Frysinger sbsf->data = data; 197b6c2956dSSimon Glass sbsf->cs = cs; 198ffdb20beSMike Frysinger 199ffdb20beSMike Frysinger return 0; 200ffdb20beSMike Frysinger 201ffdb20beSMike Frysinger error: 2021603bf3cSSimon Glass debug("%s: Got error %d\n", __func__, ret); 203b6c2956dSSimon Glass return ret; 204ffdb20beSMike Frysinger } 205ffdb20beSMike Frysinger 206b6c2956dSSimon Glass static int sandbox_sf_remove(struct udevice *dev) 207ffdb20beSMike Frysinger { 208b6c2956dSSimon Glass struct sandbox_spi_flash *sbsf = dev_get_priv(dev); 209ffdb20beSMike Frysinger 210ffdb20beSMike Frysinger os_close(sbsf->fd); 211b6c2956dSSimon Glass 212b6c2956dSSimon Glass return 0; 213ffdb20beSMike Frysinger } 214ffdb20beSMike Frysinger 215b6c2956dSSimon Glass static void sandbox_sf_cs_activate(struct udevice *dev) 216ffdb20beSMike Frysinger { 217b6c2956dSSimon Glass struct sandbox_spi_flash *sbsf = dev_get_priv(dev); 218ffdb20beSMike Frysinger 219ffdb20beSMike Frysinger debug("sandbox_sf: CS activated; state is fresh!\n"); 220ffdb20beSMike Frysinger 221ffdb20beSMike Frysinger /* CS is asserted, so reset state */ 222ffdb20beSMike Frysinger sbsf->off = 0; 223ffdb20beSMike Frysinger sbsf->addr_bytes = 0; 224ffdb20beSMike Frysinger sbsf->pad_addr_bytes = 0; 225ffdb20beSMike Frysinger sbsf->state = SF_CMD; 226ffdb20beSMike Frysinger sbsf->cmd = SF_CMD; 227ffdb20beSMike Frysinger } 228ffdb20beSMike Frysinger 229b6c2956dSSimon Glass static void sandbox_sf_cs_deactivate(struct udevice *dev) 230ffdb20beSMike Frysinger { 231ffdb20beSMike Frysinger debug("sandbox_sf: CS deactivated; cmd done processing!\n"); 232ffdb20beSMike Frysinger } 233ffdb20beSMike Frysinger 234b6c2956dSSimon Glass /* 235b6c2956dSSimon Glass * There are times when the data lines are allowed to tristate. What 236b6c2956dSSimon Glass * is actually sensed on the line depends on the hardware. It could 237b6c2956dSSimon Glass * always be 0xFF/0x00 (if there are pull ups/downs), or things could 238b6c2956dSSimon Glass * float and so we'd get garbage back. This func encapsulates that 239b6c2956dSSimon Glass * scenario so we can worry about the details here. 240b6c2956dSSimon Glass */ 241b6c2956dSSimon Glass static void sandbox_spi_tristate(u8 *buf, uint len) 242b6c2956dSSimon Glass { 243b6c2956dSSimon Glass /* XXX: make this into a user config option ? */ 244b6c2956dSSimon Glass memset(buf, 0xff, len); 245b6c2956dSSimon Glass } 246b6c2956dSSimon Glass 247ffdb20beSMike Frysinger /* Figure out what command this stream is telling us to do */ 248ffdb20beSMike Frysinger static int sandbox_sf_process_cmd(struct sandbox_spi_flash *sbsf, const u8 *rx, 249ffdb20beSMike Frysinger u8 *tx) 250ffdb20beSMike Frysinger { 251ffdb20beSMike Frysinger enum sandbox_sf_state oldstate = sbsf->state; 252ffdb20beSMike Frysinger 253ffdb20beSMike Frysinger /* We need to output a byte for the cmd byte we just ate */ 254b6c2956dSSimon Glass if (tx) 255ffdb20beSMike Frysinger sandbox_spi_tristate(tx, 1); 256ffdb20beSMike Frysinger 257ffdb20beSMike Frysinger sbsf->cmd = rx[0]; 258ffdb20beSMike Frysinger switch (sbsf->cmd) { 259ffdb20beSMike Frysinger case CMD_READ_ID: 260ffdb20beSMike Frysinger sbsf->state = SF_ID; 261ffdb20beSMike Frysinger sbsf->cmd = SF_ID; 262ffdb20beSMike Frysinger break; 263ffdb20beSMike Frysinger case CMD_READ_ARRAY_FAST: 264ffdb20beSMike Frysinger sbsf->pad_addr_bytes = 1; 265ffdb20beSMike Frysinger case CMD_READ_ARRAY_SLOW: 266ffdb20beSMike Frysinger case CMD_PAGE_PROGRAM: 267ffdb20beSMike Frysinger sbsf->state = SF_ADDR; 268ffdb20beSMike Frysinger break; 269ffdb20beSMike Frysinger case CMD_WRITE_DISABLE: 270ffdb20beSMike Frysinger debug(" write disabled\n"); 271ffdb20beSMike Frysinger sbsf->status &= ~STAT_WEL; 272ffdb20beSMike Frysinger break; 273ffdb20beSMike Frysinger case CMD_READ_STATUS: 274ffdb20beSMike Frysinger sbsf->state = SF_READ_STATUS; 275ffdb20beSMike Frysinger break; 276ffdb20beSMike Frysinger case CMD_READ_STATUS1: 277ffdb20beSMike Frysinger sbsf->state = SF_READ_STATUS1; 278ffdb20beSMike Frysinger break; 279ffdb20beSMike Frysinger case CMD_WRITE_ENABLE: 280ffdb20beSMike Frysinger debug(" write enabled\n"); 281ffdb20beSMike Frysinger sbsf->status |= STAT_WEL; 282ffdb20beSMike Frysinger break; 283b6c2956dSSimon Glass case CMD_WRITE_STATUS: 284b6c2956dSSimon Glass sbsf->state = SF_WRITE_STATUS; 285b6c2956dSSimon Glass break; 286ffdb20beSMike Frysinger default: { 287110bdee0SSimon Glass int flags = sbsf->data->flags; 288ffdb20beSMike Frysinger 289110bdee0SSimon Glass /* we only support erase here */ 290110bdee0SSimon Glass if (sbsf->cmd == CMD_ERASE_CHIP) { 291110bdee0SSimon Glass sbsf->erase_size = sbsf->data->sector_size * 292110bdee0SSimon Glass sbsf->data->nr_sectors; 293110bdee0SSimon Glass } else if (sbsf->cmd == CMD_ERASE_4K && (flags & SECT_4K)) { 294110bdee0SSimon Glass sbsf->erase_size = 4 << 10; 295ddc2dfbbSJagan Teki } else if (sbsf->cmd == CMD_ERASE_64K && !(flags & SECT_4K)) { 296110bdee0SSimon Glass sbsf->erase_size = 64 << 10; 297110bdee0SSimon Glass } else { 298ffdb20beSMike Frysinger debug(" cmd unknown: %#x\n", sbsf->cmd); 299b6c2956dSSimon Glass return -EIO; 300ffdb20beSMike Frysinger } 301110bdee0SSimon Glass sbsf->state = SF_ADDR; 302110bdee0SSimon Glass break; 303110bdee0SSimon Glass } 304ffdb20beSMike Frysinger } 305ffdb20beSMike Frysinger 306ffdb20beSMike Frysinger if (oldstate != sbsf->state) 307ffdb20beSMike Frysinger debug(" cmd: transition to %s state\n", 308ffdb20beSMike Frysinger sandbox_sf_state_name(sbsf->state)); 309ffdb20beSMike Frysinger 310ffdb20beSMike Frysinger return 0; 311ffdb20beSMike Frysinger } 312ffdb20beSMike Frysinger 313ffdb20beSMike Frysinger int sandbox_erase_part(struct sandbox_spi_flash *sbsf, int size) 314ffdb20beSMike Frysinger { 315ffdb20beSMike Frysinger int todo; 316ffdb20beSMike Frysinger int ret; 317ffdb20beSMike Frysinger 318ffdb20beSMike Frysinger while (size > 0) { 319b4141195SMasahiro Yamada todo = min(size, (int)sizeof(sandbox_sf_0xff)); 320ffdb20beSMike Frysinger ret = os_write(sbsf->fd, sandbox_sf_0xff, todo); 321ffdb20beSMike Frysinger if (ret != todo) 322ffdb20beSMike Frysinger return ret; 323ffdb20beSMike Frysinger size -= todo; 324ffdb20beSMike Frysinger } 325ffdb20beSMike Frysinger 326ffdb20beSMike Frysinger return 0; 327ffdb20beSMike Frysinger } 328ffdb20beSMike Frysinger 329b6c2956dSSimon Glass static int sandbox_sf_xfer(struct udevice *dev, unsigned int bitlen, 330b6c2956dSSimon Glass const void *rxp, void *txp, unsigned long flags) 331ffdb20beSMike Frysinger { 332b6c2956dSSimon Glass struct sandbox_spi_flash *sbsf = dev_get_priv(dev); 333b6c2956dSSimon Glass const uint8_t *rx = rxp; 334b6c2956dSSimon Glass uint8_t *tx = txp; 335ffdb20beSMike Frysinger uint cnt, pos = 0; 336b6c2956dSSimon Glass int bytes = bitlen / 8; 337ffdb20beSMike Frysinger int ret; 338ffdb20beSMike Frysinger 339ffdb20beSMike Frysinger debug("sandbox_sf: state:%x(%s) bytes:%u\n", sbsf->state, 340ffdb20beSMike Frysinger sandbox_sf_state_name(sbsf->state), bytes); 341ffdb20beSMike Frysinger 342b6c2956dSSimon Glass if ((flags & SPI_XFER_BEGIN)) 343b6c2956dSSimon Glass sandbox_sf_cs_activate(dev); 344b6c2956dSSimon Glass 345ffdb20beSMike Frysinger if (sbsf->state == SF_CMD) { 346ffdb20beSMike Frysinger /* Figure out the initial state */ 347b6c2956dSSimon Glass ret = sandbox_sf_process_cmd(sbsf, rx, tx); 348b6c2956dSSimon Glass if (ret) 349b6c2956dSSimon Glass return ret; 350ffdb20beSMike Frysinger ++pos; 351ffdb20beSMike Frysinger } 352ffdb20beSMike Frysinger 353ffdb20beSMike Frysinger /* Process the remaining data */ 354ffdb20beSMike Frysinger while (pos < bytes) { 355ffdb20beSMike Frysinger switch (sbsf->state) { 356ffdb20beSMike Frysinger case SF_ID: { 357ffdb20beSMike Frysinger u8 id; 358ffdb20beSMike Frysinger 359ffdb20beSMike Frysinger debug(" id: off:%u tx:", sbsf->off); 360110bdee0SSimon Glass if (sbsf->off < IDCODE_LEN) { 361110bdee0SSimon Glass /* Extract correct byte from ID 0x00aabbcc */ 362*f790ca7cSJagan Teki id = ((((sbsf->data)->id[0]) << 16) | 363*f790ca7cSJagan Teki (((sbsf->data)->id[1]) << 8 | 364*f790ca7cSJagan Teki ((sbsf->data)->id[2]))) >> 365110bdee0SSimon Glass (8 * (IDCODE_LEN - 1 - sbsf->off)); 366110bdee0SSimon Glass } else { 367ffdb20beSMike Frysinger id = 0; 368110bdee0SSimon Glass } 369110bdee0SSimon Glass debug("%d %02x\n", sbsf->off, id); 370ffdb20beSMike Frysinger tx[pos++] = id; 371ffdb20beSMike Frysinger ++sbsf->off; 372ffdb20beSMike Frysinger break; 373ffdb20beSMike Frysinger } 374ffdb20beSMike Frysinger case SF_ADDR: 375ffdb20beSMike Frysinger debug(" addr: bytes:%u rx:%02x ", sbsf->addr_bytes, 376ffdb20beSMike Frysinger rx[pos]); 377ffdb20beSMike Frysinger 378ffdb20beSMike Frysinger if (sbsf->addr_bytes++ < SF_ADDR_LEN) 379ffdb20beSMike Frysinger sbsf->off = (sbsf->off << 8) | rx[pos]; 380ffdb20beSMike Frysinger debug("addr:%06x\n", sbsf->off); 381ffdb20beSMike Frysinger 382b6c2956dSSimon Glass if (tx) 383b6c2956dSSimon Glass sandbox_spi_tristate(&tx[pos], 1); 384b6c2956dSSimon Glass pos++; 385ffdb20beSMike Frysinger 386ffdb20beSMike Frysinger /* See if we're done processing */ 387ffdb20beSMike Frysinger if (sbsf->addr_bytes < 388ffdb20beSMike Frysinger SF_ADDR_LEN + sbsf->pad_addr_bytes) 389ffdb20beSMike Frysinger break; 390ffdb20beSMike Frysinger 391ffdb20beSMike Frysinger /* Next state! */ 392ffdb20beSMike Frysinger if (os_lseek(sbsf->fd, sbsf->off, OS_SEEK_SET) < 0) { 393ffdb20beSMike Frysinger puts("sandbox_sf: os_lseek() failed"); 394b6c2956dSSimon Glass return -EIO; 395ffdb20beSMike Frysinger } 396ffdb20beSMike Frysinger switch (sbsf->cmd) { 397ffdb20beSMike Frysinger case CMD_READ_ARRAY_FAST: 398ffdb20beSMike Frysinger case CMD_READ_ARRAY_SLOW: 399ffdb20beSMike Frysinger sbsf->state = SF_READ; 400ffdb20beSMike Frysinger break; 401ffdb20beSMike Frysinger case CMD_PAGE_PROGRAM: 402ffdb20beSMike Frysinger sbsf->state = SF_WRITE; 403ffdb20beSMike Frysinger break; 404ffdb20beSMike Frysinger default: 405ffdb20beSMike Frysinger /* assume erase state ... */ 406ffdb20beSMike Frysinger sbsf->state = SF_ERASE; 407ffdb20beSMike Frysinger goto case_sf_erase; 408ffdb20beSMike Frysinger } 409ffdb20beSMike Frysinger debug(" cmd: transition to %s state\n", 410ffdb20beSMike Frysinger sandbox_sf_state_name(sbsf->state)); 411ffdb20beSMike Frysinger break; 412ffdb20beSMike Frysinger case SF_READ: 413ffdb20beSMike Frysinger /* 414ffdb20beSMike Frysinger * XXX: need to handle exotic behavior: 415ffdb20beSMike Frysinger * - reading past end of device 416ffdb20beSMike Frysinger */ 417ffdb20beSMike Frysinger 418ffdb20beSMike Frysinger cnt = bytes - pos; 419ffdb20beSMike Frysinger debug(" tx: read(%u)\n", cnt); 420b6c2956dSSimon Glass assert(tx); 421ffdb20beSMike Frysinger ret = os_read(sbsf->fd, tx + pos, cnt); 422ffdb20beSMike Frysinger if (ret < 0) { 423b6c2956dSSimon Glass puts("sandbox_sf: os_read() failed\n"); 424b6c2956dSSimon Glass return -EIO; 425ffdb20beSMike Frysinger } 426ffdb20beSMike Frysinger pos += ret; 427ffdb20beSMike Frysinger break; 428ffdb20beSMike Frysinger case SF_READ_STATUS: 429ffdb20beSMike Frysinger debug(" read status: %#x\n", sbsf->status); 430ffdb20beSMike Frysinger cnt = bytes - pos; 431ffdb20beSMike Frysinger memset(tx + pos, sbsf->status, cnt); 432ffdb20beSMike Frysinger pos += cnt; 433ffdb20beSMike Frysinger break; 434ffdb20beSMike Frysinger case SF_READ_STATUS1: 435ffdb20beSMike Frysinger debug(" read status: %#x\n", sbsf->status); 436ffdb20beSMike Frysinger cnt = bytes - pos; 437ffdb20beSMike Frysinger memset(tx + pos, sbsf->status >> 8, cnt); 438ffdb20beSMike Frysinger pos += cnt; 439ffdb20beSMike Frysinger break; 440b6c2956dSSimon Glass case SF_WRITE_STATUS: 441b6c2956dSSimon Glass debug(" write status: %#x (ignored)\n", rx[pos]); 442b6c2956dSSimon Glass pos = bytes; 443b6c2956dSSimon Glass break; 444ffdb20beSMike Frysinger case SF_WRITE: 445ffdb20beSMike Frysinger /* 446ffdb20beSMike Frysinger * XXX: need to handle exotic behavior: 447ffdb20beSMike Frysinger * - unaligned addresses 448ffdb20beSMike Frysinger * - more than a page (256) worth of data 449ffdb20beSMike Frysinger * - reading past end of device 450ffdb20beSMike Frysinger */ 451ffdb20beSMike Frysinger if (!(sbsf->status & STAT_WEL)) { 452ffdb20beSMike Frysinger puts("sandbox_sf: write enable not set before write\n"); 453ffdb20beSMike Frysinger goto done; 454ffdb20beSMike Frysinger } 455ffdb20beSMike Frysinger 456ffdb20beSMike Frysinger cnt = bytes - pos; 457ffdb20beSMike Frysinger debug(" rx: write(%u)\n", cnt); 458b6c2956dSSimon Glass if (tx) 459ffdb20beSMike Frysinger sandbox_spi_tristate(&tx[pos], cnt); 460ffdb20beSMike Frysinger ret = os_write(sbsf->fd, rx + pos, cnt); 461ffdb20beSMike Frysinger if (ret < 0) { 462ffdb20beSMike Frysinger puts("sandbox_spi: os_write() failed\n"); 463b6c2956dSSimon Glass return -EIO; 464ffdb20beSMike Frysinger } 465ffdb20beSMike Frysinger pos += ret; 466ffdb20beSMike Frysinger sbsf->status &= ~STAT_WEL; 467ffdb20beSMike Frysinger break; 468ffdb20beSMike Frysinger case SF_ERASE: 469ffdb20beSMike Frysinger case_sf_erase: { 470ffdb20beSMike Frysinger if (!(sbsf->status & STAT_WEL)) { 471ffdb20beSMike Frysinger puts("sandbox_sf: write enable not set before erase\n"); 472ffdb20beSMike Frysinger goto done; 473ffdb20beSMike Frysinger } 474ffdb20beSMike Frysinger 475ffdb20beSMike Frysinger /* verify address is aligned */ 476110bdee0SSimon Glass if (sbsf->off & (sbsf->erase_size - 1)) { 477ffdb20beSMike Frysinger debug(" sector erase: cmd:%#x needs align:%#x, but we got %#x\n", 478110bdee0SSimon Glass sbsf->cmd, sbsf->erase_size, 479ffdb20beSMike Frysinger sbsf->off); 480ffdb20beSMike Frysinger sbsf->status &= ~STAT_WEL; 481ffdb20beSMike Frysinger goto done; 482ffdb20beSMike Frysinger } 483ffdb20beSMike Frysinger 484110bdee0SSimon Glass debug(" sector erase addr: %u, size: %u\n", sbsf->off, 485110bdee0SSimon Glass sbsf->erase_size); 486ffdb20beSMike Frysinger 487ffdb20beSMike Frysinger cnt = bytes - pos; 488b6c2956dSSimon Glass if (tx) 489ffdb20beSMike Frysinger sandbox_spi_tristate(&tx[pos], cnt); 490ffdb20beSMike Frysinger pos += cnt; 491ffdb20beSMike Frysinger 492ffdb20beSMike Frysinger /* 493ffdb20beSMike Frysinger * TODO(vapier@gentoo.org): latch WIP in status, and 494ffdb20beSMike Frysinger * delay before clearing it ? 495ffdb20beSMike Frysinger */ 496110bdee0SSimon Glass ret = sandbox_erase_part(sbsf, sbsf->erase_size); 497ffdb20beSMike Frysinger sbsf->status &= ~STAT_WEL; 498ffdb20beSMike Frysinger if (ret) { 499ffdb20beSMike Frysinger debug("sandbox_sf: Erase failed\n"); 500ffdb20beSMike Frysinger goto done; 501ffdb20beSMike Frysinger } 502ffdb20beSMike Frysinger goto done; 503ffdb20beSMike Frysinger } 504ffdb20beSMike Frysinger default: 505ffdb20beSMike Frysinger debug(" ??? no idea what to do ???\n"); 506ffdb20beSMike Frysinger goto done; 507ffdb20beSMike Frysinger } 508ffdb20beSMike Frysinger } 509ffdb20beSMike Frysinger 510ffdb20beSMike Frysinger done: 511b6c2956dSSimon Glass if (flags & SPI_XFER_END) 512b6c2956dSSimon Glass sandbox_sf_cs_deactivate(dev); 513b6c2956dSSimon Glass return pos == bytes ? 0 : -EIO; 514ffdb20beSMike Frysinger } 515ffdb20beSMike Frysinger 516b6c2956dSSimon Glass int sandbox_sf_ofdata_to_platdata(struct udevice *dev) 517b6c2956dSSimon Glass { 518b6c2956dSSimon Glass struct sandbox_spi_flash_plat_data *pdata = dev_get_platdata(dev); 519b6c2956dSSimon Glass const void *blob = gd->fdt_blob; 520b6c2956dSSimon Glass int node = dev->of_offset; 521b6c2956dSSimon Glass 522b6c2956dSSimon Glass pdata->filename = fdt_getprop(blob, node, "sandbox,filename", NULL); 523b6c2956dSSimon Glass pdata->device_name = fdt_getprop(blob, node, "compatible", NULL); 524b6c2956dSSimon Glass if (!pdata->filename || !pdata->device_name) { 525b6c2956dSSimon Glass debug("%s: Missing properties, filename=%s, device_name=%s\n", 526b6c2956dSSimon Glass __func__, pdata->filename, pdata->device_name); 527b6c2956dSSimon Glass return -EINVAL; 528b6c2956dSSimon Glass } 529b6c2956dSSimon Glass 530b6c2956dSSimon Glass return 0; 531b6c2956dSSimon Glass } 532b6c2956dSSimon Glass 533b6c2956dSSimon Glass static const struct dm_spi_emul_ops sandbox_sf_emul_ops = { 534ffdb20beSMike Frysinger .xfer = sandbox_sf_xfer, 535ffdb20beSMike Frysinger }; 536ffdb20beSMike Frysinger 537b6c2956dSSimon Glass #ifdef CONFIG_SPI_FLASH 538ffdb20beSMike Frysinger static int sandbox_cmdline_cb_spi_sf(struct sandbox_state *state, 539ffdb20beSMike Frysinger const char *arg) 540ffdb20beSMike Frysinger { 541ffdb20beSMike Frysinger unsigned long bus, cs; 542ffdb20beSMike Frysinger const char *spec = sandbox_spi_parse_spec(arg, &bus, &cs); 543ffdb20beSMike Frysinger 544ffdb20beSMike Frysinger if (!spec) 545ffdb20beSMike Frysinger return 1; 546ffdb20beSMike Frysinger 547ffdb20beSMike Frysinger /* 548ffdb20beSMike Frysinger * It is safe to not make a copy of 'spec' because it comes from the 549ffdb20beSMike Frysinger * command line. 550ffdb20beSMike Frysinger * 551ffdb20beSMike Frysinger * TODO(sjg@chromium.org): It would be nice if we could parse the 552ffdb20beSMike Frysinger * spec here, but the problem is that no U-Boot init has been done 553ffdb20beSMike Frysinger * yet. Perhaps we can figure something out. 554ffdb20beSMike Frysinger */ 555ffdb20beSMike Frysinger state->spi[bus][cs].spec = spec; 55620f655daSSimon Glass debug("%s: Setting up spec '%s' for bus %ld, cs %ld\n", __func__, 55720f655daSSimon Glass spec, bus, cs); 55820f655daSSimon Glass 559ffdb20beSMike Frysinger return 0; 560ffdb20beSMike Frysinger } 561ffdb20beSMike Frysinger SANDBOX_CMDLINE_OPT(spi_sf, 1, "connect a SPI flash: <bus>:<cs>:<id>:<file>"); 562b6c2956dSSimon Glass 563b6c2956dSSimon Glass int sandbox_sf_bind_emul(struct sandbox_state *state, int busnum, int cs, 564b6c2956dSSimon Glass struct udevice *bus, int of_offset, const char *spec) 565b6c2956dSSimon Glass { 566b6c2956dSSimon Glass struct udevice *emul; 567b6c2956dSSimon Glass char name[20], *str; 568b6c2956dSSimon Glass struct driver *drv; 569b6c2956dSSimon Glass int ret; 570b6c2956dSSimon Glass 571b6c2956dSSimon Glass /* now the emulator */ 572b6c2956dSSimon Glass strncpy(name, spec, sizeof(name) - 6); 573b6c2956dSSimon Glass name[sizeof(name) - 6] = '\0'; 574b6c2956dSSimon Glass strcat(name, "-emul"); 575b6c2956dSSimon Glass str = strdup(name); 576b6c2956dSSimon Glass if (!str) 577b6c2956dSSimon Glass return -ENOMEM; 578b6c2956dSSimon Glass drv = lists_driver_lookup_name("sandbox_sf_emul"); 579b6c2956dSSimon Glass if (!drv) { 580b6c2956dSSimon Glass puts("Cannot find sandbox_sf_emul driver\n"); 581b6c2956dSSimon Glass return -ENOENT; 582b6c2956dSSimon Glass } 583b6c2956dSSimon Glass ret = device_bind(bus, drv, str, NULL, of_offset, &emul); 584b6c2956dSSimon Glass if (ret) { 585b6c2956dSSimon Glass printf("Cannot create emul device for spec '%s' (err=%d)\n", 586b6c2956dSSimon Glass spec, ret); 587b6c2956dSSimon Glass return ret; 588b6c2956dSSimon Glass } 589b6c2956dSSimon Glass state->spi[busnum][cs].emul = emul; 590b6c2956dSSimon Glass 591b6c2956dSSimon Glass return 0; 592b6c2956dSSimon Glass } 593b6c2956dSSimon Glass 594b6c2956dSSimon Glass void sandbox_sf_unbind_emul(struct sandbox_state *state, int busnum, int cs) 595b6c2956dSSimon Glass { 596d0cff03eSSimon Glass struct udevice *dev; 597d0cff03eSSimon Glass 598d0cff03eSSimon Glass dev = state->spi[busnum][cs].emul; 599d0cff03eSSimon Glass device_remove(dev); 600d0cff03eSSimon Glass device_unbind(dev); 601b6c2956dSSimon Glass state->spi[busnum][cs].emul = NULL; 602b6c2956dSSimon Glass } 603b6c2956dSSimon Glass 604b6c2956dSSimon Glass static int sandbox_sf_bind_bus_cs(struct sandbox_state *state, int busnum, 605b6c2956dSSimon Glass int cs, const char *spec) 606b6c2956dSSimon Glass { 607b6c2956dSSimon Glass struct udevice *bus, *slave; 608b6c2956dSSimon Glass int ret; 609b6c2956dSSimon Glass 610b6c2956dSSimon Glass ret = uclass_find_device_by_seq(UCLASS_SPI, busnum, true, &bus); 611b6c2956dSSimon Glass if (ret) { 612b6c2956dSSimon Glass printf("Invalid bus %d for spec '%s' (err=%d)\n", busnum, 613b6c2956dSSimon Glass spec, ret); 614b6c2956dSSimon Glass return ret; 615b6c2956dSSimon Glass } 616ff56bba2SSimon Glass ret = spi_find_chip_select(bus, cs, &slave); 617b6c2956dSSimon Glass if (!ret) { 618b6c2956dSSimon Glass printf("Chip select %d already exists for spec '%s'\n", cs, 619b6c2956dSSimon Glass spec); 620b6c2956dSSimon Glass return -EEXIST; 621b6c2956dSSimon Glass } 622b6c2956dSSimon Glass 6236b18656aSSimon Glass ret = device_bind_driver(bus, "spi_flash_std", spec, &slave); 624b6c2956dSSimon Glass if (ret) 625b6c2956dSSimon Glass return ret; 626b6c2956dSSimon Glass 627b6c2956dSSimon Glass return sandbox_sf_bind_emul(state, busnum, cs, bus, -1, spec); 628b6c2956dSSimon Glass } 629b6c2956dSSimon Glass 630b6c2956dSSimon Glass int sandbox_spi_get_emul(struct sandbox_state *state, 631b6c2956dSSimon Glass struct udevice *bus, struct udevice *slave, 632b6c2956dSSimon Glass struct udevice **emulp) 633b6c2956dSSimon Glass { 634b6c2956dSSimon Glass struct sandbox_spi_info *info; 635b6c2956dSSimon Glass int busnum = bus->seq; 636b6c2956dSSimon Glass int cs = spi_chip_select(slave); 637b6c2956dSSimon Glass int ret; 638b6c2956dSSimon Glass 639b6c2956dSSimon Glass info = &state->spi[busnum][cs]; 640b6c2956dSSimon Glass if (!info->emul) { 641b6c2956dSSimon Glass /* Use the same device tree node as the SPI flash device */ 642b6c2956dSSimon Glass debug("%s: busnum=%u, cs=%u: binding SPI flash emulation: ", 643b6c2956dSSimon Glass __func__, busnum, cs); 644b6c2956dSSimon Glass ret = sandbox_sf_bind_emul(state, busnum, cs, bus, 645b6c2956dSSimon Glass slave->of_offset, slave->name); 646b6c2956dSSimon Glass if (ret) { 647b6c2956dSSimon Glass debug("failed (err=%d)\n", ret); 648b6c2956dSSimon Glass return ret; 649b6c2956dSSimon Glass } 650b6c2956dSSimon Glass debug("OK\n"); 651b6c2956dSSimon Glass } 652b6c2956dSSimon Glass *emulp = info->emul; 653b6c2956dSSimon Glass 654b6c2956dSSimon Glass return 0; 655b6c2956dSSimon Glass } 656b6c2956dSSimon Glass 657b6c2956dSSimon Glass int dm_scan_other(bool pre_reloc_only) 658b6c2956dSSimon Glass { 659b6c2956dSSimon Glass struct sandbox_state *state = state_get_current(); 660b6c2956dSSimon Glass int busnum, cs; 661b6c2956dSSimon Glass 662b6c2956dSSimon Glass if (pre_reloc_only) 663b6c2956dSSimon Glass return 0; 664b6c2956dSSimon Glass for (busnum = 0; busnum < CONFIG_SANDBOX_SPI_MAX_BUS; busnum++) { 665b6c2956dSSimon Glass for (cs = 0; cs < CONFIG_SANDBOX_SPI_MAX_CS; cs++) { 666b6c2956dSSimon Glass const char *spec = state->spi[busnum][cs].spec; 667b6c2956dSSimon Glass int ret; 668b6c2956dSSimon Glass 669b6c2956dSSimon Glass if (spec) { 670b6c2956dSSimon Glass ret = sandbox_sf_bind_bus_cs(state, busnum, 671b6c2956dSSimon Glass cs, spec); 672b6c2956dSSimon Glass if (ret) { 673b6c2956dSSimon Glass debug("%s: Bind failed for bus %d, cs %d\n", 674b6c2956dSSimon Glass __func__, busnum, cs); 675b6c2956dSSimon Glass return ret; 676b6c2956dSSimon Glass } 67720f655daSSimon Glass debug("%s: Setting up spec '%s' for bus %d, cs %d\n", 67820f655daSSimon Glass __func__, spec, busnum, cs); 679b6c2956dSSimon Glass } 680b6c2956dSSimon Glass } 681b6c2956dSSimon Glass } 682b6c2956dSSimon Glass 683b6c2956dSSimon Glass return 0; 684b6c2956dSSimon Glass } 685b6c2956dSSimon Glass #endif 686b6c2956dSSimon Glass 687b6c2956dSSimon Glass static const struct udevice_id sandbox_sf_ids[] = { 688b6c2956dSSimon Glass { .compatible = "sandbox,spi-flash" }, 689b6c2956dSSimon Glass { } 690b6c2956dSSimon Glass }; 691b6c2956dSSimon Glass 692b6c2956dSSimon Glass U_BOOT_DRIVER(sandbox_sf_emul) = { 693b6c2956dSSimon Glass .name = "sandbox_sf_emul", 694b6c2956dSSimon Glass .id = UCLASS_SPI_EMUL, 695b6c2956dSSimon Glass .of_match = sandbox_sf_ids, 696b6c2956dSSimon Glass .ofdata_to_platdata = sandbox_sf_ofdata_to_platdata, 697b6c2956dSSimon Glass .probe = sandbox_sf_probe, 698b6c2956dSSimon Glass .remove = sandbox_sf_remove, 699b6c2956dSSimon Glass .priv_auto_alloc_size = sizeof(struct sandbox_spi_flash), 700b6c2956dSSimon Glass .platdata_auto_alloc_size = sizeof(struct sandbox_spi_flash_plat_data), 701b6c2956dSSimon Glass .ops = &sandbox_sf_emul_ops, 702b6c2956dSSimon Glass }; 703