Message ID | 20190925141147.191166-14-sjg@chromium.org |
---|---|
State | Superseded |
Delegated to: | Bin Meng |
Headers | show |
Series | x86: Various modifications to prepare for FSP2 | expand |
Hi Simon, On Wed, Sep 25, 2019 at 10:12 PM Simon Glass <sjg@chromium.org> wrote: > > At present SPI-flash testing relies on a sandbox driver which emulates the > SPI bus and implements a flash chip behind that emulated bus. > > This provides good coverage but can only implement features supported by > the SPI bus. > > Add a new 'direct' SPI flash which is implemented directly by sandbox. > This allows us to write a very simple test of the uclass interface. > > Signed-off-by: Simon Glass <sjg@chromium.org> > --- > > Changes in v2: None > > arch/sandbox/dts/test.dts | 4 ++ > drivers/mtd/spi/Makefile | 2 +- > drivers/mtd/spi/sandbox_direct.c | 99 ++++++++++++++++++++++++++++++++ > test/dm/sf.c | 42 ++++++++++++++ > 4 files changed, 146 insertions(+), 1 deletion(-) > create mode 100644 drivers/mtd/spi/sandbox_direct.c > > diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts > index 27b0baab278..208551d7c19 100644 > --- a/arch/sandbox/dts/test.dts > +++ b/arch/sandbox/dts/test.dts > @@ -619,6 +619,10 @@ > }; > }; > > + spi-flash@0 { > + compatible = "sandbox,spi-flash-direct"; > + }; > + > syscon0: syscon@0 { > compatible = "sandbox,syscon0"; > reg = <0x10 16>; > diff --git a/drivers/mtd/spi/Makefile b/drivers/mtd/spi/Makefile > index 11a8f55132a..c700258254b 100644 > --- a/drivers/mtd/spi/Makefile > +++ b/drivers/mtd/spi/Makefile > @@ -21,4 +21,4 @@ obj-$(CONFIG_SPI_FLASH) += spi-nor.o > obj-$(CONFIG_SPI_FLASH_DATAFLASH) += sf_dataflash.o > obj-$(CONFIG_SPI_FLASH_INTEL_FAST) += intel_fast_spi.o > obj-$(CONFIG_SPI_FLASH_MTD) += sf_mtd.o > -obj-$(CONFIG_SPI_FLASH_SANDBOX) += sandbox.o > +obj-$(CONFIG_SPI_FLASH_SANDBOX) += sandbox.o sandbox_direct.o > diff --git a/drivers/mtd/spi/sandbox_direct.c b/drivers/mtd/spi/sandbox_direct.c > new file mode 100644 > index 00000000000..43d8907710c > --- /dev/null > +++ b/drivers/mtd/spi/sandbox_direct.c > @@ -0,0 +1,99 @@ > +// SPDX-License-Identifier: GPL-2.0+ > +/* > + * Simulate a flash chip without an underlying SPI layer. Behaviour is only > + * useful for testing. > + * > + * Copyright 2019 Google LLC > + * > + * Licensed under the GPL-2 or later. > + */ > + > +#define LOG_CATEGORY UCLASS_SPI_FLASH > + > +#include <common.h> > +#include <dm.h> > +#include <spi_flash.h> > + > +/** > + * struct sandbox_direct_priv - private data for this driver > + * > + * @read_byte: Byte to return when reading from the driver > + */ > +struct sandbox_direct_priv { > + char read_byte; Just 'byte'? Since it stores a byte that is not only for "read", but also for "write" > + int write_prot; > +}; > + > +static int sandbox_direct_read(struct udevice *dev, u32 offset, size_t len, > + void *buf) > +{ > + struct sandbox_direct_priv *priv = dev_get_priv(dev); > + > + if (offset == 1) > + return -EIO; > + memset(buf, priv->read_byte, len); > + > + return 0; > +} > + > +static int sandbox_direct_write(struct udevice *dev, u32 offset, size_t len, > + const void *buf) > +{ > + struct sandbox_direct_priv *priv = dev_get_priv(dev); > + > + if (offset == 1) > + return -EIO; No "priv->write_prot" check? > + if (len > 0) > + priv->read_byte = *(u8 *)buf; > + > + return 0; > +} > + > +static int sandbox_direct_erase(struct udevice *dev, u32 offset, size_t len) > +{ > + struct sandbox_direct_priv *priv = dev_get_priv(dev); > + > + if (offset == 1) > + return -EIO; > + if (len > 0) > + priv->read_byte = 'c'; > + > + return 0; > +} > + > +static int sandbox_direct_get_sw_write_prot(struct udevice *dev) > +{ > + struct sandbox_direct_priv *priv = dev_get_priv(dev); > + > + return priv->write_prot++ ? 1 : 0; > +} > + > +static int sandbox_direct_probe(struct udevice *dev) > +{ > + struct sandbox_direct_priv *priv = dev_get_priv(dev); > + > + priv->read_byte = 'a'; > + > + return 0; > +} > + > +static struct dm_spi_flash_ops sandbox_direct_ops = { > + .read = sandbox_direct_read, > + .write = sandbox_direct_write, > + .erase = sandbox_direct_erase, > + .get_sw_write_prot = sandbox_direct_get_sw_write_prot, > +}; > + > +static const struct udevice_id sandbox_direct_ids[] = { > + { .compatible = "sandbox,spi-flash-direct" }, > + { } > +}; > + > +U_BOOT_DRIVER(sandbox_sf_direct) = { > + .name = "sandbox_sf_direct", > + .id = UCLASS_SPI_FLASH, > + .of_match = sandbox_direct_ids, > + .probe = sandbox_direct_probe, > + .ops = &sandbox_direct_ops, > + .priv_auto_alloc_size = sizeof(struct sandbox_direct_priv), > +}; > diff --git a/test/dm/sf.c b/test/dm/sf.c > index 3788d59052e..56277954c23 100644 > --- a/test/dm/sf.c > +++ b/test/dm/sf.c > @@ -14,8 +14,13 @@ > #include <asm/test.h> > #include <dm/test.h> > #include <dm/util.h> > +#include <dm/uclass.h> > #include <test/ut.h> > > +enum { > + BUF_SIZE = 4, > +}; > + > /* Simple test of sandbox SPI flash */ > static int dm_test_spi_flash(struct unit_test_state *uts) > { > @@ -91,3 +96,40 @@ static int dm_test_spi_flash_func(struct unit_test_state *uts) > return 0; > } > DM_TEST(dm_test_spi_flash_func, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); > + > +/* Test of the direct SPI flash interface (no SPI layer) */ > +static int dm_test_spi_flash_direct(struct unit_test_state *uts) > +{ > + struct udevice *dev; > + char buf[BUF_SIZE]; > + int i; > + > + ut_assertok(uclass_get_device(UCLASS_SPI_FLASH, 1, &dev)); > + > + /* Check the read call */ > + ut_asserteq(-EIO, spi_flash_read_dm(dev, 1, BUF_SIZE, buf)); > + ut_assertok(spi_flash_read_dm(dev, 0, BUF_SIZE, buf)); > + for (i = 0; i < BUF_SIZE; i++) > + ut_asserteq('a', buf[i]); > + > + /* Check the write call */ > + ut_asserteq(-EIO, spi_flash_write_dm(dev, 1, BUF_SIZE, buf)); > + ut_assertok(spi_flash_write_dm(dev, 0, 1, "b")); > + ut_assertok(spi_flash_read_dm(dev, 0, BUF_SIZE, buf)); > + for (i = 0; i < BUF_SIZE; i++) > + ut_asserteq('b', buf[i]); > + > + /* Check erase */ > + ut_asserteq(-EIO, spi_flash_erase_dm(dev, 1, BUF_SIZE)); > + ut_assertok(spi_flash_erase_dm(dev, 0, 1)); > + ut_assertok(spi_flash_read_dm(dev, 0, BUF_SIZE, buf)); > + for (i = 0; i < BUF_SIZE; i++) > + ut_asserteq('c', buf[i]); > + > + /* Check write protection */ > + ut_asserteq(0, spl_flash_get_sw_write_prot(dev)); > + ut_asserteq(1, spl_flash_get_sw_write_prot(dev)); > + > + return 0; > +} > +DM_TEST(dm_test_spi_flash_direct, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); > -- Regards, Bin
diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts index 27b0baab278..208551d7c19 100644 --- a/arch/sandbox/dts/test.dts +++ b/arch/sandbox/dts/test.dts @@ -619,6 +619,10 @@ }; }; + spi-flash@0 { + compatible = "sandbox,spi-flash-direct"; + }; + syscon0: syscon@0 { compatible = "sandbox,syscon0"; reg = <0x10 16>; diff --git a/drivers/mtd/spi/Makefile b/drivers/mtd/spi/Makefile index 11a8f55132a..c700258254b 100644 --- a/drivers/mtd/spi/Makefile +++ b/drivers/mtd/spi/Makefile @@ -21,4 +21,4 @@ obj-$(CONFIG_SPI_FLASH) += spi-nor.o obj-$(CONFIG_SPI_FLASH_DATAFLASH) += sf_dataflash.o obj-$(CONFIG_SPI_FLASH_INTEL_FAST) += intel_fast_spi.o obj-$(CONFIG_SPI_FLASH_MTD) += sf_mtd.o -obj-$(CONFIG_SPI_FLASH_SANDBOX) += sandbox.o +obj-$(CONFIG_SPI_FLASH_SANDBOX) += sandbox.o sandbox_direct.o diff --git a/drivers/mtd/spi/sandbox_direct.c b/drivers/mtd/spi/sandbox_direct.c new file mode 100644 index 00000000000..43d8907710c --- /dev/null +++ b/drivers/mtd/spi/sandbox_direct.c @@ -0,0 +1,99 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Simulate a flash chip without an underlying SPI layer. Behaviour is only + * useful for testing. + * + * Copyright 2019 Google LLC + * + * Licensed under the GPL-2 or later. + */ + +#define LOG_CATEGORY UCLASS_SPI_FLASH + +#include <common.h> +#include <dm.h> +#include <spi_flash.h> + +/** + * struct sandbox_direct_priv - private data for this driver + * + * @read_byte: Byte to return when reading from the driver + */ +struct sandbox_direct_priv { + char read_byte; + int write_prot; +}; + +static int sandbox_direct_read(struct udevice *dev, u32 offset, size_t len, + void *buf) +{ + struct sandbox_direct_priv *priv = dev_get_priv(dev); + + if (offset == 1) + return -EIO; + memset(buf, priv->read_byte, len); + + return 0; +} + +static int sandbox_direct_write(struct udevice *dev, u32 offset, size_t len, + const void *buf) +{ + struct sandbox_direct_priv *priv = dev_get_priv(dev); + + if (offset == 1) + return -EIO; + if (len > 0) + priv->read_byte = *(u8 *)buf; + + return 0; +} + +static int sandbox_direct_erase(struct udevice *dev, u32 offset, size_t len) +{ + struct sandbox_direct_priv *priv = dev_get_priv(dev); + + if (offset == 1) + return -EIO; + if (len > 0) + priv->read_byte = 'c'; + + return 0; +} + +static int sandbox_direct_get_sw_write_prot(struct udevice *dev) +{ + struct sandbox_direct_priv *priv = dev_get_priv(dev); + + return priv->write_prot++ ? 1 : 0; +} + +static int sandbox_direct_probe(struct udevice *dev) +{ + struct sandbox_direct_priv *priv = dev_get_priv(dev); + + priv->read_byte = 'a'; + + return 0; +} + +static struct dm_spi_flash_ops sandbox_direct_ops = { + .read = sandbox_direct_read, + .write = sandbox_direct_write, + .erase = sandbox_direct_erase, + .get_sw_write_prot = sandbox_direct_get_sw_write_prot, +}; + +static const struct udevice_id sandbox_direct_ids[] = { + { .compatible = "sandbox,spi-flash-direct" }, + { } +}; + +U_BOOT_DRIVER(sandbox_sf_direct) = { + .name = "sandbox_sf_direct", + .id = UCLASS_SPI_FLASH, + .of_match = sandbox_direct_ids, + .probe = sandbox_direct_probe, + .ops = &sandbox_direct_ops, + .priv_auto_alloc_size = sizeof(struct sandbox_direct_priv), +}; diff --git a/test/dm/sf.c b/test/dm/sf.c index 3788d59052e..56277954c23 100644 --- a/test/dm/sf.c +++ b/test/dm/sf.c @@ -14,8 +14,13 @@ #include <asm/test.h> #include <dm/test.h> #include <dm/util.h> +#include <dm/uclass.h> #include <test/ut.h> +enum { + BUF_SIZE = 4, +}; + /* Simple test of sandbox SPI flash */ static int dm_test_spi_flash(struct unit_test_state *uts) { @@ -91,3 +96,40 @@ static int dm_test_spi_flash_func(struct unit_test_state *uts) return 0; } DM_TEST(dm_test_spi_flash_func, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); + +/* Test of the direct SPI flash interface (no SPI layer) */ +static int dm_test_spi_flash_direct(struct unit_test_state *uts) +{ + struct udevice *dev; + char buf[BUF_SIZE]; + int i; + + ut_assertok(uclass_get_device(UCLASS_SPI_FLASH, 1, &dev)); + + /* Check the read call */ + ut_asserteq(-EIO, spi_flash_read_dm(dev, 1, BUF_SIZE, buf)); + ut_assertok(spi_flash_read_dm(dev, 0, BUF_SIZE, buf)); + for (i = 0; i < BUF_SIZE; i++) + ut_asserteq('a', buf[i]); + + /* Check the write call */ + ut_asserteq(-EIO, spi_flash_write_dm(dev, 1, BUF_SIZE, buf)); + ut_assertok(spi_flash_write_dm(dev, 0, 1, "b")); + ut_assertok(spi_flash_read_dm(dev, 0, BUF_SIZE, buf)); + for (i = 0; i < BUF_SIZE; i++) + ut_asserteq('b', buf[i]); + + /* Check erase */ + ut_asserteq(-EIO, spi_flash_erase_dm(dev, 1, BUF_SIZE)); + ut_assertok(spi_flash_erase_dm(dev, 0, 1)); + ut_assertok(spi_flash_read_dm(dev, 0, BUF_SIZE, buf)); + for (i = 0; i < BUF_SIZE; i++) + ut_asserteq('c', buf[i]); + + /* Check write protection */ + ut_asserteq(0, spl_flash_get_sw_write_prot(dev)); + ut_asserteq(1, spl_flash_get_sw_write_prot(dev)); + + return 0; +} +DM_TEST(dm_test_spi_flash_direct, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
At present SPI-flash testing relies on a sandbox driver which emulates the SPI bus and implements a flash chip behind that emulated bus. This provides good coverage but can only implement features supported by the SPI bus. Add a new 'direct' SPI flash which is implemented directly by sandbox. This allows us to write a very simple test of the uclass interface. Signed-off-by: Simon Glass <sjg@chromium.org> --- Changes in v2: None arch/sandbox/dts/test.dts | 4 ++ drivers/mtd/spi/Makefile | 2 +- drivers/mtd/spi/sandbox_direct.c | 99 ++++++++++++++++++++++++++++++++ test/dm/sf.c | 42 ++++++++++++++ 4 files changed, 146 insertions(+), 1 deletion(-) create mode 100644 drivers/mtd/spi/sandbox_direct.c