[U-Boot] [PATCH] atmel_df_pow2: standalone to convert dataflashes to pow2

Atmel DataFlashes by default operate with pages with 1056 byte pages. They also have a "power of 2" mode where the pages are 1024 bytes in size. The latter mode is required in order to boot with a Blackfin processor, so many people wish to convert their DataFlashes on their development systems to this mode. This standalone application does just that.
Signed-off-by: Mike Frysinger vapier@gentoo.org --- examples/.gitignore | 1 + examples/Makefile | 4 + examples/atmel_df_pow2.c | 206 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 211 insertions(+), 0 deletions(-) create mode 100644 examples/atmel_df_pow2.c
diff --git a/examples/.gitignore b/examples/.gitignore index 0d1864c..7b783fc 100644 --- a/examples/.gitignore +++ b/examples/.gitignore @@ -1,4 +1,5 @@ /82559_eeprom +/atmel_df_pow2 /hello_world /interrupt /mem_to_mem_idma2intr diff --git a/examples/Makefile b/examples/Makefile index dbcfa92..9f67afd 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -86,6 +86,10 @@ ELF = hello_world SREC = hello_world.srec BIN = hello_world.bin
+ELF += atmel_df_pow2 +SREC += atmel_df_pow2.srec +BIN += atmel_df_pow2.bin + ifeq ($(CPU),mpc8xx) ELF += test_burst SREC += test_burst.srec diff --git a/examples/atmel_df_pow2.c b/examples/atmel_df_pow2.c new file mode 100644 index 0000000..e6d02b1 --- /dev/null +++ b/examples/atmel_df_pow2.c @@ -0,0 +1,206 @@ +/* + * atmel_df_pow2.c - convert Atmel Dataflashes to Power of 2 mode + * + * Copyright 2009 Analog Devices Inc. + * + * Licensed under the 2-clause BSD. + */ + +#include <common.h> +#include <exports.h> + +#define CMD_ID 0x9f +#define CMD_STAT 0xd7 +#define CMD_CFG 0x3d + +static int flash_cmd(struct spi_slave *slave, uchar cmd, uchar *buf, int len) +{ + buf[0] = cmd; + return spi_xfer(slave, 8 * len, buf, buf, SPI_XFER_BEGIN | SPI_XFER_END); +} + +static int flash_status(struct spi_slave *slave) +{ + uchar buf[2]; + if (flash_cmd(slave, CMD_STAT, buf, sizeof(buf))) + return -1; + return buf[1]; +} + +static int flash_set_pow2(struct spi_slave *slave) +{ + int ret; + uchar buf[4]; + + buf[1] = 0x2a; + buf[2] = 0x80; + buf[3] = 0xa6; + + ret = flash_cmd(slave, CMD_CFG, buf, sizeof(buf)); + if (ret) + return ret; + + /* wait Tp, or 6 msec */ + udelay(6000x); + + ret = flash_status(slave); + if (ret == -1) + return 1; + + return ret & 0x1 ? 0 : 1; +} + +static int flash_check(struct spi_slave *slave) +{ + int ret; + uchar buf[4]; + + ret = flash_cmd(slave, CMD_ID, buf, sizeof(buf)); + if (ret) + return ret; + + if (buf[1] != 0x1F) { + printf("atmel flash not found (id[0] = %#x)\n", buf[1]); + return 1; + } + + if ((buf[2] >> 5) != 0x1) { + printf("AT45 flash not found (id[0] = %#x)\n", buf[2]); + return 2; + } + + return 0; +} + +static char *getline(void) +{ + static char buffer[100]; + char c; + size_t i; + + i = 0; + while (1) { + buffer[i] = '\0'; + + c = getc(); + + switch (c) { + case '\r': /* Enter/Return key */ + case '\n': + puts("\n"); + return buffer; + + case 0x03: /* ^C - break */ + return NULL; + + case 0x5F: + case 0x08: /* ^H - backspace */ + case 0x7F: /* DEL - backspace */ + if (i) { + puts("\b \b"); + i--; + } + break; + + default: + /* Ignore control characters */ + if (c < 0x20) + break; + /* Queue up all other characters */ + buffer[i++] = c; + printf("%c", c); + break; + } + } +} + +int atmel_df_pow2(int argc, char *argv[]) +{ + /* Print the ABI version */ + app_startup(argv); + if (XF_VERSION != get_version()) { + printf("Expects ABI version %d\n", XF_VERSION); + printf("Actual U-Boot ABI version %lu\n", get_version()); + printf("Can't run\n\n"); + return 1; + } + + spi_init(); + + while (1) { + struct spi_slave *slave; + char *line, *p; + int bus, cs, status; + + puts("\nenter the [BUS:]CS of the SPI flash: "); + line = getline(); + + /* CTRL+C */ + if (!line) + return 0; + if (line[0] == '\0') + continue; + + bus = cs = simple_strtoul(line, &p, 10); + if (*p) { + if (*p == ':') { + ++p; + cs = simple_strtoul(p, &p, 10); + } + if (*p) { + puts("invalid format, please try again\n"); + continue; + } + } else + bus = 0; + + printf("\ngoing to work with dataflash at %i:%i\n", bus, cs); + + /* use a low speed -- it'll work with all devices, and + * speed here doesn't really matter. + */ + slave = spi_setup_slave(bus, cs, 1000, SPI_MODE_3); + if (!slave) { + puts("unable to setup slave\n"); + continue; + } + + if (spi_claim_bus(slave)) { + spi_free_slave(slave); + continue; + } + + if (flash_check(slave)) { + puts("no flash found\n"); + goto done; + } + + status = flash_status(slave); + if (status == -1) { + puts("unable to read status register\n"); + goto done; + } + if (status & 0x1) { + puts("flash is already in power-of-2 mode!\n"); + goto done; + } + + puts("are you sure you wish to set power-of-2 mode?\n"); + puts("this operation is permanent and irreversible\n"); + printf("enter YES to continue: "); + line = getline(); + if (!line || strcmp(line, "YES")) + goto done; + + if (flash_set_pow2(slave)) { + puts("setting pow2 mode failed\n"); + goto done; + } + + puts("OK!\n"); + + done: + spi_release_bus(slave); + spi_free_slave(slave); + } +}

