diff mbox

[U-Boot,2/2] spi: Add SPI flash test

Message ID 1348878482-1730-2-git-send-email-sjg@chromium.org
State Superseded, archived
Delegated to: Tom Rini
Headers show

Commit Message

Simon Glass Sept. 29, 2012, 12:28 a.m. UTC
It is useful to have a basic SPI flash test, which tests that the SPI chip,
the SPI bus and the driver are behaving.

This test erases part of the flash, writes data and reads it back as a
sanity check that all is well.

Use CONFIG_SF_TEST to enable it.

Signed-off-by: Simon Glass <sjg@chromium.org>
---
 README          |    5 ++
 common/cmd_sf.c |  160 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 165 insertions(+), 0 deletions(-)

Comments

Tom Rini Oct. 1, 2012, 5:32 p.m. UTC | #1
On Fri, Sep 28, 2012 at 05:28:01PM -0700, Simon Glass wrote:

> It is useful to have a basic SPI flash test, which tests that the SPI chip,
> the SPI bus and the driver are behaving.
> 
> This test erases part of the flash, writes data and reads it back as a
> sanity check that all is well.
> 
> Use CONFIG_SF_TEST to enable it.
> 
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>  README          |    5 ++
>  common/cmd_sf.c |  160 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 165 insertions(+), 0 deletions(-)
> 
> diff --git a/README b/README
> index 5793b0a..8f601ae 100644
> --- a/README
> +++ b/README
> @@ -2309,6 +2309,11 @@ The following options need to be configured:
>  		CONFIG_SF_DEFAULT_MODE 		(see include/spi.h)
>  		CONFIG_SF_DEFAULT_SPEED		in Hz
>  
> +		CONFIG_CMD_SF_TEST
> +
> +		Define this option to include a destructive SPI flash
> +		test ('sf test').
> +

Lets make this note as well that it is of course a destructive test.

[snip]
> +static int do_spi_flash_test(void)
> +{
> +	/* TODO(sjg@chromium.org): Support cmdline parameters for these */

Lets just add that now? :)  Thanks.
Simon Glass Oct. 8, 2012, 11 p.m. UTC | #2
Hi Tom,

On Mon, Oct 1, 2012 at 10:32 AM, Tom Rini <trini@ti.com> wrote:
> On Fri, Sep 28, 2012 at 05:28:01PM -0700, Simon Glass wrote:
>
>> It is useful to have a basic SPI flash test, which tests that the SPI chip,
>> the SPI bus and the driver are behaving.
>>
>> This test erases part of the flash, writes data and reads it back as a
>> sanity check that all is well.
>>
>> Use CONFIG_SF_TEST to enable it.
>>
>> Signed-off-by: Simon Glass <sjg@chromium.org>
>> ---
>>  README          |    5 ++
>>  common/cmd_sf.c |  160 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
>>  2 files changed, 165 insertions(+), 0 deletions(-)
>>
>> diff --git a/README b/README
>> index 5793b0a..8f601ae 100644
>> --- a/README
>> +++ b/README
>> @@ -2309,6 +2309,11 @@ The following options need to be configured:
>>               CONFIG_SF_DEFAULT_MODE          (see include/spi.h)
>>               CONFIG_SF_DEFAULT_SPEED         in Hz
>>
>> +             CONFIG_CMD_SF_TEST
>> +
>> +             Define this option to include a destructive SPI flash
>> +             test ('sf test').
>> +
>
> Lets make this note as well that it is of course a destructive test.

Do you mean change the comment?

>
> [snip]
>> +static int do_spi_flash_test(void)
>> +{
>> +     /* TODO(sjg@chromium.org): Support cmdline parameters for these */
>
> Lets just add that now? :)  Thanks.

Fair enough, will do.

Regards,
Simon

