Hi Mike,
On Sun, Jan 22, 2012 at 10:30 PM, Mike Frysinger vap...@gentoo.org wrote:
This adds a SPI flash driver which simulates SPI flash clients.
Currently supports the bare min that U-Boot requires: you can
probe, read, erase, and write. Should be easy to extend to make
it behave more exactly like a real SPI flash, but this is good
enough to merge now.
Signed-off-by: Mike Frysinger vap...@gentoo.org
---
drivers/mtd/spi/Makefile | 1 +
drivers/mtd/spi/sandbox.c | 318
+
drivers/spi/sandbox_spi.c | 5 +
3 files changed, 324 insertions(+), 0 deletions(-)
create mode 100644 drivers/mtd/spi/sandbox.c
Again would like a few comments / docs. I'm pleased you have done this
- it is much more comprehensive than my noddy implementation.
diff --git a/drivers/mtd/spi/Makefile b/drivers/mtd/spi/Makefile
index 90f8392..fb37807 100644
--- a/drivers/mtd/spi/Makefile
+++ b/drivers/mtd/spi/Makefile
@@ -33,6 +33,7 @@ COBJS-$(CONFIG_SPI_FLASH) += spi_flash.o
COBJS-$(CONFIG_SPI_FLASH_ATMEL) += atmel.o
COBJS-$(CONFIG_SPI_FLASH_EON) += eon.o
COBJS-$(CONFIG_SPI_FLASH_MACRONIX) += macronix.o
+COBJS-$(CONFIG_SPI_FLASH_SANDBOX) += sandbox.o
COBJS-$(CONFIG_SPI_FLASH_SPANSION) += spansion.o
COBJS-$(CONFIG_SPI_FLASH_SST) += sst.o
COBJS-$(CONFIG_SPI_FLASH_STMICRO) += stmicro.o
diff --git a/drivers/mtd/spi/sandbox.c b/drivers/mtd/spi/sandbox.c
new file mode 100644
index 000..a1bb641
--- /dev/null
+++ b/drivers/mtd/spi/sandbox.c
@@ -0,0 +1,318 @@
+/*
+ * Simulate a SPI flash
+ *
+ * Copyright (c) 2011-2012 The Chromium OS Authors.
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include common.h
+#include malloc.h
+#include spi.h
+#include os.h
+
+#include spi_flash.h
+#include spi_flash_internal.h
+
+#include asm/spi.h
+
These are the different commands, right?
+typedef enum {
+ SF_CMD, SF_ID, SF_READ, SF_WRITE, SF_ERASE, SF_READ_STATUS, SF_WREN,
SF_WRDI,
+} sb_sf_state;
+
+#define STAT_WIP (1 0)
+#define STAT_WEL (1 1)
What are these? Status bus? If so, perhaps a comment for each?
+
+struct sb_spi_flash_erase_commands {
+ u8 cmd;
+ u32 size;
+};
+#define IDCODE_LEN 5
+#define MAX_ERASE_CMDS 2
+struct sb_spi_flash_data {
+ const char *name;
+ u8 idcode[IDCODE_LEN];
+ u32 size;
+ const struct sb_spi_flash_erase_commands erase_cmds[MAX_ERASE_CMDS];
+};
+
+struct sb_spi_flash {
+ sb_sf_state state;
+ uint off;
+ const struct sb_spi_flash_data *data;
+ int fd;
+ u8 status;
+};
All of the above could do with some comments IMO...
+
+static const char *sb_sf_state_name(sb_sf_state state)
+{
+ static const char * const states[] = {
+ CMD, ID, READ, WRITE, ERASE, READ_STATUS, WREN,
WRDI,
+ };
I wonder if it would be better to put this array up next to the enum?
+ return states[state];
+}
+
These are the emulated devices I think.
+static const struct sb_spi_flash_data sb_sf_flashes[] = {
+ {
+ M25P16, { 0x20, 0x20, 0x15 }, (2 * 1024 * 1024),
+ { /* erase commands */
+ { 0xd8, (64 * 1024), }, /* sector */
+ { 0xc7, (2 * 1024 * 1024), }, /* bulk */
Is 10, 20 better? Not sure.
+ },
+ },
+};
+
+static u8 sb_sf_0xff[0x1];
Perhaps we should add an os_fputc() instead? Or perhaps write in smaller chunks?
+
+static int sb_sf_setup(void **priv, const char *spec)
+{
+ /* spec = idcode:file */
+ struct sb_spi_flash *sbsf;
+ const char *file;
+ size_t i, len, idname_len;
+ const struct sb_spi_flash_data *data;
+
+ file = strchr(spec, ':');
+ if (!file)
+ goto error;
+ idname_len = file - spec;
+ ++file;
+
+ for (i = 0; i ARRAY_SIZE(sb_sf_flashes); ++i) {
+ data = sb_sf_flashes[i];
+ len = strlen(data-name);
+ if (idname_len != len)
+ continue;
+ if (!memcmp(spec, data-name, len))
+ break;
+ }
+ if (i == ARRAY_SIZE(sb_sf_flashes)) {
+ printf(sandbox_spi_flash: unknown flash '%*s'\n,
+ (int)idname_len, file);
+ goto error;
+ }
+
+ if (sb_sf_0xff[0] == 0x00)
+ memset(sb_sf_0xff, 0xff, sizeof(sb_sf_0xff));
+
+ sbsf = malloc(sizeof(*sbsf));
+ if (!sbsf)
+ goto error;
+
+ sbsf-fd = os_open(file, 02);
+ if (sbsf-fd == -1) {
+ free(sbsf);
+ goto error;
+ }
+
+ sbsf-state = SF_CMD;
+ sbsf-data = data;
+
+ *priv = sbsf;
+ return 0;
+
+ error:
+