Atmel DataFlashes by default operate with pages with 1056 byte pages. They also have a "power of 2" mode where the pages are 1024 bytes in size.
Page size is not always 1056/1024 bytes, it is depended on total memory size.
if (flash_set_pow2(slave)) {
puts("setting pow2 mode failed\n");
goto done;
}
puts("OK!\n");
- done:
spi_release_bus(slave);
spi_free_slave(slave);
- }
+}
DafaFlash documentation says that "The device must be power cycled after the completion of the program cycle to set the power of 2 page size", so it would be good to print that information at the end of programming.
Regards, Andrzej Wolski
---------------------------------------------------------------------- Daj odpoczac plecom - zmien auto na rower Sprawdz >>>http://link.interia.pl/f2255

Atmel DataFlashes by default operate with pages that are slightly bigger than normal binary sizes (i.e. many are 1056 byte pages rather than 1024 bytes). However, they also have a "power of 2" mode where the pages show up with the normal binary size. The latter mode is required in order to boot with a Blackfin processor, so many people wish to convert their DataFlashes on their development systems to this mode. This standalone application does just that.
Signed-off-by: Mike Frysinger vapier@gentoo.org --- v2 - fix comments pointed out by Rafal
examples/atmel_df_pow2.c | 209 ++++++++++++++++++++++++++++++++++++++++ examples/standalone/.gitignore | 1 + examples/standalone/Makefile | 4 + 3 files changed, 214 insertions(+), 0 deletions(-) create mode 100644 examples/atmel_df_pow2.c
diff --git a/examples/atmel_df_pow2.c b/examples/atmel_df_pow2.c new file mode 100644 index 0000000..db0cd69 --- /dev/null +++ b/examples/atmel_df_pow2.c @@ -0,0 +1,209 @@ +/* + * atmel_df_pow2.c - convert Atmel Dataflashes to Power of 2 mode + * + * Copyright 2009 Analog Devices Inc. + * + * Licensed under the 2-clause BSD. + */ + +#include <common.h> +#include <exports.h> + +#define CMD_ID 0x9f +#define CMD_STAT 0xd7 +#define CMD_CFG 0x3d + +static int flash_cmd(struct spi_slave *slave, uchar cmd, uchar *buf, int len) +{ + buf[0] = cmd; + return spi_xfer(slave, 8 * len, buf, buf, SPI_XFER_BEGIN | SPI_XFER_END); +} + +static int flash_status(struct spi_slave *slave) +{ + uchar buf[2]; + if (flash_cmd(slave, CMD_STAT, buf, sizeof(buf))) + return -1; + return buf[1]; +} + +static int flash_set_pow2(struct spi_slave *slave) +{ + int ret; + uchar buf[4]; + + buf[1] = 0x2a; + buf[2] = 0x80; + buf[3] = 0xa6; + + ret = flash_cmd(slave, CMD_CFG, buf, sizeof(buf)); + if (ret) + return ret; + + /* wait Tp, or 6 msec */ + udelay(6000); + + ret = flash_status(slave); + if (ret == -1) + return 1; + + return ret & 0x1 ? 0 : 1; +} + +static int flash_check(struct spi_slave *slave) +{ + int ret; + uchar buf[4]; + + ret = flash_cmd(slave, CMD_ID, buf, sizeof(buf)); + if (ret) + return ret; + + if (buf[1] != 0x1F) { + printf("atmel flash not found (id[0] = %#x)\n", buf[1]); + return 1; + } + + if ((buf[2] >> 5) != 0x1) { + printf("AT45 flash not found (id[0] = %#x)\n", buf[2]); + return 2; + } + + return 0; +} + +static char *getline(void) +{ + static char buffer[100]; + char c; + size_t i; + + i = 0; + while (1) { + buffer[i] = '\0'; + + c = getc(); + + switch (c) { + case '\r': /* Enter/Return key */ + case '\n': + puts("\n"); + return buffer; + + case 0x03: /* ^C - break */ + return NULL; + + case 0x5F: + case 0x08: /* ^H - backspace */ + case 0x7F: /* DEL - backspace */ + if (i) { + puts("\b \b"); + i--; + } + break; + + default: + /* Ignore control characters */ + if (c < 0x20) + break; + /* Queue up all other characters */ + buffer[i++] = c; + printf("%c", c); + break; + } + } +} + +int atmel_df_pow2(int argc, char *argv[]) +{ + /* Print the ABI version */ + app_startup(argv); + if (XF_VERSION != get_version()) { + printf("Expects ABI version %d\n", XF_VERSION); + printf("Actual U-Boot ABI version %lu\n", get_version()); + printf("Can't run\n\n"); + return 1; + } + + spi_init(); + + while (1) { + struct spi_slave *slave; + char *line, *p; + int bus, cs, status; + + puts("\nenter the [BUS:]CS of the SPI flash: "); + line = getline(); + + /* CTRL+C */ + if (!line) + return 0; + if (line[0] == '\0') + continue; + + bus = cs = simple_strtoul(line, &p, 10); + if (*p) { + if (*p == ':') { + ++p; + cs = simple_strtoul(p, &p, 10); + } + if (*p) { + puts("invalid format, please try again\n"); + continue; + } + } else + bus = 0; + + printf("\ngoing to work with dataflash at %i:%i\n", bus, cs); + + /* use a low speed -- it'll work with all devices, and + * speed here doesn't really matter. + */ + slave = spi_setup_slave(bus, cs, 1000, SPI_MODE_3); + if (!slave) { + puts("unable to setup slave\n"); + continue; + } + + if (spi_claim_bus(slave)) { + spi_free_slave(slave); + continue; + } + + if (flash_check(slave)) { + puts("no flash found\n"); + goto done; + } + + status = flash_status(slave); + if (status == -1) { + puts("unable to read status register\n"); + goto done; + } + if (status & 0x1) { + puts("flash is already in power-of-2 mode!\n"); + goto done; + } + + puts("are you sure you wish to set power-of-2 mode?\n"); + puts("this operation is permanent and irreversible\n"); + printf("enter YES to continue: "); + line = getline(); + if (!line || strcmp(line, "YES")) + goto done; + + if (flash_set_pow2(slave)) { + puts("setting pow2 mode failed\n"); + goto done; + } + + puts( + "Configuration should be updated now. You will have to\n" + "power cycle the part in order to finish the conversion.\n" + ); + + done: + spi_release_bus(slave); + spi_free_slave(slave); + } +} diff --git a/examples/standalone/.gitignore b/examples/standalone/.gitignore index 0d1864c..7b783fc 100644 --- a/examples/standalone/.gitignore +++ b/examples/standalone/.gitignore @@ -1,4 +1,5 @@ /82559_eeprom +/atmel_df_pow2 /hello_world /interrupt /mem_to_mem_idma2intr diff --git a/examples/standalone/Makefile b/examples/standalone/Makefile index dbcfa92..9f67afd 100644 --- a/examples/standalone/Makefile +++ b/examples/standalone/Makefile @@ -86,6 +86,10 @@ ELF = hello_world SREC = hello_world.srec BIN = hello_world.bin
+ELF += atmel_df_pow2 +SREC += atmel_df_pow2.srec +BIN += atmel_df_pow2.bin + ifeq ($(CPU),mpc8xx) ELF += test_burst SREC += test_burst.srec

