11542ac5bb16e9a7aef21c4438aed077a3aa9991
[openocd.git] / src / flash / nor / xmc1xxx.c
1 /*
2 * XMC1000 flash driver
3 *
4 * Copyright (c) 2016 Andreas Färber
5 *
6 * License: GPL-2.0+
7 */
8
9 #ifdef HAVE_CONFIG_H
10 #include "config.h"
11 #endif
12
13 #include "imp.h"
14 #include <helper/binarybuffer.h>
15 #include <target/algorithm.h>
16 #include <target/armv7m.h>
17
18 #define FLASH_BASE 0x10000000
19 #define PAU_BASE 0x40000000
20 #define SCU_BASE 0x40010000
21 #define NVM_BASE 0x40050000
22
23 #define FLASH_CS0 (FLASH_BASE + 0xf00)
24
25 #define PAU_FLSIZE (PAU_BASE + 0x404)
26
27 #define SCU_IDCHIP (SCU_BASE + 0x004)
28
29 #define NVMSTATUS (NVM_BASE + 0x00)
30 #define NVMPROG (NVM_BASE + 0x04)
31 #define NVMCONF (NVM_BASE + 0x08)
32
33 #define NVMSTATUS_BUSY (1 << 0)
34 #define NVMSTATUS_VERR_MASK (0x3 << 2)
35
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)
39
40 #define NVMPROG_ACTION_ONE_SHOT_ONCE (1 << 4)
41 #define NVMPROG_ACTION_ONE_SHOT_CONTINUOUS (2 << 4)
42
43 #define NVMPROG_ACTION_VERIFY_EACH (1 << 6)
44 #define NVMPROG_ACTION_VERIFY_NO (2 << 6)
45 #define NVMPROG_ACTION_VERIFY_ARRAY (3 << 6)
46
47 #define NVMPROG_ACTION_IDLE 0x00
48 #define NVMPROG_ACTION_MASK 0xff
49
50 #define NVM_WORD_SIZE 4
51 #define NVM_BLOCK_SIZE (4 * NVM_WORD_SIZE)
52 #define NVM_PAGE_SIZE (16 * NVM_BLOCK_SIZE)
53
54 struct xmc1xxx_flash_bank {
55 bool probed;
56 };
57
58 static int xmc1xxx_nvm_set_idle(struct target *target)
59 {
60 return target_write_u16(target, NVMPROG, NVMPROG_ACTION_IDLE);
61 }
62
63 static int xmc1xxx_nvm_check_idle(struct target *target)
64 {
65 uint16_t val;
66 int retval;
67
68 retval = target_read_u16(target, NVMPROG, &val);
69 if (retval != ERROR_OK)
70 return retval;
71 if ((val & NVMPROG_ACTION_MASK) != NVMPROG_ACTION_IDLE) {
72 LOG_WARNING("NVMPROG.ACTION");
73 retval = xmc1xxx_nvm_set_idle(target);
74 }
75
76 return retval;
77 }
78
79 static int xmc1xxx_erase(struct flash_bank *bank, unsigned int first,
80 unsigned int last)
81 {
82 struct target *target = bank->target;
83 struct working_area *workarea;
84 struct reg_param reg_params[3];
85 struct armv7m_algorithm armv7m_algo;
86 unsigned i;
87 int retval;
88 const uint8_t erase_code[] = {
89 #include "../../../contrib/loaders/flash/xmc1xxx/erase.inc"
90 };
91
92 LOG_DEBUG("Infineon XMC1000 erase sectors %u to %u", first, last);
93
94 if (bank->target->state != TARGET_HALTED) {
95 LOG_WARNING("Cannot communicate... target not halted.");
96 return ERROR_TARGET_NOT_HALTED;
97 }
98
99 retval = xmc1xxx_nvm_check_idle(target);
100 if (retval != ERROR_OK)
101 return retval;
102
103 retval = target_alloc_working_area(target, sizeof(erase_code),
104 &workarea);
105 if (retval != ERROR_OK) {
106 LOG_ERROR("No working area available.");
107 retval = ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
108 goto err_alloc_code;
109 }
110 retval = target_write_buffer(target, workarea->address,
111 sizeof(erase_code), erase_code);
112 if (retval != ERROR_OK)
113 goto err_write_code;
114
115 armv7m_algo.common_magic = ARMV7M_COMMON_MAGIC;
116 armv7m_algo.core_mode = ARM_MODE_THREAD;
117
118 init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT);
119 init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
120 init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT);
121
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);
127
128 retval = target_run_algorithm(target,
129 0, NULL,
130 ARRAY_SIZE(reg_params), reg_params,
131 workarea->address, 0,
132 1000, &armv7m_algo);
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;
140 goto err_run;
141 }
142
143 for (unsigned int sector = first; sector <= last; sector++)
144 bank->sectors[sector].is_erased = 1;
145
146 err_run:
147 for (i = 0; i < ARRAY_SIZE(reg_params); i++)
148 destroy_reg_param(&reg_params[i]);
149
150 err_write_code:
151 target_free_working_area(target, workarea);
152
153 err_alloc_code:
154 return retval;
155 }
156
157 static int xmc1xxx_erase_check(struct flash_bank *bank)
158 {
159 struct target *target = bank->target;
160 struct working_area *workarea;
161 struct reg_param reg_params[3];
162 struct armv7m_algorithm armv7m_algo;
163 uint16_t val;
164 unsigned i;
165 int retval;
166 const uint8_t erase_check_code[] = {
167 #include "../../../contrib/loaders/flash/xmc1xxx/erase_check.inc"
168 };
169
170 if (bank->target->state != TARGET_HALTED) {
171 LOG_WARNING("Cannot communicate... target not halted.");
172 return ERROR_TARGET_NOT_HALTED;
173 }
174
175 retval = target_alloc_working_area(target, sizeof(erase_check_code),
176 &workarea);
177 if (retval != ERROR_OK) {
178 LOG_ERROR("No working area available.");
179 retval = ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
180 goto err_alloc_code;
181 }
182 retval = target_write_buffer(target, workarea->address,
183 sizeof(erase_check_code), erase_check_code);
184 if (retval != ERROR_OK)
185 goto err_write_code;
186
187 armv7m_algo.common_magic = ARMV7M_COMMON_MAGIC;
188 armv7m_algo.core_mode = ARM_MODE_THREAD;
189
190 init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT);
191 init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
192 init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT);
193
194 buf_set_u32(reg_params[0].value, 0, 32, NVM_BASE);
195
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);
200
201 retval = xmc1xxx_nvm_check_idle(target);
202 if (retval != ERROR_OK)
203 goto err_nvmprog;
204
205 LOG_DEBUG("Erase-checking 0x%08" PRIx32, start);
206 retval = target_run_algorithm(target,
207 0, NULL,
208 ARRAY_SIZE(reg_params), reg_params,
209 workarea->address, 0,
210 1000, &armv7m_algo);
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;
218 goto err_run;
219 }
220
221 retval = target_read_u16(target, NVMSTATUS, &val);
222 if (retval != ERROR_OK) {
223 LOG_ERROR("Couldn't read NVMSTATUS");
224 goto err_nvmstatus;
225 }
226 bank->sectors[sector].is_erased = (val & NVMSTATUS_VERR_MASK) ? 0 : 1;
227 }
228
229 err_nvmstatus:
230 err_run:
231 err_nvmprog:
232 for (i = 0; i < ARRAY_SIZE(reg_params); i++)
233 destroy_reg_param(&reg_params[i]);
234
235 err_write_code:
236 target_free_working_area(target, workarea);
237
238 err_alloc_code:
239 return retval;
240 }
241
242 static int xmc1xxx_write(struct flash_bank *bank, const uint8_t *buffer,
243 uint32_t offset, uint32_t byte_count)
244 {
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);
250 unsigned i;
251 int retval;
252 const uint8_t write_code[] = {
253 #include "../../../contrib/loaders/flash/xmc1xxx/write.inc"
254 };
255
256 LOG_DEBUG("Infineon XMC1000 write at 0x%08" PRIx32 " (%" PRIu32 " bytes)",
257 offset, byte_count);
258
259 if (offset & (NVM_BLOCK_SIZE - 1)) {
260 LOG_ERROR("offset 0x%" PRIx32 " breaks required block alignment",
261 offset);
262 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
263 }
264 if (byte_count & (NVM_BLOCK_SIZE - 1)) {
265 LOG_WARNING("length %" PRIu32 " is not block aligned, rounding up",
266 byte_count);
267 }
268
269 if (target->state != TARGET_HALTED) {
270 LOG_WARNING("Cannot communicate... target not halted.");
271 return ERROR_TARGET_NOT_HALTED;
272 }
273
274 retval = target_alloc_working_area(target, sizeof(write_code),
275 &code_workarea);
276 if (retval != ERROR_OK) {
277 LOG_ERROR("No working area available for write code.");
278 retval = ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
279 goto err_alloc_code;
280 }
281 retval = target_write_buffer(target, code_workarea->address,
282 sizeof(write_code), write_code);
283 if (retval != ERROR_OK)
284 goto err_write_code;
285
286 retval = target_alloc_working_area(target, MAX(NVM_BLOCK_SIZE,
287 MIN(block_count * NVM_BLOCK_SIZE, target_get_working_area_avail(target))),
288 &data_workarea);
289 if (retval != ERROR_OK) {
290 LOG_ERROR("No working area available for write data.");
291 retval = ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
292 goto err_alloc_data;
293 }
294
295 armv7m_algo.common_magic = ARMV7M_COMMON_MAGIC;
296 armv7m_algo.core_mode = ARM_MODE_THREAD;
297
298 init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT);
299 init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
300 init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT);
301 init_reg_param(&reg_params[3], "r3", 32, PARAM_OUT);
302
303 buf_set_u32(reg_params[0].value, 0, 32, NVM_BASE);
304
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;
308
309 LOG_DEBUG("copying %" PRIu32 " bytes to SRAM " TARGET_ADDR_FMT,
310 MIN(blocks * NVM_BLOCK_SIZE, byte_count),
311 data_workarea->address);
312
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;
318 goto err_write_data;
319 }
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;
328 goto err_write_pad;
329 }
330 }
331
332 LOG_DEBUG("writing 0x%08" PRIx32 "-0x%08" PRIx32 " (%" PRIu32 "x)",
333 addr, addr + blocks * NVM_BLOCK_SIZE - 1, blocks);
334
335 retval = xmc1xxx_nvm_check_idle(target);
336 if (retval != ERROR_OK)
337 goto err_nvmprog;
338
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);
342
343 retval = target_run_algorithm(target,
344 0, NULL,
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;
355 goto err_run;
356 }
357
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);
362 }
363
364 err_run:
365 err_nvmprog:
366 err_write_pad:
367 err_write_data:
368 for (i = 0; i < ARRAY_SIZE(reg_params); i++)
369 destroy_reg_param(&reg_params[i]);
370
371 target_free_working_area(target, data_workarea);
372 err_alloc_data:
373 err_write_code:
374 target_free_working_area(target, code_workarea);
375
376 err_alloc_code:
377 return retval;
378 }
379
380 static int xmc1xxx_protect_check(struct flash_bank *bank)
381 {
382 uint32_t nvmconf;
383 unsigned int num_protected;
384 int retval;
385
386 if (bank->target->state != TARGET_HALTED) {
387 LOG_WARNING("Cannot communicate... target not halted.");
388 return ERROR_TARGET_NOT_HALTED;
389 }
390
391 retval = target_read_u32(bank->target, NVMCONF, &nvmconf);
392 if (retval != ERROR_OK) {
393 LOG_ERROR("Cannot read NVMCONF register.");
394 return retval;
395 }
396 LOG_DEBUG("NVMCONF = %08" PRIx32, nvmconf);
397
398 num_protected = (nvmconf >> 4) & 0xff;
399
400 for (unsigned int i = 0; i < bank->num_sectors; i++)
401 bank->sectors[i].is_protected = (i < num_protected) ? 1 : 0;
402
403 return ERROR_OK;
404 }
405
406 static int xmc1xxx_get_info_command(struct flash_bank *bank, struct command_invocation *cmd)
407 {
408 uint32_t chipid[8];
409 int i, retval;
410
411 if (bank->target->state != TARGET_HALTED) {
412 LOG_WARNING("Cannot communicate... target not halted.");
413 return ERROR_TARGET_NOT_HALTED;
414 }
415
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);
421 return retval;
422 }
423 LOG_DEBUG("ID[%d] = %08" PRIX32, i, chipid[i]);
424 }
425 retval = target_read_u32(bank->target, SCU_BASE + 0x000, &chipid[7]);
426 if (retval != ERROR_OK) {
427 LOG_ERROR("Cannot read DBGROMID register.");
428 return retval;
429 }
430 LOG_DEBUG("ID[7] = %08" PRIX32, chipid[7]);
431
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);
439
440 return ERROR_OK;
441 }
442
443 static int xmc1xxx_probe(struct flash_bank *bank)
444 {
445 struct xmc1xxx_flash_bank *xmc_bank = bank->driver_priv;
446 uint32_t flash_addr = bank->base;
447 uint32_t idchip, flsize;
448 int retval;
449
450 if (xmc_bank->probed)
451 return ERROR_OK;
452
453 if (bank->target->state != TARGET_HALTED) {
454 LOG_WARNING("Cannot communicate... target not halted.");
455 return ERROR_TARGET_NOT_HALTED;
456 }
457
458 retval = target_read_u32(bank->target, SCU_IDCHIP, &idchip);
459 if (retval != ERROR_OK) {
460 LOG_ERROR("Cannot read IDCHIP register.");
461 return retval;
462 }
463
464 if ((idchip & 0xffff0000) != 0x10000) {
465 LOG_ERROR("IDCHIP register does not match XMC1xxx.");
466 return ERROR_FAIL;
467 }
468
469 LOG_DEBUG("IDCHIP = %08" PRIx32, idchip);
470
471 retval = target_read_u32(bank->target, PAU_FLSIZE, &flsize);
472 if (retval != ERROR_OK) {
473 LOG_ERROR("Cannot read FLSIZE register.");
474 return retval;
475 }
476
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++) {
482 if (i == 0) {
483 bank->sectors[i].size = 0x200;
484 bank->sectors[i].offset = 0xE00;
485 flash_addr += 0x1000;
486 } else {
487 bank->sectors[i].size = 4 * 1024;
488 bank->sectors[i].offset = flash_addr - bank->base;
489 flash_addr += bank->sectors[i].size;
490 }
491 bank->sectors[i].is_erased = -1;
492 bank->sectors[i].is_protected = -1;
493 }
494
495 xmc_bank->probed = true;
496
497 return ERROR_OK;
498 }
499
500 static int xmc1xxx_auto_probe(struct flash_bank *bank)
501 {
502 struct xmc1xxx_flash_bank *xmc_bank = bank->driver_priv;
503
504 if (xmc_bank->probed)
505 return ERROR_OK;
506
507 return xmc1xxx_probe(bank);
508 }
509
510 FLASH_BANK_COMMAND_HANDLER(xmc1xxx_flash_bank_command)
511 {
512 struct xmc1xxx_flash_bank *xmc_bank;
513
514 xmc_bank = malloc(sizeof(struct xmc1xxx_flash_bank));
515 if (!xmc_bank)
516 return ERROR_FLASH_OPERATION_FAILED;
517
518 xmc_bank->probed = false;
519
520 bank->driver_priv = xmc_bank;
521
522 return ERROR_OK;
523 }
524
525 static const struct command_registration xmc1xxx_exec_command_handlers[] = {
526 COMMAND_REGISTRATION_DONE
527 };
528
529 static const struct command_registration xmc1xxx_command_handlers[] = {
530 {
531 .name = "xmc1xxx",
532 .mode = COMMAND_ANY,
533 .help = "xmc1xxx flash command group",
534 .usage = "",
535 .chain = xmc1xxx_exec_command_handlers,
536 },
537 COMMAND_REGISTRATION_DONE
538 };
539
540 const struct flash_driver xmc1xxx_flash = {
541 .name = "xmc1xxx",
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,
553 };

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)