
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