flash/nor: add support for Nuvoton NPCX series flash
[fw/openocd] / src / flash / nor / efm32.c
index 479e0d475829bc6dd8c405a6c4270c41664fbdc1..ab0186d7d297b7e9bc66e685bfb61a1dde0b3a1f 100644 (file)
@@ -99,7 +99,7 @@ struct efm32_family_data {
 };
 
 struct efm32x_flash_bank {
-       int probed;
+       bool probed;
        uint32_t lb_page[LOCKBITS_PAGE_SZ/4];
        uint32_t reg_base;
        uint32_t reg_lock;
@@ -169,6 +169,7 @@ static const struct efm32_family_data efm32_families[] = {
                { 91, "EFM32JG13B Jade", .series = 1 },
                { 100, "EFM32GG11B Giant", .series = 1, .msc_regbase = 0x40000000 },
                { 103, "EFM32TG11B Tiny", .series = 1, .msc_regbase = 0x40000000 },
+               { 106, "EFM32GG12B Giant", .series = 1, .msc_regbase = 0x40000000 },
                { 120, "EZR32WG Wonder", .series = 0 },
                { 121, "EZR32LG Leopard", .series = 0 },
                { 122, "EZR32HG Happy", .series = 0, .page_size = 1024 },
@@ -231,7 +232,7 @@ static int efm32x_read_info(struct flash_bank *bank,
        memset(efm32_info, 0, sizeof(struct efm32_info));
 
        ret = target_read_u32(bank->target, CPUID, &cpuid);
-       if (ERROR_OK != ret)
+       if (ret != ERROR_OK)
                return ret;
 
        if (((cpuid >> 4) & 0xfff) == 0xc23) {
@@ -246,23 +247,23 @@ static int efm32x_read_info(struct flash_bank *bank,
        }
 
        ret = efm32x_get_flash_size(bank, &(efm32_info->flash_sz_kib));
-       if (ERROR_OK != ret)
+       if (ret != ERROR_OK)
                return ret;
 
        ret = efm32x_get_ram_size(bank, &(efm32_info->ram_sz_kib));
-       if (ERROR_OK != ret)
+       if (ret != ERROR_OK)
                return ret;
 
        ret = efm32x_get_part_num(bank, &(efm32_info->part_num));
-       if (ERROR_OK != ret)
+       if (ret != ERROR_OK)
                return ret;
 
        ret = efm32x_get_part_family(bank, &(efm32_info->part_family));
-       if (ERROR_OK != ret)
+       if (ret != ERROR_OK)
                return ret;
 
        ret = efm32x_get_prod_rev(bank, &(efm32_info->prod_rev));
-       if (ERROR_OK != ret)
+       if (ret != ERROR_OK)
                return ret;
 
        for (size_t i = 0; i < ARRAY_SIZE(efm32_families); i++) {
@@ -270,7 +271,7 @@ static int efm32x_read_info(struct flash_bank *bank,
                        efm32_info->family_data = &efm32_families[i];
        }
 
-       if (efm32_info->family_data == NULL) {
+       if (!efm32_info->family_data) {
                LOG_ERROR("Unknown MCU family %d", efm32_info->part_family);
                return ERROR_FAIL;
        }
@@ -295,7 +296,7 @@ static int efm32x_read_info(struct flash_bank *bank,
                uint8_t pg_size = 0;
                ret = target_read_u8(bank->target, EFM32_MSC_DI_PAGE_SIZE,
                        &pg_size);
-               if (ERROR_OK != ret)
+               if (ret != ERROR_OK)
                        return ret;
 
                efm32_info->page_size = (1 << ((pg_size+10) & 0xff));
@@ -323,23 +324,7 @@ static int efm32x_read_info(struct flash_bank *bank,
        return ERROR_OK;
 }
 
-/*
- * Helper to create a human friendly string describing a part
- */
-static int efm32x_decode_info(struct efm32_info *info, char *buf, int buf_size)
-{
-       int printed = 0;
-       printed = snprintf(buf, buf_size, "%s Gecko, rev %d",
-                       info->family_data->name, info->prod_rev);
-
-       if (printed >= buf_size)
-               return ERROR_BUF_TOO_SMALL;
-
-       return ERROR_OK;
-}
-
-/* flash bank efm32 <base> <size> 0 0 <target#>
- */
+/* flash bank efm32 <base> <size> 0 0 <target#> */
 FLASH_BANK_COMMAND_HANDLER(efm32x_flash_bank_command)
 {
        struct efm32x_flash_bank *efm32x_info;
@@ -350,7 +335,7 @@ FLASH_BANK_COMMAND_HANDLER(efm32x_flash_bank_command)
        efm32x_info = malloc(sizeof(struct efm32x_flash_bank));
 
        bank->driver_priv = efm32x_info;
-       efm32x_info->probed = 0;
+       efm32x_info->probed = false;
        memset(efm32x_info->lb_page, 0xff, LOCKBITS_PAGE_SZ);
 
        return ERROR_OK;
@@ -364,7 +349,7 @@ static int efm32x_set_reg_bits(struct flash_bank *bank, uint32_t reg,
        uint32_t reg_val = 0;
 
        ret = efm32x_read_reg_u32(bank, reg, &reg_val);
-       if (ERROR_OK != ret)
+       if (ret != ERROR_OK)
                return ret;
 
        if (set)
@@ -396,12 +381,12 @@ static int efm32x_wait_status(struct flash_bank *bank, int timeout,
 
        while (1) {
                ret = efm32x_read_reg_u32(bank, EFM32_MSC_REG_STATUS, &status);
-               if (ERROR_OK != ret)
+               if (ret != ERROR_OK)
                        break;
 
                LOG_DEBUG("status: 0x%" PRIx32 "", status);
 
-               if (((status & wait_mask) == 0) && (0 == wait_for_set))
+               if (((status & wait_mask) == 0) && (wait_for_set == 0))
                        break;
                else if (((status & wait_mask) != 0) && wait_for_set)
                        break;
@@ -435,16 +420,16 @@ static int efm32x_erase_page(struct flash_bank *bank, uint32_t addr)
        LOG_DEBUG("erasing flash page at 0x%08" PRIx32, addr);
 
        ret = efm32x_write_reg_u32(bank, EFM32_MSC_REG_ADDRB, addr);
-       if (ERROR_OK != ret)
+       if (ret != ERROR_OK)
                return ret;
 
        ret = efm32x_set_reg_bits(bank, EFM32_MSC_REG_WRITECMD,
                EFM32_MSC_WRITECMD_LADDRIM_MASK, 1);
-       if (ERROR_OK != ret)
+       if (ret != ERROR_OK)
                return ret;
 
        ret = efm32x_read_reg_u32(bank, EFM32_MSC_REG_STATUS, &status);
-       if (ERROR_OK != ret)
+       if (ret != ERROR_OK)
                return ret;
 
        LOG_DEBUG("status 0x%" PRIx32, status);
@@ -459,34 +444,34 @@ static int efm32x_erase_page(struct flash_bank *bank, uint32_t addr)
 
        ret = efm32x_set_reg_bits(bank, EFM32_MSC_REG_WRITECMD,
                EFM32_MSC_WRITECMD_ERASEPAGE_MASK, 1);
-       if (ERROR_OK != ret)
+       if (ret != ERROR_OK)
                return ret;
 
        return efm32x_wait_status(bank, EFM32_FLASH_ERASE_TMO,
                EFM32_MSC_STATUS_BUSY_MASK, 0);
 }
 
-static int efm32x_erase(struct flash_bank *bank, int first, int last)
+static int efm32x_erase(struct flash_bank *bank, unsigned int first,
+               unsigned int last)
 {
        struct target *target = bank->target;
-       int i = 0;
        int ret = 0;
 
-       if (TARGET_HALTED != target->state) {
+       if (target->state != TARGET_HALTED) {
                LOG_ERROR("Target not halted");
                return ERROR_TARGET_NOT_HALTED;
        }
 
        efm32x_msc_lock(bank, 0);
        ret = efm32x_set_wren(bank, 1);
-       if (ERROR_OK != ret) {
+       if (ret != ERROR_OK) {
                LOG_ERROR("Failed to enable MSC write");
                return ret;
        }
 
-       for (i = first; i <= last; i++) {
+       for (unsigned int i = first; i <= last; i++) {
                ret = efm32x_erase_page(bank, bank->sectors[i].offset);
-               if (ERROR_OK != ret)
+               if (ret != ERROR_OK)
                        LOG_ERROR("Failed to erase page %d", i);
        }
 
@@ -500,7 +485,6 @@ static int efm32x_read_lock_data(struct flash_bank *bank)
 {
        struct efm32x_flash_bank *efm32x_info = bank->driver_priv;
        struct target *target = bank->target;
-       int i = 0;
        int data_size = 0;
        uint32_t *ptr = NULL;
        int ret = 0;
@@ -512,9 +496,9 @@ static int efm32x_read_lock_data(struct flash_bank *bank)
 
        ptr = efm32x_info->lb_page;
 
-       for (i = 0; i < data_size; i++, ptr++) {
+       for (int i = 0; i < data_size; i++, ptr++) {
                ret = target_read_u32(target, EFM32_MSC_LOCK_BITS+i*4, ptr);
-               if (ERROR_OK != ret) {
+               if (ret != ERROR_OK) {
                        LOG_ERROR("Failed to read PLW %d", i);
                        return ret;
                }
@@ -525,7 +509,7 @@ static int efm32x_read_lock_data(struct flash_bank *bank)
        /* ULW, word 126 */
        ptr = efm32x_info->lb_page + 126;
        ret = target_read_u32(target, EFM32_MSC_LOCK_BITS+126*4, ptr);
-       if (ERROR_OK != ret) {
+       if (ret != ERROR_OK) {
                LOG_ERROR("Failed to read ULW");
                return ret;
        }
@@ -533,7 +517,7 @@ static int efm32x_read_lock_data(struct flash_bank *bank)
        /* DLW, word 127 */
        ptr = efm32x_info->lb_page + 127;
        ret = target_read_u32(target, EFM32_MSC_LOCK_BITS+127*4, ptr);
-       if (ERROR_OK != ret) {
+       if (ret != ERROR_OK) {
                LOG_ERROR("Failed to read DLW");
                return ret;
        }
@@ -541,7 +525,7 @@ static int efm32x_read_lock_data(struct flash_bank *bank)
        /* MLW, word 125, present in GG, LG, PG, JG, EFR32 */
        ptr = efm32x_info->lb_page + 125;
        ret = target_read_u32(target, EFM32_MSC_LOCK_BITS+125*4, ptr);
-       if (ERROR_OK != ret) {
+       if (ret != ERROR_OK) {
                LOG_ERROR("Failed to read MLW");
                return ret;
        }
@@ -549,7 +533,7 @@ static int efm32x_read_lock_data(struct flash_bank *bank)
        /* ALW, word 124, present in GG, LG, PG, JG, EFR32 */
        ptr = efm32x_info->lb_page + 124;
        ret = target_read_u32(target, EFM32_MSC_LOCK_BITS+124*4, ptr);
-       if (ERROR_OK != ret) {
+       if (ret != ERROR_OK) {
                LOG_ERROR("Failed to read ALW");
                return ret;
        }
@@ -557,7 +541,7 @@ static int efm32x_read_lock_data(struct flash_bank *bank)
        /* CLW1, word 123, present in EFR32 */
        ptr = efm32x_info->lb_page + 123;
        ret = target_read_u32(target, EFM32_MSC_LOCK_BITS+123*4, ptr);
-       if (ERROR_OK != ret) {
+       if (ret != ERROR_OK) {
                LOG_ERROR("Failed to read CLW1");
                return ret;
        }
@@ -565,7 +549,7 @@ static int efm32x_read_lock_data(struct flash_bank *bank)
        /* CLW0, word 122, present in GG, LG, PG, JG, EFR32 */
        ptr = efm32x_info->lb_page + 122;
        ret = target_read_u32(target, EFM32_MSC_LOCK_BITS+122*4, ptr);
-       if (ERROR_OK != ret) {
+       if (ret != ERROR_OK) {
                LOG_ERROR("Failed to read CLW0");
                return ret;
        }
@@ -579,7 +563,7 @@ static int efm32x_write_lock_data(struct flash_bank *bank)
        int ret = 0;
 
        ret = efm32x_erase_page(bank, EFM32_MSC_LOCK_BITS);
-       if (ERROR_OK != ret) {
+       if (ret != ERROR_OK) {
                LOG_ERROR("Failed to erase LB page");
                return ret;
        }
@@ -615,10 +599,10 @@ static int efm32x_set_page_lock(struct flash_bank *bank, size_t page, int set)
        return ERROR_OK;
 }
 
-static int efm32x_protect(struct flash_bank *bank, int set, int first, int last)
+static int efm32x_protect(struct flash_bank *bank, int set, unsigned int first,
+               unsigned int last)
 {
        struct target *target = bank->target;
-       int i = 0;
        int ret = 0;
 
        if (!set) {
@@ -631,16 +615,16 @@ static int efm32x_protect(struct flash_bank *bank, int set, int first, int last)
                return ERROR_TARGET_NOT_HALTED;
        }
 
-       for (i = first; i <= last; i++) {
+       for (unsigned int i = first; i <= last; i++) {
                ret = efm32x_set_page_lock(bank, i, set);
-               if (ERROR_OK != ret) {
+               if (ret != ERROR_OK) {
                        LOG_ERROR("Failed to set lock on page %d", i);
                        return ret;
                }
        }
 
        ret = efm32x_write_lock_data(bank);
-       if (ERROR_OK != ret) {
+       if (ret != ERROR_OK) {
                LOG_ERROR("Failed to write LB page");
                return ret;
        }
@@ -828,16 +812,16 @@ static int efm32x_write_word(struct flash_bank *bank, uint32_t addr,
        keep_alive();
 
        ret = efm32x_write_reg_u32(bank, EFM32_MSC_REG_ADDRB, addr);
-       if (ERROR_OK != ret)
+       if (ret != ERROR_OK)
                return ret;
 
        ret = efm32x_set_reg_bits(bank, EFM32_MSC_REG_WRITECMD,
                EFM32_MSC_WRITECMD_LADDRIM_MASK, 1);
-       if (ERROR_OK != ret)
+       if (ret != ERROR_OK)
                return ret;
 
        ret = efm32x_read_reg_u32(bank, EFM32_MSC_REG_STATUS, &status);
-       if (ERROR_OK != ret)
+       if (ret != ERROR_OK)
                return ret;
 
        LOG_DEBUG("status 0x%" PRIx32, status);
@@ -852,27 +836,27 @@ static int efm32x_write_word(struct flash_bank *bank, uint32_t addr,
 
        ret = efm32x_wait_status(bank, EFM32_FLASH_WDATAREADY_TMO,
                EFM32_MSC_STATUS_WDATAREADY_MASK, 1);
-       if (ERROR_OK != ret) {
+       if (ret != ERROR_OK) {
                LOG_ERROR("Wait for WDATAREADY failed");
                return ret;
        }
 
        ret = efm32x_write_reg_u32(bank, EFM32_MSC_REG_WDATA, val);
-       if (ERROR_OK != ret) {
+       if (ret != ERROR_OK) {
                LOG_ERROR("WDATA write failed");
                return ret;
        }
 
        ret = efm32x_write_reg_u32(bank, EFM32_MSC_REG_WRITECMD,
                EFM32_MSC_WRITECMD_WRITEONCE_MASK);
-       if (ERROR_OK != ret) {
+       if (ret != ERROR_OK) {
                LOG_ERROR("WRITECMD write failed");
                return ret;
        }
 
        ret = efm32x_wait_status(bank, EFM32_FLASH_WRITE_TMO,
                EFM32_MSC_STATUS_BUSY_MASK, 0);
-       if (ERROR_OK != ret) {
+       if (ret != ERROR_OK) {
                LOG_ERROR("Wait for BUSY failed");
                return ret;
        }
@@ -901,7 +885,7 @@ static int efm32x_write(struct flash_bank *bank, const uint8_t *buffer,
                uint32_t old_count = count;
                count = (old_count | 3) + 1;
                new_buffer = malloc(count);
-               if (new_buffer == NULL) {
+               if (!new_buffer) {
                        LOG_ERROR("odd number of bytes to write and no memory "
                                "for padding buffer");
                        return ERROR_FAIL;
@@ -951,9 +935,7 @@ reset_pg_and_lock:
                retval = retval2;
 
 cleanup:
-       if (new_buffer)
-               free(new_buffer);
-
+       free(new_buffer);
        return retval;
 }
 
@@ -962,57 +944,50 @@ static int efm32x_probe(struct flash_bank *bank)
        struct efm32x_flash_bank *efm32x_info = bank->driver_priv;
        struct efm32_info efm32_mcu_info;
        int ret;
-       int i;
        uint32_t base_address = 0x00000000;
-       char buf[256];
 
-       efm32x_info->probed = 0;
+       efm32x_info->probed = false;
        memset(efm32x_info->lb_page, 0xff, LOCKBITS_PAGE_SZ);
 
        ret = efm32x_read_info(bank, &efm32_mcu_info);
-       if (ERROR_OK != ret)
-               return ret;
-
-       ret = efm32x_decode_info(&efm32_mcu_info, buf, sizeof(buf));
-       if (ERROR_OK != ret)
+       if (ret != ERROR_OK)
                return ret;
 
-       LOG_INFO("detected part: %s", buf);
+       LOG_INFO("detected part: %s Gecko, rev %d",
+                       efm32_mcu_info.family_data->name, efm32_mcu_info.prod_rev);
        LOG_INFO("flash size = %dkbytes", efm32_mcu_info.flash_sz_kib);
        LOG_INFO("flash page size = %dbytes", efm32_mcu_info.page_size);
 
-       assert(0 != efm32_mcu_info.page_size);
+       assert(efm32_mcu_info.page_size != 0);
 
        int num_pages = efm32_mcu_info.flash_sz_kib * 1024 /
                efm32_mcu_info.page_size;
 
        assert(num_pages > 0);
 
-       if (bank->sectors) {
-               free(bank->sectors);
-               bank->sectors = NULL;
-       }
+       free(bank->sectors);
+       bank->sectors = NULL;
 
        bank->base = base_address;
        bank->size = (num_pages * efm32_mcu_info.page_size);
        bank->num_sectors = num_pages;
 
        ret = efm32x_read_lock_data(bank);
-       if (ERROR_OK != ret) {
+       if (ret != ERROR_OK) {
                LOG_ERROR("Failed to read LB data");
                return ret;
        }
 
        bank->sectors = malloc(sizeof(struct flash_sector) * num_pages);
 
-       for (i = 0; i < num_pages; i++) {
+       for (int i = 0; i < num_pages; i++) {
                bank->sectors[i].offset = i * efm32_mcu_info.page_size;
                bank->sectors[i].size = efm32_mcu_info.page_size;
                bank->sectors[i].is_erased = -1;
                bank->sectors[i].is_protected = 1;
        }
 
-       efm32x_info->probed = 1;
+       efm32x_info->probed = true;
 
        return ERROR_OK;
 }
@@ -1029,7 +1004,6 @@ static int efm32x_protect_check(struct flash_bank *bank)
 {
        struct target *target = bank->target;
        int ret = 0;
-       int i = 0;
 
        if (target->state != TARGET_HALTED) {
                LOG_ERROR("Target not halted");
@@ -1037,31 +1011,32 @@ static int efm32x_protect_check(struct flash_bank *bank)
        }
 
        ret = efm32x_read_lock_data(bank);
-       if (ERROR_OK != ret) {
+       if (ret != ERROR_OK) {
                LOG_ERROR("Failed to read LB data");
                return ret;
        }
 
-       assert(NULL != bank->sectors);
+       assert(bank->sectors);
 
-       for (i = 0; i < bank->num_sectors; i++)
+       for (unsigned int i = 0; i < bank->num_sectors; i++)
                bank->sectors[i].is_protected = efm32x_get_page_lock(bank, i);
 
        return ERROR_OK;
 }
 
-static int get_efm32x_info(struct flash_bank *bank, char *buf, int buf_size)
+static int get_efm32x_info(struct flash_bank *bank, struct command_invocation *cmd)
 {
        struct efm32_info info;
-       int ret = 0;
+       int ret;
 
        ret = efm32x_read_info(bank, &info);
-       if (ERROR_OK != ret) {
+       if (ret != ERROR_OK) {
                LOG_ERROR("Failed to read EFM32 info");
                return ret;
        }
 
-       return efm32x_decode_info(&info, buf, buf_size);
+       command_print_sameline(cmd, "%s Gecko, rev %d", info.family_data->name, info.prod_rev);
+       return ERROR_OK;
 }
 
 COMMAND_HANDLER(efm32x_handle_debuglock_command)
@@ -1073,7 +1048,7 @@ COMMAND_HANDLER(efm32x_handle_debuglock_command)
 
        struct flash_bank *bank;
        int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
-       if (ERROR_OK != retval)
+       if (retval != ERROR_OK)
                return retval;
 
        struct efm32x_flash_bank *efm32x_info = bank->driver_priv;
@@ -1090,7 +1065,7 @@ COMMAND_HANDLER(efm32x_handle_debuglock_command)
        *ptr = 0;
 
        retval = efm32x_write_lock_data(bank);
-       if (ERROR_OK != retval) {
+       if (retval != ERROR_OK) {
                LOG_ERROR("Failed to write LB page");
                return retval;
        }