cfi: support for 16-bit flash with reversed endianness 41/3041/4
authorEsben Haabendal <esben@haabendal.dk>
Fri, 23 Oct 2015 08:12:59 +0000 (10:12 +0200)
committerAndreas Fritiofson <andreas.fritiofson@gmail.com>
Sat, 13 Feb 2016 23:09:40 +0000 (23:09 +0000)
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>
doc/openocd.texi
src/flash/nor/cfi.c
src/flash/nor/cfi.h

index 2e451140ee706bc7bb3d16ff564030d044d208ed..acda084d94e98d2a98ee4a800fda8f5010f76f1f 100644 (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)
index efa0aeecf00a5c96aca8f43e039e6a1247f90d71..b808830010250e1731cc3ced3d22021a53207925 100644 (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;
 
index d92fcc0b1d85bf211d8fa003fbccb581c9629159..5bd25e97241294831208c66dec19246a01f7e155 100644 (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;
 

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)