>
> --
> Tom
Tom Rini Oct. 8, 2012, 11:03 p.m. UTC | #3
On Mon, Oct 08, 2012 at 04:00:08PM -0700, Simon Glass wrote:
> Hi Tom,
> 
> On Mon, Oct 1, 2012 at 10:32 AM, Tom Rini <trini@ti.com> wrote:
> > On Fri, Sep 28, 2012 at 05:28:01PM -0700, Simon Glass wrote:
> >
> >> It is useful to have a basic SPI flash test, which tests that the SPI chip,
> >> the SPI bus and the driver are behaving.
> >>
> >> This test erases part of the flash, writes data and reads it back as a
> >> sanity check that all is well.
> >>
> >> Use CONFIG_SF_TEST to enable it.
> >>
> >> Signed-off-by: Simon Glass <sjg@chromium.org>
> >> ---
> >>  README          |    5 ++
> >>  common/cmd_sf.c |  160 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
> >>  2 files changed, 165 insertions(+), 0 deletions(-)
> >>
> >> diff --git a/README b/README
> >> index 5793b0a..8f601ae 100644
> >> --- a/README
> >> +++ b/README
> >> @@ -2309,6 +2309,11 @@ The following options need to be configured:
> >>               CONFIG_SF_DEFAULT_MODE          (see include/spi.h)
> >>               CONFIG_SF_DEFAULT_SPEED         in Hz
> >>
> >> +             CONFIG_CMD_SF_TEST
> >> +
> >> +             Define this option to include a destructive SPI flash
> >> +             test ('sf test').
> >> +
> >
> > Lets make this note as well that it is of course a destructive test.
> 
> Do you mean change the comment?

Um.  I had reading comprehension issues that morning.  I can see right
now that it says it's destructive.

> > [snip]
> >> +static int do_spi_flash_test(void)
> >> +{
> >> +     /* TODO(sjg@chromium.org): Support cmdline parameters for these */
> >
> > Lets just add that now? :)  Thanks.
> 
> Fair enough, will do.

Thanks!
Wolfgang Denk Dec. 19, 2012, 11:12 p.m. UTC | #4
Dear Simon Glass,

In message <1348878482-1730-2-git-send-email-sjg@chromium.org> you wrote:
> It is useful to have a basic SPI flash test, which tests that the SPI chip,
> the SPI bus and the driver are behaving.
> 
> This test erases part of the flash, writes data and reads it back as a
> sanity check that all is well.
> 
> Use CONFIG_SF_TEST to enable it.

Adding dead code ?

Please don't.

Best regards,

Wolfgang Denk

--
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd@denx.de
No, I'm not going to explain it. If you  can't  figure  it  out,  you
didn't want to know anyway... :-)
                   - Larry Wall in <1991Aug7.180856.2854@netlabs.com>
diff mbox

Patch

diff --git a/README b/README
index 5793b0a..8f601ae 100644
--- a/README
+++ b/README
@@ -2309,6 +2309,11 @@  The following options need to be configured:
 		CONFIG_SF_DEFAULT_MODE 		(see include/spi.h)
 		CONFIG_SF_DEFAULT_SPEED		in Hz
 
+		CONFIG_CMD_SF_TEST
+
+		Define this option to include a destructive SPI flash
+		test ('sf test').
+
 - SystemACE Support:
 		CONFIG_SYSTEMACE
 
diff --git a/common/cmd_sf.c b/common/cmd_sf.c
index e22a45e..2462c25 100644
--- a/common/cmd_sf.c
+++ b/common/cmd_sf.c
@@ -5,6 +5,7 @@ 
  * Licensed under the GPL-2 or later.
  */
 
+#include <div64.h>
 #include <common.h>
 #include <malloc.h>
 #include <spi_flash.h>
@@ -312,6 +313,153 @@  static int do_spi_flash_erase(int argc, char * const argv[])
 	return 0;
 }
 
