static int sandbox_spi_xfer(struct udevice *slave, unsigned int bitlen, const void *dout, void *din, unsigned long flags) { struct udevice *bus = slave->parent; struct sandbox_state *state = state_get_current(); struct dm_spi_emul_ops *ops; struct udevice *emul; uint bytes = bitlen / 8, i; int ret; u8 *tx = (void *)dout, *rx = din; uint busnum, cs; if (bitlen == 0) return 0; /* we can only do 8 bit transfers */ if (bitlen % 8) { printf("sandbox_spi: xfer: invalid bitlen size %u; needs to be 8bit\n", bitlen); return -EINVAL; } busnum = bus->seq; cs = spi_chip_select(slave); if (busnum >= CONFIG_SANDBOX_SPI_MAX_BUS || cs >= CONFIG_SANDBOX_SPI_MAX_CS) { printf("%s: busnum=%u, cs=%u: out of range\n", __func__, busnum, cs); return -ENOENT; } ret = sandbox_spi_get_emul(state, bus, slave, &emul); if (ret) { printf("%s: busnum=%u, cs=%u: no emulation available (err=%d)\n", __func__, busnum, cs, ret); return -ENOENT; } ret = device_probe(emul); if (ret) return ret; /* make sure rx/tx buffers are full so clients can assume */ if (!tx) { debug("sandbox_spi: xfer: auto-allocating tx scratch buffer\n"); tx = malloc(bytes); if (!tx) { debug("sandbox_spi: Out of memory\n"); return -ENOMEM; } } if (!rx) { debug("sandbox_spi: xfer: auto-allocating rx scratch buffer\n"); rx = malloc(bytes); if (!rx) { debug("sandbox_spi: Out of memory\n"); return -ENOMEM; } } ops = spi_emul_get_ops(emul); ret = ops->xfer(emul, bitlen, dout, din, flags); debug("sandbox_spi: xfer: got back %i (that's %s)\n rx:", ret, ret ? "bad" : "good"); for (i = 0; i < bytes; ++i) debug(" %u:%02x", i, rx[i]); debug("\n"); if (tx != dout) free(tx); if (rx != din) free(rx); return ret; }
/** * 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. */ static int sandbox_sf_probe(struct udevice *dev) { /* spec = idcode:file */ struct sandbox_spi_flash *sbsf = dev_get_priv(dev); size_t len, idname_len; 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; debug("%s: bus %d, looking for emul=%p: ", __func__, bus->seq, dev); 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) { 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_nor_ids; data->name; data++) { len = strlen(data->name); if (idname_len != len) continue; if (!strncasecmp(spec, data->name, len)) break; } if (!data->name) { printf("%s: unknown flash '%*s'\n", __func__, (int)idname_len, spec); ret = -EINVAL; goto error; } if (sandbox_sf_0xff[0] == 0x00) memset(sandbox_sf_0xff, 0xff, sizeof(sandbox_sf_0xff)); sbsf->fd = os_open(pdata->filename, 02); if (sbsf->fd == -1) { printf("%s: unable to open file '%s'\n", __func__, pdata->filename); ret = -EIO; goto error; } sbsf->data = data; sbsf->cs = cs; return 0; error: debug("%s: Got error %d\n", __func__, ret); return ret; }