Constify struct flash_driver instances
[fw/openocd] / 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 " TARGET_ADDR_FMT,
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 const 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         .free_driver_priv = default_flash_free_driver_priv,
550 };