Support for SST 39VF3201C NOR flash 49/1449/6
authorIS2T <devel@is2t.com>
Wed, 19 Jun 2013 06:03:17 +0000 (08:03 +0200)
committerSpencer Oliver <spen@spen-soft.co.uk>
Mon, 1 Jul 2013 08:39:36 +0000 (08:39 +0000)
 * Add Thumb-2 code to write flash memories that don't support DQ5 polling
 * Make sure default values for unlock commands are set even if there is no PRI information given by the flash
 * Add a fixup to disable DQ5 polling for the SST 39VF3201C

Change-Id: Ib08cf20547d0f500d5f78241521e6b49050c3d40
Signed-off-by: IS2T development team <dev.is2t@gmail.com>
Reviewed-on: http://openocd.zylin.com/1449
Tested-by: jenkins
Reviewed-by: Spencer Oliver <spen@spen-soft.co.uk>
contrib/loaders/flash/armv7m_cfi_span_16_dq7.s [new file with mode: 0644]
src/flash/nor/cfi.c
src/flash/nor/cfi.h

diff --git a/contrib/loaders/flash/armv7m_cfi_span_16_dq7.s b/contrib/loaders/flash/armv7m_cfi_span_16_dq7.s
new file mode 100644 (file)
index 0000000..5b29a3b
--- /dev/null
@@ -0,0 +1,72 @@
+/***************************************************************************
+ *   Copyright (C) 2005, 2007 by Dominic Rath                              *
+ *   Dominic.Rath@gmx.de                                                   *
+ *   Copyright (C) 2010 Spencer Oliver                                     *
+ *   spen@spen-soft.co.uk                                                  *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.           *
+ ***************************************************************************/
+
+       .text
+       .syntax unified
+       .arch armv7-m
+       .thumb
+       .thumb_func
+
+       .align 2
+
+/* input parameters - */
+/*     R0 = source address */
+/*     R1 = destination address */
+/*     R2 = number of writes */
+/*     R3 = flash write command */
+/*     R4 = constant to mask DQ7 bits */
+/* output parameters - */
+/*     R5 = 0x80 ok 0x00 bad */
+/* temp registers - */
+/*     R6 = value read from flash to test status */
+/*     R7 = holding register */
+/* unlock registers - */
+/*  R8 = unlock1_addr */
+/*  R9 = unlock1_cmd */
+/*  R10 = unlock2_addr */
+/*  R11 = unlock2_cmd */
+
+code:
+       ldrh    r5, [r0], #2
+       strh    r9, [r8]
+       strh    r11, [r10]
+       strh    r3, [r8]
+       strh    r5, [r1]
+       nop
+busy:
+       ldrh    r6, [r1]
+       eor             r7, r5, r6
+       ands    r7, r4, r7
+       bne             busy
+       subs    r2, r2, #1      /* 0x1 */
+       beq             success
+       add             r1, r1, #2      /* 0x2 */
+       b               code
+
+success:
+       mov             r5, #128        /* 0x80 */
+       b               done
+
+done:
+       bkpt #0
+
+       .end
index 9fe1173af7572ccbf5504b27125dd5ba8dbb5bbe..c443de2dd666669cb1e497ce2c2ced3842fd03c5 100644 (file)
 #define AT49BV6416      0x00d6
 #define AT49BV6416T     0x00d2
 
