X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=drivers%2Fmtd%2Fspi%2Fsandbox.c;h=084c66e9840b43c06b8b8b2a14182d0011a577b6;hb=b3192f48c19c15d37ba69722b2846de4b73b27cd;hp=1cf2f98310a17493a5a99cce29caa652cb9aabd1;hpb=1fba907f9a8d178eee960294ecffc8ee8bc6b00d;p=oweals%2Fu-boot.git diff --git a/drivers/mtd/spi/sandbox.c b/drivers/mtd/spi/sandbox.c index 1cf2f98310..084c66e984 100644 --- a/drivers/mtd/spi/sandbox.c +++ b/drivers/mtd/spi/sandbox.c @@ -8,6 +8,8 @@ * Licensed under the GPL-2 or later. */ +#define LOG_CATEGORY UCLASS_SPI_FLASH + #include #include #include @@ -24,8 +26,6 @@ #include #include -DECLARE_GLOBAL_DATA_PTR; - /* * The different states that our SPI flash transitions between. * We need to keep track of this across multiple xfer calls since @@ -43,6 +43,7 @@ enum sandbox_sf_state { SF_WRITE_STATUS, /* write the flash's status register */ }; +#if CONFIG_IS_ENABLED(LOG) static const char *sandbox_sf_state_name(enum sandbox_sf_state state) { static const char * const states[] = { @@ -51,10 +52,13 @@ static const char *sandbox_sf_state_name(enum sandbox_sf_state state) }; return states[state]; } +#endif /* LOG */ /* Bits for the status register */ #define STAT_WIP (1 << 0) #define STAT_WEL (1 << 1) +#define STAT_BP_SHIFT 2 +#define STAT_BP_MASK (7 << STAT_BP_SHIFT) /* Assume all SPI flashes have 3 byte addresses since they do atm */ #define SF_ADDR_LEN 3 @@ -88,7 +92,7 @@ struct sandbox_spi_flash { /* The current flash status (see STAT_XXX defines above) */ u16 status; /* Data describing the flash we're emulating */ - const struct spi_flash_params *data; + const struct flash_info *data; /* The file on disk to serv up data from */ int fd; }; @@ -100,71 +104,58 @@ struct sandbox_spi_flash_plat_data { int cs; }; +void sandbox_sf_set_block_protect(struct udevice *dev, int bp_mask) +{ + struct sandbox_spi_flash *sbsf = dev_get_priv(dev); + + sbsf->status &= ~STAT_BP_MASK; + sbsf->status |= bp_mask << STAT_BP_SHIFT; +} + /** * This is a very strange probe function. If it has platform data (which may * have come from the device tree) then this function gets the filename and - * device type from there. Failing that it looks at the command line - * parameter. + * device type from there. */ static int sandbox_sf_probe(struct udevice *dev) { /* spec = idcode:file */ struct sandbox_spi_flash *sbsf = dev_get_priv(dev); - const char *file; size_t len, idname_len; - const struct spi_flash_params *data; + const struct flash_info *data; struct sandbox_spi_flash_plat_data *pdata = dev_get_platdata(dev); struct sandbox_state *state = state_get_current(); + struct dm_spi_slave_platdata *slave_plat; struct udevice *bus = dev->parent; const char *spec = NULL; + struct udevice *emul; int ret = 0; int cs = -1; - int i; debug("%s: bus %d, looking for emul=%p: ", __func__, bus->seq, dev); - if (bus->seq >= 0 && bus->seq < CONFIG_SANDBOX_SPI_MAX_BUS) { - for (i = 0; i < CONFIG_SANDBOX_SPI_MAX_CS; i++) { - if (state->spi[bus->seq][i].emul == dev) - cs = i; - } - } - if (cs == -1) { - printf("Error: Unknown chip select for device '%s'", - dev->name); - return -EINVAL; + ret = sandbox_spi_get_emul(state, bus, dev, &emul); + if (ret) { + printf("Error: Unknown chip select for device '%s'\n", + dev->name); + return ret; } + slave_plat = dev_get_parent_platdata(dev); + cs = slave_plat->cs; debug("found at cs %d\n", cs); if (!pdata->filename) { - struct sandbox_state *state = state_get_current(); - - assert(bus->seq != -1); - if (bus->seq < CONFIG_SANDBOX_SPI_MAX_BUS) - spec = state->spi[bus->seq][cs].spec; - if (!spec) - return -ENOENT; - - file = strchr(spec, ':'); - if (!file) { - printf("sandbox_sf: unable to parse file\n"); - ret = -EINVAL; - goto error; - } - idname_len = file - spec; - pdata->filename = file + 1; - pdata->device_name = spec; - ++file; - } else { - spec = strchr(pdata->device_name, ','); - if (spec) - spec++; - else - spec = pdata->device_name; - idname_len = strlen(spec); + printf("Error: No filename available\n"); + return -EINVAL; } + spec = strchr(pdata->device_name, ','); + if (spec) + spec++; + else + spec = pdata->device_name; + idname_len = strlen(spec); debug("%s: device='%s'\n", __func__, spec); - for (data = spi_flash_params_table; data->name; data++) { + for (data = spi_nor_ids; data->name; data++) { len = strlen(data->name); if (idname_len != len) continue; @@ -172,7 +163,7 @@ static int sandbox_sf_probe(struct udevice *dev) break; } if (!data->name) { - printf("sandbox_sf: unknown flash '%*s'\n", (int)idname_len, + printf("%s: unknown flash '%*s'\n", __func__, (int)idname_len, spec); ret = -EINVAL; goto error; @@ -183,8 +174,7 @@ static int sandbox_sf_probe(struct udevice *dev) sbsf->fd = os_open(pdata->filename, 02); if (sbsf->fd == -1) { - free(sbsf); - printf("sandbox_sf: unable to open file '%s'\n", + printf("%s: unable to open file '%s'\n", __func__, pdata->filename); ret = -EIO; goto error; @@ -196,6 +186,7 @@ static int sandbox_sf_probe(struct udevice *dev) return 0; error: + debug("%s: Got error %d\n", __func__, ret); return ret; } @@ -212,7 +203,7 @@ static void sandbox_sf_cs_activate(struct udevice *dev) { struct sandbox_spi_flash *sbsf = dev_get_priv(dev); - debug("sandbox_sf: CS activated; state is fresh!\n"); + log_content("sandbox_sf: CS activated; state is fresh!\n"); /* CS is asserted, so reset state */ sbsf->off = 0; @@ -224,7 +215,7 @@ static void sandbox_sf_cs_activate(struct udevice *dev) static void sandbox_sf_cs_deactivate(struct udevice *dev) { - debug("sandbox_sf: CS deactivated; cmd done processing!\n"); + log_content("sandbox_sf: CS deactivated; cmd done processing!\n"); } /* @@ -252,46 +243,43 @@ static int sandbox_sf_process_cmd(struct sandbox_spi_flash *sbsf, const u8 *rx, sbsf->cmd = rx[0]; switch (sbsf->cmd) { - case CMD_READ_ID: + case SPINOR_OP_RDID: sbsf->state = SF_ID; sbsf->cmd = SF_ID; break; - case CMD_READ_ARRAY_FAST: + case SPINOR_OP_READ_FAST: sbsf->pad_addr_bytes = 1; - case CMD_READ_ARRAY_SLOW: - case CMD_PAGE_PROGRAM: + case SPINOR_OP_READ: + case SPINOR_OP_PP: sbsf->state = SF_ADDR; break; - case CMD_WRITE_DISABLE: + case SPINOR_OP_WRDI: debug(" write disabled\n"); sbsf->status &= ~STAT_WEL; break; - case CMD_READ_STATUS: + case SPINOR_OP_RDSR: sbsf->state = SF_READ_STATUS; break; - case CMD_READ_STATUS1: + case SPINOR_OP_RDSR2: sbsf->state = SF_READ_STATUS1; break; - case CMD_WRITE_ENABLE: + case SPINOR_OP_WREN: debug(" write enabled\n"); sbsf->status |= STAT_WEL; break; - case CMD_WRITE_STATUS: + case SPINOR_OP_WRSR: sbsf->state = SF_WRITE_STATUS; break; default: { int flags = sbsf->data->flags; /* we only support erase here */ - if (sbsf->cmd == CMD_ERASE_CHIP) { + if (sbsf->cmd == SPINOR_OP_CHIP_ERASE) { sbsf->erase_size = sbsf->data->sector_size * - sbsf->data->nr_sectors; - } else if (sbsf->cmd == CMD_ERASE_4K && (flags & SECT_4K)) { + sbsf->data->n_sectors; + } else if (sbsf->cmd == SPINOR_OP_BE_4K && (flags & SECT_4K)) { sbsf->erase_size = 4 << 10; - } else if (sbsf->cmd == CMD_ERASE_32K && (flags & SECT_32K)) { - sbsf->erase_size = 32 << 10; - } else if (sbsf->cmd == CMD_ERASE_64K && - !(flags & (SECT_4K | SECT_32K))) { + } else if (sbsf->cmd == SPINOR_OP_SE && !(flags & SECT_4K)) { sbsf->erase_size = 64 << 10; } else { debug(" cmd unknown: %#x\n", sbsf->cmd); @@ -303,8 +291,8 @@ static int sandbox_sf_process_cmd(struct sandbox_spi_flash *sbsf, const u8 *rx, } if (oldstate != sbsf->state) - debug(" cmd: transition to %s state\n", - sandbox_sf_state_name(sbsf->state)); + log_content(" cmd: transition to %s state\n", + sandbox_sf_state_name(sbsf->state)); return 0; } @@ -315,7 +303,7 @@ int sandbox_erase_part(struct sandbox_spi_flash *sbsf, int size) int ret; while (size > 0) { - todo = min(size, sizeof(sandbox_sf_0xff)); + todo = min(size, (int)sizeof(sandbox_sf_0xff)); ret = os_write(sbsf->fd, sandbox_sf_0xff, todo); if (ret != todo) return ret; @@ -335,8 +323,8 @@ static int sandbox_sf_xfer(struct udevice *dev, unsigned int bitlen, int bytes = bitlen / 8; int ret; - debug("sandbox_sf: state:%x(%s) bytes:%u\n", sbsf->state, - sandbox_sf_state_name(sbsf->state), bytes); + log_content("sandbox_sf: state:%x(%s) bytes:%u\n", sbsf->state, + sandbox_sf_state_name(sbsf->state), bytes); if ((flags & SPI_XFER_BEGIN)) sandbox_sf_cs_activate(dev); @@ -355,26 +343,27 @@ static int sandbox_sf_xfer(struct udevice *dev, unsigned int bitlen, case SF_ID: { u8 id; - debug(" id: off:%u tx:", sbsf->off); + log_content(" id: off:%u tx:", sbsf->off); if (sbsf->off < IDCODE_LEN) { /* Extract correct byte from ID 0x00aabbcc */ - id = sbsf->data->jedec >> + id = ((JEDEC_MFR(sbsf->data) << 16) | + JEDEC_ID(sbsf->data)) >> (8 * (IDCODE_LEN - 1 - sbsf->off)); } else { id = 0; } - debug("%d %02x\n", sbsf->off, id); + log_content("%d %02x\n", sbsf->off, id); tx[pos++] = id; ++sbsf->off; break; } case SF_ADDR: - debug(" addr: bytes:%u rx:%02x ", sbsf->addr_bytes, - rx[pos]); + log_content(" addr: bytes:%u rx:%02x ", + sbsf->addr_bytes, rx[pos]); if (sbsf->addr_bytes++ < SF_ADDR_LEN) sbsf->off = (sbsf->off << 8) | rx[pos]; - debug("addr:%06x\n", sbsf->off); + log_content("addr:%06x\n", sbsf->off); if (tx) sandbox_spi_tristate(&tx[pos], 1); @@ -391,11 +380,11 @@ static int sandbox_sf_xfer(struct udevice *dev, unsigned int bitlen, return -EIO; } switch (sbsf->cmd) { - case CMD_READ_ARRAY_FAST: - case CMD_READ_ARRAY_SLOW: + case SPINOR_OP_READ_FAST: + case SPINOR_OP_READ: sbsf->state = SF_READ; break; - case CMD_PAGE_PROGRAM: + case SPINOR_OP_PP: sbsf->state = SF_WRITE; break; default: @@ -403,8 +392,8 @@ static int sandbox_sf_xfer(struct udevice *dev, unsigned int bitlen, sbsf->state = SF_ERASE; goto case_sf_erase; } - debug(" cmd: transition to %s state\n", - sandbox_sf_state_name(sbsf->state)); + log_content(" cmd: transition to %s state\n", + sandbox_sf_state_name(sbsf->state)); break; case SF_READ: /* @@ -413,7 +402,7 @@ static int sandbox_sf_xfer(struct udevice *dev, unsigned int bitlen, */ cnt = bytes - pos; - debug(" tx: read(%u)\n", cnt); + log_content(" tx: read(%u)\n", cnt); assert(tx); ret = os_read(sbsf->fd, tx + pos, cnt); if (ret < 0) { @@ -423,19 +412,19 @@ static int sandbox_sf_xfer(struct udevice *dev, unsigned int bitlen, pos += ret; break; case SF_READ_STATUS: - debug(" read status: %#x\n", sbsf->status); + log_content(" read status: %#x\n", sbsf->status); cnt = bytes - pos; memset(tx + pos, sbsf->status, cnt); pos += cnt; break; case SF_READ_STATUS1: - debug(" read status: %#x\n", sbsf->status); + log_content(" read status: %#x\n", sbsf->status); cnt = bytes - pos; memset(tx + pos, sbsf->status >> 8, cnt); pos += cnt; break; case SF_WRITE_STATUS: - debug(" write status: %#x (ignored)\n", rx[pos]); + log_content(" write status: %#x (ignored)\n", rx[pos]); pos = bytes; break; case SF_WRITE: @@ -451,7 +440,7 @@ static int sandbox_sf_xfer(struct udevice *dev, unsigned int bitlen, } cnt = bytes - pos; - debug(" rx: write(%u)\n", cnt); + log_content(" rx: write(%u)\n", cnt); if (tx) sandbox_spi_tristate(&tx[pos], cnt); ret = os_write(sbsf->fd, rx + pos, cnt); @@ -471,15 +460,15 @@ static int sandbox_sf_xfer(struct udevice *dev, unsigned int bitlen, /* verify address is aligned */ if (sbsf->off & (sbsf->erase_size - 1)) { - debug(" sector erase: cmd:%#x needs align:%#x, but we got %#x\n", - sbsf->cmd, sbsf->erase_size, - sbsf->off); + log_content(" sector erase: cmd:%#x needs align:%#x, but we got %#x\n", + sbsf->cmd, sbsf->erase_size, + sbsf->off); sbsf->status &= ~STAT_WEL; goto done; } - debug(" sector erase addr: %u, size: %u\n", sbsf->off, - sbsf->erase_size); + log_content(" sector erase addr: %u, size: %u\n", + sbsf->off, sbsf->erase_size); cnt = bytes - pos; if (tx) @@ -493,13 +482,13 @@ static int sandbox_sf_xfer(struct udevice *dev, unsigned int bitlen, ret = sandbox_erase_part(sbsf, sbsf->erase_size); sbsf->status &= ~STAT_WEL; if (ret) { - debug("sandbox_sf: Erase failed\n"); + log_content("sandbox_sf: Erase failed\n"); goto done; } goto done; } default: - debug(" ??? no idea what to do ???\n"); + log_content(" ??? no idea what to do ???\n"); goto done; } } @@ -513,11 +502,9 @@ static int sandbox_sf_xfer(struct udevice *dev, unsigned int bitlen, int sandbox_sf_ofdata_to_platdata(struct udevice *dev) { struct sandbox_spi_flash_plat_data *pdata = dev_get_platdata(dev); - const void *blob = gd->fdt_blob; - int node = dev->of_offset; - pdata->filename = fdt_getprop(blob, node, "sandbox,filename", NULL); - pdata->device_name = fdt_getprop(blob, node, "compatible", NULL); + pdata->filename = dev_read_string(dev, "sandbox,filename"); + pdata->device_name = dev_read_string(dev, "compatible"); if (!pdata->filename || !pdata->device_name) { debug("%s: Missing properties, filename=%s, device_name=%s\n", __func__, pdata->filename, pdata->device_name); @@ -532,30 +519,8 @@ static const struct dm_spi_emul_ops sandbox_sf_emul_ops = { }; #ifdef CONFIG_SPI_FLASH -static int sandbox_cmdline_cb_spi_sf(struct sandbox_state *state, - const char *arg) -{ - unsigned long bus, cs; - const char *spec = sandbox_spi_parse_spec(arg, &bus, &cs); - - if (!spec) - return 1; - - /* - * It is safe to not make a copy of 'spec' because it comes from the - * command line. - * - * TODO(sjg@chromium.org): It would be nice if we could parse the - * spec here, but the problem is that no U-Boot init has been done - * yet. Perhaps we can figure something out. - */ - state->spi[bus][cs].spec = spec; - return 0; -} -SANDBOX_CMDLINE_OPT(spi_sf, 1, "connect a SPI flash: :::"); - int sandbox_sf_bind_emul(struct sandbox_state *state, int busnum, int cs, - struct udevice *bus, int of_offset, const char *spec) + struct udevice *bus, ofnode node, const char *spec) { struct udevice *emul; char name[20], *str; @@ -566,16 +531,17 @@ int sandbox_sf_bind_emul(struct sandbox_state *state, int busnum, int cs, strncpy(name, spec, sizeof(name) - 6); name[sizeof(name) - 6] = '\0'; strcat(name, "-emul"); - str = strdup(name); - if (!str) - return -ENOMEM; drv = lists_driver_lookup_name("sandbox_sf_emul"); if (!drv) { puts("Cannot find sandbox_sf_emul driver\n"); return -ENOENT; } - ret = device_bind(bus, drv, str, NULL, of_offset, &emul); + str = strdup(name); + if (!str) + return -ENOMEM; + ret = device_bind_ofnode(bus, drv, str, NULL, node, &emul); if (ret) { + free(str); printf("Cannot create emul device for spec '%s' (err=%d)\n", spec, ret); return ret; @@ -587,33 +553,12 @@ int sandbox_sf_bind_emul(struct sandbox_state *state, int busnum, int cs, void sandbox_sf_unbind_emul(struct sandbox_state *state, int busnum, int cs) { - state->spi[busnum][cs].emul = NULL; -} - -static int sandbox_sf_bind_bus_cs(struct sandbox_state *state, int busnum, - int cs, const char *spec) -{ - struct udevice *bus, *slave; - int ret; - - ret = uclass_find_device_by_seq(UCLASS_SPI, busnum, true, &bus); - if (ret) { - printf("Invalid bus %d for spec '%s' (err=%d)\n", busnum, - spec, ret); - return ret; - } - ret = device_find_child_by_seq(bus, cs, true, &slave); - if (!ret) { - printf("Chip select %d already exists for spec '%s'\n", cs, - spec); - return -EEXIST; - } - - ret = spi_bind_device(bus, cs, "spi_flash_std", spec, &slave); - if (ret) - return ret; + struct udevice *dev; - return sandbox_sf_bind_emul(state, busnum, cs, bus, -1, spec); + dev = state->spi[busnum][cs].emul; + device_remove(dev, DM_REMOVE_NORMAL); + device_unbind(dev); + state->spi[busnum][cs].emul = NULL; } int sandbox_spi_get_emul(struct sandbox_state *state, @@ -631,7 +576,7 @@ int sandbox_spi_get_emul(struct sandbox_state *state, debug("%s: busnum=%u, cs=%u: binding SPI flash emulation: ", __func__, busnum, cs); ret = sandbox_sf_bind_emul(state, busnum, cs, bus, - slave->of_offset, slave->name); + dev_ofnode(slave), slave->name); if (ret) { debug("failed (err=%d)\n", ret); return ret; @@ -642,33 +587,6 @@ int sandbox_spi_get_emul(struct sandbox_state *state, return 0; } - -int dm_scan_other(bool pre_reloc_only) -{ - struct sandbox_state *state = state_get_current(); - int busnum, cs; - - if (pre_reloc_only) - return 0; - for (busnum = 0; busnum < CONFIG_SANDBOX_SPI_MAX_BUS; busnum++) { - for (cs = 0; cs < CONFIG_SANDBOX_SPI_MAX_CS; cs++) { - const char *spec = state->spi[busnum][cs].spec; - int ret; - - if (spec) { - ret = sandbox_sf_bind_bus_cs(state, busnum, - cs, spec); - if (ret) { - debug("%s: Bind failed for bus %d, cs %d\n", - __func__, busnum, cs); - return ret; - } - } - } - } - - return 0; -} #endif static const struct udevice_id sandbox_sf_ids[] = {