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/+/9459

-- gerrit

commit 0728a6534feb6d94d62cf17383760f7725b04469
Author: Jérôme Pouiller <[email protected]>
Date:   Wed Feb 11 16:50:01 2026 +0100

    flash/nor/efm32: Fix page size for user data bank
    
    On Series-0/1 devices, the user data bank is always only one sector and
    the size of the page is the same than the main flash bank.
    
    On Series-2, these parameters are stored in separated registers.
    
    Reported-by: Marc Schink <[email protected]>
    Change-Id: Ie6bbb61dcd8d94facde47200118ff585efc0d7fb
    Signed-off-by: Jérôme Pouiller <[email protected]>

diff --git a/src/flash/nor/efm32.c b/src/flash/nor/efm32.c
index dfbc788de6..36d5342d68 100644
--- a/src/flash/nor/efm32.c
+++ b/src/flash/nor/efm32.c
@@ -108,6 +108,7 @@ struct efm32_msc_offset {
        target_addr_t off_writecmd;
        target_addr_t off_addrb;
        target_addr_t off_wdata;
+       target_addr_t off_userdatasize;
 
 #define EFM32_MSC_STATUS_BUSY_MASK           0x0001
 #define EFM32_MSC_STATUS_LOCKED_MASK         0x0002
@@ -139,6 +140,7 @@ static const struct efm32_msc_offset efm32_msc_offset[] = {
                .off_wdata     = 0x0018,
                .off_status    = 0x001c,
                .off_lock      = 0x003c,
+               .off_userdatasize = 0x0000, /* Does not exist in Series 0/1 */
                .flash_write_code = efm32_flash_write_code_s0_s1,
                .flash_write_code_len = sizeof(efm32_flash_write_code_s0_s1),
        },
@@ -149,6 +151,7 @@ static const struct efm32_msc_offset efm32_msc_offset[] = {
                .off_wdata     = 0x0018,
                .off_status    = 0x001c,
                .off_lock      = 0x0040,
+               .off_userdatasize = 0x0000, /* Does not exist in Series 0/1 */
                .flash_write_code = efm32_flash_write_code_s0_s1,
                .flash_write_code_len = sizeof(efm32_flash_write_code_s0_s1),
        },
@@ -159,6 +162,7 @@ static const struct efm32_msc_offset efm32_msc_offset[] = {
                .off_wdata     = 0x0018,
                .off_status    = 0x001c,
                .off_lock      = 0x0040,
+               .off_userdatasize = 0x0034,
                .flash_write_code = efm32_flash_write_code_s2,
                .flash_write_code_len = sizeof(efm32_flash_write_code_s2),
        },
@@ -197,7 +201,6 @@ struct efm32_family_data {
 
        /* Page size in bytes, or 0 to read from msc_di->page_size */
        int page_size;
-
 };
 
 struct efm32_info {
@@ -210,6 +213,7 @@ struct efm32_info {
        uint16_t flash_sz_kib;
        uint16_t ram_sz_kib;
        uint16_t page_size;
+       uint16_t page_size_ud;
 };
 
 struct efm32_flash_chip {
@@ -311,21 +315,22 @@ static int efm32_read_info(struct flash_bank *bank)
 {
        struct efm32_flash_chip *efm32_info = bank->driver_priv;
        struct efm32_info *efm32_mcu_info = &efm32_info->info;
-       uint8_t tmp;
+       uint8_t tmp8;
+       uint32_t tmp32;
        size_t i;
        int ret;
 
        memset(efm32_mcu_info, 0, sizeof(struct efm32_info));
 
-       ret = target_read_u8(bank->target, EFM32_DI_PART_FAMILY, &tmp);
+       ret = target_read_u8(bank->target, EFM32_DI_PART_FAMILY, &tmp8);
        if (ret != ERROR_OK)
                return ret;
        for (i = 0; i < ARRAY_SIZE(efm32_families); i++) {
-               if (efm32_families[i].part_id == tmp)
+               if (efm32_families[i].part_id == tmp8)
                        efm32_mcu_info->family_data = &efm32_families[i];
        }
        if (!efm32_mcu_info->family_data) {
-               LOG_ERROR("Unknown MCU family %d", tmp);
+               LOG_ERROR("Unknown MCU family %d", tmp8);
                return ERROR_FAIL;
        }
 
@@ -379,11 +384,11 @@ static int efm32_read_info(struct flash_bank *bank)
        } else {
                ret = target_read_u8(bank->target,
                                                         
efm32_mcu_info->di_addr->page_size,
-                                                        &tmp);
+                                                        &tmp8);
                if (ret != ERROR_OK)
                        return ret;
 
-               efm32_mcu_info->page_size = BIT(tmp) * 1024;
+               efm32_mcu_info->page_size = BIT(tmp8) * 1024;
        }
        if (efm32_mcu_info->page_size !=  512 &&
                efm32_mcu_info->page_size != 1024 &&
@@ -393,6 +398,17 @@ static int efm32_read_info(struct flash_bank *bank)
                LOG_ERROR("Invalid page size %u", efm32_mcu_info->page_size);
                return ERROR_FAIL;
        }
+       if (efm32_mcu_info->family_data->page_size != 2) {
+               efm32_mcu_info->page_size_ud = efm32_mcu_info->page_size;
+       } else {
+               ret = target_read_u32(bank->target,
+                                                        
efm32_mcu_info->di_addr->page_size,
+                                                        &tmp32);
+               if (ret != ERROR_OK)
+                       return ret;
+
+               efm32_mcu_info->page_size_ud = FIELD_GET(0x0000FF00, tmp32) * 
1024;
+       }
 
        return ERROR_OK;
 }
@@ -1179,8 +1195,9 @@ static int efm32_probe(struct flash_bank *bank)
 {
        struct efm32_flash_chip *efm32_info = bank->driver_priv;
        struct efm32_info *efm32_mcu_info = &efm32_info->info;
-       uint32_t base_address = EFM32_FLASH_BASE_V2;
        int bank_index = efm32_get_bank_index(bank->base);
+       uint32_t base_address = EFM32_FLASH_BASE_V2;
+       uint32_t page_size, userdatasize;
        char strbuf[256];
        int ret;
 
@@ -1210,15 +1227,25 @@ static int efm32_probe(struct flash_bank *bank)
        bank->sectors = NULL;
 
        if (bank->base == base_address) {
-               bank->num_sectors = efm32_mcu_info->flash_sz_kib * 1024 / 
efm32_mcu_info->page_size;
+               page_size = efm32_mcu_info->page_size;
+               bank->num_sectors = efm32_mcu_info->flash_sz_kib * 1024 / 
page_size;
                assert(bank->num_sectors > 0);
-       } else {
+       } else if (efm32_info->info.family_data->series != 2) {
+               page_size = efm32_mcu_info->page_size_ud;
                bank->num_sectors = 1;
+       } else {
+               ret = efm32_read_reg_u32(bank,
+                                                                
efm32_info->info.msc_offset->off_userdatasize,
+                                                                &userdatasize);
+               if (ret != ERROR_OK) {
+                       LOG_ERROR("Failed to read page size");
+                       return ret;
+               }
+               page_size = efm32_mcu_info->page_size_ud;
+               bank->num_sectors = (userdatasize * 256) / page_size;
        }
-       bank->size = bank->num_sectors * efm32_mcu_info->page_size;
-       bank->sectors = alloc_block_array(0,
-                                                                         
efm32_mcu_info->page_size,
-                                                                         
bank->num_sectors);
+       bank->size = bank->num_sectors * page_size;
+       bank->sectors = alloc_block_array(0, page_size, bank->num_sectors);
        if (!bank->sectors)
                return ERROR_FAIL;
 

-- 

Reply via email to