Hi Mike,
examples/atmel_df_pow2.c | 209 ++++++++++++++++++++++++++++++++++++++++ examples/standalone/.gitignore | 1 + examples/standalone/Makefile | 4 + 3 files changed, 214 insertions(+), 0 deletions(-) create mode 100644 examples/atmel_df_pow2.c
I think there will be some build issues since atmel_df_pow2.c is outside the examples/standalone directory. I imagine you wanted to put atmel_df_pow2.c inside examples/standalone?
<snip>
diff --git a/examples/standalone/Makefile b/examples/standalone/Makefile index dbcfa92..9f67afd 100644 --- a/examples/standalone/Makefile +++ b/examples/standalone/Makefile @@ -86,6 +86,10 @@ ELF = hello_world SREC = hello_world.srec BIN = hello_world.bin
+ELF += atmel_df_pow2 +SREC += atmel_df_pow2.srec +BIN += atmel_df_pow2.bin
These new files aren't going to compile for a lot of boards as is, some conditional compilation will be necessary.
Best, Peter

On Tuesday 21 July 2009 23:52:21 Peter Tyser wrote:
examples/atmel_df_pow2.c examples/standalone/.gitignore examples/standalone/Makefile 3 files changed, 214 insertions(+), 0 deletions(-) create mode 100644 examples/atmel_df_pow2.c
I think there will be some build issues since atmel_df_pow2.c is outside the examples/standalone directory. I imagine you wanted to put atmel_df_pow2.c inside examples/standalone?
git's automerging isnt as smart as i'd like it sometimes
--- a/examples/standalone/Makefile +++ b/examples/standalone/Makefile @@ -86,6 +86,10 @@ ELF = hello_world SREC = hello_world.srec BIN = hello_world.bin
+ELF += atmel_df_pow2 +SREC += atmel_df_pow2.srec +BIN += atmel_df_pow2.bin
These new files aren't going to compile for a lot of boards as is, some conditional compilation will be necessary.
you'll have to be a little more specific. this driver only uses common spi functions, so no, there shouldnt be any build failures. -mike