+#ifdef CONFIG_CMD_SF_TEST
+enum {
+	STAGE_ERASE,
+	STAGE_CHECK,
+	STAGE_WRITE,
+	STAGE_READ,
+
+	STAGE_COUNT,
+};
+
+static char *stage_name[STAGE_COUNT] = {
+	"erase",
+	"check",
+	"write",
+	"read",
+};
+
+struct test_info {
+	int stage;
+	int bytes;
+	unsigned base_ms;
+	unsigned time_ms[STAGE_COUNT];
+};
+
+static void show_time(struct test_info *test, int stage)
+{
+	uint64_t speed;	/* KiB/s */
+	int bps;	/* Bits per second */
+
+	speed = (long long)test->bytes * 1000;
+	do_div(speed, test->time_ms[stage] * 1024);
+	bps = speed * 8;
+
+	printf("%d %s: %d: %d KiB/s %d.%03d Mbps\n", stage, stage_name[stage],
+	       test->time_ms[stage], (int)speed, bps / 1000, bps % 1000);
+}
+
+static void spi_test_next_stage(struct test_info *test)
+{
+	test->time_ms[test->stage] = get_timer(test->base_ms);
+	show_time(test, test->stage);
+	test->base_ms = get_timer(0);
+	test->stage++;
+}
+
+/**
+ * Run a test on the SPI flash
+ *
+ * @param flash		SPI flash to use
+ * @param buf		Source buffer for data to write
+ * @param len		Size of data to read/write
+ * @param offset	Offset within flash to check
+ * @param vbuf		Verification buffer
+ * @return 0 if ok, -1 on error
+ */
+static int spi_flash_test(struct spi_flash *flash, char *buf, ulong len,
+			   ulong offset, char *vbuf)
+{
+	struct test_info test;
+	int i;
+
+	printf("SPI flash test:\n");
+	memset(&test, '\0', sizeof(test));
+	test.base_ms = get_timer(0);
+	test.bytes = len;
+	if (spi_flash_erase(flash, offset, len)) {
+		printf("Erase failed\n");
+		return -1;
+	}
+	spi_test_next_stage(&test);
+
+	if (spi_flash_read(flash, offset, len, vbuf)) {
+		printf("Check read failed\n");
+		return -1;
+	}
+	for (i = 0; i < len; i++) {
+		if (vbuf[i] != 0xff) {
+			printf("Check failed at %d\n", i);
+			print_buffer(i, vbuf + i, 1, min(len - i, 0x40), 0);
+			return -1;
+		}
+	}
+	spi_test_next_stage(&test);
+
+	if (spi_flash_write(flash, offset, len, buf)) {
+		printf("Write failed\n");
+		return -1;
+	}
+	memset(vbuf, '\0', len);
+	spi_test_next_stage(&test);
+
+	if (spi_flash_read(flash, offset, len, vbuf)) {
+		printf("Read failed\n");
+		return -1;
+	}
+	spi_test_next_stage(&test);
+
+	for (i = 0; i < len; i++) {
+		if (buf[i] != vbuf[i]) {
+			printf("Verify failed at %d, good data:\n", i);
+			print_buffer(i, buf + i, 1, min(len - i, 0x40), 0);
+			printf("Bad data:\n");
+			print_buffer(i, vbuf + i, 1, min(len - i, 0x40), 0);
+			return -1;
+		}
+	}
+	printf("Test passed\n");
+	for (i = 0; i < STAGE_COUNT; i++)
+		show_time(&test, i);
+
+	return 0;
+}
+
+static int do_spi_flash_test(void)
+{
+	/* TODO(sjg@chromium.org): Support cmdline parameters for these */
+	unsigned long offset = 0x8000;
+	unsigned long len = 0x10000;
+	char *buf = (char *)CONFIG_SYS_TEXT_BASE;
+	char *vbuf;
+	int ret;
+
+	vbuf = malloc(len);
+	if (!vbuf) {
+		printf("Cannot allocate memory\n");
+		return 1;
+	}
+	buf = malloc(len);
+	if (!buf) {
+		free(vbuf);
+		printf("Cannot allocate memory\n");
+		return 1;
+	}
+
+	memcpy(buf, (char *)CONFIG_SYS_TEXT_BASE, len);
+	ret = spi_flash_test(flash, buf, len, offset, vbuf);
+	free(vbuf);
+	free(buf);
+	if (ret) {
+		printf("Test failed\n");
+		return 1;
+	}
+
+	return 0;
+}
+#endif /* CONFIG_CMD_SF_TEST */
+
 static int do_spi_flash(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
 	const char *cmd;
@@ -341,6 +489,10 @@  static int do_spi_flash(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[
 		ret = do_spi_flash_read_write(argc, argv);
 	else if (strcmp(cmd, "erase") == 0)
 		ret = do_spi_flash_erase(argc, argv);
+#ifdef CONFIG_CMD_SF_TEST
+	else if (!strcmp(cmd, "test"))
+		ret = do_spi_flash_test();
+#endif
 	else
 		ret = -1;
 
@@ -352,6 +504,13 @@  usage:
 	return CMD_RET_USAGE;
 }
 
+#ifdef CONFIG_CMD_SF_TEST
+#define SF_TEST_HELP "\nsf test				" \
+		"- run a very basic destructive test"
+#else
+#define SF_TEST_HELP
+#endif
+
 U_BOOT_CMD(
 	sf,	5,	1,	do_spi_flash,
 	"SPI flash sub-system",
@@ -365,4 +524,5 @@  U_BOOT_CMD(
 	"				  `+len' round up `len' to block size\n"
 	"sf update addr offset len	- erase and write `len' bytes from memory\n"
 	"				  at `addr' to flash at `offset'"
+	SF_TEST_HELP
 );