psoc4: support for Cypress PSoC 41xx/42xx family
[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 uint16_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 uint16_t row_size;
116 uint32_t user_bank_size;
117 int probed;
118 uint32_t silicon_id;
119 uint8_t chip_protection;
120 uint16_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%" PRIx32 "", silicon);
338 LOG_DEBUG("protection: 0x%" 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%" 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%" PRIx32 " / %d size %d",
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 int i;
585 uint16_t flash_size_in_kb = 0;
586 uint16_t max_flash_size_in_kb;
587 uint32_t cpu_id;
588 uint32_t silicon_id;
589 int row_size;
590 uint32_t base_address = 0x00000000;
591 uint8_t protection;
592
593 if (target->state != TARGET_HALTED) {
594 LOG_ERROR("Target not halted");
595 return ERROR_TARGET_NOT_HALTED;
596 }
597
598 psoc4_info->probed = 0;
599 psoc4_info->cmd_program_row = PSOC4_CMD_PROGRAM_ROW;
600
601 /* Get the CPUID from the ARM Core
602 * http://infocenter.arm.com/help/topic/com.arm.doc.ddi0432c/DDI0432C_cortex_m0_r0p0_trm.pdf 4.2.1 */
603 int retval = target_read_u32(target, 0xE000ED00, &cpu_id);
604 if (retval != ERROR_OK)
605 return retval;
606
607 LOG_DEBUG("cpu id = 0x%08" PRIx32 "", cpu_id);
608
609 /* set page size, protection granularity and max flash size depending on family */
610 switch ((cpu_id >> 4) & 0xFFF) {
611 case 0xc20: /* M0 -> PSoC4 */
612 row_size = 128;
613 max_flash_size_in_kb = 32;
614 break;
615 default:
616 LOG_WARNING("Cannot identify target as a PSoC 4 family.");
617 return ERROR_FAIL;
618 }
619
620 uint32_t spcif_geometry;
621 retval = target_read_u32(target, PSOC4_SPCIF_GEOMETRY, &spcif_geometry);
622 if (retval == ERROR_OK) {
623 row_size = 128 * ((spcif_geometry >> 22) & 3);
624 flash_size_in_kb = (spcif_geometry & 0xffff) * 256 / 1024;
625 LOG_INFO("SPCIF geometry: %d kb flash, row %d bytes.", flash_size_in_kb, row_size);
626 }
627
628 /* ST-Link v2 has 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 %dk 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 = %d 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 int 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 for (i = 0; i < num_rows; i++) {
688 bank->sectors[i].offset = i * row_size;
689 bank->sectors[i].size = row_size;
690 bank->sectors[i].is_erased = -1;
691 bank->sectors[i].is_protected = 1;
692 }
693
694 LOG_INFO("flash bank set %d rows", num_rows);
695 psoc4_info->probed = 1;
696
697 return ERROR_OK;
698 }
699
700 static int psoc4_auto_probe(struct flash_bank *bank)
701 {
702 struct psoc4_flash_bank *psoc4_info = bank->driver_priv;
703 if (psoc4_info->probed)
704 return ERROR_OK;
705 return psoc4_probe(bank);
706 }
707
708
709 static int get_psoc4_info(struct flash_bank *bank, char *buf, int buf_size)
710 {
711 struct psoc4_flash_bank *psoc4_info = bank->driver_priv;
712 int printed = 0;
713
714 if (psoc4_info->probed == 0)
715 return ERROR_FAIL;
716
717 const struct psoc4_chip_details *details = psoc4_details_by_id(psoc4_info->silicon_id);
718
719 if (details)
720 printed = snprintf(buf, buf_size, "PSoC 4 %s rev 0x%04" PRIx16 " package %s",
721 details->type, psoc4_info->silicon_id & 0xffff, details->package);
722 else
723 printed = snprintf(buf, buf_size, "PSoC 4 silicon id 0x%08" PRIx32 "",
724 psoc4_info->silicon_id);
725
726 buf += printed;
727 buf_size -= printed;
728
729 const char *prot_txt = psoc4_decode_chip_protection(psoc4_info->chip_protection);
730 snprintf(buf, buf_size, " flash %d kb %s", bank->size / 1024, prot_txt);
731 return ERROR_OK;
732 }
733
734
735 COMMAND_HANDLER(psoc4_handle_mass_erase_command)
736 {
737 if (CMD_ARGC < 1)
738 return ERROR_COMMAND_SYNTAX_ERROR;
739
740 struct flash_bank *bank;
741 int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
742 if (ERROR_OK != retval)
743 return retval;
744
745 retval = psoc4_mass_erase(bank);
746 if (retval == ERROR_OK)
747 command_print(CMD_CTX, "psoc mass erase complete");
748 else
749 command_print(CMD_CTX, "psoc mass erase failed");
750
751 return retval;
752 }
753
754
755 static const struct command_registration psoc4_exec_command_handlers[] = {
756 {
757 .name = "mass_erase",
758 .handler = psoc4_handle_mass_erase_command,
759 .mode = COMMAND_EXEC,
760 .usage = "bank_id",
761 .help = "Erase entire flash device.",
762 },
763 {
764 .name = "flash_autoerase",
765 .handler = psoc4_handle_flash_autoerase_command,
766 .mode = COMMAND_EXEC,
767 .usage = "bank_id on|off",
768 .help = "Set autoerase mode for flash bank.",
769 },
770 COMMAND_REGISTRATION_DONE
771 };
772
773 static const struct command_registration psoc4_command_handlers[] = {
774 {
775 .name = "psoc4",
776 .mode = COMMAND_ANY,
777 .help = "PSoC 4 flash command group",
778 .usage = "",
779 .chain = psoc4_exec_command_handlers,
780 },
781 COMMAND_REGISTRATION_DONE
782 };
783
784 struct flash_driver psoc4_flash = {
785 .name = "psoc4",
786 .commands = psoc4_command_handlers,
787 .flash_bank_command = psoc4_flash_bank_command,
788 .erase = psoc4_erase,
789 .protect = psoc4_protect,
790 .write = psoc4_write,
791 .read = default_flash_read,
792 .probe = psoc4_probe,
793 .auto_probe = psoc4_auto_probe,
794 .erase_check = default_flash_blank_check,
795 .protect_check = psoc4_protect_check,
796 .info = get_psoc4_info,
797 };

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)