EFM32 Wonder Gecko Family support
[openocd.git] / src / flash / nor / efm32.c
index 57566499908e54d74c7946ca136e5e8e7838e2bd..858bb0a70885257d3f3799baef33b39e8ebe4b59 100644 (file)
@@ -24,7 +24,7 @@
  *   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.,                                       *
- *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.           *
  ***************************************************************************/
 
 #ifdef HAVE_CONFIG_H
@@ -42,6 +42,7 @@
 #define EFM_FAMILY_ID_GIANT_GECKO       72
 #define EFM_FAMILY_ID_TINY_GECKO        73
 #define EFM_FAMILY_ID_LEOPARD_GECKO     74
+#define EFM_FAMILY_ID_WONDER_GECKO      75
 
 #define EFM32_FLASH_ERASE_TMO           100
 #define EFM32_FLASH_WDATAREADY_TMO      100
@@ -85,7 +86,7 @@
 
 struct efm32x_flash_bank {
        int probed;
-       uint8_t lb_page[LOCKBITS_PAGE_SZ];
+       uint32_t lb_page[LOCKBITS_PAGE_SZ/4];
 };
 
 struct efm32_info {
@@ -139,8 +140,10 @@ static int efm32x_read_info(struct flash_bank *bank,
 
        if (((cpuid >> 4) & 0xfff) == 0xc23) {
                /* Cortex M3 device */
+       } else if (((cpuid >> 4) & 0xfff) == 0xc24) {
+               /* Cortex M4 device */
        } else {
-               LOG_ERROR("Target is not CortexM3");
+               LOG_ERROR("Target is not CortexM3 or M4");
                return ERROR_FAIL;
        }
 
@@ -169,17 +172,37 @@ static int efm32x_read_info(struct flash_bank *bank,
                efm32_info->page_size = 512;
        else if (EFM_FAMILY_ID_GIANT_GECKO == efm32_info->part_family ||
                        EFM_FAMILY_ID_LEOPARD_GECKO == efm32_info->part_family) {
-               uint8_t pg_size = 0;
+               if (efm32_info->prod_rev >= 18) {
+                       uint8_t pg_size = 0;
+                       ret = target_read_u8(bank->target, EFM32_MSC_DI_PAGE_SIZE,
+                               &pg_size);
+                       if (ERROR_OK != ret)
+                               return ret;
+
+                       efm32_info->page_size = (1 << ((pg_size+10) & 0xff));
+               } else {
+                       /* EFM32 GG/LG errata: MEM_INFO_PAGE_SIZE is invalid
+                          for MCUs with PROD_REV < 18 */
+                       if (efm32_info->flash_sz_kib < 512)
+                               efm32_info->page_size = 2048;
+                       else
+                               efm32_info->page_size = 4096;
+               }
 
+               if ((2048 != efm32_info->page_size) &&
+                               (4096 != efm32_info->page_size)) {
+                       LOG_ERROR("Invalid page size %u", efm32_info->page_size);
+                       return ERROR_FAIL;
+               }
+       } else if (EFM_FAMILY_ID_WONDER_GECKO == efm32_info->part_family) {
+               uint8_t pg_size = 0;
                ret = target_read_u8(bank->target, EFM32_MSC_DI_PAGE_SIZE,
                        &pg_size);
                if (ERROR_OK != ret)
                        return ret;
 
                efm32_info->page_size = (1 << ((pg_size+10) & 0xff));
-
-               if ((2048 != efm32_info->page_size) &&
-                               (4096 != efm32_info->page_size)) {
+               if (2048 != efm32_info->page_size) {
                        LOG_ERROR("Invalid page size %u", efm32_info->page_size);
                        return ERROR_FAIL;
                }
@@ -284,7 +307,7 @@ static int efm32x_erase_page(struct flash_bank *bank, uint32_t addr)
        int ret = 0;
        uint32_t status = 0;
 
-       LOG_DEBUG("erasing flash page at 0x%08x", addr);
+       LOG_DEBUG("erasing flash page at 0x%08" PRIx32, addr);
 
        ret = target_write_u32(bank->target, EFM32_MSC_ADDRB, addr);
        if (ERROR_OK != ret)
@@ -299,13 +322,13 @@ static int efm32x_erase_page(struct flash_bank *bank, uint32_t addr)
        if (ERROR_OK != ret)
                return ret;
 
-       LOG_DEBUG("status 0x%x", status);
+       LOG_DEBUG("status 0x%" PRIx32, status);
 
        if (status & EFM32_MSC_STATUS_LOCKED_MASK) {
                LOG_ERROR("Page is locked");
                return ERROR_FAIL;
        } else if (status & EFM32_MSC_STATUS_INVADDR_MASK) {
-               LOG_ERROR("Invalid address 0x%x", addr);
+               LOG_ERROR("Invalid address 0x%" PRIx32, addr);
                return ERROR_FAIL;
        }
 
@@ -362,7 +385,7 @@ static int efm32x_read_lock_data(struct flash_bank *bank)
        data_size = bank->num_sectors / 8; /* number of data bytes */
        data_size /= 4; /* ...and data dwords */
 
-       ptr = (uint32_t *)efm32x_info->lb_page;
+       ptr = efm32x_info->lb_page;
 
        for (i = 0; i < data_size; i++, ptr++) {
                ret = target_read_u32(target, EFM32_MSC_LOCK_BITS+i*4, ptr);
@@ -375,7 +398,7 @@ static int efm32x_read_lock_data(struct flash_bank *bank)
        /* also, read ULW, DLW and MLW */
 
        /* ULW, word 126 */
-       ptr = ((uint32_t *)efm32x_info->lb_page) + 126;
+       ptr = efm32x_info->lb_page + 126;
        ret = target_read_u32(target, EFM32_MSC_LOCK_BITS+126*4, ptr);
        if (ERROR_OK != ret) {
                LOG_ERROR("Failed to read ULW");
@@ -383,7 +406,7 @@ static int efm32x_read_lock_data(struct flash_bank *bank)
        }
 
        /* DLW, word 127 */
-       ptr = ((uint32_t *)efm32x_info->lb_page) + 127;
+       ptr = efm32x_info->lb_page + 127;
        ret = target_read_u32(target, EFM32_MSC_LOCK_BITS+127*4, ptr);
        if (ERROR_OK != ret) {
                LOG_ERROR("Failed to read DLW");
@@ -391,7 +414,7 @@ static int efm32x_read_lock_data(struct flash_bank *bank)
        }
 
        /* MLW, word 125, present in GG and LG */
-       ptr = ((uint32_t *)efm32x_info->lb_page) + 125;
+       ptr = efm32x_info->lb_page + 125;
        ret = target_read_u32(target, EFM32_MSC_LOCK_BITS+125*4, ptr);
        if (ERROR_OK != ret) {
                LOG_ERROR("Failed to read MLW");
@@ -412,14 +435,14 @@ static int efm32x_write_lock_data(struct flash_bank *bank)
                return ret;
        }
 
-       return efm32x_write(bank, efm32x_info->lb_page, EFM32_MSC_LOCK_BITS,
+       return efm32x_write(bank, (uint8_t *)efm32x_info->lb_page, EFM32_MSC_LOCK_BITS,
                LOCKBITS_PAGE_SZ);
 }
 
 static int efm32x_get_page_lock(struct flash_bank *bank, size_t page)
 {
        struct efm32x_flash_bank *efm32x_info = bank->driver_priv;
-       uint32_t dw = ((uint32_t *)efm32x_info->lb_page)[page >> 5];
+       uint32_t dw = efm32x_info->lb_page[page >> 5];
        uint32_t mask = 0;
 
        mask = 1 << (page & 0x1f);
@@ -430,7 +453,7 @@ static int efm32x_get_page_lock(struct flash_bank *bank, size_t page)
 static int efm32x_set_page_lock(struct flash_bank *bank, size_t page, int set)
 {
        struct efm32x_flash_bank *efm32x_info = bank->driver_priv;
-       uint32_t *dw = &((uint32_t *)efm32x_info->lb_page)[page >> 5];
+       uint32_t *dw = &efm32x_info->lb_page[page >> 5];
        uint32_t mask = 0;
 
        mask = 1 << (page & 0x1f);
@@ -570,8 +593,7 @@ static int efm32x_write_block(struct flash_bank *bank, uint8_t *buf,
        };
 
        ret = target_write_buffer(target, write_algorithm->address,
-               sizeof(efm32x_flash_write_code),
-               (uint8_t *)efm32x_flash_write_code);
+                       sizeof(efm32x_flash_write_code), efm32x_flash_write_code);
        if (ret != ERROR_OK)
                return ret;
 
@@ -602,7 +624,7 @@ static int efm32x_write_block(struct flash_bank *bank, uint8_t *buf,
        buf_set_u32(reg_params[4].value, 0, 32, address);
 
        armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
-       armv7m_info.core_mode = ARMV7M_MODE_ANY;
+       armv7m_info.core_mode = ARM_MODE_THREAD;
 
        ret = target_run_flash_async_algorithm(target, buf, count, 4,
                        0, NULL,
@@ -673,13 +695,13 @@ static int efm32x_write_word(struct flash_bank *bank, uint32_t addr,
        if (ERROR_OK != ret)
                return ret;
 
-       LOG_DEBUG("status 0x%x", status);
+       LOG_DEBUG("status 0x%" PRIx32, status);
 
        if (status & EFM32_MSC_STATUS_LOCKED_MASK) {
                LOG_ERROR("Page is locked");
                return ERROR_FAIL;
        } else if (status & EFM32_MSC_STATUS_INVADDR_MASK) {
-               LOG_ERROR("Invalid address 0x%x", addr);
+               LOG_ERROR("Invalid address 0x%" PRIx32, addr);
                return ERROR_FAIL;
        }
 
@@ -739,7 +761,7 @@ static int efm32x_write(struct flash_bank *bank, uint8_t *buffer,
                                "for padding buffer");
                        return ERROR_FAIL;
                }
-               LOG_INFO("odd number of bytes to write (%d), extending to %d "
+               LOG_INFO("odd number of bytes to write (%" PRIu32 "), extending to %" PRIu32 " "
                        "and padding with 0xff", old_count, count);
                memset(buffer, 0xff, count);
                buffer = memcpy(new_buffer, buffer, old_count);
@@ -818,6 +840,9 @@ static int efm32x_probe(struct flash_bank *bank)
                case EFM_FAMILY_ID_LEOPARD_GECKO:
                        LOG_INFO("Leopard Gecko MCU detected");
                        break;
+               case EFM_FAMILY_ID_WONDER_GECKO:
+                       LOG_INFO("Wonder Gecko MCU detected");
+                       break;
                default:
                        LOG_ERROR("Unsupported MCU family %d",
                                efm32_mcu_info.part_family);
@@ -928,6 +953,9 @@ static int get_efm32x_info(struct flash_bank *bank, char *buf, int buf_size)
                case EFM_FAMILY_ID_LEOPARD_GECKO:
                        printed = snprintf(buf, buf_size, "Leopard Gecko");
                        break;
+               case EFM_FAMILY_ID_WONDER_GECKO:
+                       printed = snprintf(buf, buf_size, "Wonder Gecko");
+                       break;
        }
 
        buf += printed;

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)