cfi: support for 16-bit flash with reversed endianness

This is for targets where flash controller has reverse endianness
compared to target.  For these, the 'bus_swap' parameter can be given to the
CFI driver, which will cause command CFI commands to be written with
bytes swapped.  This is only for x16 CFI flash.

Change-Id: I698b768e92e65d160232e90b0e81a824e3c81a46
Signed-off-by: Esben Haabendal <esben@haabendal.dk>
Reviewed-on: http://openocd.zylin.com/3041
Tested-by: jenkins
Reviewed-by: Spencer Oliver <spen@spen-soft.co.uk>
This commit is contained in:
Esben Haabendal 2015-10-23 10:12:59 +02:00 committed by Andreas Fritiofson
parent d5a2c0c10e
commit 32b67ee3c9
3 changed files with 21 additions and 5 deletions

View File

@ -4806,6 +4806,7 @@ The CFI driver can accept the following optional parameters, in any order:
@item @var{jedec_probe} ... is used to detect certain non-CFI flash ROMs,
like AM29LV010 and similar types.
@item @var{x16_as_x8} ... when a 16-bit flash is hooked up to an 8-bit bus.
@item @var{bus_swap} ... when data bytes in a 16-bit flash needs to be swapped.
@end itemize
To configure two adjacent banks of 16 MBytes each, both sixteen bits (two bytes)

View File

@ -136,6 +136,7 @@ static inline uint32_t flash_address(struct flash_bank *bank, int sector, uint32
static void cfi_command(struct flash_bank *bank, uint8_t cmd, uint8_t *cmd_buf)
{
int i;
struct cfi_flash_bank *cfi_info = bank->driver_priv;
/* clear whole buffer, to ensure bits that exceed the bus_width
* are set to zero
@ -143,7 +144,7 @@ static void cfi_command(struct flash_bank *bank, uint8_t cmd, uint8_t *cmd_buf)
for (i = 0; i < CFI_MAX_BUS_WIDTH; i++)
cmd_buf[i] = 0;
if (bank->target->endianness == TARGET_LITTLE_ENDIAN) {
if (cfi_info->endianness == TARGET_LITTLE_ENDIAN) {
for (i = bank->bus_width; i > 0; i--)
*cmd_buf++ = (i & (bank->chip_width - 1)) ? 0x0 : cmd;
} else {
@ -167,6 +168,7 @@ static int cfi_send_command(struct flash_bank *bank, uint8_t cmd, uint32_t addre
static int cfi_query_u8(struct flash_bank *bank, int sector, uint32_t offset, uint8_t *val)
{
struct target *target = bank->target;
struct cfi_flash_bank *cfi_info = bank->driver_priv;
uint8_t data[CFI_MAX_BUS_WIDTH];
int retval;
@ -175,7 +177,7 @@ static int cfi_query_u8(struct flash_bank *bank, int sector, uint32_t offset, ui
if (retval != ERROR_OK)
return retval;
if (bank->target->endianness == TARGET_LITTLE_ENDIAN)
if (cfi_info->endianness == TARGET_LITTLE_ENDIAN)
*val = data[0];
else
*val = data[bank->bus_width - 1];
@ -190,6 +192,7 @@ static int cfi_query_u8(struct flash_bank *bank, int sector, uint32_t offset, ui
static int cfi_get_u8(struct flash_bank *bank, int sector, uint32_t offset, uint8_t *val)
{
struct target *target = bank->target;
struct cfi_flash_bank *cfi_info = bank->driver_priv;
uint8_t data[CFI_MAX_BUS_WIDTH];
int i;
@ -199,7 +202,7 @@ static int cfi_get_u8(struct flash_bank *bank, int sector, uint32_t offset, uint
if (retval != ERROR_OK)
return retval;
if (bank->target->endianness == TARGET_LITTLE_ENDIAN) {
if (cfi_info->endianness == TARGET_LITTLE_ENDIAN) {
for (i = 0; i < bank->bus_width / bank->chip_width; i++)
data[0] |= data[i];
@ -236,7 +239,7 @@ static int cfi_query_u16(struct flash_bank *bank, int sector, uint32_t offset, u
return retval;
}
if (bank->target->endianness == TARGET_LITTLE_ENDIAN)
if (cfi_info->endianness == TARGET_LITTLE_ENDIAN)
*val = data[0] | data[bank->bus_width] << 8;
else
*val = data[bank->bus_width - 1] | data[(2 * bank->bus_width) - 1] << 8;
@ -266,7 +269,7 @@ static int cfi_query_u32(struct flash_bank *bank, int sector, uint32_t offset, u
return retval;
}
if (bank->target->endianness == TARGET_LITTLE_ENDIAN)
if (cfi_info->endianness == TARGET_LITTLE_ENDIAN)
*val = data[0] | data[bank->bus_width] << 8 |
data[bank->bus_width * 2] << 16 | data[bank->bus_width * 3] << 24;
else
@ -803,6 +806,7 @@ static int cfi_intel_info(struct flash_bank *bank, char *buf, int buf_size)
FLASH_BANK_COMMAND_HANDLER(cfi_flash_bank_command)
{
struct cfi_flash_bank *cfi_info;
int bus_swap = 0;
if (CMD_ARGC < 6)
return ERROR_COMMAND_SYNTAX_ERROR;
@ -836,10 +840,19 @@ FLASH_BANK_COMMAND_HANDLER(cfi_flash_bank_command)
for (unsigned i = 6; i < CMD_ARGC; i++) {
if (strcmp(CMD_ARGV[i], "x16_as_x8") == 0)
cfi_info->x16_as_x8 = 1;
else if (strcmp(CMD_ARGV[i], "bus_swap") == 0)
bus_swap = 1;
else if (strcmp(CMD_ARGV[i], "jedec_probe") == 0)
cfi_info->jedec_probe = 1;
}
if (bus_swap)
cfi_info->endianness =
bank->target->endianness == TARGET_LITTLE_ENDIAN ?
TARGET_BIG_ENDIAN : TARGET_LITTLE_ENDIAN;
else
cfi_info->endianness = bank->target->endianness;
/* bank wasn't probed yet */
cfi_info->qry[0] = 0xff;

View File

@ -30,6 +30,8 @@ struct cfi_flash_bank {
int not_cfi;
int probed;
enum target_endianness endianness;
uint16_t manufacturer;
uint16_t device_id;