-static struct cfi_unlock_addresses cfi_unlock_addresses[] = {
+static const struct cfi_unlock_addresses cfi_unlock_addresses[] = {
        [CFI_UNLOCK_555_2AA] = { .unlock1 = 0x555, .unlock2 = 0x2aa },
        [CFI_UNLOCK_5555_2AAA] = { .unlock1 = 0x5555, .unlock2 = 0x2aaa },
 };
 
+static const int cfi_status_poll_mask_dq6_dq7 = CFI_STATUS_POLL_MASK_DQ6_DQ7;
+
 /* CFI fixups forward declarations */
-static void cfi_fixup_0002_erase_regions(struct flash_bank *bank, void *param);
-static void cfi_fixup_0002_unlock_addresses(struct flash_bank *bank, void *param);
-static void cfi_fixup_reversed_erase_regions(struct flash_bank *bank, void *param);
-static void cfi_fixup_0002_write_buffer(struct flash_bank *bank, void *param);
+static void cfi_fixup_0002_erase_regions(struct flash_bank *bank, const void *param);
+static void cfi_fixup_0002_unlock_addresses(struct flash_bank *bank, const void *param);
+static void cfi_fixup_reversed_erase_regions(struct flash_bank *bank, const void *param);
+static void cfi_fixup_0002_write_buffer(struct flash_bank *bank, const void *param);
+static void cfi_fixup_0002_polling_bits(struct flash_bank *bank, const void *param);
 
 /* fixup after reading cmdset 0002 primary query table */
 static const struct cfi_fixup cfi_0002_fixups[] = {
@@ -71,6 +74,8 @@ static const struct cfi_fixup cfi_0002_fixups[] = {
         &cfi_unlock_addresses[CFI_UNLOCK_5555_2AAA]},
        {CFI_MFR_SST, 0x274b, cfi_fixup_0002_unlock_addresses,
         &cfi_unlock_addresses[CFI_UNLOCK_5555_2AAA]},
+       {CFI_MFR_SST, 0x235f, cfi_fixup_0002_polling_bits,      /* 39VF3201C */
+        &cfi_status_poll_mask_dq6_dq7},
        {CFI_MFR_SST, 0x236d, cfi_fixup_0002_unlock_addresses,
         &cfi_unlock_addresses[CFI_UNLOCK_555_2AA]},
        {CFI_MFR_ATMEL, 0x00C8, cfi_fixup_reversed_erase_regions, NULL},
@@ -522,6 +527,11 @@ static int cfi_read_spansion_pri_ext(struct flash_bank *bank)
        if (retval != ERROR_OK)
                return retval;
 
+       /* default values for implementation specific workarounds */
+       pri_ext->_unlock1 = cfi_unlock_addresses[CFI_UNLOCK_555_2AA].unlock1;
+       pri_ext->_unlock2 = cfi_unlock_addresses[CFI_UNLOCK_555_2AA].unlock2;
+       pri_ext->_reversed_geometry = 0;
+
        if ((pri_ext->pri[0] != 'P') || (pri_ext->pri[1] != 'R') || (pri_ext->pri[2] != 'I')) {
                retval = cfi_send_command(bank, 0xf0, flash_address(bank, 0, 0x0));
                if (retval != ERROR_OK)
@@ -590,11 +600,6 @@ static int cfi_read_spansion_pri_ext(struct flash_bank *bank)
 
        LOG_DEBUG("WP# protection 0x%x", pri_ext->TopBottom);
 
-       /* default values for implementation specific workarounds */
-       pri_ext->_unlock1 = cfi_unlock_addresses[CFI_UNLOCK_555_2AA].unlock1;
-       pri_ext->_unlock2 = cfi_unlock_addresses[CFI_UNLOCK_555_2AA].unlock2;
-       pri_ext->_reversed_geometry = 0;
-
        return ERROR_OK;
 }
 
@@ -1695,7 +1700,7 @@ static int cfi_spansion_write_block(struct flash_bank *bank, uint8_t *buffer,
                0xeafffffe              /* b    81ac <sp_16_done>               */
        };
 
-       /* see contib/loaders/flash/armv7m_cfi_span_16.s for src */
+       /* see contrib/loaders/flash/armv7m_cfi_span_16.s for src */
        static const uint32_t armv7m_word_16_code[] = {
                0x5B02F830,
                0x9000F8A8,
@@ -1717,7 +1722,36 @@ static int cfi_spansion_write_block(struct flash_bank *bank, uint8_t *buffer,
                0x0000BE00
        };
 
-       /* see contib/loaders/flash/armv4_5_cfi_span_16_dq7.s for src */
+       /* see contrib/loaders/flash/armv7m_cfi_span_16_dq7.s for src */
+       static const uint32_t armv7m_word_16_code_dq7only[] = {
+               /* 00000000 <code>: */
+               0x5B02F830,             /* ldrh.w       r5, [r0], #2    */
+               0x9000F8A8,             /* strh.w       r9, [r8]                */
+               0xB000F8AA,             /* strh.w       fp, [sl]                */
+               0x3000F8A8,             /* strh.w       r3, [r8]                */
+               0xBF00800D,             /* strh r5, [r1, #0]            */
+                                               /* nop                                          */
+
+               /* 00000014 <busy>: */
+               0xEA85880E,             /* ldrh r6, [r1, #0]            */
+                                               /* eor.w        r7, r5, r6              */
+               0x40270706,             /* ands         r7, r4                  */
+               0x3A01D1FA,             /* bne.n        14 <busy>               */
+                                               /* subs r2, #1                          */
+               0xF101D002,             /* beq.n        28 <success>    */
+               0xE7EB0102,             /* add.w        r1, r1, #2              */
+                                               /* b.n  0 <code>                        */
+
+               /* 00000028 <success>: */
+               0x0580F04F,             /* mov.w        r5, #128                */
+               0xBF00E7FF,             /* b.n  30 <done>                       */
+                                               /* nop (for alignment purposes) */
+
+               /* 00000030 <done>: */
+               0x0000BE00              /* bkpt 0x0000                          */
+       };
+
+       /* see contrib/loaders/flash/armv4_5_cfi_span_16_dq7.s for src */
        static const uint32_t armv4_5_word_16_code_dq7only[] = {
                /* <sp_16_code>:                                */
                0xe0d050b2,             /* ldrh r5, [r0], #2                    */
@@ -1741,7 +1775,7 @@ static int cfi_spansion_write_block(struct flash_bank *bank, uint8_t *buffer,
                0xeafffffe              /* b    81ac <sp_16_done>               */
        };
 
-       /* see contib/loaders/flash/armv4_5_cfi_span_8.s for src */
+       /* see contrib/loaders/flash/armv4_5_cfi_span_8.s for src */
        static const uint32_t armv4_5_word_8_code[] = {
                /* 000081b0 <sp_16_code_end>:   */
                0xe4d05001,             /* ldrb r5, [r0], #1                    */
@@ -1817,11 +1851,13 @@ static int cfi_spansion_write_block(struct flash_bank *bank, uint8_t *buffer,
                        } else {
                                /* No DQ5 support. Use DQ7 DATA# polling only. */
                                if (is_armv7m(target_to_armv7m(target))) {
-                                       LOG_ERROR("Unknown ARM architecture");
-                                       return ERROR_FAIL;
+                                       /* armv7m target */
+                                       target_code_src = armv7m_word_16_code_dq7only;
+                                       target_code_size = sizeof(armv7m_word_16_code_dq7only);
+                               } else { /* armv4_5 target */
+                                       target_code_src = armv4_5_word_16_code_dq7only;
+                                       target_code_size = sizeof(armv4_5_word_16_code_dq7only);
                                }
-                               target_code_src = armv4_5_word_16_code_dq7only;
-                               target_code_size = sizeof(armv4_5_word_16_code_dq7only);
                        }
                        break;
                case 4:
@@ -2427,7 +2463,7 @@ static int cfi_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offset,
        return cfi_reset(bank);
 }
 
-static void cfi_fixup_reversed_erase_regions(struct flash_bank *bank, void *param)
+static void cfi_fixup_reversed_erase_regions(struct flash_bank *bank, const void *param)
 {
        (void) param;
        struct cfi_flash_bank *cfi_info = bank->driver_priv;
@@ -2436,7 +2472,7 @@ static void cfi_fixup_reversed_erase_regions(struct flash_bank *bank, void *para
        pri_ext->_reversed_geometry = 1;
 }
 
-static void cfi_fixup_0002_erase_regions(struct flash_bank *bank, void *param)
+static void cfi_fixup_0002_erase_regions(struct flash_bank *bank, const void *param)
 {
        int i;
        struct cfi_flash_bank *cfi_info = bank->driver_priv;
@@ -2457,16 +2493,24 @@ static void cfi_fixup_0002_erase_regions(struct flash_bank *bank, void *param)
        }
 }
 
-static void cfi_fixup_0002_unlock_addresses(struct flash_bank *bank, void *param)
+static void cfi_fixup_0002_unlock_addresses(struct flash_bank *bank, const void *param)
 {
        struct cfi_flash_bank *cfi_info = bank->driver_priv;
        struct cfi_spansion_pri_ext *pri_ext = cfi_info->pri_ext;
-       struct cfi_unlock_addresses *unlock_addresses = param;
+       const struct cfi_unlock_addresses *unlock_addresses = param;
 
        pri_ext->_unlock1 = unlock_addresses->unlock1;
        pri_ext->_unlock2 = unlock_addresses->unlock2;
 }
 
+static void cfi_fixup_0002_polling_bits(struct flash_bank *bank, const void *param)
+{
+       struct cfi_flash_bank *cfi_info = bank->driver_priv;
+       const int status_poll_mask = *(const int *)param;
+
+       cfi_info->status_poll_mask = status_poll_mask;
+}
+
 
 static int cfi_query_string(struct flash_bank *bank, int address)
 {
@@ -3028,7 +3072,7 @@ static int get_cfi_info(struct flash_bank *bank, char *buf, int buf_size)
        return ERROR_OK;
 }
 
-static void cfi_fixup_0002_write_buffer(struct flash_bank *bank, void *param)
+static void cfi_fixup_0002_write_buffer(struct flash_bank *bank, const void *param)
 {
        struct cfi_flash_bank *cfi_info = bank->driver_priv;
 
index b587ed48213d17765ad6367458ec84c7778ed0d7..d92fcc0b1d85bf211d8fa003fbccb581c9629159 100644 (file)
@@ -143,8 +143,8 @@ struct cfi_unlock_addresses {
 struct cfi_fixup {
        uint16_t mfr;
        uint16_t id;
-       void (*fixup)(struct flash_bank *bank, void *param);
-       void *param;
+       void (*fixup)(struct flash_bank *bank, const void *param);
+       const void *param;
 };
 
 #define CFI_MFR_AMD            0x0001

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)