This is an automated email from Gerrit. "Jérôme Pouiller <[email protected]>" just uploaded a new patch set to Gerrit, which you can find at https://review.openocd.org/c/openocd/+/9446
-- gerrit commit d471bdf4ab5a85b6aedf99fb5e801fedc0236916 Author: Jérôme Pouiller <[email protected]> Date: Wed Jan 28 13:51:26 2026 +0100 flash/nor/efm32: Identify Series-2 Silabs Series 2 SoCs change the structure to store the device identification. The legacy series relied on family identifier and a part number (part_num) while Series-2 store several fields in a uint32_t (part_info). In addition, various fileds related to the flash geometry are not stored on the same addresses. These addresses were hard coded. We now have to a structure (efm32_dev_info_addr) store the various configuration. The new series also have a different address for msc register base. Rather than relying on "reg_base" in efm32_flash_chip, we take this opportunity to centralize the information in struct efm32_families. For uniformity, we also also remove "reg_lock" of the struct efm32_flash_chip. We will have to rework the way its work in future patches anyway. Co-developed-by: Peter Johanson <[email protected]> Signed-off-by: Peter Johanson <[email protected]> Signed-off-by: Jérôme Pouiller <[email protected]> Change-Id: Ia863520a1b5840c707e7678d909b2b590ea27e4e diff --git a/src/flash/nor/efm32.c b/src/flash/nor/efm32.c index 9208ec2d79..0663f312ba 100644 --- a/src/flash/nor/efm32.c +++ b/src/flash/nor/efm32.c @@ -30,49 +30,73 @@ #include <target/armv7m.h> #include <target/cortex_m.h> -#define EFM_FAMILY_ID_GIANT_GECKO 72 -#define EFM_FAMILY_ID_LEOPARD_GECKO 74 - #define EFM32_FLASH_BASE 0 /* size in bytes, not words; must fit all Gecko devices */ #define LOCKWORDS_SZ 512 #define EFM32_MSC_INFO_BASE 0x0fe00000 - -#define EFM32_MSC_USER_DATA EFM32_MSC_INFO_BASE +#define EFM32_MSC_USER_DATA (EFM32_MSC_INFO_BASE + 0x0000) #define EFM32_MSC_LOCK_BITS (EFM32_MSC_INFO_BASE + 0x4000) -#define EFM32_MSC_LOCK_BITS_EXTRA (EFM32_MSC_LOCK_BITS + LOCKWORDS_SZ) -#define EFM32_MSC_DEV_INFO (EFM32_MSC_INFO_BASE + 0x8000) - -/* PAGE_SIZE is not present in Zero, Happy and the original Gecko MCU */ -#define EFM32_MSC_DI_PAGE_SIZE (EFM32_MSC_DEV_INFO + 0x1e7) -#define EFM32_MSC_DI_FLASH_SZ (EFM32_MSC_DEV_INFO + 0x1f8) -#define EFM32_MSC_DI_RAM_SZ (EFM32_MSC_DEV_INFO + 0x1fa) -#define EFM32_MSC_DI_PART_NUM (EFM32_MSC_DEV_INFO + 0x1fc) -#define EFM32_MSC_DI_PART_FAMILY (EFM32_MSC_DEV_INFO + 0x1fe) -#define EFM32_MSC_DI_PROD_REV (EFM32_MSC_DEV_INFO + 0x1ff) - -#define EFM32_MSC_REGBASE 0x400c0000 -#define EFM32_MSC_REGBASE_SERIES1 0x400e0000 -#define EFM32_MSC_REG_WRITECTRL 0x008 -#define EFM32_MSC_WRITECTRL_WREN_MASK 0x1 -#define EFM32_MSC_REG_WRITECMD 0x00c -#define EFM32_MSC_WRITECMD_LADDRIM_MASK 0x1 -#define EFM32_MSC_WRITECMD_ERASEPAGE_MASK 0x2 -#define EFM32_MSC_WRITECMD_WRITEONCE_MASK 0x8 -#define EFM32_MSC_REG_ADDRB 0x010 -#define EFM32_MSC_REG_WDATA 0x018 -#define EFM32_MSC_REG_STATUS 0x01c -#define EFM32_MSC_STATUS_BUSY_MASK 0x1 -#define EFM32_MSC_STATUS_LOCKED_MASK 0x2 -#define EFM32_MSC_STATUS_INVADDR_MASK 0x4 -#define EFM32_MSC_STATUS_WDATAREADY_MASK 0x8 -#define EFM32_MSC_STATUS_WORDTIMEOUT_MASK 0x10 -#define EFM32_MSC_STATUS_ERASEABORTED_MASK 0x20 -#define EFM32_MSC_REG_LOCK 0x03c -#define EFM32_MSC_REG_LOCK_SERIES1 0x040 -#define EFM32_MSC_LOCK_LOCKKEY 0x1b71 +#define EFM32_MSC_LOCK_BITS_EXTRA (EFM32_MSC_INFO_BASE + 0x4200) + +struct efm32_dev_info_addr { + uint32_t part_num; + uint32_t part_rev; +#define EFM32_DI_PARTINFO_NUM_MASK 0x0000ffff +#define EFM32_DI_PARTINFO_FAMILY_MASK 0x00ff0000 +#define EFM32_DI_PARTINFO_TYPE_MASK 0x3f000000 + uint32_t part_info; + uint32_t page_size; + uint32_t flash_sz; + uint32_t ram_sz; +}; + +#define EFM32_DI_PART_FAMILY (EFM32_MSC_INFO_BASE + 0x81fe) + +static const struct efm32_dev_info_addr efm32_dev_info_addr[] = { + [0] = { + .part_num = EFM32_MSC_INFO_BASE + 0x81fc, + .part_rev = EFM32_MSC_INFO_BASE + 0x81ff, + .part_info = 0x00000000, /* Not used in Series 0/1 */ + .page_size = EFM32_MSC_INFO_BASE + 0x81e7, + .flash_sz = EFM32_MSC_INFO_BASE + 0x81f8, + .ram_sz = EFM32_MSC_INFO_BASE + 0x81fa, + }, + [1] = { + .part_num = EFM32_MSC_INFO_BASE + 0x81fc, + .part_rev = EFM32_MSC_INFO_BASE + 0x81ff, + .part_info = 0x0000000, /* Not used in Series 0/1 */ + .page_size = EFM32_MSC_INFO_BASE + 0x81e7, + .flash_sz = EFM32_MSC_INFO_BASE + 0x81f8, + .ram_sz = EFM32_MSC_INFO_BASE + 0x81fa, + }, + [2] = { + .part_num = 0x00000000, /* Not used in Series 2 */ + .part_rev = EFM32_MSC_INFO_BASE + 0x8002, + .part_info = EFM32_MSC_INFO_BASE + 0x8004, + .page_size = EFM32_MSC_INFO_BASE + 0x8008, + .flash_sz = EFM32_MSC_INFO_BASE + 0x800c, + .ram_sz = EFM32_MSC_INFO_BASE + 0x800e, + }, +}; + +#define EFM32_MSC_REG_WRITECTRL 0x0008 +#define EFM32_MSC_WRITECTRL_WREN_MASK 0x0001 +#define EFM32_MSC_REG_WRITECMD 0x000c +#define EFM32_MSC_WRITECMD_LADDRIM_MASK 0x0001 +#define EFM32_MSC_WRITECMD_ERASEPAGE_MASK 0x0002 +#define EFM32_MSC_WRITECMD_WRITEONCE_MASK 0x0008 +#define EFM32_MSC_REG_ADDRB 0x0010 +#define EFM32_MSC_REG_WDATA 0x0018 +#define EFM32_MSC_REG_STATUS 0x001c +#define EFM32_MSC_STATUS_BUSY_MASK 0x0001 +#define EFM32_MSC_STATUS_LOCKED_MASK 0x0002 +#define EFM32_MSC_STATUS_INVADDR_MASK 0x0004 +#define EFM32_MSC_STATUS_WDATAREADY_MASK 0x0008 +#define EFM32_MSC_STATUS_WORDTIMEOUT_MASK 0x0010 +#define EFM32_MSC_STATUS_ERASEABORTED_MASK 0x0020 +#define EFM32_MSC_LOCK_LOCKKEY 0x1b71 enum efm32_bank_index { EFM32_BANK_INDEX_MAIN, @@ -96,27 +120,24 @@ static int efm32_get_bank_index(target_addr_t base) } struct efm32_family_data { - int family_id; - const char *name; - - /* EFM32 series (EFM32LG995F is the "old" series 0, while EFR32MG12P132 - is the "new" series 1). Determines location of MSC registers. */ + int part_id; int series; + const char *name; + uint32_t msc_regbase; - /* Page size in bytes, or 0 to read from EFM32_MSC_DI_PAGE_SIZE */ + /* Page size in bytes, or 0 to read from msc_di->page_size */ int page_size; - /* MSC register base address, or 0 to use default */ - uint32_t msc_regbase; }; struct efm32_info { const struct efm32_family_data *family_data; + const struct efm32_dev_info_addr *di_addr; + uint16_t part_num; /* Series 0/1 only */ + uint32_t part_info; /* Series 2 only */ + uint8_t part_rev; uint16_t flash_sz_kib; uint16_t ram_sz_kib; - uint16_t part_num; - uint8_t part_family; - uint8_t prod_rev; uint16_t page_size; }; @@ -124,69 +145,68 @@ struct efm32_flash_chip { struct efm32_info info; bool probed[EFM32_N_BANKS]; uint32_t lb_page[LOCKWORDS_SZ / 4]; - uint32_t reg_base; - uint32_t reg_lock; uint32_t refcount; }; static const struct efm32_family_data efm32_families[] = { - { 16, "EFR32MG1P Mighty", .series = 1 }, - { 17, "EFR32MG1B Mighty", .series = 1 }, - { 18, "EFR32MG1V Mighty", .series = 1 }, - { 19, "EFR32BG1P Blue", .series = 1 }, - { 20, "EFR32BG1B Blue", .series = 1 }, - { 21, "EFR32BG1V Blue", .series = 1 }, - { 25, "EFR32FG1P Flex", .series = 1 }, - { 26, "EFR32FG1B Flex", .series = 1 }, - { 27, "EFR32FG1V Flex", .series = 1 }, - { 28, "EFR32MG2P Mighty", .series = 1 }, - { 29, "EFR32MG2B Mighty", .series = 1 }, - { 30, "EFR32MG2V Mighty", .series = 1 }, - { 31, "EFR32BG12P Blue", .series = 1 }, - { 32, "EFR32BG12B Blue", .series = 1 }, - { 33, "EFR32BG12V Blue", .series = 1 }, - { 37, "EFR32FG12P Flex", .series = 1 }, - { 38, "EFR32FG12B Flex", .series = 1 }, - { 39, "EFR32FG12V Flex", .series = 1 }, - { 40, "EFR32MG13P Mighty", .series = 1 }, - { 41, "EFR32MG13B Mighty", .series = 1 }, - { 42, "EFR32MG13V Mighty", .series = 1 }, - { 43, "EFR32BG13P Blue", .series = 1 }, - { 44, "EFR32BG13B Blue", .series = 1 }, - { 45, "EFR32BG13V Blue", .series = 1 }, - { 46, "EFR32ZG13P Zen", .series = 1 }, - { 49, "EFR32FG13P Flex", .series = 1 }, - { 50, "EFR32FG13B Flex", .series = 1 }, - { 51, "EFR32FG13V Flex", .series = 1 }, - { 52, "EFR32MG14P Mighty", .series = 1 }, - { 53, "EFR32MG14B Mighty", .series = 1 }, - { 54, "EFR32MG14V Mighty", .series = 1 }, - { 55, "EFR32BG14P Blue", .series = 1 }, - { 56, "EFR32BG14B Blue", .series = 1 }, - { 57, "EFR32BG14V Blue", .series = 1 }, - { 58, "EFR32ZG14P Zen", .series = 1 }, - { 61, "EFR32FG14P Flex", .series = 1 }, - { 62, "EFR32FG14B Flex", .series = 1 }, - { 63, "EFR32FG14V Flex", .series = 1 }, - { 71, "EFM32G", .series = 0, .page_size = 512 }, - { 72, "EFM32GG Giant", .series = 0 }, - { 73, "EFM32TG Tiny", .series = 0, .page_size = 512 }, - { 74, "EFM32LG Leopard", .series = 0 }, - { 75, "EFM32WG Wonder", .series = 0 }, - { 76, "EFM32ZG Zero", .series = 0, .page_size = 1024 }, - { 77, "EFM32HG Happy", .series = 0, .page_size = 1024 }, - { 81, "EFM32PG1B Pearl", .series = 1 }, - { 83, "EFM32JG1B Jade", .series = 1 }, - { 85, "EFM32PG12B Pearl", .series = 1 }, - { 87, "EFM32JG12B Jade", .series = 1 }, - { 89, "EFM32PG13B Pearl", .series = 1 }, - { 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 }, + { 16, 1, "EFR32MG1P Mighty", .msc_regbase = 0x400e0000 }, + { 17, 1, "EFR32MG1B Mighty", .msc_regbase = 0x400e0000 }, + { 18, 1, "EFR32MG1V Mighty", .msc_regbase = 0x400e0000 }, + { 19, 1, "EFR32BG1P Blue", .msc_regbase = 0x400e0000 }, + { 20, 1, "EFR32BG1B Blue", .msc_regbase = 0x400e0000 }, + { 21, 1, "EFR32BG1V Blue", .msc_regbase = 0x400e0000 }, + { 25, 1, "EFR32FG1P Flex", .msc_regbase = 0x400e0000 }, + { 26, 1, "EFR32FG1B Flex", .msc_regbase = 0x400e0000 }, + { 27, 1, "EFR32FG1V Flex", .msc_regbase = 0x400e0000 }, + { 28, 1, "EFR32MG12P Mighty", .msc_regbase = 0x400e0000 }, + { 29, 1, "EFR32MG12B Mighty", .msc_regbase = 0x400e0000 }, + { 30, 1, "EFR32MG12V Mighty", .msc_regbase = 0x400e0000 }, + { 31, 1, "EFR32BG12P Blue", .msc_regbase = 0x400e0000 }, + { 32, 1, "EFR32BG12B Blue", .msc_regbase = 0x400e0000 }, + { 33, 1, "EFR32BG12V Blue", .msc_regbase = 0x400e0000 }, + { 37, 1, "EFR32FG12P Flex", .msc_regbase = 0x400e0000 }, + { 38, 1, "EFR32FG12B Flex", .msc_regbase = 0x400e0000 }, + { 39, 1, "EFR32FG12V Flex", .msc_regbase = 0x400e0000 }, + { 40, 1, "EFR32MG13P Mighty", .msc_regbase = 0x400e0000 }, + { 41, 1, "EFR32MG13B Mighty", .msc_regbase = 0x400e0000 }, + { 42, 1, "EFR32MG13V Mighty", .msc_regbase = 0x400e0000 }, + { 43, 1, "EFR32BG13P Blue", .msc_regbase = 0x400e0000 }, + { 44, 1, "EFR32BG13B Blue", .msc_regbase = 0x400e0000 }, + { 45, 1, "EFR32BG13V Blue", .msc_regbase = 0x400e0000 }, + { 46, 1, "EFR32ZG13P Zen", .msc_regbase = 0x400e0000 }, + { 49, 1, "EFR32FG13P Flex", .msc_regbase = 0x400e0000 }, + { 50, 1, "EFR32FG13B Flex", .msc_regbase = 0x400e0000 }, + { 51, 1, "EFR32FG13V Flex", .msc_regbase = 0x400e0000 }, + { 52, 1, "EFR32MG14P Mighty", .msc_regbase = 0x400e0000 }, + { 53, 1, "EFR32MG14B Mighty", .msc_regbase = 0x400e0000 }, + { 54, 1, "EFR32MG14V Mighty", .msc_regbase = 0x400e0000 }, + { 55, 1, "EFR32BG14P Blue", .msc_regbase = 0x400e0000 }, + { 56, 1, "EFR32BG14B Blue", .msc_regbase = 0x400e0000 }, + { 57, 1, "EFR32BG14V Blue", .msc_regbase = 0x400e0000 }, + { 58, 1, "EFR32ZG14P Zen", .msc_regbase = 0x400e0000 }, + { 61, 1, "EFR32FG14P Flex", .msc_regbase = 0x400e0000 }, + { 62, 1, "EFR32FG14B Flex", .msc_regbase = 0x400e0000 }, + { 63, 1, "EFR32FG14V Flex", .msc_regbase = 0x400e0000 }, + { 71, 0, "EFM32G", .msc_regbase = 0x400c0000, .page_size = 512 }, + { 72, 0, "EFM32GG Giant", .msc_regbase = 0x400c0000 }, + { 73, 0, "EFM32TG Tiny", .msc_regbase = 0x400c0000, .page_size = 512 }, + { 74, 0, "EFM32LG Leopard", .msc_regbase = 0x400c0000 }, + { 75, 0, "EFM32WG Wonder", .msc_regbase = 0x400c0000 }, + { 76, 0, "EFM32ZG Zero", .msc_regbase = 0x400c0000, .page_size = 1024 }, + { 77, 0, "EFM32HG Happy", .msc_regbase = 0x400c0000, .page_size = 1024 }, + { 81, 1, "EFM32PG1B Pearl", .msc_regbase = 0x400e0000 }, + { 83, 1, "EFM32JG1B Jade", .msc_regbase = 0x400e0000 }, + { 85, 1, "EFM32PG12B Pearl", .msc_regbase = 0x400e0000 }, + { 87, 1, "EFM32JG12B Jade", .msc_regbase = 0x400e0000 }, + { 89, 1, "EFM32PG13B Pearl", .msc_regbase = 0x400e0000 }, + { 91, 1, "EFM32JG13B Jade", .msc_regbase = 0x400e0000 }, + { 100, 1, "EFM32GG11B Giant", .msc_regbase = 0x40000000 }, + { 103, 1, "EFM32TG11B Tiny", .msc_regbase = 0x40000000 }, + { 106, 1, "EFM32GG12B Giant", .msc_regbase = 0x40000000 }, + { 120, 0, "EZR32WG Wonder", .msc_regbase = 0x400c0000 }, + { 121, 0, "EZR32LG Leopard", .msc_regbase = 0x400c0000 }, + { 122, 0, "EZR32HG Happy", .msc_regbase = 0x400c0000, .page_size = 1024 }, + { 128, 2, "EFR32/EFM32 Series-2", .msc_regbase = 0x50030000 }, }; const struct flash_driver efm32_flash; @@ -196,129 +216,110 @@ static int efm32_priv_write(struct flash_bank *bank, const uint8_t *buffer, static int efm32_write_only_lockbits(struct flash_bank *bank); -static int efm32_get_flash_size(struct flash_bank *bank, uint16_t *flash_sz) -{ - return target_read_u16(bank->target, EFM32_MSC_DI_FLASH_SZ, flash_sz); -} - -static int efm32_get_ram_size(struct flash_bank *bank, uint16_t *ram_sz) -{ - return target_read_u16(bank->target, EFM32_MSC_DI_RAM_SZ, ram_sz); -} - -static int efm32_get_part_num(struct flash_bank *bank, uint16_t *pnum) -{ - return target_read_u16(bank->target, EFM32_MSC_DI_PART_NUM, pnum); -} - -static int efm32_get_part_family(struct flash_bank *bank, uint8_t *pfamily) -{ - return target_read_u8(bank->target, EFM32_MSC_DI_PART_FAMILY, pfamily); -} - -static int efm32_get_prod_rev(struct flash_bank *bank, uint8_t *prev) -{ - return target_read_u8(bank->target, EFM32_MSC_DI_PROD_REV, prev); -} - static int efm32_read_reg_u32(struct flash_bank *bank, target_addr_t offset, uint32_t *value) { struct efm32_flash_chip *efm32_info = bank->driver_priv; - uint32_t base = efm32_info->reg_base; - return target_read_u32(bank->target, base + offset, value); + return target_read_u32(bank->target, + efm32_info->info.family_data->msc_regbase + offset, + value); } static int efm32_write_reg_u32(struct flash_bank *bank, target_addr_t offset, uint32_t value) { struct efm32_flash_chip *efm32_info = bank->driver_priv; - uint32_t base = efm32_info->reg_base; - return target_write_u32(bank->target, base + offset, value); + return target_write_u32(bank->target, + efm32_info->info.family_data->msc_regbase + offset, + value); } static int efm32_read_info(struct flash_bank *bank) { - int ret; struct efm32_flash_chip *efm32_info = bank->driver_priv; struct efm32_info *efm32_mcu_info = &efm32_info->info; + uint8_t tmp; + size_t i; + int ret; memset(efm32_mcu_info, 0, sizeof(struct efm32_info)); - ret = efm32_get_flash_size(bank, &efm32_mcu_info->flash_sz_kib); + ret = target_read_u8(bank->target, EFM32_DI_PART_FAMILY, &tmp); if (ret != ERROR_OK) return ret; + for (i = 0; i < ARRAY_SIZE(efm32_families); i++) { + if (efm32_families[i].part_id == tmp) + efm32_mcu_info->family_data = &efm32_families[i]; + } + if (!efm32_mcu_info->family_data) { + LOG_ERROR("Unknown MCU family %d", tmp); + return ERROR_FAIL; + } - ret = efm32_get_ram_size(bank, &efm32_mcu_info->ram_sz_kib); - if (ret != ERROR_OK) - return ret; + efm32_mcu_info->di_addr = &efm32_dev_info_addr[efm32_mcu_info->family_data->series]; - ret = efm32_get_part_num(bank, &efm32_mcu_info->part_num); + if (efm32_mcu_info->family_data->series == 2) { + ret = target_read_u32(bank->target, + efm32_mcu_info->di_addr->part_info, + &efm32_mcu_info->part_info); + if (ret != ERROR_OK) + return ret; + } else { + ret = target_read_u16(bank->target, + efm32_mcu_info->di_addr->part_num, + &efm32_mcu_info->part_num); + if (ret != ERROR_OK) + return ret; + } + + ret = target_read_u8(bank->target, + efm32_mcu_info->di_addr->part_rev, + &efm32_mcu_info->part_rev); if (ret != ERROR_OK) return ret; - ret = efm32_get_part_family(bank, &efm32_mcu_info->part_family); + ret = target_read_u16(bank->target, + efm32_mcu_info->di_addr->flash_sz, + &efm32_mcu_info->flash_sz_kib); if (ret != ERROR_OK) return ret; - ret = efm32_get_prod_rev(bank, &efm32_mcu_info->prod_rev); + ret = target_read_u16(bank->target, + efm32_mcu_info->di_addr->ram_sz, + &efm32_mcu_info->ram_sz_kib); if (ret != ERROR_OK) return ret; - for (size_t i = 0; i < ARRAY_SIZE(efm32_families); i++) { - if (efm32_families[i].family_id == efm32_mcu_info->part_family) - efm32_mcu_info->family_data = &efm32_families[i]; - } - - if (!efm32_mcu_info->family_data) { - LOG_ERROR("Unknown MCU family %d", efm32_mcu_info->part_family); - return ERROR_FAIL; - } - - switch (efm32_mcu_info->family_data->series) { - case 0: - efm32_info->reg_base = EFM32_MSC_REGBASE; - efm32_info->reg_lock = EFM32_MSC_REG_LOCK; - break; - case 1: - efm32_info->reg_base = EFM32_MSC_REGBASE_SERIES1; - efm32_info->reg_lock = EFM32_MSC_REG_LOCK_SERIES1; - break; - } - - if (efm32_mcu_info->family_data->msc_regbase != 0) - efm32_info->reg_base = efm32_mcu_info->family_data->msc_regbase; - if (efm32_mcu_info->family_data->page_size != 0) { efm32_mcu_info->page_size = efm32_mcu_info->family_data->page_size; + } else if ((efm32_mcu_info->family_data->part_id == 72 || + efm32_mcu_info->family_data->part_id == 74) && + efm32_mcu_info->part_rev < 18) { + /* EFM32 GG/LG errata: MEM_INFO_PAGE_SIZE is invalid for MCUs + * with part_rev < 18 + */ + if (efm32_mcu_info->flash_sz_kib < 512) + efm32_mcu_info->page_size = 2048; + else + efm32_mcu_info->page_size = 4096; } else { - uint8_t pg_size = 0; - ret = target_read_u8(bank->target, EFM32_MSC_DI_PAGE_SIZE, &pg_size); + ret = target_read_u8(bank->target, + efm32_mcu_info->di_addr->page_size, + &tmp); if (ret != ERROR_OK) return ret; - efm32_mcu_info->page_size = BIT((pg_size + 10) & 0xff); - - if (efm32_mcu_info->part_family == EFM_FAMILY_ID_GIANT_GECKO || - efm32_mcu_info->part_family == EFM_FAMILY_ID_LEOPARD_GECKO) { - /* Giant or Leopard Gecko */ - if (efm32_mcu_info->prod_rev < 18) { - /* EFM32 GG/LG errata: MEM_INFO_PAGE_SIZE is invalid - for MCUs with PROD_REV < 18 */ - if (efm32_mcu_info->flash_sz_kib < 512) - efm32_mcu_info->page_size = 2048; - else - efm32_mcu_info->page_size = 4096; - } - } - - if (efm32_mcu_info->page_size != 2048 && - efm32_mcu_info->page_size != 4096) { - LOG_ERROR("Invalid page size %u", efm32_mcu_info->page_size); - return ERROR_FAIL; - } + efm32_mcu_info->page_size = BIT(tmp) * 1024; + } + if (efm32_mcu_info->page_size != 512 && + efm32_mcu_info->page_size != 1024 && + efm32_mcu_info->page_size != 2048 && + efm32_mcu_info->page_size != 4096 && + efm32_mcu_info->page_size != 8192) { + LOG_ERROR("Invalid page size %u", efm32_mcu_info->page_size); + return ERROR_FAIL; } return ERROR_OK; @@ -413,9 +414,16 @@ static int efm32_set_wren(struct flash_bank *bank, int write_enable) static int efm32_msc_lock(struct flash_bank *bank, int lock) { struct efm32_flash_chip *efm32_info = bank->driver_priv; + struct efm32_info *efm32_mcu_info = &efm32_info->info; + uint32_t val = lock ? 0 : EFM32_MSC_LOCK_LOCKKEY; + uint32_t reg; + + if (efm32_mcu_info->family_data->series == 1) + reg = 0x040; + else + reg = 0x03c; - return efm32_write_reg_u32(bank, efm32_info->reg_lock, - (lock ? 0 : EFM32_MSC_LOCK_LOCKKEY)); + return efm32_write_reg_u32(bank, reg, val); } static int efm32_wait_status(struct flash_bank *bank, int timeout_ms, @@ -846,7 +854,7 @@ static int efm32_write_block(struct flash_bank *bank, const uint8_t *buf, init_reg_param(®_params[3], "r3", 32, PARAM_OUT); /* buffer end */ init_reg_param(®_params[4], "r4", 32, PARAM_IN_OUT); /* target address */ - buf_set_u32(reg_params[0].value, 0, 32, efm32_info->reg_base); + buf_set_u32(reg_params[0].value, 0, 32, efm32_info->info.family_data->msc_regbase); buf_set_u32(reg_params[1].value, 0, 32, count); buf_set_u32(reg_params[2].value, 0, 32, source->address); buf_set_u32(reg_params[3].value, 0, 32, source->address + source->size); @@ -1063,7 +1071,7 @@ static int efm32_probe(struct flash_bank *bank) return ret; LOG_INFO("detected part: %s Gecko, rev %d", - efm32_mcu_info->family_data->name, efm32_mcu_info->prod_rev); + efm32_mcu_info->family_data->name, efm32_mcu_info->part_rev); LOG_INFO("flash size = %d KiB", efm32_mcu_info->flash_sz_kib); LOG_INFO("flash page size = %d B", efm32_mcu_info->page_size); @@ -1148,7 +1156,7 @@ static int efm32_get_info(struct flash_bank *bank, struct command_invocation *cm command_print_sameline(cmd, "%s Gecko, rev %d", efm32_info->info.family_data->name, - efm32_info->info.prod_rev); + efm32_info->info.part_rev); return ERROR_OK; } --
