flash/nor/avrf: add ATmega32U4 support
[openocd.git] / src / flash / nor / xmc1xxx.c
blob6e30fc125c00fb79cb95e1b092e85f377b090511
1 // SPDX-License-Identifier: GPL-2.0-or-later
3 /*
4 * XMC1000 flash driver
6 * Copyright (c) 2016 Andreas Färber
7 */
9 #ifdef HAVE_CONFIG_H
10 #include "config.h"
11 #endif
13 #include "imp.h"
14 #include <helper/align.h>
15 #include <helper/binarybuffer.h>
16 #include <target/algorithm.h>
17 #include <target/armv7m.h>
19 #define FLASH_BASE 0x10000000
20 #define PAU_BASE 0x40000000
21 #define SCU_BASE 0x40010000
22 #define NVM_BASE 0x40050000
24 #define FLASH_CS0 (FLASH_BASE + 0xf00)
26 #define PAU_FLSIZE (PAU_BASE + 0x404)
28 #define SCU_IDCHIP (SCU_BASE + 0x004)
30 #define NVMSTATUS (NVM_BASE + 0x00)
31 #define NVMPROG (NVM_BASE + 0x04)
32 #define NVMCONF (NVM_BASE + 0x08)
34 #define NVMSTATUS_BUSY (1 << 0)
35 #define NVMSTATUS_VERR_MASK (0x3 << 2)
37 #define NVMPROG_ACTION_OPTYPE_IDLE_VERIFY (0 << 0)
38 #define NVMPROG_ACTION_OPTYPE_WRITE (1 << 0)
39 #define NVMPROG_ACTION_OPTYPE_PAGE_ERASE (2 << 0)
41 #define NVMPROG_ACTION_ONE_SHOT_ONCE (1 << 4)
42 #define NVMPROG_ACTION_ONE_SHOT_CONTINUOUS (2 << 4)
44 #define NVMPROG_ACTION_VERIFY_EACH (1 << 6)
45 #define NVMPROG_ACTION_VERIFY_NO (2 << 6)
46 #define NVMPROG_ACTION_VERIFY_ARRAY (3 << 6)
48 #define NVMPROG_ACTION_IDLE 0x00
49 #define NVMPROG_ACTION_MASK 0xff
51 #define NVM_WORD_SIZE 4
52 #define NVM_BLOCK_SIZE (4 * NVM_WORD_SIZE)
53 #define NVM_PAGE_SIZE (16 * NVM_BLOCK_SIZE)
55 struct xmc1xxx_flash_bank {
56 bool probed;
59 static int xmc1xxx_nvm_set_idle(struct target *target)
61 return target_write_u16(target, NVMPROG, NVMPROG_ACTION_IDLE);
64 static int xmc1xxx_nvm_check_idle(struct target *target)
66 uint16_t val;
67 int retval;
69 retval = target_read_u16(target, NVMPROG, &val);
70 if (retval != ERROR_OK)
71 return retval;
72 if ((val & NVMPROG_ACTION_MASK) != NVMPROG_ACTION_IDLE) {
73 LOG_WARNING("NVMPROG.ACTION");
74 retval = xmc1xxx_nvm_set_idle(target);
77 return retval;
80 static int xmc1xxx_erase(struct flash_bank *bank, unsigned int first,
81 unsigned int last)
83 struct target *target = bank->target;
84 struct working_area *workarea;
85 struct reg_param reg_params[3];
86 struct armv7m_algorithm armv7m_algo;
87 unsigned i;
88 int retval;
89 const uint8_t erase_code[] = {
90 #include "../../../contrib/loaders/flash/xmc1xxx/erase.inc"
93 LOG_DEBUG("Infineon XMC1000 erase sectors %u to %u", first, last);
95 if (bank->target->state != TARGET_HALTED) {
96 LOG_WARNING("Cannot communicate... target not halted.");
97 return ERROR_TARGET_NOT_HALTED;
100 retval = xmc1xxx_nvm_check_idle(target);
101 if (retval != ERROR_OK)
102 return retval;
104 retval = target_alloc_working_area(target, sizeof(erase_code),
105 &workarea);
106 if (retval != ERROR_OK) {
107 LOG_ERROR("No working area available.");
108 retval = ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
109 goto err_alloc_code;
111 retval = target_write_buffer(target, workarea->address,
112 sizeof(erase_code), erase_code);
113 if (retval != ERROR_OK)
114 goto err_write_code;
116 armv7m_algo.common_magic = ARMV7M_COMMON_MAGIC;
117 armv7m_algo.core_mode = ARM_MODE_THREAD;
119 init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT);
120 init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
121 init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT);
123 buf_set_u32(reg_params[0].value, 0, 32, NVM_BASE);
124 buf_set_u32(reg_params[1].value, 0, 32, bank->base +
125 bank->sectors[first].offset);
126 buf_set_u32(reg_params[2].value, 0, 32, bank->base +
127 bank->sectors[last].offset + bank->sectors[last].size);
129 retval = target_run_algorithm(target,
130 0, NULL,
131 ARRAY_SIZE(reg_params), reg_params,
132 workarea->address, 0,
133 1000, &armv7m_algo);
134 if (retval != ERROR_OK) {
135 LOG_ERROR("Error executing flash sector erase "
136 "programming algorithm");
137 retval = xmc1xxx_nvm_set_idle(target);
138 if (retval != ERROR_OK)
139 LOG_WARNING("Couldn't restore NVMPROG.ACTION");
140 retval = ERROR_FLASH_OPERATION_FAILED;
141 goto err_run;
144 err_run:
145 for (i = 0; i < ARRAY_SIZE(reg_params); i++)
146 destroy_reg_param(&reg_params[i]);
148 err_write_code:
149 target_free_working_area(target, workarea);
151 err_alloc_code:
152 return retval;
155 static int xmc1xxx_erase_check(struct flash_bank *bank)
157 struct target *target = bank->target;
158 struct working_area *workarea;
159 struct reg_param reg_params[3];
160 struct armv7m_algorithm armv7m_algo;
161 uint16_t val;
162 unsigned i;
163 int retval;
164 const uint8_t erase_check_code[] = {
165 #include "../../../contrib/loaders/flash/xmc1xxx/erase_check.inc"
168 if (bank->target->state != TARGET_HALTED) {
169 LOG_WARNING("Cannot communicate... target not halted.");
170 return ERROR_TARGET_NOT_HALTED;
173 retval = target_alloc_working_area(target, sizeof(erase_check_code),
174 &workarea);
175 if (retval != ERROR_OK) {
176 LOG_ERROR("No working area available.");
177 retval = ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
178 goto err_alloc_code;
180 retval = target_write_buffer(target, workarea->address,
181 sizeof(erase_check_code), erase_check_code);
182 if (retval != ERROR_OK)
183 goto err_write_code;
185 armv7m_algo.common_magic = ARMV7M_COMMON_MAGIC;
186 armv7m_algo.core_mode = ARM_MODE_THREAD;
188 init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT);
189 init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
190 init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT);
192 buf_set_u32(reg_params[0].value, 0, 32, NVM_BASE);
194 for (unsigned int sector = 0; sector < bank->num_sectors; sector++) {
195 uint32_t start = bank->base + bank->sectors[sector].offset;
196 buf_set_u32(reg_params[1].value, 0, 32, start);
197 buf_set_u32(reg_params[2].value, 0, 32, start + bank->sectors[sector].size);
199 retval = xmc1xxx_nvm_check_idle(target);
200 if (retval != ERROR_OK)
201 goto err_nvmprog;
203 LOG_DEBUG("Erase-checking 0x%08" PRIx32, start);
204 retval = target_run_algorithm(target,
205 0, NULL,
206 ARRAY_SIZE(reg_params), reg_params,
207 workarea->address, 0,
208 1000, &armv7m_algo);
209 if (retval != ERROR_OK) {
210 LOG_ERROR("Error executing flash sector erase check "
211 "programming algorithm");
212 retval = xmc1xxx_nvm_set_idle(target);
213 if (retval != ERROR_OK)
214 LOG_WARNING("Couldn't restore NVMPROG.ACTION");
215 retval = ERROR_FLASH_OPERATION_FAILED;
216 goto err_run;
219 retval = target_read_u16(target, NVMSTATUS, &val);
220 if (retval != ERROR_OK) {
221 LOG_ERROR("Couldn't read NVMSTATUS");
222 goto err_nvmstatus;
224 bank->sectors[sector].is_erased = (val & NVMSTATUS_VERR_MASK) ? 0 : 1;
227 err_nvmstatus:
228 err_run:
229 err_nvmprog:
230 for (i = 0; i < ARRAY_SIZE(reg_params); i++)
231 destroy_reg_param(&reg_params[i]);
233 err_write_code:
234 target_free_working_area(target, workarea);
236 err_alloc_code:
237 return retval;
240 static int xmc1xxx_write(struct flash_bank *bank, const uint8_t *buffer,
241 uint32_t offset, uint32_t byte_count)
243 struct target *target = bank->target;
244 struct working_area *code_workarea, *data_workarea;
245 struct reg_param reg_params[4];
246 struct armv7m_algorithm armv7m_algo;
247 uint32_t block_count = DIV_ROUND_UP(byte_count, NVM_BLOCK_SIZE);
248 unsigned i;
249 int retval;
250 const uint8_t write_code[] = {
251 #include "../../../contrib/loaders/flash/xmc1xxx/write.inc"
254 LOG_DEBUG("Infineon XMC1000 write at 0x%08" PRIx32 " (%" PRIu32 " bytes)",
255 offset, byte_count);
257 if (!IS_ALIGNED(offset, NVM_BLOCK_SIZE)) {
258 LOG_ERROR("offset 0x%" PRIx32 " breaks required block alignment",
259 offset);
260 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
262 if (!IS_ALIGNED(byte_count, NVM_BLOCK_SIZE)) {
263 LOG_WARNING("length %" PRIu32 " is not block aligned, rounding up",
264 byte_count);
267 if (target->state != TARGET_HALTED) {
268 LOG_WARNING("Cannot communicate... target not halted.");
269 return ERROR_TARGET_NOT_HALTED;
272 retval = target_alloc_working_area(target, sizeof(write_code),
273 &code_workarea);
274 if (retval != ERROR_OK) {
275 LOG_ERROR("No working area available for write code.");
276 retval = ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
277 goto err_alloc_code;
279 retval = target_write_buffer(target, code_workarea->address,
280 sizeof(write_code), write_code);
281 if (retval != ERROR_OK)
282 goto err_write_code;
284 retval = target_alloc_working_area(target, MAX(NVM_BLOCK_SIZE,
285 MIN(block_count * NVM_BLOCK_SIZE, target_get_working_area_avail(target))),
286 &data_workarea);
287 if (retval != ERROR_OK) {
288 LOG_ERROR("No working area available for write data.");
289 retval = ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
290 goto err_alloc_data;
293 armv7m_algo.common_magic = ARMV7M_COMMON_MAGIC;
294 armv7m_algo.core_mode = ARM_MODE_THREAD;
296 init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT);
297 init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
298 init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT);
299 init_reg_param(&reg_params[3], "r3", 32, PARAM_OUT);
301 buf_set_u32(reg_params[0].value, 0, 32, NVM_BASE);
303 while (byte_count > 0) {
304 uint32_t blocks = MIN(block_count, data_workarea->size / NVM_BLOCK_SIZE);
305 uint32_t addr = bank->base + offset;
307 LOG_DEBUG("copying %" PRIu32 " bytes to SRAM " TARGET_ADDR_FMT,
308 MIN(blocks * NVM_BLOCK_SIZE, byte_count),
309 data_workarea->address);
311 retval = target_write_buffer(target, data_workarea->address,
312 MIN(blocks * NVM_BLOCK_SIZE, byte_count), buffer);
313 if (retval != ERROR_OK) {
314 LOG_ERROR("Error writing data buffer");
315 retval = ERROR_FLASH_OPERATION_FAILED;
316 goto err_write_data;
318 if (byte_count < blocks * NVM_BLOCK_SIZE) {
319 retval = target_write_memory(target,
320 data_workarea->address + byte_count, 1,
321 blocks * NVM_BLOCK_SIZE - byte_count,
322 &bank->default_padded_value);
323 if (retval != ERROR_OK) {
324 LOG_ERROR("Error writing data padding");
325 retval = ERROR_FLASH_OPERATION_FAILED;
326 goto err_write_pad;
330 LOG_DEBUG("writing 0x%08" PRIx32 "-0x%08" PRIx32 " (%" PRIu32 "x)",
331 addr, addr + blocks * NVM_BLOCK_SIZE - 1, blocks);
333 retval = xmc1xxx_nvm_check_idle(target);
334 if (retval != ERROR_OK)
335 goto err_nvmprog;
337 buf_set_u32(reg_params[1].value, 0, 32, addr);
338 buf_set_u32(reg_params[2].value, 0, 32, data_workarea->address);
339 buf_set_u32(reg_params[3].value, 0, 32, blocks);
341 retval = target_run_algorithm(target,
342 0, NULL,
343 ARRAY_SIZE(reg_params), reg_params,
344 code_workarea->address, 0,
345 5 * 60 * 1000, &armv7m_algo);
346 if (retval != ERROR_OK) {
347 LOG_ERROR("Error executing flash write "
348 "programming algorithm");
349 retval = xmc1xxx_nvm_set_idle(target);
350 if (retval != ERROR_OK)
351 LOG_WARNING("Couldn't restore NVMPROG.ACTION");
352 retval = ERROR_FLASH_OPERATION_FAILED;
353 goto err_run;
356 block_count -= blocks;
357 offset += blocks * NVM_BLOCK_SIZE;
358 buffer += blocks * NVM_BLOCK_SIZE;
359 byte_count -= MIN(blocks * NVM_BLOCK_SIZE, byte_count);
362 err_run:
363 err_nvmprog:
364 err_write_pad:
365 err_write_data:
366 for (i = 0; i < ARRAY_SIZE(reg_params); i++)
367 destroy_reg_param(&reg_params[i]);
369 target_free_working_area(target, data_workarea);
370 err_alloc_data:
371 err_write_code:
372 target_free_working_area(target, code_workarea);
374 err_alloc_code:
375 return retval;
378 static int xmc1xxx_protect_check(struct flash_bank *bank)
380 uint32_t nvmconf;
381 unsigned int num_protected;
382 int retval;
384 if (bank->target->state != TARGET_HALTED) {
385 LOG_WARNING("Cannot communicate... target not halted.");
386 return ERROR_TARGET_NOT_HALTED;
389 retval = target_read_u32(bank->target, NVMCONF, &nvmconf);
390 if (retval != ERROR_OK) {
391 LOG_ERROR("Cannot read NVMCONF register.");
392 return retval;
394 LOG_DEBUG("NVMCONF = %08" PRIx32, nvmconf);
396 num_protected = (nvmconf >> 4) & 0xff;
398 for (unsigned int i = 0; i < bank->num_sectors; i++)
399 bank->sectors[i].is_protected = (i < num_protected) ? 1 : 0;
401 return ERROR_OK;
404 static int xmc1xxx_get_info_command(struct flash_bank *bank, struct command_invocation *cmd)
406 uint32_t chipid[8];
407 int i, retval;
409 if (bank->target->state != TARGET_HALTED) {
410 LOG_WARNING("Cannot communicate... target not halted.");
411 return ERROR_TARGET_NOT_HALTED;
414 /* Obtain the 8-word Chip Identification Number */
415 for (i = 0; i < 7; i++) {
416 retval = target_read_u32(bank->target, FLASH_CS0 + i * 4, &chipid[i]);
417 if (retval != ERROR_OK) {
418 LOG_ERROR("Cannot read CS0 register %i.", i);
419 return retval;
421 LOG_DEBUG("ID[%d] = %08" PRIX32, i, chipid[i]);
423 retval = target_read_u32(bank->target, SCU_BASE + 0x000, &chipid[7]);
424 if (retval != ERROR_OK) {
425 LOG_ERROR("Cannot read DBGROMID register.");
426 return retval;
428 LOG_DEBUG("ID[7] = %08" PRIX32, chipid[7]);
430 command_print_sameline(cmd,
431 "XMC%" PRIx32 "00 %" PRIX32 " flash %" PRIu32 "KB ROM %" PRIu32 "KB SRAM %" PRIu32 "KB",
432 (chipid[0] >> 12) & 0xff,
433 0xAA + (chipid[7] >> 28) - 1,
434 (((chipid[6] >> 12) & 0x3f) - 1) * 4,
435 (((chipid[4] >> 8) & 0x3f) * 256) / 1024,
436 (((chipid[5] >> 8) & 0x1f) * 256 * 4) / 1024);
438 return ERROR_OK;
441 static int xmc1xxx_probe(struct flash_bank *bank)
443 struct xmc1xxx_flash_bank *xmc_bank = bank->driver_priv;
444 uint32_t flash_addr = bank->base;
445 uint32_t idchip, flsize;
446 int retval;
448 if (xmc_bank->probed)
449 return ERROR_OK;
451 if (bank->target->state != TARGET_HALTED) {
452 LOG_WARNING("Cannot communicate... target not halted.");
453 return ERROR_TARGET_NOT_HALTED;
456 retval = target_read_u32(bank->target, SCU_IDCHIP, &idchip);
457 if (retval != ERROR_OK) {
458 LOG_ERROR("Cannot read IDCHIP register.");
459 return retval;
462 if ((idchip & 0xffff0000) != 0x10000) {
463 LOG_ERROR("IDCHIP register does not match XMC1xxx.");
464 return ERROR_FAIL;
467 LOG_DEBUG("IDCHIP = %08" PRIx32, idchip);
469 retval = target_read_u32(bank->target, PAU_FLSIZE, &flsize);
470 if (retval != ERROR_OK) {
471 LOG_ERROR("Cannot read FLSIZE register.");
472 return retval;
475 bank->num_sectors = 1 + ((flsize >> 12) & 0x3f) - 1;
476 bank->size = bank->num_sectors * 4 * 1024;
477 bank->sectors = calloc(bank->num_sectors,
478 sizeof(struct flash_sector));
479 for (unsigned int i = 0; i < bank->num_sectors; i++) {
480 if (i == 0) {
481 bank->sectors[i].size = 0x200;
482 bank->sectors[i].offset = 0xE00;
483 flash_addr += 0x1000;
484 } else {
485 bank->sectors[i].size = 4 * 1024;
486 bank->sectors[i].offset = flash_addr - bank->base;
487 flash_addr += bank->sectors[i].size;
489 bank->sectors[i].is_erased = -1;
490 bank->sectors[i].is_protected = -1;
493 xmc_bank->probed = true;
495 return ERROR_OK;
498 static int xmc1xxx_auto_probe(struct flash_bank *bank)
500 struct xmc1xxx_flash_bank *xmc_bank = bank->driver_priv;
502 if (xmc_bank->probed)
503 return ERROR_OK;
505 return xmc1xxx_probe(bank);
508 FLASH_BANK_COMMAND_HANDLER(xmc1xxx_flash_bank_command)
510 struct xmc1xxx_flash_bank *xmc_bank;
512 xmc_bank = malloc(sizeof(struct xmc1xxx_flash_bank));
513 if (!xmc_bank)
514 return ERROR_FLASH_OPERATION_FAILED;
516 xmc_bank->probed = false;
518 bank->driver_priv = xmc_bank;
520 return ERROR_OK;
523 const struct flash_driver xmc1xxx_flash = {
524 .name = "xmc1xxx",
525 .flash_bank_command = xmc1xxx_flash_bank_command,
526 .info = xmc1xxx_get_info_command,
527 .probe = xmc1xxx_probe,
528 .auto_probe = xmc1xxx_auto_probe,
529 .protect_check = xmc1xxx_protect_check,
530 .read = default_flash_read,
531 .erase = xmc1xxx_erase,
532 .erase_check = xmc1xxx_erase_check,
533 .write = xmc1xxx_write,
534 .free_driver_priv = default_flash_free_driver_priv,