46 #define EFM32_FLASH_OPERATION_TIMEOUT 100
48 #define EFM32_FLASH_BASE_V1 0x00000000
49 #define EFM32_FLASH_BASE_V2 0x08000000
52 #define LOCKWORDS_SZ 512
54 #define EFM32_MSC_INFO_BASE 0x0fe00000
55 #define EFM32_MSC_USER_DATA (EFM32_MSC_INFO_BASE + 0x0000)
56 #define EFM32_MSC_LOCK_BITS (EFM32_MSC_INFO_BASE + 0x4000)
57 #define EFM32_MSC_LOCK_BITS_EXTRA (EFM32_MSC_INFO_BASE + 0x4200)
62 #define EFM32_DI_PARTINFO_NUM_MASK 0x0000ffff
63 #define EFM32_DI_PARTINFO_FAMILY_MASK 0x00ff0000
64 #define EFM32_DI_PARTINFO_TYPE_MASK 0x3f000000
66 #define EFM32_DI_PARTINFO_PAGE_SZ_MASK 0x000000ff
67 #define EFM32_DI_PARTINFO_PAGE_SZ_UD_MASK 0x0000ff00
73 #define EFM32_DI_PART_FAMILY (EFM32_MSC_INFO_BASE + 0x81fe)
79 .part_info = 0x00000000,
87 .part_info = 0x0000000,
93 .part_num = 0x00000000,
104 #define EFM32_MSC_WRITECTRL_WREN_MASK 0x0001
107 #define EFM32_MSC_WRITECMD_LADDRIM_MASK 0x0001
108 #define EFM32_MSC_WRITECMD_ERASEPAGE_MASK 0x0002
109 #define EFM32_MSC_WRITECMD_WRITEONCE_MASK 0x0008
115 #define EFM32_MSC_STATUS_BUSY_MASK 0x0001
116 #define EFM32_MSC_STATUS_LOCKED_MASK 0x0002
117 #define EFM32_MSC_STATUS_INVADDR_MASK 0x0004
118 #define EFM32_MSC_STATUS_WDATAREADY_MASK 0x0008
121 #define EFM32_MSC_LOCK_LOCKKEY 0x1b71
130 #include "../../../contrib/loaders/flash/silabs/silabs_s0_s1.inc"
134 #include "../../../contrib/loaders/flash/silabs/silabs_s2.inc"
140 .off_writecmd = 0x000c,
143 .off_status = 0x001c,
145 .off_userdatasize = 0x0000,
150 .off_writectrl = 0x0008,
151 .off_writecmd = 0x000c,
154 .off_status = 0x001c,
156 .off_userdatasize = 0x0000,
161 .off_writectrl = 0x000c,
162 .off_writecmd = 0x0010,
165 .off_status = 0x001c,
167 .off_userdatasize = 0x0034,
174 #define EFM32_CMU_REG_CLKEN1_SET 0x50009068
229 { 16, 1,
"EFR32MG1P Mighty", .
msc_regbase = 0x400e0000 },
230 { 17, 1,
"EFR32MG1B Mighty", .msc_regbase = 0x400e0000 },
231 { 18, 1,
"EFR32MG1V Mighty", .msc_regbase = 0x400e0000 },
232 { 19, 1,
"EFR32BG1P Blue", .msc_regbase = 0x400e0000 },
233 { 20, 1,
"EFR32BG1B Blue", .msc_regbase = 0x400e0000 },
234 { 21, 1,
"EFR32BG1V Blue", .msc_regbase = 0x400e0000 },
235 { 25, 1,
"EFR32FG1P Flex", .msc_regbase = 0x400e0000 },
236 { 26, 1,
"EFR32FG1B Flex", .msc_regbase = 0x400e0000 },
237 { 27, 1,
"EFR32FG1V Flex", .msc_regbase = 0x400e0000 },
238 { 28, 1,
"EFR32MG12P Mighty", .msc_regbase = 0x400e0000 },
239 { 29, 1,
"EFR32MG12B Mighty", .msc_regbase = 0x400e0000 },
240 { 30, 1,
"EFR32MG12V Mighty", .msc_regbase = 0x400e0000 },
241 { 31, 1,
"EFR32BG12P Blue", .msc_regbase = 0x400e0000 },
242 { 32, 1,
"EFR32BG12B Blue", .msc_regbase = 0x400e0000 },
243 { 33, 1,
"EFR32BG12V Blue", .msc_regbase = 0x400e0000 },
244 { 37, 1,
"EFR32FG12P Flex", .msc_regbase = 0x400e0000 },
245 { 38, 1,
"EFR32FG12B Flex", .msc_regbase = 0x400e0000 },
246 { 39, 1,
"EFR32FG12V Flex", .msc_regbase = 0x400e0000 },
247 { 40, 1,
"EFR32MG13P Mighty", .msc_regbase = 0x400e0000 },
248 { 41, 1,
"EFR32MG13B Mighty", .msc_regbase = 0x400e0000 },
249 { 42, 1,
"EFR32MG13V Mighty", .msc_regbase = 0x400e0000 },
250 { 43, 1,
"EFR32BG13P Blue", .msc_regbase = 0x400e0000 },
251 { 44, 1,
"EFR32BG13B Blue", .msc_regbase = 0x400e0000 },
252 { 45, 1,
"EFR32BG13V Blue", .msc_regbase = 0x400e0000 },
253 { 46, 1,
"EFR32ZG13P Zen", .msc_regbase = 0x400e0000 },
254 { 49, 1,
"EFR32FG13P Flex", .msc_regbase = 0x400e0000 },
255 { 50, 1,
"EFR32FG13B Flex", .msc_regbase = 0x400e0000 },
256 { 51, 1,
"EFR32FG13V Flex", .msc_regbase = 0x400e0000 },
257 { 52, 1,
"EFR32MG14P Mighty", .msc_regbase = 0x400e0000 },
258 { 53, 1,
"EFR32MG14B Mighty", .msc_regbase = 0x400e0000 },
259 { 54, 1,
"EFR32MG14V Mighty", .msc_regbase = 0x400e0000 },
260 { 55, 1,
"EFR32BG14P Blue", .msc_regbase = 0x400e0000 },
261 { 56, 1,
"EFR32BG14B Blue", .msc_regbase = 0x400e0000 },
262 { 57, 1,
"EFR32BG14V Blue", .msc_regbase = 0x400e0000 },
263 { 58, 1,
"EFR32ZG14P Zen", .msc_regbase = 0x400e0000 },
264 { 61, 1,
"EFR32FG14P Flex", .msc_regbase = 0x400e0000 },
265 { 62, 1,
"EFR32FG14B Flex", .msc_regbase = 0x400e0000 },
266 { 63, 1,
"EFR32FG14V Flex", .msc_regbase = 0x400e0000 },
267 { 71, 0,
"EFM32G", .msc_regbase = 0x400c0000, .page_size = 512 },
268 { 72, 0,
"EFM32GG Giant", .msc_regbase = 0x400c0000 },
269 { 73, 0,
"EFM32TG Tiny", .msc_regbase = 0x400c0000, .page_size = 512 },
270 { 74, 0,
"EFM32LG Leopard", .msc_regbase = 0x400c0000 },
271 { 75, 0,
"EFM32WG Wonder", .msc_regbase = 0x400c0000 },
272 { 76, 0,
"EFM32ZG Zero", .msc_regbase = 0x400c0000, .page_size = 1024 },
273 { 77, 0,
"EFM32HG Happy", .msc_regbase = 0x400c0000, .page_size = 1024 },
274 { 81, 1,
"EFM32PG1B Pearl", .msc_regbase = 0x400e0000 },
275 { 83, 1,
"EFM32JG1B Jade", .msc_regbase = 0x400e0000 },
276 { 85, 1,
"EFM32PG12B Pearl", .msc_regbase = 0x400e0000 },
277 { 87, 1,
"EFM32JG12B Jade", .msc_regbase = 0x400e0000 },
278 { 89, 1,
"EFM32PG13B Pearl", .msc_regbase = 0x400e0000 },
279 { 91, 1,
"EFM32JG13B Jade", .msc_regbase = 0x400e0000 },
280 { 100, 1,
"EFM32GG11B Giant", .msc_regbase = 0x40000000 },
281 { 103, 1,
"EFM32TG11B Tiny", .msc_regbase = 0x40000000 },
282 { 106, 1,
"EFM32GG12B Giant", .msc_regbase = 0x40000000 },
283 { 120, 0,
"EZR32WG Wonder", .msc_regbase = 0x400c0000 },
284 { 121, 0,
"EZR32LG Leopard", .msc_regbase = 0x400c0000 },
285 { 122, 0,
"EZR32HG Happy", .msc_regbase = 0x400c0000, .page_size = 1024 },
286 { 128, 2,
"EFR32/EFM32 Series-2", .msc_regbase = 0x50030000 },
322 memset(efm32_mcu_info, 0,
sizeof(
struct efm32_info));
333 LOG_ERROR(
"Unknown MCU family %d", val8);
419 if (bank_index < 0) {
420 LOG_ERROR(
"Flash bank with base address %" PRIx32
" is not supported",
421 (uint32_t)
bank->base);
429 bank_iter = bank_iter->
next) {
431 bank_iter->target ==
bank->target &&
500 LOG_WARNING(
"Don't know EFR/EFM Gx family number, can't set MSC register. Use default values..");
516 uint32_t bitmask,
int set)
519 uint32_t reg_val = 0;
552 uint32_t wait_mask,
bool wait_for_set)
567 if (!(
status & wait_mask) && !wait_for_set)
569 if ((
status & wait_mask) && wait_for_set)
573 LOG_ERROR(
"timed out waiting for MSC status");
660 for (
unsigned int i = first; i <= last; i++) {
674 LOG_ERROR(
"Failed to restore lockbits after erase");
685 uint32_t *ptr =
NULL;
688 assert(
bank->num_sectors > 0);
691 data_size = (
bank->num_sectors + 31) / 32;
695 for (
int i = 0; i < data_size; i++, ptr++) {
772 uint8_t *extra_data =
NULL;
775 extra_data = malloc(extra_bytes);
778 extra_bytes, extra_data);
780 LOG_ERROR(
"Failed to read extra contents of LB page");
800 LOG_ERROR(
"Failed to restore extra contents of LB page");
814 switch (
bank->base) {
830 return (dw &
mask) ? 0 : 1;
839 LOG_ERROR(
"Locking user and lockbits pages is not supported yet");
843 uint32_t *dw = &
efm32_info->lb_page[page >> 5];
844 uint32_t
mask =
BIT(page & 0x1f);
874 for (
unsigned int i = first; i <= last; i++) {
877 LOG_ERROR(
"Failed to set lock on page %d", i);
904 LOG_WARNING(
"no working area available, can't do block memory writes");
916 LOG_WARNING(
"no large enough working area available, can't do block memory writes");
949 LOG_ERROR(
"flash write failed at address 0x%" PRIx32,
954 LOG_ERROR(
"flash memory write protected");
959 LOG_ERROR(
"invalid flash memory write address");
1028 LOG_ERROR(
"Wait for WDATAREADY failed");
1062 uint8_t *new_buffer =
NULL;
1070 LOG_ERROR(
"addr 0x%" PRIx32
" breaks required 4-byte alignment",
addr);
1075 uint32_t old_count =
count;
1076 count = (old_count | 3) + 1;
1077 new_buffer = malloc(
count);
1079 LOG_ERROR(
"odd number of bytes to write and no memory for padding buffer");
1082 LOG_INFO(
"odd number of bytes to write (%" PRIu32
"), extending to %"
1083 PRIu32
" and padding with 0xff", old_count,
count);
1084 memset(new_buffer, 0xff,
count);
1088 uint32_t words_remaining =
count / 4;
1089 int retval, retval2;
1107 LOG_WARNING(
"couldn't use block writes, falling back to single memory accesses");
1109 while (words_remaining > 0) {
1111 memcpy(&value,
buffer,
sizeof(uint32_t));
1115 goto reset_pg_and_lock;
1138 LOG_ERROR(
"Cannot write to lock words");
1145 char *buf,
size_t len)
1148 snprintf(buf, len,
"%s Gecko, rev %" PRIu8,
1160 const char *types =
"FMBZxP";
1161 if (dev_type > strlen(types)) {
1162 snprintf(buf, len,
"Unknown MCU family %u", dev_type);
1166 char dev_num_letter =
'A' + (dev_num / 1000);
1167 unsigned int dev_num_digits = dev_num % 1000;
1169 snprintf(buf, len,
"%s%cG%u %c%03u, rev %" PRIu8,
1170 types[dev_type] ==
'P' ?
"EFM32" :
"EFR32",
1188 assert(bank_index >= 0);
1210 free(
bank->sectors);
1214 if (
bank->base == base_address) {
1217 assert(
bank->num_sectors > 0);
1220 bank->num_sectors = 1;
1226 uint32_t userdatasize;
1252 assert(bank_index >= 0);
1279 assert(
bank->sectors);
1281 for (
unsigned int i = 0; i <
bank->num_sectors; i++)
1329 LOG_ERROR(
"Failed to enable MSC clock");
1339 command_print(
CMD,
"efm32 debug interface locked, reset the device to apply");
1346 .
name =
"debuglock",
1347 .handler = efm32_handle_debuglock_command,
1350 .help =
"Lock the debug interface of the device.",
1359 .help =
"Silicon Labs (EFM32 and EFR32) flash command group",
1369 .flash_bank_command = efm32_flash_bank_command,
void init_reg_param(struct reg_param *param, const char *reg_name, uint32_t size, enum param_direction direction)
void destroy_reg_param(struct reg_param *param)
#define ARMV7M_COMMON_MAGIC
Support functions to access arbitrary bits in a byte array.
static uint32_t buf_get_u32(const uint8_t *_buffer, unsigned int first, unsigned int num)
Retrieves num bits from _buffer, starting at the first bit, returning the bits in a 32-bit word.
static void buf_set_u32(uint8_t *_buffer, unsigned int first, unsigned int num, uint32_t value)
Sets num bits in _buffer, starting at the first bit, using the bits in value.
#define FIELD_GET(_mask, _value)
FIELD_GET(_mask, _value) - Extract a value from a bitfield @_mask: Bitfield mask @_value: Bitfield va...
void command_print_sameline(struct command_invocation *cmd, const char *format,...)
void command_print(struct command_invocation *cmd, const char *format,...)
#define CMD
Use this macro to access the command being handled, rather than accessing the variable directly.
#define CALL_COMMAND_HANDLER(name, extra ...)
Use this to macro to call a command helper (or a nested handler).
#define ERROR_COMMAND_SYNTAX_ERROR
#define CMD_ARGC
Use this macro to access the number of arguments for the command being handled, rather than accessing...
#define COMMAND_REGISTRATION_DONE
Use this as the last entry in an array of command_registration records.
uint64_t buffer
Pointer to data buffer to send over SPI.
uint32_t page_size
Page size.
uint32_t buffer_size
Size of dw_spi_program::buffer.
uint32_t address
Starting address. Sector aligned.
#define EFM32_DI_PARTINFO_PAGE_SZ_MASK
#define EFM32_DI_PART_FAMILY
static const struct efm32_family_data efm32_families[]
static int efm32_get_bank_index(target_addr_t base)
static int efm32_set_reg_bits(struct flash_bank *bank, uint32_t reg, uint32_t bitmask, int set)
static int efm32_erase(struct flash_bank *bank, unsigned int first, unsigned int last)
static int efm32_set_page_lock(struct flash_bank *bank, size_t page, int set)
static int efm32_protect_check(struct flash_bank *bank)
#define EFM32_MSC_INFO_BASE
COMMAND_HANDLER(efm32_handle_debuglock_command)
static int efm32_wait_status(struct flash_bank *bank, int timeout_ms, uint32_t wait_mask, bool wait_for_set)
#define EFM32_FLASH_OPERATION_TIMEOUT
static int efm32_get_page_lock(struct flash_bank *bank, size_t page)
#define EFM32_DI_PARTINFO_TYPE_MASK
#define EFM32_DI_PARTINFO_FAMILY_MASK
#define EFM32_MSC_LOCK_BITS
static int efm32_set_wren(struct flash_bank *bank, int write_enable)
static int efm32_write_word(struct flash_bank *bank, uint32_t addr, uint32_t val)
static int efm32_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count)
static int efm32_write_lock_data(struct flash_bank *bank)
#define EFM32_CMU_REG_CLKEN1_SET
static int efm32_msc_clock_enable(struct flash_bank *bank)
static int efm32_write_block(struct flash_bank *bank, const uint8_t *buf, uint32_t address, uint32_t count)
#define EFM32_MSC_USER_DATA
#define EFM32_MSC_STATUS_WDATAREADY_MASK
#define EFM32_MSC_STATUS_BUSY_MASK
static int efm32_protect(struct flash_bank *bank, int set, unsigned int first, unsigned int last)
static int efm32_read_lock_data(struct flash_bank *bank)
static int efm32_probe(struct flash_bank *bank)
#define EFM32_MSC_LOCK_BITS_EXTRA
#define EFM32_MSC_WRITECMD_LADDRIM_MASK
static int efm32_write_only_lockbits(struct flash_bank *bank)
#define EFM32_MSC_LOCK_LOCKKEY
static int efm32_priv_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t addr, uint32_t count)
FLASH_BANK_COMMAND_HANDLER(efm32_flash_bank_command)
#define EFM32_MSC_WRITECMD_WRITEONCE_MASK
static char * efm32_get_str_identifier(struct efm32_info *efm32_mcu_info, char *buf, size_t len)
#define EFM32_MSC_WRITECTRL_WREN_MASK
static int efm32_erase_page(struct flash_bank *bank, uint32_t addr)
const struct flash_driver efm32_flash
static int efm32_msc_lock(struct flash_bank *bank, int lock)
static int efm32_write_reg_u32(struct flash_bank *bank, target_addr_t offset, uint32_t value)
static int efm32_auto_probe(struct flash_bank *bank)
#define EFM32_DI_PARTINFO_NUM_MASK
static void efm32_free_driver_priv(struct flash_bank *bank)
Remove flash structure corresponding to this bank, if and only if it's not used by any others.
#define EFM32_DI_PARTINFO_PAGE_SZ_UD_MASK
#define EFM32_FLASH_BASE_V1
@ EFM32_BANK_INDEX_USER_DATA
@ EFM32_BANK_INDEX_LOCK_BITS
static int efm32_get_info(struct flash_bank *bank, struct command_invocation *cmd)
#define EFM32_FLASH_BASE_V2
static const struct command_registration efm32_command_handlers[]
static const uint8_t efm32_flash_write_code_s0_s1[]
static const struct command_registration efm32_exec_command_handlers[]
static int efm32_read_reg_u32(struct flash_bank *bank, target_addr_t offset, uint32_t *value)
#define EFM32_MSC_STATUS_INVADDR_MASK
#define EFM32_MSC_STATUS_LOCKED_MASK
static const uint8_t efm32_flash_write_code_s2[]
static int efm32_read_info(struct flash_bank *bank)
#define EFM32_MSC_WRITECMD_ERASEPAGE_MASK
#define ERROR_FLASH_OPER_UNSUPPORTED
#define ERROR_FLASH_OPERATION_FAILED
#define ERROR_FLASH_DST_BREAKS_ALIGNMENT
struct flash_sector * alloc_block_array(uint32_t offset, uint32_t size, unsigned int num_blocks)
Allocate and fill an array of sectors or protection blocks.
int default_flash_blank_check(struct flash_bank *bank)
Provides default erased-bank check handling.
int default_flash_read(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, uint32_t count)
Provides default read implementation for flash memory.
struct flash_bank * flash_bank_list(void)
void alive_sleep(uint64_t ms)
#define LOG_WARNING(expr ...)
#define LOG_ERROR(expr ...)
#define LOG_INFO(expr ...)
#define LOG_DEBUG(expr ...)
target_addr_t addr
Start address to search for the control block.
unsigned int common_magic
When run_command is called, a new instance will be created on the stack, filled with the proper value...
uint32_t lb_page[LOCKWORDS_SZ/4]
bool probed[EFM32_N_BANKS]
const struct efm32_dev_info_addr * di_addr
const struct efm32_family_data * family_data
const struct efm32_msc_offset * msc_offset
target_addr_t off_writecmd
target_addr_t off_userdatasize
size_t flash_write_code_len
target_addr_t off_writectrl
const uint8_t * flash_write_code
Provides details of a flash bank, available either on-chip or through a major interface.
struct flash_bank * next
The next flash bank on this chip.
Provides the implementation-independent structure that defines all of the callbacks required by OpenO...
const char * name
Gives a human-readable name of this flash driver, This field is used to select and initialize the dri...
int target_write_buffer(struct target *target, target_addr_t address, uint32_t size, const uint8_t *buffer)
int target_read_buffer(struct target *target, target_addr_t address, uint32_t size, uint8_t *buffer)
int target_read_u8(struct target *target, target_addr_t address, uint8_t *value)
uint32_t target_get_working_area_avail(struct target *target)
int target_alloc_working_area(struct target *target, uint32_t size, struct working_area **area)
int target_write_u32(struct target *target, target_addr_t address, uint32_t value)
int target_free_working_area(struct target *target, struct working_area *area)
Free a working area.
int target_read_u16(struct target *target, target_addr_t address, uint16_t *value)
int target_run_flash_async_algorithm(struct target *target, const uint8_t *buffer, uint32_t count, int block_size, int num_mem_params, struct mem_param *mem_params, int num_reg_params, struct reg_param *reg_params, uint32_t buffer_start, uint32_t buffer_size, uint32_t entry_point, uint32_t exit_point, void *arch_info)
Streams data to a circular buffer on target intended for consumption by code running asynchronously o...
int target_read_u32(struct target *target, target_addr_t address, uint32_t *value)
#define ERROR_TARGET_NOT_HALTED
#define ERROR_TARGET_RESOURCE_NOT_AVAILABLE
#define ARRAY_SIZE(x)
Compute the number of elements of a variable length array.