--- a/examples/standalone/Makefile +++ b/examples/standalone/Makefile @@ -86,6 +86,10 @@ ELF = hello_world SREC = hello_world.srec BIN = hello_world.bin
+ELF += atmel_df_pow2 +SREC += atmel_df_pow2.srec +BIN += atmel_df_pow2.bin
These new files aren't going to compile for a lot of boards as is, some conditional compilation will be necessary.
you'll have to be a little more specific. this driver only uses common spi functions, so no, there shouldnt be any build failures.
The majority of boards don't have SPI functionality. I just tried applying this patch, moving atmel_df_pow2 into examples/standalone, and I get:
ptyser@ptyser-laptop u-boot $ make mrproper ptyser@ptyser-laptop u-boot $ make XPEDITE5370_config Configuring for XPEDITE5370 board... ptyser@ptyser-laptop u-boot $ make -s atmel_df_pow2.c:16: warning: 'struct spi_slave' declared inside parameter list atmel_df_pow2.c:16: warning: its scope is only this definition or declaration, which is probably not what you want atmel_df_pow2.c: In function 'flash_cmd': atmel_df_pow2.c:19: warning: implicit declaration of function 'spi_xfer' atmel_df_pow2.c:19: error: 'SPI_XFER_BEGIN' undeclared (first use in this function) ... and so on ...
Adding #include <spi.h> gets rid of some warnings, but there's still a number of undefined references: ptyser@ptyser-laptop u-boot $ make -s atmel_df_pow2.o: In function `atmel_df_pow2': /home/ptyser/u-boot/examples/standalone/atmel_df_pow2.c:129: undefined reference to `spi_init' /home/ptyser/u-boot/examples/standalone/atmel_df_pow2.c:163: undefined reference to `spi_setup_slave' /home/ptyser/u-boot/examples/standalone/atmel_df_pow2.c:169: undefined reference to `spi_claim_bus' ... and so on ...
I imagine the majority of boards will have the same issues.
Peter

