From: Simon Glass Date: Mon, 21 Oct 2019 03:31:47 +0000 (-0600) Subject: spi: Add support for memory-mapped flash X-Git-Tag: v2020.01-rc2~21^2~10 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=c53b318e1bad2e0d5c2b846fadfc79ec77bfc5f7;p=oweals%2Fu-boot.git spi: Add support for memory-mapped flash 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 Reviewed-by: Bin Meng --- diff --git a/drivers/spi/sandbox_spi.c b/drivers/spi/sandbox_spi.c index 16473ec7a0..6b610ff823 100644 --- a/drivers/spi/sandbox_spi.c +++ b/drivers/spi/sandbox_spi.c @@ -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[] = { diff --git a/drivers/spi/spi-uclass.c b/drivers/spi/spi-uclass.c index 947516073e..665611f7e2 100644 --- a/drivers/spi/spi-uclass.c +++ b/drivers/spi/spi-uclass.c @@ -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)); diff --git a/include/spi.h b/include/spi.h index 3f79168df3..6fbb4336ce 100644 --- a/include/spi.h +++ b/include/spi.h @@ -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 { @@ -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) diff --git a/test/dm/sf.c b/test/dm/sf.c index 3788d59052..65aab4f2e9 100644 --- a/test/dm/sf.c +++ b/test/dm/sf.c @@ -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); @@ -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