openocd: fix SPDX tag format for files .c
[fw/openocd] / src / flash / nor / xmc1xxx.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2
3 /*
4  * XMC1000 flash driver
5  *
6  * Copyright (c) 2016 Andreas Färber
7  */
8
9 #ifdef HAVE_CONFIG_H
10 #include "config.h"
11 #endif
12
13 #include "imp.h"
14 #include <helper/align.h>
15 #include <helper/binarybuffer.h>
16 #include <target/algorithm.h>
17 #include <target/armv7m.h>
18
19 #define FLASH_BASE      0x10000000
20 #define PAU_BASE        0x40000000
21 #define SCU_BASE        0x40010000
22 #define NVM_BASE        0x40050000
23
24 #define FLASH_CS0       (FLASH_BASE + 0xf00)
25
26 #define PAU_FLSIZE      (PAU_BASE + 0x404)
27
28 #define SCU_IDCHIP      (SCU_BASE + 0x004)
29
30 #define NVMSTATUS       (NVM_BASE + 0x00)
31 #define NVMPROG         (NVM_BASE + 0x04)
32 #define NVMCONF         (NVM_BASE + 0x08)
33
34 #define NVMSTATUS_BUSY          (1 << 0)
35 #define NVMSTATUS_VERR_MASK     (0x3 << 2)
36
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)
40
41 #define NVMPROG_ACTION_ONE_SHOT_ONCE            (1 << 4)
42 #define NVMPROG_ACTION_ONE_SHOT_CONTINUOUS      (2 << 4)
43
44 #define NVMPROG_ACTION_VERIFY_EACH              (1 << 6)
45 #define NVMPROG_ACTION_VERIFY_NO                (2 << 6)
46 #define NVMPROG_ACTION_VERIFY_ARRAY             (3 << 6)
47
48 #define NVMPROG_ACTION_IDLE     0x00
49 #define NVMPROG_ACTION_MASK     0xff
50
51 #define NVM_WORD_SIZE 4
52 #define NVM_BLOCK_SIZE (4 * NVM_WORD_SIZE)
53 #define NVM_PAGE_SIZE (16 * NVM_BLOCK_SIZE)
54
55 struct xmc1xxx_flash_bank {
56         bool probed;
57 };
58
59 static int xmc1xxx_nvm_set_idle(struct target *target)
60 {
61         return target_write_u16(target, NVMPROG, NVMPROG_ACTION_IDLE);
62 }
63
64 static int xmc1xxx_nvm_check_idle(struct target *target)
65 {
66         uint16_t val;
67         int retval;
68
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);
75         }
76
77         return retval;
78 }
79
80 static int xmc1xxx_erase(struct flash_bank *bank, unsigned int first,
81                 unsigned int last)
82 {
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"
91         };
92
93         LOG_DEBUG("Infineon XMC1000 erase sectors %u to %u", first, last);
94
95         if (bank->target->state != TARGET_HALTED) {
96                 LOG_WARNING("Cannot communicate... target not halted.");
97                 return ERROR_TARGET_NOT_HALTED;
98         }
99
100         retval = xmc1xxx_nvm_check_idle(target);
101         if (retval != ERROR_OK)
102                 return retval;
103
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;
110         }
111         retval = target_write_buffer(target, workarea->address,
112                         sizeof(erase_code), erase_code);
113         if (retval != ERROR_OK)
114                 goto err_write_code;
115
116         armv7m_algo.common_magic = ARMV7M_COMMON_MAGIC;
117         armv7m_algo.core_mode = ARM_MODE_THREAD;
118
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);
122
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);
128
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;
142         }
143
144 err_run:
145         for (i = 0; i < ARRAY_SIZE(reg_params); i++)
146                 destroy_reg_param(&reg_params[i]);
147
148 err_write_code:
149         target_free_working_area(target, workarea);
150
151 err_alloc_code:
152         return retval;
153 }
154
155 static int xmc1xxx_erase_check(struct flash_bank *bank)
156 {
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"
166         };
167
168         if (bank->target->state != TARGET_HALTED) {
169                 LOG_WARNING("Cannot communicate... target not halted.");
170                 return ERROR_TARGET_NOT_HALTED;
171         }
172
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;
179         }
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;
184
185         armv7m_algo.common_magic = ARMV7M_COMMON_MAGIC;
186         armv7m_algo.core_mode = ARM_MODE_THREAD;
187
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);
191
192         buf_set_u32(reg_params[0].value, 0, 32, NVM_BASE);
193
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);
198
199                 retval = xmc1xxx_nvm_check_idle(target);
200                 if (retval != ERROR_OK)
201                         goto err_nvmprog;
202
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;
217                 }
218
219                 retval = target_read_u16(target, NVMSTATUS, &val);
220                 if (retval != ERROR_OK) {
221                         LOG_ERROR("Couldn't read NVMSTATUS");
222                         goto err_nvmstatus;
223                 }
224                 bank->sectors[sector].is_erased = (val & NVMSTATUS_VERR_MASK) ? 0 : 1;
225         }
226
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]);
232
233 err_write_code:
234         target_free_working_area(target, workarea);
235
236 err_alloc_code:
237         return retval;
238 }
239
240 static int xmc1xxx_write(struct flash_bank *bank, const uint8_t *buffer,
241                 uint32_t offset, uint32_t byte_count)
242 {
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"
252         };
253
254         LOG_DEBUG("Infineon XMC1000 write at 0x%08" PRIx32 " (%" PRIu32 " bytes)",
255                 offset, byte_count);
256
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;
261         }
262         if (!IS_ALIGNED(byte_count, NVM_BLOCK_SIZE)) {
263                 LOG_WARNING("length %" PRIu32 " is not block aligned, rounding up",
264                         byte_count);
265         }
266
267         if (target->state != TARGET_HALTED) {
268                 LOG_WARNING("Cannot communicate... target not halted.");
269                 return ERROR_TARGET_NOT_HALTED;
270         }
271
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;
278         }
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;
283
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;
291         }
292
293         armv7m_algo.common_magic = ARMV7M_COMMON_MAGIC;
294         armv7m_algo.core_mode = ARM_MODE_THREAD;
295
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);
300
301         buf_set_u32(reg_params[0].value, 0, 32, NVM_BASE);
302
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;
306
307                 LOG_DEBUG("copying %" PRIu32 " bytes to SRAM " TARGET_ADDR_FMT,
308                         MIN(blocks * NVM_BLOCK_SIZE, byte_count),
309                         data_workarea->address);
310
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;
317                 }
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;
327                         }
328                 }
329
330                 LOG_DEBUG("writing 0x%08" PRIx32 "-0x%08" PRIx32 " (%" PRIu32 "x)",
331                         addr, addr + blocks * NVM_BLOCK_SIZE - 1, blocks);
332
333                 retval = xmc1xxx_nvm_check_idle(target);
334                 if (retval != ERROR_OK)
335                         goto err_nvmprog;
336
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);
340
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;
354                 }
355
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);
360         }
361
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]);
368
369         target_free_working_area(target, data_workarea);
370 err_alloc_data:
371 err_write_code:
372         target_free_working_area(target, code_workarea);
373
374 err_alloc_code:
375         return retval;
376 }
377
378 static int xmc1xxx_protect_check(struct flash_bank *bank)
379 {
380         uint32_t nvmconf;
381         unsigned int num_protected;
382         int 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 (unsigned int 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, struct command_invocation *cmd)
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         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);
437
438         return ERROR_OK;
439 }
440
441 static int xmc1xxx_probe(struct flash_bank *bank)
442 {
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;
447
448         if (xmc_bank->probed)
449                 return ERROR_OK;
450
451         if (bank->target->state != TARGET_HALTED) {
452                 LOG_WARNING("Cannot communicate... target not halted.");
453                 return ERROR_TARGET_NOT_HALTED;
454         }
455
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;
460         }
461
462         if ((idchip & 0xffff0000) != 0x10000) {
463                 LOG_ERROR("IDCHIP register does not match XMC1xxx.");
464                 return ERROR_FAIL;
465         }
466
467         LOG_DEBUG("IDCHIP = %08" PRIx32, idchip);
468
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;
473         }
474
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;
488                 }
489                 bank->sectors[i].is_erased = -1;
490                 bank->sectors[i].is_protected = -1;
491         }
492
493         xmc_bank->probed = true;
494
495         return ERROR_OK;
496 }
497
498 static int xmc1xxx_auto_probe(struct flash_bank *bank)
499 {
500         struct xmc1xxx_flash_bank *xmc_bank = bank->driver_priv;
501
502         if (xmc_bank->probed)
503                 return ERROR_OK;
504
505         return xmc1xxx_probe(bank);
506 }
507
508 FLASH_BANK_COMMAND_HANDLER(xmc1xxx_flash_bank_command)
509 {
510         struct xmc1xxx_flash_bank *xmc_bank;
511
512         xmc_bank = malloc(sizeof(struct xmc1xxx_flash_bank));
513         if (!xmc_bank)
514                 return ERROR_FLASH_OPERATION_FAILED;
515
516         xmc_bank->probed = false;
517
518         bank->driver_priv = xmc_bank;
519
520         return ERROR_OK;
521 }
522
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,
535 };