Skip to content

Commit

Permalink
spi: Add support for memory-mapped flash
Browse files Browse the repository at this point in the history
On x86 platforms the SPI flash can be mapped into memory so that the
contents can be read with normal memory accesses.

Add a new SPI method to find the location of the SPI flash in memory. This
differs from the existing device-tree "memory-map" mechanism in that the
location can be discovered at run-time.

Signed-off-by: Simon Glass <[email protected]>
Reviewed-by: Bin Meng <[email protected]>
  • Loading branch information
sjg20 authored and lbmeng committed Nov 2, 2019
1 parent e1500a6 commit c53b318
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 0 deletions.
11 changes: 11 additions & 0 deletions drivers/spi/sandbox_spi.c
Original file line number Diff line number Diff line change
Expand Up @@ -122,11 +122,22 @@ static int sandbox_cs_info(struct udevice *bus, uint cs,
return 0;
}

static int sandbox_spi_get_mmap(struct udevice *dev, ulong *map_basep,
uint *map_sizep, uint *offsetp)
{
*map_basep = 0x1000;
*map_sizep = 0x2000;
*offsetp = 0x100;

return 0;
}

static const struct dm_spi_ops sandbox_spi_ops = {
.xfer = sandbox_spi_xfer,
.set_speed = sandbox_spi_set_speed,
.set_mode = sandbox_spi_set_mode,
.cs_info = sandbox_cs_info,
.get_mmap = sandbox_spi_get_mmap,
};

static const struct udevice_id sandbox_spi_ids[] = {
Expand Down
14 changes: 14 additions & 0 deletions drivers/spi/spi-uclass.c
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,20 @@ int dm_spi_xfer(struct udevice *dev, unsigned int bitlen,
return spi_get_ops(bus)->xfer(dev, bitlen, dout, din, flags);
}

int dm_spi_get_mmap(struct udevice *dev, ulong *map_basep, uint *map_sizep,
uint *offsetp)
{
struct udevice *bus = dev->parent;
struct dm_spi_ops *ops = spi_get_ops(bus);

if (bus->uclass->uc_drv->id != UCLASS_SPI)
return -EOPNOTSUPP;
if (!ops->get_mmap)
return -ENOSYS;

return ops->get_mmap(dev, map_basep, map_sizep, offsetp);
}

int spi_claim_bus(struct spi_slave *slave)
{
return log_ret(dm_spi_claim_bus(slave->dev));
Expand Down
27 changes: 27 additions & 0 deletions include/spi.h
Original file line number Diff line number Diff line change
Expand Up @@ -462,6 +462,19 @@ struct dm_spi_ops {
* is invalid, other -ve value on error
*/
int (*cs_info)(struct udevice *bus, uint cs, struct spi_cs_info *info);

/**
* get_mmap() - Get memory-mapped SPI
*
* @dev: The SPI flash slave device
* @map_basep: Returns base memory address for mapped SPI
* @map_sizep: Returns size of mapped SPI
* @offsetp: Returns start offset of SPI flash where the map works
* correctly (offsets before this are not visible)
* @return 0 if OK, -EFAULT if memory mapping is not available
*/
int (*get_mmap)(struct udevice *dev, ulong *map_basep,
uint *map_sizep, uint *offsetp);
};

struct dm_spi_emul_ops {
Expand Down Expand Up @@ -650,6 +663,20 @@ void dm_spi_release_bus(struct udevice *dev);
int dm_spi_xfer(struct udevice *dev, unsigned int bitlen,
const void *dout, void *din, unsigned long flags);

/**
* spi_get_mmap() - Get memory-mapped SPI
*
* @dev: SPI slave device to check
* @map_basep: Returns base memory address for mapped SPI
* @map_sizep: Returns size of mapped SPI
* @offsetp: Returns start offset of SPI flash where the map works
* correctly (offsets before this are not visible)
* @return 0 if OK, -ENOSYS if no operation, -EFAULT if memory mapping is not
* available
*/
int dm_spi_get_mmap(struct udevice *dev, ulong *map_basep, uint *map_sizep,
uint *offsetp);

/* Access the operations for a SPI device */
#define spi_get_ops(dev) ((struct dm_spi_ops *)(dev)->driver->ops)
#define spi_emul_get_ops(dev) ((struct dm_spi_emul_ops *)(dev)->driver->ops)
Expand Down
9 changes: 9 additions & 0 deletions test/dm/sf.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ static int dm_test_spi_flash(struct unit_test_state *uts)
int full_size = 0x200000;
int size = 0x10000;
u8 *src, *dst;
uint map_size;
ulong map_base;
uint offset;
int i;

src = map_sysmem(0x20000, full_size);
Expand Down Expand Up @@ -54,6 +57,12 @@ static int dm_test_spi_flash(struct unit_test_state *uts)
sandbox_sf_set_block_protect(emul, 0);
ut_asserteq(0, spl_flash_get_sw_write_prot(dev));

/* Check mapping */
ut_assertok(dm_spi_get_mmap(dev, &map_base, &map_size, &offset));
ut_asserteq(0x1000, map_base);
ut_asserteq(0x2000, map_size);
ut_asserteq(0x100, offset);

/*
* Since we are about to destroy all devices, we must tell sandbox
* to forget the emulation device
Expand Down

0 comments on commit c53b318

Please sign in to comment.