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>__archive__
parent
d5a2c0c10e
commit
32b67ee3c9
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -30,6 +30,8 @@ struct cfi_flash_bank {
|
|||
int not_cfi;
|
||||
int probed;
|
||||
|
||||
enum target_endianness endianness;
|
||||
|
||||
uint16_t manufacturer;
|
||||
uint16_t device_id;
|
||||
|
||||
|
|
Loading…
Reference in New Issue