Added support for STMicroelectronics BlueNRG-1 and BlueNRG-2 SoC
[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, int first, int last)
80 {
81 struct target *target = bank->target;
82 struct working_area *workarea;
83 struct reg_param reg_params[3];
84 struct armv7m_algorithm armv7m_algo;
85 unsigned i;
86 int retval, sector;
87 const uint8_t erase_code[] = {
88 #include "../../../contrib/loaders/flash/xmc1xxx/erase.inc"
89 };
90
91 LOG_DEBUG("Infineon XMC1000 erase sectors %d to %d", first, last);
92
93 if (bank->target->state != TARGET_HALTED) {
94 LOG_WARNING("Cannot communicate... target not halted.");
95 return ERROR_TARGET_NOT_HALTED;
96 }
97
98 retval = xmc1xxx_nvm_check_idle(target);
99 if (retval != ERROR_OK)
100 return retval;
101
102 retval = target_alloc_working_area(target, sizeof(erase_code),
103 &workarea);
104 if (retval != ERROR_OK) {
105 LOG_ERROR("No working area available.");
106 retval = ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
107 goto err_alloc_code;
108 }
109 retval = target_write_buffer(target, workarea->address,
110 sizeof(erase_code), erase_code);
111 if (retval != ERROR_OK)
112 goto err_write_code;
113
114 armv7m_algo.common_magic = ARMV7M_COMMON_MAGIC;
115 armv7m_algo.core_mode = ARM_MODE_THREAD;
116
117 init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT);
118 init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
119 init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT);
120
121 buf_set_u32(reg_params[0].value, 0, 32, NVM_BASE);
122 buf_set_u32(reg_params[1].value, 0, 32, bank->base +
123 bank->sectors[first].offset);
124 buf_set_u32(reg_params[2].value, 0, 32, bank->base +
125 bank->sectors[last].offset + bank->sectors[last].size);
126
127 retval = target_run_algorithm(target,
128 0, NULL,
129 ARRAY_SIZE(reg_params), reg_params,
130 workarea->address, 0,
131 1000, &armv7m_algo);
132 if (retval != ERROR_OK) {
133 LOG_ERROR("Error executing flash sector erase "
134 "programming algorithm");
135 retval = xmc1xxx_nvm_set_idle(target);
136 if (retval != ERROR_OK)
137 LOG_WARNING("Couldn't restore NVMPROG.ACTION");
138 retval = ERROR_FLASH_OPERATION_FAILED;
139 goto err_run;
140 }
141
142 for (sector = first; sector <= last; sector++)
143 bank->sectors[sector].is_erased = 1;
144
145 err_run:
146 for (i = 0; i < ARRAY_SIZE(reg_params); i++)
147 destroy_reg_param(&reg_params[i]);
148
149 err_write_code:
150 target_free_working_area(target, workarea);
151
152 err_alloc_code:
153 return retval;
154 }
155
156 static int xmc1xxx_erase_check(struct flash_bank *bank)
157 {
158 struct target *target = bank->target;
159 struct working_area *workarea;
160 struct reg_param reg_params[3];
161 struct armv7m_algorithm armv7m_algo;
162 uint16_t val;
163 unsigned i;
164 int retval, sector;
165 const uint8_t erase_check_code[] = {
166 #include "../../../contrib/loaders/flash/xmc1xxx/erase_check.inc"
167 };
168
169 if (bank->target->state != TARGET_HALTED) {
170 LOG_WARNING("Cannot communicate... target not halted.");
171 return ERROR_TARGET_NOT_HALTED;
172 }
173
174 retval = target_alloc_working_area(target, sizeof(erase_check_code),
175 &workarea);
176 if (retval != ERROR_OK) {
177 LOG_ERROR("No working area available.");
178 retval = ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
179 goto err_alloc_code;
180 }
181 retval = target_write_buffer(target, workarea->address,
182 sizeof(erase_check_code), erase_check_code);
183 if (retval != ERROR_OK)
184 goto err_write_code;
185
186 armv7m_algo.common_magic = ARMV7M_COMMON_MAGIC;
187 armv7m_algo.core_mode = ARM_MODE_THREAD;
188
189 init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT);
190 init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
191 init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT);
192
193 buf_set_u32(reg_params[0].value, 0, 32, NVM_BASE);
194
195 for (sector = 0; sector < bank->num_sectors; sector++) {
196 uint32_t start = bank->base + bank->sectors[sector].offset;
197 buf_set_u32(reg_params[1].value, 0, 32, start);
198 buf_set_u32(reg_params[2].value, 0, 32, start + bank->sectors[sector].size);
199
200 retval = xmc1xxx_nvm_check_idle(target);
201 if (retval != ERROR_OK)
202 goto err_nvmprog;
203
204 LOG_DEBUG("Erase-checking 0x%08" PRIx32, start);
205 retval = target_run_algorithm(target,
206 0, NULL,
207 ARRAY_SIZE(reg_params), reg_params,
208 workarea->address, 0,
209 1000, &armv7m_algo);
210 if (retval != ERROR_OK) {
211 LOG_ERROR("Error executing flash sector erase check "
212 "programming algorithm");
213 retval = xmc1xxx_nvm_set_idle(target);
214 if (retval != ERROR_OK)
215 LOG_WARNING("Couldn't restore NVMPROG.ACTION");
216 retval = ERROR_FLASH_OPERATION_FAILED;
217 goto err_run;
218 }
219
220 retval = target_read_u16(target, NVMSTATUS, &val);
221 if (retval != ERROR_OK) {
222 LOG_ERROR("Couldn't read NVMSTATUS");
223 goto err_nvmstatus;
224 }
225 bank->sectors[sector].is_erased = (val & NVMSTATUS_VERR_MASK) ? 0 : 1;
226 }
227
228 err_nvmstatus:
229 err_run:
230 err_nvmprog:
231 for (i = 0; i < ARRAY_SIZE(reg_params); i++)
232 destroy_reg_param(&reg_params[i]);
233
234 err_write_code:
235 target_free_working_area(target, workarea);
236
237 err_alloc_code:
238 return retval;
239 }
240
241 static int xmc1xxx_write(struct flash_bank *bank, const uint8_t *buffer,
242 uint32_t offset, uint32_t byte_count)
243 {
244 struct target *target = bank->target;
245 struct working_area *code_workarea, *data_workarea;
246 struct reg_param reg_params[4];
247 struct armv7m_algorithm armv7m_algo;
248 uint32_t block_count = DIV_ROUND_UP(byte_count, NVM_BLOCK_SIZE);
249 unsigned i;
250 int retval;
251 const uint8_t write_code[] = {
252 #include "../../../contrib/loaders/flash/xmc1xxx/write.inc"
253 };
254
255 LOG_DEBUG("Infineon XMC1000 write at 0x%08" PRIx32 " (%" PRId32 " bytes)",
256 offset, byte_count);
257
258 if (offset & (NVM_BLOCK_SIZE - 1)) {
259 LOG_ERROR("offset 0x%" PRIx32 " breaks required block alignment",
260 offset);
261 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
262 }
263 if (byte_count & (NVM_BLOCK_SIZE - 1)) {
264 LOG_WARNING("length %" PRId32 " is not block aligned, rounding up",
265 byte_count);
266 }
267
268 if (target->state != TARGET_HALTED) {
269 LOG_WARNING("Cannot communicate... target not halted.");
270 return ERROR_TARGET_NOT_HALTED;
271 }
272
273 retval = target_alloc_working_area(target, sizeof(write_code),
274 &code_workarea);
275 if (retval != ERROR_OK) {
276 LOG_ERROR("No working area available for write code.");
277 retval = ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
278 goto err_alloc_code;
279 }
280 retval = target_write_buffer(target, code_workarea->address,
281 sizeof(write_code), write_code);
282 if (retval != ERROR_OK)
283 goto err_write_code;
284
285 retval = target_alloc_working_area(target, MAX(NVM_BLOCK_SIZE,
286 MIN(block_count * NVM_BLOCK_SIZE, target_get_working_area_avail(target))),
287 &data_workarea);
288 if (retval != ERROR_OK) {
289 LOG_ERROR("No working area available for write data.");
290 retval = ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
291 goto err_alloc_data;
292 }
293
294 armv7m_algo.common_magic = ARMV7M_COMMON_MAGIC;
295 armv7m_algo.core_mode = ARM_MODE_THREAD;
296
297 init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT);
298 init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
299 init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT);
300 init_reg_param(&reg_params[3], "r3", 32, PARAM_OUT);
301
302 buf_set_u32(reg_params[0].value, 0, 32, NVM_BASE);
303
304 while (byte_count > 0) {
305 uint32_t blocks = MIN(block_count, data_workarea->size / NVM_BLOCK_SIZE);
306 uint32_t addr = bank->base + offset;
307
308 LOG_DEBUG("copying %" PRId32 " bytes to SRAM 0x%08" TARGET_PRIxADDR,
309 MIN(blocks * NVM_BLOCK_SIZE, byte_count),
310 data_workarea->address);
311
312 retval = target_write_buffer(target, data_workarea->address,
313 MIN(blocks * NVM_BLOCK_SIZE, byte_count), buffer);
314 if (retval != ERROR_OK) {
315 LOG_ERROR("Error writing data buffer");
316 retval = ERROR_FLASH_OPERATION_FAILED;
317 goto err_write_data;
318 }
319 if (byte_count < blocks * NVM_BLOCK_SIZE) {
320 retval = target_write_memory(target,
321 data_workarea->address + byte_count, 1,
322 blocks * NVM_BLOCK_SIZE - byte_count,
323 &bank->default_padded_value);
324 if (retval != ERROR_OK) {
325 LOG_ERROR("Error writing data padding");
326 retval = ERROR_FLASH_OPERATION_FAILED;
327 goto err_write_pad;
328 }
329 }
330
331 LOG_DEBUG("writing 0x%08" PRIx32 "-0x%08" PRIx32 " (%" PRId32 "x)",
332 addr, addr + blocks * NVM_BLOCK_SIZE - 1, blocks);
333
334 retval = xmc1xxx_nvm_check_idle(target);
335 if (retval != ERROR_OK)
336 goto err_nvmprog;
337
338 buf_set_u32(reg_params[1].value, 0, 32, addr);
339 buf_set_u32(reg_params[2].value, 0, 32, data_workarea->address);
340 buf_set_u32(reg_params[3].value, 0, 32, blocks);
341
342 retval = target_run_algorithm(target,
343 0, NULL,
344 ARRAY_SIZE(reg_params), reg_params,
345 code_workarea->address, 0,
346 5 * 60 * 1000, &armv7m_algo);
347 if (retval != ERROR_OK) {
348 LOG_ERROR("Error executing flash write "
349 "programming algorithm");
350 retval = xmc1xxx_nvm_set_idle(target);
351 if (retval != ERROR_OK)
352 LOG_WARNING("Couldn't restore NVMPROG.ACTION");
353 retval = ERROR_FLASH_OPERATION_FAILED;
354 goto err_run;
355 }
356
357 block_count -= blocks;
358 offset += blocks * NVM_BLOCK_SIZE;
359 buffer += blocks * NVM_BLOCK_SIZE;
360 byte_count -= MIN(blocks * NVM_BLOCK_SIZE, byte_count);
361 }
362
363 err_run:
364 err_nvmprog:
365 err_write_pad:
366 err_write_data:
367 for (i = 0; i < ARRAY_SIZE(reg_params); i++)
368 destroy_reg_param(&reg_params[i]);
369
370 target_free_working_area(target, data_workarea);
371 err_alloc_data:
372 err_write_code:
373 target_free_working_area(target, code_workarea);
374
375 err_alloc_code:
376 return retval;
377 }
378
379 static int xmc1xxx_protect_check(struct flash_bank *bank)
380 {
381 uint32_t nvmconf;
382 int i, num_protected, retval;
383
384 if (bank->target->state != TARGET_HALTED) {
385 LOG_WARNING("Cannot communicate... target not halted.");
386 return ERROR_TARGET_NOT_HALTED;
387 }
388
389 retval = target_read_u32(bank->target, NVMCONF, &nvmconf);
390 if (retval != ERROR_OK) {
391 LOG_ERROR("Cannot read NVMCONF register.");
392 return retval;
393 }
394 LOG_DEBUG("NVMCONF = %08" PRIx32, nvmconf);
395
396 num_protected = (nvmconf >> 4) & 0xff;
397
398 for (i = 0; i < bank->num_sectors; i++)
399 bank->sectors[i].is_protected = (i < num_protected) ? 1 : 0;
400
401 return ERROR_OK;
402 }
403
404 static int xmc1xxx_get_info_command(struct flash_bank *bank, char *buf, int buf_size)
405 {
406 uint32_t chipid[8];
407 int i, retval;
408
409 if (bank->target->state != TARGET_HALTED) {
410 LOG_WARNING("Cannot communicate... target not halted.");
411 return ERROR_TARGET_NOT_HALTED;
412 }
413
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;
420 }
421 LOG_DEBUG("ID[%d] = %08" PRIX32, i, chipid[i]);
422 }
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;
427 }
428 LOG_DEBUG("ID[7] = %08" PRIX32, chipid[7]);
429
430 snprintf(buf, buf_size, "XMC%" PRIx32 "00 %X flash %uKB ROM %uKB SRAM %uKB",
431 (chipid[0] >> 12) & 0xff,
432 0xAA + (chipid[7] >> 28) - 1,
433 (((chipid[6] >> 12) & 0x3f) - 1) * 4,
434 (((chipid[4] >> 8) & 0x3f) * 256) / 1024,
435 (((chipid[5] >> 8) & 0x1f) * 256 * 4) / 1024);
436
437 return ERROR_OK;
438 }
439
440 static int xmc1xxx_probe(struct flash_bank *bank)
441 {
442 struct xmc1xxx_flash_bank *xmc_bank = bank->driver_priv;
443 uint32_t flash_addr = bank->base;
444 uint32_t idchip, flsize;
445 int i, retval;
446
447 if (xmc_bank->probed)
448 return ERROR_OK;
449
450 if (bank->target->state != TARGET_HALTED) {
451 LOG_WARNING("Cannot communicate... target not halted.");
452 return ERROR_TARGET_NOT_HALTED;
453 }
454
455 retval = target_read_u32(bank->target, SCU_IDCHIP, &idchip);
456 if (retval != ERROR_OK) {
457 LOG_ERROR("Cannot read IDCHIP register.");
458 return retval;
459 }
460
461 if ((idchip & 0xffff0000) != 0x10000) {
462 LOG_ERROR("IDCHIP register does not match XMC1xxx.");
463 return ERROR_FAIL;
464 }
465
466 LOG_DEBUG("IDCHIP = %08" PRIx32, idchip);
467
468 retval = target_read_u32(bank->target, PAU_FLSIZE, &flsize);
469 if (retval != ERROR_OK) {
470 LOG_ERROR("Cannot read FLSIZE register.");
471 return retval;
472 }
473
474 bank->num_sectors = 1 + ((flsize >> 12) & 0x3f) - 1;
475 bank->size = bank->num_sectors * 4 * 1024;
476 bank->sectors = calloc(bank->num_sectors,
477 sizeof(struct flash_sector));
478 for (i = 0; i < bank->num_sectors; i++) {
479 if (i == 0) {
480 bank->sectors[i].size = 0x200;
481 bank->sectors[i].offset = 0xE00;
482 flash_addr += 0x1000;
483 } else {
484 bank->sectors[i].size = 4 * 1024;
485 bank->sectors[i].offset = flash_addr - bank->base;
486 flash_addr += bank->sectors[i].size;
487 }
488 bank->sectors[i].is_erased = -1;
489 bank->sectors[i].is_protected = -1;
490 }
491
492 xmc_bank->probed = true;
493
494 return ERROR_OK;
495 }
496
497 static int xmc1xxx_auto_probe(struct flash_bank *bank)
498 {
499 struct xmc1xxx_flash_bank *xmc_bank = bank->driver_priv;
500
501 if (xmc_bank->probed)
502 return ERROR_OK;
503
504 return xmc1xxx_probe(bank);
505 }
506
507 FLASH_BANK_COMMAND_HANDLER(xmc1xxx_flash_bank_command)
508 {
509 struct xmc1xxx_flash_bank *xmc_bank;
510
511 xmc_bank = malloc(sizeof(struct xmc1xxx_flash_bank));
512 if (!xmc_bank)
513 return ERROR_FLASH_OPERATION_FAILED;
514
515 xmc_bank->probed = false;
516
517 bank->driver_priv = xmc_bank;
518
519 return ERROR_OK;
520 }
521
522 static const struct command_registration xmc1xxx_exec_command_handlers[] = {
523 COMMAND_REGISTRATION_DONE
524 };
525
526 static const struct command_registration xmc1xxx_command_handlers[] = {
527 {
528 .name = "xmc1xxx",
529 .mode = COMMAND_ANY,
530 .help = "xmc1xxx flash command group",
531 .usage = "",
532 .chain = xmc1xxx_exec_command_handlers,
533 },
534 COMMAND_REGISTRATION_DONE
535 };
536
537 struct flash_driver xmc1xxx_flash = {
538 .name = "xmc1xxx",
539 .commands = xmc1xxx_command_handlers,
540 .flash_bank_command = xmc1xxx_flash_bank_command,
541 .info = xmc1xxx_get_info_command,
542 .probe = xmc1xxx_probe,
543 .auto_probe = xmc1xxx_auto_probe,
544 .protect_check = xmc1xxx_protect_check,
545 .read = default_flash_read,
546 .erase = xmc1xxx_erase,
547 .erase_check = xmc1xxx_erase_check,
548 .write = xmc1xxx_write,
549 };

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)