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>master
parent
cb95c7a935
commit
65f6f07b72
@ -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); |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue