4 * Copyright (c) 2016 Andreas Färber
14 #include <helper/binarybuffer.h>
15 #include <target/algorithm.h>
16 #include <target/armv7m.h>
18 #define FLASH_BASE 0x10000000
19 #define PAU_BASE 0x40000000
20 #define SCU_BASE 0x40010000
21 #define NVM_BASE 0x40050000
23 #define FLASH_CS0 (FLASH_BASE + 0xf00)
25 #define PAU_FLSIZE (PAU_BASE + 0x404)
27 #define SCU_IDCHIP (SCU_BASE + 0x004)
29 #define NVMSTATUS (NVM_BASE + 0x00)
30 #define NVMPROG (NVM_BASE + 0x04)
31 #define NVMCONF (NVM_BASE + 0x08)
33 #define NVMSTATUS_BUSY (1 << 0)
34 #define NVMSTATUS_VERR_MASK (0x3 << 2)
36 #define NVMPROG_ACTION_OPTYPE_IDLE_VERIFY (0 << 0)
37 #define NVMPROG_ACTION_OPTYPE_WRITE (1 << 0)
38 #define NVMPROG_ACTION_OPTYPE_PAGE_ERASE (2 << 0)
40 #define NVMPROG_ACTION_ONE_SHOT_ONCE (1 << 4)
41 #define NVMPROG_ACTION_ONE_SHOT_CONTINUOUS (2 << 4)
43 #define NVMPROG_ACTION_VERIFY_EACH (1 << 6)
44 #define NVMPROG_ACTION_VERIFY_NO (2 << 6)
45 #define NVMPROG_ACTION_VERIFY_ARRAY (3 << 6)
47 #define NVMPROG_ACTION_IDLE 0x00
48 #define NVMPROG_ACTION_MASK 0xff
50 #define NVM_WORD_SIZE 4
51 #define NVM_BLOCK_SIZE (4 * NVM_WORD_SIZE)
52 #define NVM_PAGE_SIZE (16 * NVM_BLOCK_SIZE)
54 struct xmc1xxx_flash_bank {
58 static int xmc1xxx_nvm_set_idle(struct target *target)
60 return target_write_u16(target, NVMPROG, NVMPROG_ACTION_IDLE);
63 static int xmc1xxx_nvm_check_idle(struct target *target)
68 retval = target_read_u16(target, NVMPROG, &val);
69 if (retval != ERROR_OK)
71 if ((val & NVMPROG_ACTION_MASK) != NVMPROG_ACTION_IDLE) {
72 LOG_WARNING("NVMPROG.ACTION");
73 retval = xmc1xxx_nvm_set_idle(target);
79 static int xmc1xxx_erase(struct flash_bank *bank, unsigned int first,
82 struct target *target = bank->target;
83 struct working_area *workarea;
84 struct reg_param reg_params[3];
85 struct armv7m_algorithm armv7m_algo;
88 const uint8_t erase_code[] = {
89 #include "../../../contrib/loaders/flash/xmc1xxx/erase.inc"
92 LOG_DEBUG("Infineon XMC1000 erase sectors %u to %u", first, last);
94 if (bank->target->state != TARGET_HALTED) {
95 LOG_WARNING("Cannot communicate... target not halted.");
96 return ERROR_TARGET_NOT_HALTED;
99 retval = xmc1xxx_nvm_check_idle(target);
100 if (retval != ERROR_OK)
103 retval = target_alloc_working_area(target, sizeof(erase_code),
105 if (retval != ERROR_OK) {
106 LOG_ERROR("No working area available.");
107 retval = ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
110 retval = target_write_buffer(target, workarea->address,
111 sizeof(erase_code), erase_code);
112 if (retval != ERROR_OK)
115 armv7m_algo.common_magic = ARMV7M_COMMON_MAGIC;
116 armv7m_algo.core_mode = ARM_MODE_THREAD;
118 init_reg_param(®_params[0], "r0", 32, PARAM_OUT);
119 init_reg_param(®_params[1], "r1", 32, PARAM_OUT);
120 init_reg_param(®_params[2], "r2", 32, PARAM_OUT);
122 buf_set_u32(reg_params[0].value, 0, 32, NVM_BASE);
123 buf_set_u32(reg_params[1].value, 0, 32, bank->base +
124 bank->sectors[first].offset);
125 buf_set_u32(reg_params[2].value, 0, 32, bank->base +
126 bank->sectors[last].offset + bank->sectors[last].size);
128 retval = target_run_algorithm(target,
130 ARRAY_SIZE(reg_params), reg_params,
131 workarea->address, 0,
133 if (retval != ERROR_OK) {
134 LOG_ERROR("Error executing flash sector erase "
135 "programming algorithm");
136 retval = xmc1xxx_nvm_set_idle(target);
137 if (retval != ERROR_OK)
138 LOG_WARNING("Couldn't restore NVMPROG.ACTION");
139 retval = ERROR_FLASH_OPERATION_FAILED;
143 for (unsigned int sector = first; sector <= last; sector++)
144 bank->sectors[sector].is_erased = 1;
147 for (i = 0; i < ARRAY_SIZE(reg_params); i++)
148 destroy_reg_param(®_params[i]);
151 target_free_working_area(target, workarea);
157 static int xmc1xxx_erase_check(struct flash_bank *bank)
159 struct target *target = bank->target;
160 struct working_area *workarea;
161 struct reg_param reg_params[3];
162 struct armv7m_algorithm armv7m_algo;
166 const uint8_t erase_check_code[] = {
167 #include "../../../contrib/loaders/flash/xmc1xxx/erase_check.inc"
170 if (bank->target->state != TARGET_HALTED) {
171 LOG_WARNING("Cannot communicate... target not halted.");
172 return ERROR_TARGET_NOT_HALTED;
175 retval = target_alloc_working_area(target, sizeof(erase_check_code),
177 if (retval != ERROR_OK) {
178 LOG_ERROR("No working area available.");
179 retval = ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
182 retval = target_write_buffer(target, workarea->address,
183 sizeof(erase_check_code), erase_check_code);
184 if (retval != ERROR_OK)
187 armv7m_algo.common_magic = ARMV7M_COMMON_MAGIC;
188 armv7m_algo.core_mode = ARM_MODE_THREAD;
190 init_reg_param(®_params[0], "r0", 32, PARAM_OUT);
191 init_reg_param(®_params[1], "r1", 32, PARAM_OUT);
192 init_reg_param(®_params[2], "r2", 32, PARAM_OUT);
194 buf_set_u32(reg_params[0].value, 0, 32, NVM_BASE);
196 for (unsigned int sector = 0; sector < bank->num_sectors; sector++) {
197 uint32_t start = bank->base + bank->sectors[sector].offset;
198 buf_set_u32(reg_params[1].value, 0, 32, start);
199 buf_set_u32(reg_params[2].value, 0, 32, start + bank->sectors[sector].size);
201 retval = xmc1xxx_nvm_check_idle(target);
202 if (retval != ERROR_OK)
205 LOG_DEBUG("Erase-checking 0x%08" PRIx32, start);
206 retval = target_run_algorithm(target,
208 ARRAY_SIZE(reg_params), reg_params,
209 workarea->address, 0,
211 if (retval != ERROR_OK) {
212 LOG_ERROR("Error executing flash sector erase check "
213 "programming algorithm");
214 retval = xmc1xxx_nvm_set_idle(target);
215 if (retval != ERROR_OK)
216 LOG_WARNING("Couldn't restore NVMPROG.ACTION");
217 retval = ERROR_FLASH_OPERATION_FAILED;
221 retval = target_read_u16(target, NVMSTATUS, &val);
222 if (retval != ERROR_OK) {
223 LOG_ERROR("Couldn't read NVMSTATUS");
226 bank->sectors[sector].is_erased = (val & NVMSTATUS_VERR_MASK) ? 0 : 1;
232 for (i = 0; i < ARRAY_SIZE(reg_params); i++)
233 destroy_reg_param(®_params[i]);
236 target_free_working_area(target, workarea);
242 static int xmc1xxx_write(struct flash_bank *bank, const uint8_t *buffer,
243 uint32_t offset, uint32_t byte_count)
245 struct target *target = bank->target;
246 struct working_area *code_workarea, *data_workarea;
247 struct reg_param reg_params[4];
248 struct armv7m_algorithm armv7m_algo;
249 uint32_t block_count = DIV_ROUND_UP(byte_count, NVM_BLOCK_SIZE);
252 const uint8_t write_code[] = {
253 #include "../../../contrib/loaders/flash/xmc1xxx/write.inc"
256 LOG_DEBUG("Infineon XMC1000 write at 0x%08" PRIx32 " (%" PRIu32 " bytes)",
259 if (offset & (NVM_BLOCK_SIZE - 1)) {
260 LOG_ERROR("offset 0x%" PRIx32 " breaks required block alignment",
262 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
264 if (byte_count & (NVM_BLOCK_SIZE - 1)) {
265 LOG_WARNING("length %" PRIu32 " is not block aligned, rounding up",
269 if (target->state != TARGET_HALTED) {
270 LOG_WARNING("Cannot communicate... target not halted.");
271 return ERROR_TARGET_NOT_HALTED;
274 retval = target_alloc_working_area(target, sizeof(write_code),
276 if (retval != ERROR_OK) {
277 LOG_ERROR("No working area available for write code.");
278 retval = ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
281 retval = target_write_buffer(target, code_workarea->address,
282 sizeof(write_code), write_code);
283 if (retval != ERROR_OK)
286 retval = target_alloc_working_area(target, MAX(NVM_BLOCK_SIZE,
287 MIN(block_count * NVM_BLOCK_SIZE, target_get_working_area_avail(target))),
289 if (retval != ERROR_OK) {
290 LOG_ERROR("No working area available for write data.");
291 retval = ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
295 armv7m_algo.common_magic = ARMV7M_COMMON_MAGIC;
296 armv7m_algo.core_mode = ARM_MODE_THREAD;
298 init_reg_param(®_params[0], "r0", 32, PARAM_OUT);
299 init_reg_param(®_params[1], "r1", 32, PARAM_OUT);
300 init_reg_param(®_params[2], "r2", 32, PARAM_OUT);
301 init_reg_param(®_params[3], "r3", 32, PARAM_OUT);
303 buf_set_u32(reg_params[0].value, 0, 32, NVM_BASE);
305 while (byte_count > 0) {
306 uint32_t blocks = MIN(block_count, data_workarea->size / NVM_BLOCK_SIZE);
307 uint32_t addr = bank->base + offset;
309 LOG_DEBUG("copying %" PRIu32 " bytes to SRAM " TARGET_ADDR_FMT,
310 MIN(blocks * NVM_BLOCK_SIZE, byte_count),
311 data_workarea->address);
313 retval = target_write_buffer(target, data_workarea->address,
314 MIN(blocks * NVM_BLOCK_SIZE, byte_count), buffer);
315 if (retval != ERROR_OK) {
316 LOG_ERROR("Error writing data buffer");
317 retval = ERROR_FLASH_OPERATION_FAILED;
320 if (byte_count < blocks * NVM_BLOCK_SIZE) {
321 retval = target_write_memory(target,
322 data_workarea->address + byte_count, 1,
323 blocks * NVM_BLOCK_SIZE - byte_count,
324 &bank->default_padded_value);
325 if (retval != ERROR_OK) {
326 LOG_ERROR("Error writing data padding");
327 retval = ERROR_FLASH_OPERATION_FAILED;
332 LOG_DEBUG("writing 0x%08" PRIx32 "-0x%08" PRIx32 " (%" PRIu32 "x)",
333 addr, addr + blocks * NVM_BLOCK_SIZE - 1, blocks);
335 retval = xmc1xxx_nvm_check_idle(target);
336 if (retval != ERROR_OK)
339 buf_set_u32(reg_params[1].value, 0, 32, addr);
340 buf_set_u32(reg_params[2].value, 0, 32, data_workarea->address);
341 buf_set_u32(reg_params[3].value, 0, 32, blocks);
343 retval = target_run_algorithm(target,
345 ARRAY_SIZE(reg_params), reg_params,
346 code_workarea->address, 0,
347 5 * 60 * 1000, &armv7m_algo);
348 if (retval != ERROR_OK) {
349 LOG_ERROR("Error executing flash write "
350 "programming algorithm");
351 retval = xmc1xxx_nvm_set_idle(target);
352 if (retval != ERROR_OK)
353 LOG_WARNING("Couldn't restore NVMPROG.ACTION");
354 retval = ERROR_FLASH_OPERATION_FAILED;
358 block_count -= blocks;
359 offset += blocks * NVM_BLOCK_SIZE;
360 buffer += blocks * NVM_BLOCK_SIZE;
361 byte_count -= MIN(blocks * NVM_BLOCK_SIZE, byte_count);
368 for (i = 0; i < ARRAY_SIZE(reg_params); i++)
369 destroy_reg_param(®_params[i]);
371 target_free_working_area(target, data_workarea);
374 target_free_working_area(target, code_workarea);
380 static int xmc1xxx_protect_check(struct flash_bank *bank)
383 unsigned int num_protected;
386 if (bank->target->state != TARGET_HALTED) {
387 LOG_WARNING("Cannot communicate... target not halted.");
388 return ERROR_TARGET_NOT_HALTED;
391 retval = target_read_u32(bank->target, NVMCONF, &nvmconf);
392 if (retval != ERROR_OK) {
393 LOG_ERROR("Cannot read NVMCONF register.");
396 LOG_DEBUG("NVMCONF = %08" PRIx32, nvmconf);
398 num_protected = (nvmconf >> 4) & 0xff;
400 for (unsigned int i = 0; i < bank->num_sectors; i++)
401 bank->sectors[i].is_protected = (i < num_protected) ? 1 : 0;
406 static int xmc1xxx_get_info_command(struct flash_bank *bank, struct command_invocation *cmd)
411 if (bank->target->state != TARGET_HALTED) {
412 LOG_WARNING("Cannot communicate... target not halted.");
413 return ERROR_TARGET_NOT_HALTED;
416 /* Obtain the 8-word Chip Identification Number */
417 for (i = 0; i < 7; i++) {
418 retval = target_read_u32(bank->target, FLASH_CS0 + i * 4, &chipid[i]);
419 if (retval != ERROR_OK) {
420 LOG_ERROR("Cannot read CS0 register %i.", i);
423 LOG_DEBUG("ID[%d] = %08" PRIX32, i, chipid[i]);
425 retval = target_read_u32(bank->target, SCU_BASE + 0x000, &chipid[7]);
426 if (retval != ERROR_OK) {
427 LOG_ERROR("Cannot read DBGROMID register.");
430 LOG_DEBUG("ID[7] = %08" PRIX32, chipid[7]);
432 command_print_sameline(cmd,
433 "XMC%" PRIx32 "00 %" PRIX32 " flash %" PRIu32 "KB ROM %" PRIu32 "KB SRAM %" PRIu32 "KB",
434 (chipid[0] >> 12) & 0xff,
435 0xAA + (chipid[7] >> 28) - 1,
436 (((chipid[6] >> 12) & 0x3f) - 1) * 4,
437 (((chipid[4] >> 8) & 0x3f) * 256) / 1024,
438 (((chipid[5] >> 8) & 0x1f) * 256 * 4) / 1024);
443 static int xmc1xxx_probe(struct flash_bank *bank)
445 struct xmc1xxx_flash_bank *xmc_bank = bank->driver_priv;
446 uint32_t flash_addr = bank->base;
447 uint32_t idchip, flsize;
450 if (xmc_bank->probed)
453 if (bank->target->state != TARGET_HALTED) {
454 LOG_WARNING("Cannot communicate... target not halted.");
455 return ERROR_TARGET_NOT_HALTED;
458 retval = target_read_u32(bank->target, SCU_IDCHIP, &idchip);
459 if (retval != ERROR_OK) {
460 LOG_ERROR("Cannot read IDCHIP register.");
464 if ((idchip & 0xffff0000) != 0x10000) {
465 LOG_ERROR("IDCHIP register does not match XMC1xxx.");
469 LOG_DEBUG("IDCHIP = %08" PRIx32, idchip);
471 retval = target_read_u32(bank->target, PAU_FLSIZE, &flsize);
472 if (retval != ERROR_OK) {
473 LOG_ERROR("Cannot read FLSIZE register.");
477 bank->num_sectors = 1 + ((flsize >> 12) & 0x3f) - 1;
478 bank->size = bank->num_sectors * 4 * 1024;
479 bank->sectors = calloc(bank->num_sectors,
480 sizeof(struct flash_sector));
481 for (unsigned int i = 0; i < bank->num_sectors; i++) {
483 bank->sectors[i].size = 0x200;
484 bank->sectors[i].offset = 0xE00;
485 flash_addr += 0x1000;
487 bank->sectors[i].size = 4 * 1024;
488 bank->sectors[i].offset = flash_addr - bank->base;
489 flash_addr += bank->sectors[i].size;
491 bank->sectors[i].is_erased = -1;
492 bank->sectors[i].is_protected = -1;
495 xmc_bank->probed = true;
500 static int xmc1xxx_auto_probe(struct flash_bank *bank)
502 struct xmc1xxx_flash_bank *xmc_bank = bank->driver_priv;
504 if (xmc_bank->probed)
507 return xmc1xxx_probe(bank);
510 FLASH_BANK_COMMAND_HANDLER(xmc1xxx_flash_bank_command)
512 struct xmc1xxx_flash_bank *xmc_bank;
514 xmc_bank = malloc(sizeof(struct xmc1xxx_flash_bank));
516 return ERROR_FLASH_OPERATION_FAILED;
518 xmc_bank->probed = false;
520 bank->driver_priv = xmc_bank;
525 static const struct command_registration xmc1xxx_exec_command_handlers[] = {
526 COMMAND_REGISTRATION_DONE
529 static const struct command_registration xmc1xxx_command_handlers[] = {
533 .help = "xmc1xxx flash command group",
535 .chain = xmc1xxx_exec_command_handlers,
537 COMMAND_REGISTRATION_DONE
540 const struct flash_driver xmc1xxx_flash = {
542 .commands = xmc1xxx_command_handlers,
543 .flash_bank_command = xmc1xxx_flash_bank_command,
544 .info = xmc1xxx_get_info_command,
545 .probe = xmc1xxx_probe,
546 .auto_probe = xmc1xxx_auto_probe,
547 .protect_check = xmc1xxx_protect_check,
548 .read = default_flash_read,
549 .erase = xmc1xxx_erase,
550 .erase_check = xmc1xxx_erase_check,
551 .write = xmc1xxx_write,
552 .free_driver_priv = default_flash_free_driver_priv,