10db783073c0516e69f6254f9959dda0243ce848
[openocd.git] / src / flash / nor / psoc4.c
1 /***************************************************************************
2 * Copyright (C) 2005 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
4 * *
5 * Copyright (C) 2008 by Spencer Oliver *
6 * spen@spen-soft.co.uk *
7 * *
8 * Copyright (C) 2011 by Andreas Fritiofson *
9 * andreas.fritiofson@gmail.com *
10 * *
11 * Copyright (C) 2014 by Tomas Vanek (PSoC 4 support derived from STM32) *
12 * vanekt@fbl.cz *
13 * *
14 * This program is free software; you can redistribute it and/or modify *
15 * it under the terms of the GNU General Public License as published by *
16 * the Free Software Foundation; either version 2 of the License, or *
17 * (at your option) any later version. *
18 * *
19 * This program is distributed in the hope that it will be useful, *
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
22 * GNU General Public License for more details. *
23 ***************************************************************************/
24
25 #ifdef HAVE_CONFIG_H
26 #include "config.h"
27 #endif
28
29 #include "imp.h"
30 #include <helper/binarybuffer.h>
31 #include <jtag/jtag.h>
32 #include <target/algorithm.h>
33 #include <target/armv7m.h>
34
35 /* device documets:
36
37 PSoC(R) 4: PSoC 4200 Family Datasheet
38 Document Number: 001-87197 Rev. *B Revised August 29, 2013
39
40 PSoC 4100/4200 Family PSoC(R) 4 Architecture TRM
41 Document No. 001-85634 Rev. *C March 25, 2014
42
43 PSoC(R) 4 Registers TRM Spec.
44 Document No. 001-85847 Rev. *A June 25, 2013
45
46 CY8C41xx, CY8C42xx Programming Specifications
47 Document No. 001-81799 Rev. *C March 4, 2014
48 */
49
50 /* register locations */
51 #define PSOC4_CPUSS_SYSREQ 0x40000004
52 #define PSOC4_CPUSS_SYSARG 0x40000008
53 #define PSOC4_TEST_MODE 0x40030014
54 #define PSOC4_SPCIF_GEOMETRY 0x400E0000
55
56 #define PSOC4_SFLASH_MACRO 0x0ffff000
57
58 /* constants */
59 #define PSOC4_SROM_KEY1 0xb6
60 #define PSOC4_SROM_KEY2 0xd3
61 #define PSOC4_SROM_SYSREQ_BIT (1<<31)
62 #define PSOC4_SROM_HMASTER_BIT (1<<30)
63 #define PSOC4_SROM_PRIVILEGED_BIT (1<<28)
64 #define PSOC4_SROM_STATUS_SUCCEEDED 0xa0000000
65 #define PSOC4_SROM_STATUS_FAILED 0xf0000000
66
67 #define PSOC4_CMD_GET_SILICON_ID 0
68 #define PSOC4_CMD_LOAD_LATCH 4
69 #define PSOC4_CMD_WRITE_ROW 5
70 #define PSOC4_CMD_PROGRAM_ROW 6
71 #define PSOC4_CMD_ERASE_ALL 0xa
72 #define PSOC4_CMD_CHECKSUM 0xb
73 #define PSOC4_CMD_WRITE_PROTECTION 0xd
74
75 #define PSOC4_CHIP_PROT_VIRGIN 0x0
76 #define PSOC4_CHIP_PROT_OPEN 0x1
77 #define PSOC4_CHIP_PROT_PROTECTED 0x2
78 #define PSOC4_CHIP_PROT_KILL 0x4
79
80
81 struct psoc4_chip_details {
82 uint16_t id;
83 const char *type;
84 const char *package;
85 uint32_t flash_size_in_kb;
86 };
87
88 /* list of PSoC 4 chips
89 * flash_size_in_kb is not necessary as it can be decoded from SPCIF_GEOMETRY
90 */
91 const struct psoc4_chip_details psoc4_devices[] = {
92 /* 4200 series */
93 { 0x04A6, "CY8C4245PVI-482", "SSOP-28", .flash_size_in_kb = 32 },
94 { 0x04B6, "CY8C4245LQI-483", "QFN-40", .flash_size_in_kb = 32 },
95 { 0x04C8, "CY8C4245AXI-483", "TQFP-44", .flash_size_in_kb = 32 },
96 { 0x04FB, "CY8C4245AXI-473", "TQFP-44", .flash_size_in_kb = 32 },
97 { 0x04F0, "CY8C4244PVI-432", "SSOP-28", .flash_size_in_kb = 16 },
98 { 0x04F1, "CY8C4244PVI-442", "SSOP-28", .flash_size_in_kb = 16 },
99 { 0x04F6, "CY8C4244LQI-443", "QFN-40", .flash_size_in_kb = 16 },
100 { 0x04FA, "CY8C4244AXI-443", "TQFP-44", .flash_size_in_kb = 16 },
101
102 /* 4100 series */
103 { 0x0410, "CY8C4124PVI-432", "SSOP-28", .flash_size_in_kb = 16 },
104 { 0x0411, "CY8C4124PVI-442", "SSOP-28", .flash_size_in_kb = 16 },
105 { 0x0416, "CY8C4124LQI-443", "QFN-40", .flash_size_in_kb = 16 },
106 { 0x041A, "CY8C4124AXI-443", "TQFP-44", .flash_size_in_kb = 16 },
107 { 0x041B, "CY8C4125AXI-473", "TQFP-44", .flash_size_in_kb = 32 },
108 { 0x0412, "CY8C4125PVI-482", "SSOP-28", .flash_size_in_kb = 32 },
109 { 0x0417, "CY8C4125LQI-483", "QFN-40", .flash_size_in_kb = 32 },
110 { 0x041C, "CY8C4125AXI-483", "TQFP-44", .flash_size_in_kb = 32 },
111 };
112
113
114 struct psoc4_flash_bank {
115 uint32_t row_size;
116 uint32_t user_bank_size;
117 int probed;
118 uint32_t silicon_id;
119 uint8_t chip_protection;
120 uint8_t cmd_program_row;
121 };
122
123
124 static const struct psoc4_chip_details *psoc4_details_by_id(uint32_t silicon_id)
125 {
126 const struct psoc4_chip_details *p = psoc4_devices;
127 unsigned int i;
128 uint16_t id = silicon_id >> 16; /* ignore die revision */
129 for (i = 0; i < sizeof(psoc4_devices)/sizeof(psoc4_devices[0]); i++, p++) {
130 if (p->id == id)
131 return p;
132 }
133 LOG_DEBUG("Unknown PSoC 4 device silicon id 0x%08" PRIx32 ".", silicon_id);
134 return NULL;
135 }
136
137 static const char *psoc4_decode_chip_protection(uint8_t protection)
138 {
139 switch (protection) {
140 case PSOC4_CHIP_PROT_VIRGIN:
141 return "protection VIRGIN";
142 case PSOC4_CHIP_PROT_OPEN:
143 return "protection open";
144 case PSOC4_CHIP_PROT_PROTECTED:
145 return "PROTECTED";
146 case PSOC4_CHIP_PROT_KILL:
147 return "protection KILL";
148 default:
149 LOG_WARNING("Unknown protection state 0x%02" PRIx8 "", protection);
150 return "";
151 }
152 }
153
154
155 /* flash bank <name> psoc <base> <size> 0 0 <target#>
156 */
157 FLASH_BANK_COMMAND_HANDLER(psoc4_flash_bank_command)
158 {
159 struct psoc4_flash_bank *psoc4_info;
160
161 if (CMD_ARGC < 6)
162 return ERROR_COMMAND_SYNTAX_ERROR;
163
164 psoc4_info = calloc(1, sizeof(struct psoc4_flash_bank));
165
166 bank->driver_priv = psoc4_info;
167 psoc4_info->user_bank_size = bank->size;
168
169 return ERROR_OK;
170 }
171
172
173 /* PSoC 4 system ROM request
174 * Setting SROM_SYSREQ_BIT in CPUSS_SYSREQ register runs NMI service
175 * in sysrem ROM. Algorithm just waits for NMI to finish.
176 * When sysreq_params_size == 0 only one parameter is passed in CPUSS_SYSARG register.
177 * Otherwise address of memory parameter block is set in CPUSS_SYSARG
178 * and the first parameter is written to the first word of parameter block
179 */
180 static int psoc4_sysreq(struct target *target, uint8_t cmd, uint16_t cmd_param,
181 uint32_t *sysreq_params, uint32_t sysreq_params_size)
182 {
183 struct working_area *sysreq_wait_algorithm;
184 struct working_area *sysreq_mem;
185
186 struct reg_param reg_params[1];
187 struct armv7m_algorithm armv7m_info;
188
189 int retval = ERROR_OK;
190
191 uint32_t param1 = PSOC4_SROM_KEY1
192 | ((PSOC4_SROM_KEY2 + cmd) << 8)
193 | (cmd_param << 16);
194
195 static uint8_t psoc4_sysreq_wait_code[] = {
196 /* system request NMI is served immediately after algo run
197 now we are done: break */
198 0x00, 0xbe, /* bkpt 0 */
199 };
200
201 const int code_words = (sizeof(psoc4_sysreq_wait_code) + 3) / 4;
202 /* stack must be aligned */
203 const int stack_size = 196;
204 /* tested stack sizes on PSoC 4:
205 ERASE_ALL 144
206 PROGRAM_ROW 112
207 other sysreq 68
208 */
209
210 /* allocate area for sysreq wait code and stack */
211 if (target_alloc_working_area(target, code_words * 4 + stack_size,
212 &sysreq_wait_algorithm) != ERROR_OK) {
213 LOG_DEBUG("no working area for sysreq code");
214 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
215 };
216
217 /* Write the code */
218 retval = target_write_buffer(target,
219 sysreq_wait_algorithm->address,
220 sizeof(psoc4_sysreq_wait_code),
221 psoc4_sysreq_wait_code);
222 if (retval != ERROR_OK) {
223 /* we already allocated the writing code, but failed to get a
224 * buffer, free the algorithm */
225 goto cleanup_algo;
226 }
227
228 if (sysreq_params_size) {
229 /* Allocate memory for sysreq_params */
230 retval = target_alloc_working_area(target, sysreq_params_size, &sysreq_mem);
231 if (retval != ERROR_OK) {
232 LOG_WARNING("no working area for sysreq parameters");
233
234 /* we already allocated the writing code, but failed to get a
235 * buffer, free the algorithm */
236 retval = ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
237 goto cleanup_algo;
238 }
239
240 /* Write sysreq_params */
241 sysreq_params[0] = param1;
242 retval = target_write_buffer(target, sysreq_mem->address,
243 sysreq_params_size, (uint8_t *)sysreq_params);
244 if (retval != ERROR_OK)
245 goto cleanup_mem;
246
247 /* Set address of sysreq parameters block */
248 retval = target_write_u32(target, PSOC4_CPUSS_SYSARG, sysreq_mem->address);
249 if (retval != ERROR_OK)
250 goto cleanup_mem;
251
252 } else {
253 /* Sysreq without memory block of parameters */
254 /* Set register parameter */
255 retval = target_write_u32(target, PSOC4_CPUSS_SYSARG, param1);
256 if (retval != ERROR_OK)
257 goto cleanup_mem;
258 }
259
260 armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
261 armv7m_info.core_mode = ARM_MODE_THREAD;
262
263 /* sysreq stack */
264 init_reg_param(&reg_params[0], "sp", 32, PARAM_OUT);
265 buf_set_u32(reg_params[0].value, 0, 32,
266 sysreq_wait_algorithm->address + sysreq_wait_algorithm->size);
267
268 struct armv7m_common *armv7m = target_to_armv7m(target);
269 if (armv7m == NULL) {
270
271 /* something is very wrong if armv7m is NULL */
272 LOG_ERROR("unable to get armv7m target");
273 goto cleanup;
274 }
275
276 /* Set SROM request */
277 retval = target_write_u32(target, PSOC4_CPUSS_SYSREQ,
278 PSOC4_SROM_SYSREQ_BIT | PSOC4_SROM_HMASTER_BIT | cmd);
279 if (retval != ERROR_OK)
280 goto cleanup;
281
282 /* Execute wait code */
283 retval = target_run_algorithm(target, 0, NULL,
284 sizeof(reg_params) / sizeof(*reg_params), reg_params,
285 sysreq_wait_algorithm->address, 0, 1000, &armv7m_info);
286 if (retval != ERROR_OK)
287 LOG_ERROR("sysreq wait code execution failed");
288
289 cleanup:
290 destroy_reg_param(&reg_params[0]);
291
292 cleanup_mem:
293 if (sysreq_params_size)
294 target_free_working_area(target, sysreq_mem);
295
296 cleanup_algo:
297 target_free_working_area(target, sysreq_wait_algorithm);
298
299 return retval;
300 }
301
302
303 /* helper routine to get silicon ID from a PSoC 4 chip */
304 static int psoc4_get_silicon_id(struct target *target, uint32_t *silicon_id, uint8_t *protection)
305 {
306 uint32_t params = PSOC4_SROM_KEY1
307 | ((PSOC4_SROM_KEY2 + PSOC4_CMD_GET_SILICON_ID) << 8);
308 uint32_t part0, part1;
309
310 int retval = psoc4_sysreq(target, PSOC4_CMD_GET_SILICON_ID, 0, NULL, 0);
311 if (retval != ERROR_OK)
312 return retval;
313
314 retval = target_read_u32(target, PSOC4_CPUSS_SYSARG, &part0);
315 if (retval != ERROR_OK)
316 return retval;
317
318 if (part0 == params) {
319 LOG_ERROR("sysreq silicon id request not served");
320 return ERROR_FAIL;
321 }
322
323 retval = target_read_u32(target, PSOC4_CPUSS_SYSREQ, &part1);
324 if (retval != ERROR_OK)
325 return retval;
326
327 uint32_t silicon = ((part0 & 0xffff) << 16)
328 | (((part0 >> 16) & 0xff) << 8)
329 | (part1 & 0xff);
330 uint8_t prot = (part1 >> 12) & 0xff;
331
332 if (silicon_id)
333 *silicon_id = silicon;
334 if (protection)
335 *protection = prot;
336
337 LOG_DEBUG("silicon id: 0x%08" PRIx32 "", silicon);
338 LOG_DEBUG("protection: 0x%02" PRIx8 "", prot);
339 return retval;
340 }
341
342
343 static int psoc4_protect_check(struct flash_bank *bank)
344 {
345 struct target *target = bank->target;
346 struct psoc4_flash_bank *psoc4_info = bank->driver_priv;
347
348 uint32_t prot_addr = PSOC4_SFLASH_MACRO;
349 uint32_t protection;
350 int i, s;
351 int num_bits;
352 int retval = ERROR_OK;
353
354 num_bits = bank->num_sectors;
355
356 for (i = 0; i < num_bits; i += 32) {
357 retval = target_read_u32(target, prot_addr, &protection);
358 if (retval != ERROR_OK)
359 return retval;
360
361 prot_addr += 4;
362
363 for (s = 0; s < 32; s++) {
364 if (i + s >= num_bits)
365 break;
366 bank->sectors[i + s].is_protected = (protection & (1 << s)) ? 1 : 0;
367 }
368 }
369
370 retval = psoc4_get_silicon_id(target, NULL, &(psoc4_info->chip_protection));
371 return retval;
372 }
373
374
375 static int psoc4_mass_erase(struct flash_bank *bank)
376 {
377 struct target *target = bank->target;
378 int i;
379
380 if (bank->target->state != TARGET_HALTED) {
381 LOG_ERROR("Target not halted");
382 return ERROR_TARGET_NOT_HALTED;
383 }
384
385 /* Call "Erase All" system ROM API */
386 uint32_t param;
387 int retval = psoc4_sysreq(target, PSOC4_CMD_ERASE_ALL,
388 0,
389 &param, sizeof(param));
390
391 if (retval == ERROR_OK)
392 /* set all sectors as erased */
393 for (i = 0; i < bank->num_sectors; i++)
394 bank->sectors[i].is_erased = 1;
395
396 return retval;
397 }
398
399
400 static int psoc4_erase(struct flash_bank *bank, int first, int last)
401 {
402 struct psoc4_flash_bank *psoc4_info = bank->driver_priv;
403 if (psoc4_info->cmd_program_row == PSOC4_CMD_WRITE_ROW) {
404 LOG_INFO("Autoerase enabled, erase command ignored");
405 return ERROR_OK;
406 }
407
408 if ((first == 0) && (last == (bank->num_sectors - 1)))
409 return psoc4_mass_erase(bank);
410
411 LOG_ERROR("Only mass erase available");
412
413 return ERROR_FAIL;
414 }
415
416
417 static int psoc4_protect(struct flash_bank *bank, int set, int first, int last)
418 {
419 struct target *target = bank->target;
420 struct psoc4_flash_bank *psoc4_info = bank->driver_priv;
421
422 if (psoc4_info->probed == 0)
423 return ERROR_FAIL;
424
425 if (target->state != TARGET_HALTED) {
426 LOG_ERROR("Target not halted");
427 return ERROR_TARGET_NOT_HALTED;
428 }
429
430 uint32_t *sysrq_buffer = NULL;
431 int retval;
432 int num_bits = bank->num_sectors;
433 const int param_sz = 8;
434 int prot_sz = num_bits / 8;
435 int chip_prot = PSOC4_CHIP_PROT_OPEN;
436 int flash_macro = 0; /* PSoC 42xx has only macro 0 */
437 int i;
438
439 sysrq_buffer = calloc(1, param_sz + prot_sz);
440 if (sysrq_buffer == NULL) {
441 LOG_ERROR("no memory for row buffer");
442 return ERROR_FAIL;
443 }
444
445 for (i = first; i < num_bits && i <= last; i++)
446 bank->sectors[i].is_protected = set;
447
448 uint32_t *p = sysrq_buffer + 2;
449 for (i = 0; i < num_bits; i++) {
450 if (bank->sectors[i].is_protected)
451 p[i / 32] |= 1 << (i % 32);
452 }
453
454 /* Call "Load Latch" system ROM API */
455 sysrq_buffer[1] = prot_sz - 1;
456 retval = psoc4_sysreq(target, PSOC4_CMD_LOAD_LATCH,
457 0, /* Byte number in latch from what to write */
458 sysrq_buffer, param_sz + psoc4_info->row_size);
459 if (retval != ERROR_OK)
460 goto cleanup;
461
462 /* Call "Write Protection" system ROM API */
463 retval = psoc4_sysreq(target, PSOC4_CMD_WRITE_PROTECTION,
464 chip_prot | (flash_macro << 8), NULL, 0);
465 cleanup:
466 if (retval != ERROR_OK)
467 psoc4_protect_check(bank);
468
469 if (sysrq_buffer)
470 free(sysrq_buffer);
471
472 return retval;
473 }
474
475
476 COMMAND_HANDLER(psoc4_handle_flash_autoerase_command)
477 {
478 if (CMD_ARGC < 1)
479 return ERROR_COMMAND_SYNTAX_ERROR;
480
481 struct flash_bank *bank;
482 int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
483 if (ERROR_OK != retval)
484 return retval;
485
486 struct psoc4_flash_bank *psoc4_info = bank->driver_priv;
487 bool enable = psoc4_info->cmd_program_row == PSOC4_CMD_WRITE_ROW;
488
489 if (CMD_ARGC >= 2)
490 COMMAND_PARSE_ON_OFF(CMD_ARGV[1], enable);
491
492 if (enable) {
493 psoc4_info->cmd_program_row = PSOC4_CMD_WRITE_ROW;
494 LOG_INFO("Flash auto-erase enabled, non mass erase commands will be ignored.");
495 } else {
496 psoc4_info->cmd_program_row = PSOC4_CMD_PROGRAM_ROW;
497 LOG_INFO("Flash auto-erase disabled. Use psoc mass_erase before flash programming.");
498 }
499
500 return retval;
501 }
502
503
504 static int psoc4_write(struct flash_bank *bank, const uint8_t *buffer,
505 uint32_t offset, uint32_t count)
506 {
507 struct psoc4_flash_bank *psoc4_info = bank->driver_priv;
508 struct target *target = bank->target;
509 uint32_t *sysrq_buffer = NULL;
510 int retval = ERROR_OK;
511 const int param_sz = 8;
512
513 if (bank->target->state != TARGET_HALTED) {
514 LOG_ERROR("Target not halted");
515 return ERROR_TARGET_NOT_HALTED;
516 }
517
518 if (offset & 0x1) {
519 LOG_ERROR("offset 0x%08" PRIx32 " breaks required 2-byte alignment", offset);
520 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
521 }
522
523 sysrq_buffer = malloc(param_sz + psoc4_info->row_size);
524 if (sysrq_buffer == NULL) {
525 LOG_ERROR("no memory for row buffer");
526 return ERROR_FAIL;
527 }
528
529 uint8_t *row_buffer = (uint8_t *)sysrq_buffer + param_sz;
530 uint32_t row_num = offset / psoc4_info->row_size;
531 uint32_t row_offset = offset - row_num * psoc4_info->row_size;
532 if (row_offset)
533 memset(row_buffer, 0, row_offset);
534
535 bool save_poll = jtag_poll_get_enabled();
536 jtag_poll_set_enabled(false);
537
538 while (count) {
539 uint32_t chunk_size = psoc4_info->row_size - row_offset;
540 if (chunk_size > count) {
541 chunk_size = count;
542 memset(row_buffer + chunk_size, 0, psoc4_info->row_size - chunk_size);
543 }
544 memcpy(row_buffer + row_offset, buffer, chunk_size);
545 LOG_DEBUG("offset / row: 0x%08" PRIx32 " / %" PRIu32 ", size %" PRIu32 "",
546 offset, row_offset, chunk_size);
547
548 /* Call "Load Latch" system ROM API */
549 sysrq_buffer[1] = psoc4_info->row_size - 1;
550 retval = psoc4_sysreq(target, PSOC4_CMD_LOAD_LATCH,
551 0, /* Byte number in latch from what to write */
552 sysrq_buffer, param_sz + psoc4_info->row_size);
553 if (retval != ERROR_OK)
554 goto cleanup;
555
556 /* Call "Program Row" or "Write Row" system ROM API */
557 uint32_t sysrq_param;
558 retval = psoc4_sysreq(target, psoc4_info->cmd_program_row,
559 row_num & 0xffff,
560 &sysrq_param, sizeof(sysrq_param));
561 if (retval != ERROR_OK)
562 goto cleanup;
563
564 buffer += chunk_size;
565 row_num++;
566 row_offset = 0;
567 count -= chunk_size;
568 }
569
570 cleanup:
571 jtag_poll_set_enabled(save_poll);
572
573 if (sysrq_buffer)
574 free(sysrq_buffer);
575
576 return retval;
577 }
578
579
580 static int psoc4_probe(struct flash_bank *bank)
581 {
582 struct psoc4_flash_bank *psoc4_info = bank->driver_priv;
583 struct target *target = bank->target;
584 uint32_t flash_size_in_kb = 0;
585 uint32_t max_flash_size_in_kb;
586 uint32_t cpu_id;
587 uint32_t silicon_id;
588 uint32_t row_size;
589 uint32_t base_address = 0x00000000;
590 uint8_t protection;
591
592 if (target->state != TARGET_HALTED) {
593 LOG_ERROR("Target not halted");
594 return ERROR_TARGET_NOT_HALTED;
595 }
596
597 psoc4_info->probed = 0;
598 psoc4_info->cmd_program_row = PSOC4_CMD_PROGRAM_ROW;
599
600 /* Get the CPUID from the ARM Core
601 * http://infocenter.arm.com/help/topic/com.arm.doc.ddi0432c/DDI0432C_cortex_m0_r0p0_trm.pdf 4.2.1 */
602 int retval = target_read_u32(target, 0xE000ED00, &cpu_id);
603 if (retval != ERROR_OK)
604 return retval;
605
606 LOG_DEBUG("cpu id = 0x%08" PRIx32 "", cpu_id);
607
608 /* set page size, protection granularity and max flash size depending on family */
609 switch ((cpu_id >> 4) & 0xFFF) {
610 case 0xc20: /* M0 -> PSoC4 */
611 row_size = 128;
612 max_flash_size_in_kb = 32;
613 break;
614 default:
615 LOG_WARNING("Cannot identify target as a PSoC 4 family.");
616 return ERROR_FAIL;
617 }
618
619 uint32_t spcif_geometry;
620 retval = target_read_u32(target, PSOC4_SPCIF_GEOMETRY, &spcif_geometry);
621 if (retval == ERROR_OK) {
622 row_size = 128 * ((spcif_geometry >> 22) & 3);
623 flash_size_in_kb = (spcif_geometry & 0xffff) * 256 / 1024;
624 LOG_INFO("SPCIF geometry: %" PRIu32 " kb flash, row %" PRIu32 " bytes.",
625 flash_size_in_kb, row_size);
626 }
627
628 /* Early revisions of ST-Link v2 have some problem reading PSOC4_SPCIF_GEOMETRY
629 and an error is reported late. Dummy read gets this error. */
630 uint32_t dummy;
631 target_read_u32(target, PSOC4_CPUSS_SYSREQ, &dummy);
632
633 /* get silicon ID from target. */
634 retval = psoc4_get_silicon_id(target, &silicon_id, &protection);
635 if (retval != ERROR_OK)
636 return retval;
637
638 const struct psoc4_chip_details *details = psoc4_details_by_id(silicon_id);
639 if (details) {
640 LOG_INFO("%s device detected.", details->type);
641 if (flash_size_in_kb == 0)
642 flash_size_in_kb = details->flash_size_in_kb;
643 else if (flash_size_in_kb != details->flash_size_in_kb)
644 LOG_ERROR("Flash size mismatch");
645 }
646
647 psoc4_info->row_size = row_size;
648 psoc4_info->silicon_id = silicon_id;
649 psoc4_info->chip_protection = protection;
650
651 /* failed reading flash size or flash size invalid (early silicon),
652 * default to max target family */
653 if (retval != ERROR_OK || flash_size_in_kb == 0xffff || flash_size_in_kb == 0) {
654 LOG_WARNING("PSoC 4 flash size failed, probe inaccurate - assuming %" PRIu32 " k flash",
655 max_flash_size_in_kb);
656 flash_size_in_kb = max_flash_size_in_kb;
657 }
658
659 /* if the user sets the size manually then ignore the probed value
660 * this allows us to work around devices that have a invalid flash size register value */
661 if (psoc4_info->user_bank_size) {
662 LOG_INFO("ignoring flash probed value, using configured bank size");
663 flash_size_in_kb = psoc4_info->user_bank_size / 1024;
664 }
665
666 LOG_INFO("flash size = %" PRIu32 " kbytes", flash_size_in_kb);
667
668 /* did we assign flash size? */
669 assert(flash_size_in_kb != 0xffff);
670
671 /* calculate numbers of pages */
672 uint32_t num_rows = flash_size_in_kb * 1024 / row_size;
673
674 /* check that calculation result makes sense */
675 assert(num_rows > 0);
676
677 if (bank->sectors) {
678 free(bank->sectors);
679 bank->sectors = NULL;
680 }
681
682 bank->base = base_address;
683 bank->size = num_rows * row_size;
684 bank->num_sectors = num_rows;
685 bank->sectors = malloc(sizeof(struct flash_sector) * num_rows);
686
687 uint32_t i;
688 for (i = 0; i < num_rows; i++) {
689 bank->sectors[i].offset = i * row_size;
690 bank->sectors[i].size = row_size;
691 bank->sectors[i].is_erased = -1;
692 bank->sectors[i].is_protected = 1;
693 }
694
695 LOG_INFO("flash bank set %" PRIu32 " rows", num_rows);
696 psoc4_info->probed = 1;
697
698 return ERROR_OK;
699 }
700
701 static int psoc4_auto_probe(struct flash_bank *bank)
702 {
703 struct psoc4_flash_bank *psoc4_info = bank->driver_priv;
704 if (psoc4_info->probed)
705 return ERROR_OK;
706 return psoc4_probe(bank);
707 }
708
709
710 static int get_psoc4_info(struct flash_bank *bank, char *buf, int buf_size)
711 {
712 struct psoc4_flash_bank *psoc4_info = bank->driver_priv;
713 int printed = 0;
714
715 if (psoc4_info->probed == 0)
716 return ERROR_FAIL;
717
718 const struct psoc4_chip_details *details = psoc4_details_by_id(psoc4_info->silicon_id);
719
720 if (details) {
721 uint32_t chip_revision = psoc4_info->silicon_id & 0xffff;
722 printed = snprintf(buf, buf_size, "PSoC 4 %s rev 0x%04" PRIx32 " package %s",
723 details->type, chip_revision, details->package);
724 } else
725 printed = snprintf(buf, buf_size, "PSoC 4 silicon id 0x%08" PRIx32 "",
726 psoc4_info->silicon_id);
727
728 buf += printed;
729 buf_size -= printed;
730
731 const char *prot_txt = psoc4_decode_chip_protection(psoc4_info->chip_protection);
732 uint32_t size_in_kb = bank->size / 1024;
733 snprintf(buf, buf_size, " flash %" PRIu32 " kb %s", size_in_kb, prot_txt);
734 return ERROR_OK;
735 }
736
737
738 COMMAND_HANDLER(psoc4_handle_mass_erase_command)
739 {
740 if (CMD_ARGC < 1)
741 return ERROR_COMMAND_SYNTAX_ERROR;
742
743 struct flash_bank *bank;
744 int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
745 if (ERROR_OK != retval)
746 return retval;
747
748 retval = psoc4_mass_erase(bank);
749 if (retval == ERROR_OK)
750 command_print(CMD_CTX, "psoc mass erase complete");
751 else
752 command_print(CMD_CTX, "psoc mass erase failed");
753
754 return retval;
755 }
756
757
758 static const struct command_registration psoc4_exec_command_handlers[] = {
759 {
760 .name = "mass_erase",
761 .handler = psoc4_handle_mass_erase_command,
762 .mode = COMMAND_EXEC,
763 .usage = "bank_id",
764 .help = "Erase entire flash device.",
765 },
766 {
767 .name = "flash_autoerase",
768 .handler = psoc4_handle_flash_autoerase_command,
769 .mode = COMMAND_EXEC,
770 .usage = "bank_id on|off",
771 .help = "Set autoerase mode for flash bank.",
772 },
773 COMMAND_REGISTRATION_DONE
774 };
775
776 static const struct command_registration psoc4_command_handlers[] = {
777 {
778 .name = "psoc4",
779 .mode = COMMAND_ANY,
780 .help = "PSoC 4 flash command group",
781 .usage = "",
782 .chain = psoc4_exec_command_handlers,
783 },
784 COMMAND_REGISTRATION_DONE
785 };
786
787 struct flash_driver psoc4_flash = {
788 .name = "psoc4",
789 .commands = psoc4_command_handlers,
790 .flash_bank_command = psoc4_flash_bank_command,
791 .erase = psoc4_erase,
792 .protect = psoc4_protect,
793 .write = psoc4_write,
794 .read = default_flash_read,
795 .probe = psoc4_probe,
796 .auto_probe = psoc4_auto_probe,
797 .erase_check = default_flash_blank_check,
798 .protect_check = psoc4_protect_check,
799 .info = get_psoc4_info,
800 };

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)