On Wednesday 22 July 2009 00:52:51 Peter Tyser wrote:
--- a/examples/standalone/Makefile +++ b/examples/standalone/Makefile @@ -86,6 +86,10 @@ ELF = hello_world SREC = hello_world.srec BIN = hello_world.bin
+ELF += atmel_df_pow2 +SREC += atmel_df_pow2.srec +BIN += atmel_df_pow2.bin
These new files aren't going to compile for a lot of boards as is, some conditional compilation will be necessary.
you'll have to be a little more specific. this driver only uses common spi functions, so no, there shouldnt be any build failures.
The majority of boards don't have SPI functionality.
which is irrelevant as the export code takes care of always providing the symbols used.
I just tried applying this patch, moving atmel_df_pow2 into examples/standalone, and I get:
ptyser@ptyser-laptop u-boot $ make mrproper ptyser@ptyser-laptop u-boot $ make XPEDITE5370_config Configuring for XPEDITE5370 board... ptyser@ptyser-laptop u-boot $ make -s atmel_df_pow2.c:16: warning: 'struct spi_slave' declared inside parameter list atmel_df_pow2.c:16: warning: its scope is only this definition or declaration, which is probably not what you want atmel_df_pow2.c: In function 'flash_cmd': atmel_df_pow2.c:19: warning: implicit declaration of function 'spi_xfer' atmel_df_pow2.c:19: error: 'SPI_XFER_BEGIN' undeclared (first use in this function) ... and so on ...
Adding #include <spi.h> gets rid of some warnings
well if you dont apply the patch properly, that's an error on your part, not mine.
but there's still a number of undefined references: ptyser@ptyser-laptop u-boot $ make -s atmel_df_pow2.o: In function `atmel_df_pow2': /home/ptyser/u-boot/examples/standalone/atmel_df_pow2.c:129: undefined reference to `spi_init' /home/ptyser/u-boot/examples/standalone/atmel_df_pow2.c:163: undefined reference to `spi_setup_slave' /home/ptyser/u-boot/examples/standalone/atmel_df_pow2.c:169: undefined reference to `spi_claim_bus' ... and so on ...
looks like you still didnt do it right. stubs.o will always end up with stub symbols which are always provided for standalone applications. -mike

On Wednesday 22 July 2009 01:25:45 Mike Frysinger wrote:
On Wednesday 22 July 2009 00:52:51 Peter Tyser wrote:
but there's still a number of undefined references: ptyser@ptyser-laptop u-boot $ make -s atmel_df_pow2.o: In function `atmel_df_pow2': /home/ptyser/u-boot/examples/standalone/atmel_df_pow2.c:129: undefined reference to `spi_init' /home/ptyser/u-boot/examples/standalone/atmel_df_pow2.c:163: undefined reference to `spi_setup_slave' /home/ptyser/u-boot/examples/standalone/atmel_df_pow2.c:169: undefined reference to `spi_claim_bus' ... and so on ...
looks like you still didnt do it right. stubs.o will always end up with stub symbols which are always provided for standalone applications.
my guess is you didnt apply the "export SPI functions to standalone apps" patch -mike

I just tried applying this patch, moving atmel_df_pow2 into examples/standalone, and I get:
ptyser@ptyser-laptop u-boot $ make mrproper ptyser@ptyser-laptop u-boot $ make XPEDITE5370_config Configuring for XPEDITE5370 board... ptyser@ptyser-laptop u-boot $ make -s atmel_df_pow2.c:16: warning: 'struct spi_slave' declared inside parameter list atmel_df_pow2.c:16: warning: its scope is only this definition or declaration, which is probably not what you want atmel_df_pow2.c: In function 'flash_cmd': atmel_df_pow2.c:19: warning: implicit declaration of function 'spi_xfer' atmel_df_pow2.c:19: error: 'SPI_XFER_BEGIN' undeclared (first use in this function) ... and so on ...
Adding #include <spi.h> gets rid of some warnings
well if you dont apply the patch properly, that's an error on your part, not mine.
I applied this patch properly, but had no idea it had a dependency as you didn't mention it in the patch. Applying "export SPI functions to standalone apps" resolved the build issue (after moving atmel_df_pow2.c to its proper location).
Still, why not make this file's compilation dependent on some define like CONFIG_ATMEL_DATAFLASH_SPI (or whatever is appropriate) when you resubmit? I have no interest in compiling it for any boards I use...
Peter

On Wednesday 22 July 2009 01:53:05 Peter Tyser wrote:
Still, why not make this file's compilation dependent on some define like CONFIG_ATMEL_DATAFLASH_SPI (or whatever is appropriate) when you resubmit? I have no interest in compiling it for any boards I use...
the current standalone Makefile isnt setup for conditional compilation, and there's multiple config options that would enable this. feel free to submit a patch for the first issue and if it does get merged, i'll look into it. -mike
participants (3)
-
Andrzej Wolski
-
Mike Frysinger
-
Peter Tyser