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

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)