detect flash chips by jedec ids instead of using hardcoded values

This commit is contained in:
Alexander Couzens 2015-06-02 11:38:54 +02:00
parent 37e46a66f3
commit 07469c59e3
11 changed files with 267 additions and 101 deletions

View File

@ -2,27 +2,3 @@
#include <config.h>
#include <asm/types.h>
#include <flash.h>
/*
* sets up flash_info and returns size of FLASH (bytes)
*/
unsigned long
flash_get_geom (flash_info_t *flash_info)
{
int i;
/* XXX this is hardcoded until we figure out how to read flash id */
flash_info->flash_id = FLASH_M25P64;
flash_info->size = CFG_FLASH_SIZE; /* bytes */
flash_info->sector_count = flash_info->size/CFG_FLASH_SECTOR_SIZE;
for (i = 0; i < flash_info->sector_count; i++) {
flash_info->start[i] = CFG_FLASH_BASE + (i * CFG_FLASH_SECTOR_SIZE);
flash_info->protect[i] = 0;
}
debug ("flash size %d, sector count = %d\n", flash_info->size, flash_info->sector_count);
return (flash_info->size);
}

View File

@ -14,6 +14,18 @@ flash_info_t flash_info[CFG_MAX_FLASH_BANKS];
#undef display
#define display(x) ;
#define SIZE_INBYTES_4MBYTES (4 * 1024 * 1024)
#define SIZE_INBYTES_8MBYTES (2 * SIZE_INBYTES_4MBYTES)
#define SIZE_INBYTES_16MBYTES (2 * SIZE_INBYTES_8MBYTES)
#define SIZE_INBYTES_4KBYTES (4 * 1024)
#define SIZE_INBYTES_64KBYTES (16 * SIZE_INBYTES_4KBYTES)
#ifndef DEFAULT_FLASH_SIZE_IN_MB
#error "DEFAULT_FLASH_SIZE_IN_MB not defined!"
#endif
/*
* statics
*/
@ -24,26 +36,34 @@ static void ar7240_spi_write_page(uint32_t addr, uint8_t * data, int len);
#endif
static void ar7240_spi_sector_erase(uint32_t addr);
static u32
ath_spi_read_id(void)
static ulong read_id(void)
{
u32 rd = 0x777777;
unsigned int flashid = 0;
ar7240_reg_wr_nf(AR7240_SPI_FS, 1);
ar7240_reg_wr_nf(AR7240_SPI_WRITE, AR7240_SPI_CS_DIS);
ar7240_spi_bit_banger(AR7240_SPI_CMD_RDID);
ar7240_spi_delay_8();
ar7240_spi_delay_8();
ar7240_spi_delay_8();
ar7240_spi_go();
rd = ar7240_reg_rd(AR7240_SPI_RD_STATUS);
ar7240_spi_bit_banger(0x9F);
debug("Flash Manuf Id 0x%x, DeviceId0 0x%x, DeviceId1 0x%x\n",
(rd >> 16) & 0xff, (rd >> 8) & 0xff, (rd >> 0) & 0xff);
return rd;
ar7240_spi_delay_8();
ar7240_spi_delay_8();
ar7240_spi_delay_8();
ar7240_spi_delay_8();
flashid = ar7240_reg_rd(AR7240_SPI_RD_STATUS);
/*
* We have 3 bytes:
* - manufacture ID (1b)
* - product ID (2b)
*/
flashid = flashid >> 8;
ar7240_spi_done();
return((ulong)flashid);
}
#ifdef ATH_SST_FLASH
void ar7240_spi_flash_unblock(void)
{
@ -55,25 +75,157 @@ void ar7240_spi_flash_unblock(void)
}
#endif
static void flash_set_geom(int size, int sector_count, int sector_size){
int i;
flash_info_t *info = &flash_info[0];
info->size = size;
info->sector_count = sector_count;
info->sector_size = sector_size;
for(i = 0; i < info->sector_count; i++){
info->start[i] = CFG_FLASH_BASE + (i * info->sector_size);
}
}
unsigned long flash_init(void)
{
#ifndef CONFIG_WASP
#ifdef ATH_SST_FLASH
ar7240_reg_wr_nf(AR7240_SPI_CLOCK, 0x3);
ar7240_spi_flash_unblock();
ar7240_reg_wr(AR7240_SPI_FS, 0);
#else
ar7240_reg_wr_nf(AR7240_SPI_CLOCK, 0x43);
#endif
#endif
ar7240_reg_rmw_set(AR7240_SPI_FS, 1);
ath_spi_read_id();
ar7240_reg_rmw_clear(AR7240_SPI_FS, 1);
flash_info_t *info;
/*
* hook into board specific code to fill flash_info
*/
return (flash_get_geom(&flash_info[0]));
info = &flash_info[0];
// spi flash clock
ar7240_reg_wr(AR7240_SPI_FS, 0x01);
ar7240_reg_wr(AR7240_SPI_CLOCK, 0x43);
ar7240_reg_wr(AR7240_SPI_FS, 0x0);
// get flash id
info->flash_id = read_id();
puts("FLASH: ");
// fill flash info based on JEDEC ID
switch(info->flash_id) {
/*
* 4M flash chips
*/
case 0x010215: // tested
flash_set_geom(SIZE_INBYTES_4MBYTES, 64, SIZE_INBYTES_64KBYTES);
puts("Spansion S25FL032P (4 MB)");
break;
case 0x1F4700:
flash_set_geom(SIZE_INBYTES_4MBYTES, 64, SIZE_INBYTES_64KBYTES);
puts("Atmel AT25DF321 (4 MB)");
break;
case 0x1C3016: // tested
flash_set_geom(SIZE_INBYTES_4MBYTES, 64, SIZE_INBYTES_64KBYTES);
puts("EON EN25Q32 (4 MB)");
break;
case 0x1C3116: // tested
flash_set_geom(SIZE_INBYTES_4MBYTES, 64, SIZE_INBYTES_64KBYTES);
puts("EON EN25F32 (4 MB)");
break;
case 0x202016:
flash_set_geom(SIZE_INBYTES_4MBYTES, 64, SIZE_INBYTES_64KBYTES);
puts("Micron M25P32 (4 MB)");
break;
case 0xEF4016:
flash_set_geom(SIZE_INBYTES_4MBYTES, 64, SIZE_INBYTES_64KBYTES);
puts("Winbond W25Q32 (4 MB)");
break;
case 0xC22016:
flash_set_geom(SIZE_INBYTES_4MBYTES, 64, SIZE_INBYTES_64KBYTES);
puts("Macronix MX25L320 (4 MB)");
break;
/*
* 8M flash chips
*/
case 0x010216:
flash_set_geom(SIZE_INBYTES_8MBYTES, 128, SIZE_INBYTES_64KBYTES);
puts("Spansion S25FL064P (8 MB)");
break;
case 0x1F4800:
flash_set_geom(SIZE_INBYTES_8MBYTES, 128, SIZE_INBYTES_64KBYTES);
puts("Atmel AT25DF641 (8 MB)");
break;
case 0x1C3017: // tested
flash_set_geom(SIZE_INBYTES_8MBYTES, 128, SIZE_INBYTES_64KBYTES);
puts("EON EN25Q64 (8 MB)");
break;
case 0x202017:
flash_set_geom(SIZE_INBYTES_8MBYTES, 128, SIZE_INBYTES_64KBYTES);
puts("Micron M25P64 (8 MB)");
break;
case 0xEF4017: // tested
flash_set_geom(SIZE_INBYTES_8MBYTES, 128, SIZE_INBYTES_64KBYTES);
puts("Winbond W25Q64 (8 MB)");
break;
case 0xC22017: // tested
case 0xC22617:
flash_set_geom(SIZE_INBYTES_8MBYTES, 128, SIZE_INBYTES_64KBYTES);
puts("Macronix MX25L64 (8 MB)");
break;
/*
* 16M flash chips
*/
case 0xEF4018: // tested
flash_set_geom(SIZE_INBYTES_16MBYTES, 256, SIZE_INBYTES_64KBYTES);
puts("Winbond W25Q128 (16 MB)");
break;
case 0xC22018:
case 0xC22618:
flash_set_geom(SIZE_INBYTES_16MBYTES, 256, SIZE_INBYTES_64KBYTES);
puts("Macronix MX25L128 (16 MB)");
break;
case 0x012018:
flash_set_geom(SIZE_INBYTES_16MBYTES, 256, SIZE_INBYTES_64KBYTES);
puts("Spansion S25FL127S (16 MB)");
break;
case 0x20BA18:
flash_set_geom(SIZE_INBYTES_16MBYTES, 256, SIZE_INBYTES_64KBYTES);
puts("Micron N25Q128 (16 MB)");
break;
/*
* Unknown flash
*/
default:
#if (DEFAULT_FLASH_SIZE_IN_MB == 4)
flash_set_geom(SIZE_INBYTES_4MBYTES, 64, SIZE_INBYTES_64KBYTES);
puts("Unknown type (using only 4 MB)\n");
#elif (DEFAULT_FLASH_SIZE_IN_MB == 8)
flash_set_geom(SIZE_INBYTES_8MBYTES, 128, SIZE_INBYTES_64KBYTES);
puts("Unknown type (using only 8 MB)\n");
#elif (DEFAULT_FLASH_SIZE_IN_MB == 16)
flash_set_geom(SIZE_INBYTES_16MBYTES, 256, SIZE_INBYTES_64KBYTES);
puts("Unknown type (using only 16 MB)\n");
#endif
printf("\nPlease, send request to add support\nfor your FLASH - JEDEC ID: 0x%06lX\n", info->flash_id);
info->flash_id = FLASH_CUSTOM;
break;
}
puts("\n");
return(info->size);
}
void
@ -103,7 +255,7 @@ flash_erase(flash_info_t *info, int s_first, int s_last)
show_activity(3);
#endif
#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
WATCHDOG_RESET();
WATCHDOG_RESET();
#endif
#endif

View File

@ -59,6 +59,6 @@
#define ar7240_spi_delay_8() ar7240_spi_bit_banger(0)
#define ar7240_spi_done() ar7240_reg_wr_nf(AR7240_SPI_FS, 0)
extern unsigned long flash_get_geom (flash_info_t *flash_info);
extern unsigned long flash_get_geom (flash_info_t *flash_info, u32 flashid);
#endif /*_FLASH_H*/

View File

@ -22,7 +22,10 @@
*/
#include <common.h>
#include <ar7240_soc.h>
#include <asm/addrspace.h>
#include <command.h>
#include <malloc.h>
#ifdef CFG_CMD_SETMAC
@ -113,25 +116,29 @@ static int backup_calibration(u8 *buffer)
{
int rc = -1;
ulong sector_size = flash_info[0].sector_size;
ushort cal_sector = flash_info[0].sector_count -1;
u8 *board_cal = (u8 *) (KSEG1ADDR(AR7240_SPI_BASE) + cal_sector * flash_info[0].sector_size);
/* read */
memcpy(buffer, (void *)BOARDCAL, CFG_FLASH_SECTOR_SIZE);
memcpy(buffer, (void *)board_cal, sector_size);
/* erase */
rc = flash_erase(flash_info, CAL_SECTOR-1, CAL_SECTOR-1);
rc = flash_erase(flash_info, cal_sector-1, cal_sector-1);
if (rc) {
printf("Backup failed because flash erase failed! rc %d\n", rc);
return 1;
}
/* cp */
rc = write_buff(flash_info, buffer, BOARDCAL-CFG_FLASH_SECTOR_SIZE, CFG_FLASH_SECTOR_SIZE);
/* writing into flash - we use the mapped flash as source */
rc = write_buff(flash_info, buffer, board_cal - sector_size, sector_size);
if (rc) {
printf("Backup failed because write to flash failed! rc %d\n", rc);
return 1;
}
/* compare */
if (memcmp(buffer, (void *)BOARDCAL-CFG_FLASH_SECTOR_SIZE, CFG_FLASH_SECTOR_SIZE)) {
if (memcmp(buffer, (void *)board_cal - sector_size, sector_size)) {
printf("Backup failed. Read back different value!\n");
return 1;
}
@ -144,8 +151,12 @@ int write_mac(u8 *buffer, u8 macs[ARRAY_SIZE(mac_location)][ETH_ALEN])
int i;
int rc;
ulong sector_size = flash_info[0].sector_size;
ushort cal_sector = flash_info[0].sector_count -1;
u8 *board_cal = (u8 *) (KSEG1ADDR(AR7240_SPI_BASE) + cal_sector * flash_info[0].sector_size);
/* read */
memcpy(buffer, (void *)BOARDCAL, CFG_FLASH_SECTOR_SIZE);
memcpy(buffer, (void *)board_cal, sector_size);
/* set macs */
for(i=0; i<ARRAY_SIZE(mac_location); i++) {
@ -153,14 +164,14 @@ int write_mac(u8 *buffer, u8 macs[ARRAY_SIZE(mac_location)][ETH_ALEN])
}
/* erase */
rc = flash_erase(flash_info, CAL_SECTOR, CAL_SECTOR);
rc = flash_erase(flash_info, cal_sector, cal_sector);
if (rc) {
printf("Write mac failed because flash_erase failed! rc %d\n", rc);
return 1;
}
/* write */
rc = write_buff(flash_info, buffer, BOARDCAL, CFG_FLASH_SECTOR_SIZE);
rc = write_buff(flash_info, buffer, board_cal, sector_size);
if (rc) {
printf("Write mac failed because write_buff failed! rc %d\n", rc);
return 1;
@ -171,10 +182,14 @@ int write_mac(u8 *buffer, u8 macs[ARRAY_SIZE(mac_location)][ETH_ALEN])
int do_setmac(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
u8 buffer[CFG_FLASH_SECTOR_SIZE];
ulong sector_size = flash_info[0].sector_size;
ushort cal_sector = flash_info[0].sector_count -1;
u8 *buffer;
u8 macs[ARRAY_SIZE(mac_location)][ETH_ALEN];
int i;
bool do_backup = true;
int rc;
/* valid arguments are:
* set_mac <mac0> <mac1> [..] or set_mac <mac0> <mac1> [..] nobackup
@ -210,26 +225,42 @@ int do_setmac(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
}
}
buffer = malloc(sector_size);
if (!buffer) {
printf("Could not allocate memory");
return CMD_RET_FAILURE;
}
if (do_backup) {
if (backup_calibration(buffer)) {
printf("Backup failed to the sector before calibration. Not updating calibration sector!");
return CMD_RET_FAILURE;
printf("Backup failed to the sector before calibration.\n"
"Not updating calibration sector!\n");
rc = CMD_RET_FAILURE;
goto out;
}
}
if (!write_mac(buffer, macs)) {
return CMD_RET_FAILURE;
rc = CMD_RET_FAILURE;
goto out;
}
return CMD_RET_SUCCESS;
rc = CMD_RET_SUCCESS;
out:
free(buffer);
return rc;
}
int do_showmac(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
int i = 0;
u8 buffer[CFG_FLASH_SECTOR_SIZE];
u8 *buffer;
u8 *mac;
memcpy(buffer, (void *)BOARDCAL, CFG_FLASH_SECTOR_SIZE);
ushort cal_sector = flash_info[0].sector_count -1;
u8 *board_cal = (u8 *) (KSEG1ADDR(AR7240_SPI_BASE) + cal_sector * flash_info[0].sector_size);
/* using mapped spi memory */
buffer = (void *)board_cal;
for (i=0; i < ARRAY_SIZE(mac_location); i++) {
mac = buffer + mac_location[i];
@ -242,10 +273,13 @@ int do_showmac(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
int do_setserial(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
u8 buffer[CFG_FLASH_SECTOR_SIZE];
u8 *buffer;
int32_t *serial;
int32_t serial_number;
int rc;
ulong sector_size = flash_info[0].sector_size;
ushort cal_sector = flash_info[0].sector_count -1;
u8 *board_cal = KSEG1ADDR(AR7240_SPI_BASE) + cal_sector * flash_info[0].sector_size;
if (argc != 2)
return CMD_RET_FAILURE;
@ -256,37 +290,51 @@ int do_setserial(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
return CMD_RET_FAILURE;
}
buffer = malloc(sector_size);
if (!buffer) {
printf("Could not allocate memory");
return CMD_RET_FAILURE;
}
/* read */
memcpy(buffer, (void *)BOARDCAL, CFG_FLASH_SECTOR_SIZE);
memcpy(buffer, (void *)board_cal, sector_size);
/* set serial number */
serial = (int32_t *) (buffer + SERIAL_LOCATION);
*serial = serial_number;
/* erase */
rc = flash_erase(flash_info, CAL_SECTOR, CAL_SECTOR);
rc = flash_erase(flash_info, cal_sector, cal_sector);
if (rc) {
printf("Write serial failed because flash_erase failed! rc %d\n", rc);
return 1;
rc = CMD_RET_SUCCESS;
goto out;
}
/* write */
rc = write_buff(flash_info, buffer, BOARDCAL, CFG_FLASH_SECTOR_SIZE);
rc = write_buff(flash_info, buffer, board_cal, sector_size);
if (rc) {
printf("Write serial failed because write_buff failed! rc %d\n", rc);
return 1;
rc = CMD_RET_FAILURE;
goto out;
}
printf("Set serial to %d\n", serial_number);
rc = CMD_RET_SUCCESS;
return CMD_RET_SUCCESS;
out:
free(buffer);
return rc;
}
int do_showserial(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
u8 buffer[CFG_FLASH_SECTOR_SIZE];
ulong sector_size = flash_info[0].sector_size;
ushort cal_sector = flash_info[0].sector_count -1;
u8 *board_cal = KSEG1ADDR(AR7240_SPI_BASE) + cal_sector * flash_info[0].sector_size;
u8 *buffer = board_cal;
int32_t *serial;
memcpy(buffer, (void *)BOARDCAL, CFG_FLASH_SECTOR_SIZE);
serial = (int32_t *) (buffer + SERIAL_LOCATION);
printf("serial %d\n", *serial);

View File

@ -21,11 +21,8 @@
* FLASH and environment organization
*-----------------------------------------------------------------------
*/
#define CFG_MAX_FLASH_BANKS 1
#define CFG_MAX_FLASH_SECT 256
#define CFG_FLASH_SECTOR_SIZE (64*1024)
#define CFG_FLASH_SIZE 0x01000000
#define DEFAULT_FLASH_SIZE_IN_MB 16
#define BOARDCAL 0x9fff0000

View File

@ -22,10 +22,7 @@
*-----------------------------------------------------------------------
*/
#define CFG_MAX_FLASH_BANKS 1
#define CFG_MAX_FLASH_SECT 128
#define CFG_FLASH_SECTOR_SIZE (64*1024)
#define CFG_FLASH_SIZE 0x00800000
#define DEFAULT_FLASH_SIZE_IN_MB 16
#define BOARDCAL 0x9f7f0000

View File

@ -22,10 +22,7 @@
*-----------------------------------------------------------------------
*/
#define CFG_MAX_FLASH_BANKS 1
#define CFG_MAX_FLASH_SECT 256
#define CFG_FLASH_SECTOR_SIZE (64*1024)
#define CFG_FLASH_SIZE 0x01000000
#define DEFAULT_FLASH_SIZE_IN_MB 16
#define BOARDCAL 0x9fff0000

View File

@ -5,6 +5,9 @@
* We boot from this flash
*/
#define CFG_FLASH_BASE 0x9f000000
#define CFG_MAX_FLASH_SECT 4096
#define CFG_MAX_FLASH_BANKS 1
#define CFG_MAX_FLASH_SECT 256
#define CFG_CMD_SETMAC

View File

@ -21,11 +21,8 @@
* FLASH and environment organization
*-----------------------------------------------------------------------
*/
#define CFG_MAX_FLASH_BANKS 1
#define CFG_MAX_FLASH_SECT 256
#define CFG_FLASH_SECTOR_SIZE (64*1024)
#define CFG_FLASH_SIZE 0x01000000
#define DEFAULT_FLASH_SIZE_IN_MB 16
#define BOARDCAL 0x9fff0000

View File

@ -22,10 +22,7 @@
*-----------------------------------------------------------------------
*/
#define CFG_MAX_FLASH_BANKS 1
#define CFG_MAX_FLASH_SECT 256
#define CFG_FLASH_SECTOR_SIZE (64*1024)
#define CFG_FLASH_SIZE 0x01000000
#define DEFAULT_FLASH_SIZE_IN_MB 16
#define BOARDCAL 0x9fff0000

View File

@ -31,6 +31,7 @@
typedef struct {
ulong size; /* total bank size in bytes */
ulong sector_size; /* size of erase unit in bytes */
ushort sector_count; /* number of erase units */
ulong flash_id; /* combined device & manufacturer code */
ulong start[CFG_MAX_FLASH_SECT]; /* physical sector start addresses */
@ -418,6 +419,7 @@ extern void flash_read_factory_serial(flash_info_t * info, void * buffer, int of
#define FLASH_M25P64 0x00F2
#define FLASH_CUSTOM 0x1111
#define FLASH_UNKNOWN 0xFFFF /* unknown flash type */