tcl/board: Add SAML11 Xplained Pro Evaluation Kit
[openocd.git] / src / flash / nor / psoc4.c
blob1eb6a26eda453426064cfba171212ab3ebea4e99
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 ***************************************************************************/
28 #ifdef HAVE_CONFIG_H
29 #include "config.h"
30 #endif
32 #include "imp.h"
33 #include <helper/binarybuffer.h>
34 #include <jtag/jtag.h>
35 #include <target/algorithm.h>
36 #include <target/armv7m.h>
38 /* device documets:
40 PSoC(R) 4: PSoC 4200 Family Datasheet
41 Document Number: 001-87197 Rev. *B Revised August 29, 2013
43 PSoC 4100/4200 Family PSoC(R) 4 Architecture TRM
44 Document No. 001-85634 Rev. *E June 28, 2016
46 PSoC(R) 4 Registers TRM Spec.
47 Document No. 001-85847 Rev. *A June 25, 2013
49 PSoC 4000 Family PSoC(R) 4 Technical Reference Manual
50 Document No. 001-89309 Rev. *B May 9, 2016
52 PSoC 41XX_BLE/42XX_BLE Family PSoC 4 BLE Architecture TRM
53 Document No. 001-92738 Rev. *C February 12, 2016
55 PSoC 4200L Family PSoC 4 Architecture TRM
56 Document No. 001-97952 Rev. *A December 15, 2015
58 PSoC 4200L Family PSoC 4 Registers TRM
59 Document No. 001-98126 Rev. *A December 16, 2015
61 PSoC 4100M/4200M Family PSoC 4 Architecture TRM
62 Document No. 001-95223 Rev. *B July 29, 2015
64 PSoC 4100S Family PSoC 4 Architecture TRM
65 Document No. 002-10621 Rev. *A July 29, 2016
67 PSoC 4100S Family PSoC 4 Registers TRM
68 Document No. 002-10523 Rev. *A July 20, 2016
70 PSoC Analog Coprocessor Architecture TRM
71 Document No. 002-10404 Rev. ** December 18, 2015
73 CY8C4Axx PSoC Analog Coprocessor Registers TRM
74 Document No. 002-10405 Rev. ** December 18, 2015
76 CY8C41xx, CY8C42xx Programming Specifications
77 Document No. 001-81799 Rev. *C March 4, 2014
79 CYBL10x6x, CY8C4127_BL, CY8C4247_BL Programming Specifications
80 Document No. 001-91508 Rev. *B September 22, 2014
82 http://dmitry.gr/index.php?r=05.Projects&proj=24.%20PSoC4%20confidential
85 /* register locations */
86 #define PSOC4_SFLASH_MACRO0 0x0FFFF000
88 #define PSOC4_CPUSS_SYSREQ_LEGACY 0x40000004
89 #define PSOC4_CPUSS_SYSARG_LEGACY 0x40000008
90 #define PSOC4_SPCIF_GEOMETRY_LEGACY 0x400E0000
92 #define PSOC4_CPUSS_SYSREQ_NEW 0x40100004
93 #define PSOC4_CPUSS_SYSARG_NEW 0x40100008
94 #define PSOC4_SPCIF_GEOMETRY_NEW 0x40110000
96 #define PSOC4_TEST_MODE 0x40030014
98 #define PSOC4_ROMTABLE_PID0 0xF0000FE0
101 /* constants */
102 #define PSOC4_SFLASH_MACRO_SIZE 0x800
103 #define PSOC4_ROWS_PER_MACRO 512
105 #define PSOC4_SROM_KEY1 0xb6
106 #define PSOC4_SROM_KEY2 0xd3
107 #define PSOC4_SROM_SYSREQ_BIT (1<<31)
108 #define PSOC4_SROM_HMASTER_BIT (1<<30)
109 #define PSOC4_SROM_PRIVILEGED_BIT (1<<28)
110 #define PSOC4_SROM_STATUS_SUCCEEDED 0xa0000000
111 #define PSOC4_SROM_STATUS_FAILED 0xf0000000
112 #define PSOC4_SROM_STATUS_MASK 0xf0000000
114 /* not documented in any TRM */
115 #define PSOC4_SROM_ERR_IMO_NOT_IMPLEM 0xf0000013
117 #define PSOC4_CMD_GET_SILICON_ID 0
118 #define PSOC4_CMD_LOAD_LATCH 4
119 #define PSOC4_CMD_WRITE_ROW 5
120 #define PSOC4_CMD_PROGRAM_ROW 6
121 #define PSOC4_CMD_ERASE_ALL 0xa
122 #define PSOC4_CMD_CHECKSUM 0xb
123 #define PSOC4_CMD_WRITE_PROTECTION 0xd
124 #define PSOC4_CMD_SET_IMO48 0x15
125 #define PSOC4_CMD_WRITE_SFLASH_ROW 0x18
127 #define PSOC4_CHIP_PROT_VIRGIN 0x0
128 #define PSOC4_CHIP_PROT_OPEN 0x1
129 #define PSOC4_CHIP_PROT_PROTECTED 0x2
130 #define PSOC4_CHIP_PROT_KILL 0x4
132 #define PSOC4_ROMTABLE_DESIGNER_CHECK 0xb4
134 #define PSOC4_FAMILY_FLAG_LEGACY 1
136 struct psoc4_chip_family {
137 uint16_t id;
138 const char *name;
139 uint32_t flags;
142 const struct psoc4_chip_family psoc4_families[] = {
143 { 0x93, "PSoC4100/4200", .flags = PSOC4_FAMILY_FLAG_LEGACY },
144 { 0x9A, "PSoC4000", .flags = 0 },
145 { 0x9E, "PSoC/PRoC BLE (119E)", .flags = 0 },
146 { 0xA0, "PSoC4200L", .flags = 0 },
147 { 0xA1, "PSoC4100M/4200M", .flags = 0 },
148 { 0xA3, "PSoC/PRoC BLE (11A3)", .flags = 0 },
149 { 0xA9, "PSoC4000S", .flags = 0 },
150 { 0xAA, "PSoC/PRoC BLE (11AA)", .flags = 0 },
151 { 0xAB, "PSoC4100S", .flags = 0 },
152 { 0xAC, "PSoC Analog Coprocessor", .flags = 0 },
153 { 0, "Unknown", .flags = 0 }
157 struct psoc4_flash_bank {
158 uint32_t row_size;
159 uint32_t user_bank_size;
160 int num_macros;
161 bool probed;
162 uint8_t cmd_program_row;
163 uint16_t family_id;
164 bool legacy_family;
165 uint32_t cpuss_sysreq_addr;
166 uint32_t cpuss_sysarg_addr;
167 uint32_t spcif_geometry_addr;
171 static const struct psoc4_chip_family *psoc4_family_by_id(uint16_t family_id)
173 const struct psoc4_chip_family *p = psoc4_families;
174 while (p->id && p->id != family_id)
175 p++;
177 return p;
180 static const char *psoc4_decode_chip_protection(uint8_t protection)
182 switch (protection) {
183 case PSOC4_CHIP_PROT_VIRGIN:
184 return "protection VIRGIN";
185 case PSOC4_CHIP_PROT_OPEN:
186 return "protection open";
187 case PSOC4_CHIP_PROT_PROTECTED:
188 return "PROTECTED";
189 case PSOC4_CHIP_PROT_KILL:
190 return "protection KILL";
191 default:
192 LOG_WARNING("Unknown protection state 0x%02" PRIx8 "", protection);
193 return "";
198 /* flash bank <name> psoc <base> <size> 0 0 <target#>
200 FLASH_BANK_COMMAND_HANDLER(psoc4_flash_bank_command)
202 struct psoc4_flash_bank *psoc4_info;
204 if (CMD_ARGC < 6)
205 return ERROR_COMMAND_SYNTAX_ERROR;
207 psoc4_info = calloc(1, sizeof(struct psoc4_flash_bank));
209 bank->driver_priv = psoc4_info;
210 bank->default_padded_value = bank->erased_value = 0x00;
211 psoc4_info->user_bank_size = bank->size;
212 psoc4_info->cmd_program_row = PSOC4_CMD_WRITE_ROW;
214 return ERROR_OK;
218 /* PSoC 4 system ROM request
219 * Setting SROM_SYSREQ_BIT in CPUSS_SYSREQ register runs NMI service
220 * in sysrem ROM. Algorithm just waits for NMI to finish.
221 * When sysreq_params_size == 0 only one parameter is passed in CPUSS_SYSARG register.
222 * Otherwise address of memory parameter block is set in CPUSS_SYSARG
223 * and the first parameter is written to the first word of parameter block
225 static int psoc4_sysreq(struct flash_bank *bank, uint8_t cmd,
226 uint16_t cmd_param,
227 uint32_t *sysreq_params, uint32_t sysreq_params_size,
228 uint32_t *sysarg_out)
230 struct target *target = bank->target;
231 struct psoc4_flash_bank *psoc4_info = bank->driver_priv;
233 struct working_area *sysreq_wait_algorithm;
234 struct working_area *sysreq_mem;
236 struct reg_param reg_params[1];
237 struct armv7m_algorithm armv7m_info;
239 int retval = ERROR_OK;
241 uint32_t param1 = PSOC4_SROM_KEY1
242 | ((PSOC4_SROM_KEY2 + cmd) << 8)
243 | (cmd_param << 16);
245 static uint8_t psoc4_sysreq_wait_code[] = {
246 /* system request NMI is served immediately after algo run
247 now we are done: break */
248 0x00, 0xbe, /* bkpt 0 */
251 const int code_words = (sizeof(psoc4_sysreq_wait_code) + 3) / 4;
252 /* stack must be aligned */
253 const int stack_size = 256;
254 /* tested stack sizes on PSoC4200:
255 ERASE_ALL 144
256 PROGRAM_ROW 112
257 other sysreq 68
260 /* allocate area for sysreq wait code and stack */
261 if (target_alloc_working_area(target, code_words * 4 + stack_size,
262 &sysreq_wait_algorithm) != ERROR_OK) {
263 LOG_DEBUG("no working area for sysreq code");
264 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
267 /* Write the code */
268 retval = target_write_buffer(target,
269 sysreq_wait_algorithm->address,
270 sizeof(psoc4_sysreq_wait_code),
271 psoc4_sysreq_wait_code);
272 if (retval != ERROR_OK) {
273 /* we already allocated the writing code, but failed to get a
274 * buffer, free the algorithm */
275 goto cleanup_algo;
278 if (sysreq_params_size) {
279 LOG_DEBUG("SYSREQ %02" PRIx8 " %04" PRIx16 " %08" PRIx32 " size %" PRIu32,
280 cmd, cmd_param, param1, sysreq_params_size);
281 /* Allocate memory for sysreq_params */
282 retval = target_alloc_working_area(target, sysreq_params_size, &sysreq_mem);
283 if (retval != ERROR_OK) {
284 LOG_WARNING("no working area for sysreq parameters");
286 /* we already allocated the writing code, but failed to get a
287 * buffer, free the algorithm */
288 retval = ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
289 goto cleanup_algo;
292 /* Write sysreq_params */
293 target_buffer_set_u32(target, (uint8_t *)sysreq_params, param1);
294 retval = target_write_buffer(target, sysreq_mem->address,
295 sysreq_params_size, (uint8_t *)sysreq_params);
296 if (retval != ERROR_OK)
297 goto cleanup_mem;
299 /* Set address of sysreq parameters block */
300 retval = target_write_u32(target, psoc4_info->cpuss_sysarg_addr, sysreq_mem->address);
301 if (retval != ERROR_OK)
302 goto cleanup_mem;
304 } else {
305 /* Sysreq without memory block of parameters */
306 LOG_DEBUG("SYSREQ %02" PRIx8 " %04" PRIx16 " %08" PRIx32,
307 cmd, cmd_param, param1);
308 /* Set register parameter */
309 retval = target_write_u32(target, psoc4_info->cpuss_sysarg_addr, param1);
310 if (retval != ERROR_OK)
311 goto cleanup_mem;
314 armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
315 armv7m_info.core_mode = ARM_MODE_THREAD;
317 /* sysreq stack */
318 init_reg_param(&reg_params[0], "sp", 32, PARAM_OUT);
319 buf_set_u32(reg_params[0].value, 0, 32,
320 sysreq_wait_algorithm->address + sysreq_wait_algorithm->size);
322 struct armv7m_common *armv7m = target_to_armv7m(target);
323 if (armv7m == NULL) {
324 /* something is very wrong if armv7m is NULL */
325 LOG_ERROR("unable to get armv7m target");
326 retval = ERROR_FAIL;
327 goto cleanup;
330 /* Set SROM request */
331 retval = target_write_u32(target, psoc4_info->cpuss_sysreq_addr,
332 PSOC4_SROM_SYSREQ_BIT | PSOC4_SROM_HMASTER_BIT | cmd);
333 if (retval != ERROR_OK)
334 goto cleanup;
336 /* Execute wait code */
337 retval = target_run_algorithm(target, 0, NULL,
338 sizeof(reg_params) / sizeof(*reg_params), reg_params,
339 sysreq_wait_algorithm->address, 0, 1000, &armv7m_info);
340 if (retval != ERROR_OK) {
341 LOG_ERROR("sysreq wait code execution failed");
342 goto cleanup;
345 uint32_t sysarg_out_tmp;
346 retval = target_read_u32(target, psoc4_info->cpuss_sysarg_addr, &sysarg_out_tmp);
347 if (retval != ERROR_OK)
348 goto cleanup;
350 if (sysarg_out) {
351 *sysarg_out = sysarg_out_tmp;
352 /* If result is an error, do not show now, let caller to decide */
353 } else if ((sysarg_out_tmp & PSOC4_SROM_STATUS_MASK) != PSOC4_SROM_STATUS_SUCCEEDED) {
354 LOG_ERROR("sysreq error 0x%" PRIx32, sysarg_out_tmp);
355 retval = ERROR_FAIL;
357 cleanup:
358 destroy_reg_param(&reg_params[0]);
360 cleanup_mem:
361 if (sysreq_params_size)
362 target_free_working_area(target, sysreq_mem);
364 cleanup_algo:
365 target_free_working_area(target, sysreq_wait_algorithm);
367 return retval;
371 /* helper routine to get silicon ID from a PSoC 4 chip */
372 static int psoc4_get_silicon_id(struct flash_bank *bank, uint32_t *silicon_id, uint16_t *family_id, uint8_t *protection)
374 struct target *target = bank->target;
375 struct psoc4_flash_bank *psoc4_info = bank->driver_priv;
377 uint32_t part0, part1;
379 int retval = psoc4_sysreq(bank, PSOC4_CMD_GET_SILICON_ID, 0, NULL, 0, &part0);
380 if (retval != ERROR_OK)
381 return retval;
383 if ((part0 & PSOC4_SROM_STATUS_MASK) != PSOC4_SROM_STATUS_SUCCEEDED) {
384 LOG_ERROR("sysreq error 0x%" PRIx32, part0);
385 return ERROR_FAIL;
388 retval = target_read_u32(target, psoc4_info->cpuss_sysreq_addr, &part1);
389 if (retval != ERROR_OK)
390 return retval;
392 /* build ID as Cypress sw does:
393 * bit 31..16 silicon ID
394 * bit 15..8 revision ID (so far 0x11 for all devices)
395 * bit 7..0 family ID (lowes 8 bits)
397 if (silicon_id)
398 *silicon_id = ((part0 & 0x0000ffff) << 16)
399 | ((part0 & 0x00ff0000) >> 8)
400 | (part1 & 0x000000ff);
402 if (family_id)
403 *family_id = part1 & 0x0fff;
405 if (protection)
406 *protection = (part1 >> 12) & 0x0f;
408 return ERROR_OK;
412 static int psoc4_get_family(struct target *target, uint16_t *family_id)
414 int retval, i;
415 uint32_t pidbf[3];
416 uint8_t pid[3];
418 retval = target_read_memory(target, PSOC4_ROMTABLE_PID0, 4, 3, (uint8_t *)pidbf);
419 if (retval != ERROR_OK)
420 return retval;
422 for (i = 0; i < 3; i++) {
423 uint32_t tmp = target_buffer_get_u32(target, (uint8_t *)(pidbf + i));
424 if (tmp & 0xffffff00) {
425 LOG_ERROR("Unexpected data in ROMTABLE");
426 return ERROR_FAIL;
428 pid[i] = tmp & 0xff;
431 uint16_t family = pid[0] | ((pid[1] & 0xf) << 8);
432 uint32_t designer = ((pid[1] & 0xf0) >> 4) | ((pid[2] & 0xf) << 4);
434 if (designer != PSOC4_ROMTABLE_DESIGNER_CHECK) {
435 LOG_ERROR("ROMTABLE designer is not Cypress");
436 return ERROR_FAIL;
439 *family_id = family;
440 return ERROR_OK;
444 static int psoc4_flash_prepare(struct flash_bank *bank)
446 struct target *target = bank->target;
447 struct psoc4_flash_bank *psoc4_info = bank->driver_priv;
449 if (target->state != TARGET_HALTED) {
450 LOG_ERROR("Target not halted");
451 return ERROR_TARGET_NOT_HALTED;
454 uint16_t family_id;
455 int retval;
457 /* get family ID from SROM call */
458 retval = psoc4_get_silicon_id(bank, NULL, &family_id, NULL);
459 if (retval != ERROR_OK)
460 return retval;
462 /* and check with family ID from ROMTABLE */
463 if (family_id != psoc4_info->family_id) {
464 LOG_ERROR("Family mismatch");
465 return ERROR_FAIL;
468 if (!psoc4_info->legacy_family) {
469 uint32_t sysreq_status;
470 retval = psoc4_sysreq(bank, PSOC4_CMD_SET_IMO48, 0, NULL, 0, &sysreq_status);
471 if (retval != ERROR_OK)
472 return retval;
474 if ((sysreq_status & PSOC4_SROM_STATUS_MASK) != PSOC4_SROM_STATUS_SUCCEEDED) {
475 /* This undocumented error code is returned probably when
476 * PSOC4_CMD_SET_IMO48 command is not implemented.
477 * Can be safely ignored, programming works.
479 if (sysreq_status == PSOC4_SROM_ERR_IMO_NOT_IMPLEM)
480 LOG_INFO("PSOC4_CMD_SET_IMO48 is not implemented on this device.");
481 else {
482 LOG_ERROR("sysreq error 0x%" PRIx32, sysreq_status);
483 return ERROR_FAIL;
488 return ERROR_OK;
492 static int psoc4_protect_check(struct flash_bank *bank)
494 struct target *target = bank->target;
495 struct psoc4_flash_bank *psoc4_info = bank->driver_priv;
497 uint32_t prot_addr = PSOC4_SFLASH_MACRO0;
498 int retval;
499 int s = 0;
500 int m, i;
501 uint8_t bf[PSOC4_ROWS_PER_MACRO/8];
503 for (m = 0; m < psoc4_info->num_macros; m++, prot_addr += PSOC4_SFLASH_MACRO_SIZE) {
504 retval = target_read_memory(target, prot_addr, 4, PSOC4_ROWS_PER_MACRO/32, bf);
505 if (retval != ERROR_OK)
506 return retval;
508 for (i = 0; i < PSOC4_ROWS_PER_MACRO && s < bank->num_sectors; i++, s++)
509 bank->sectors[s].is_protected = bf[i/8] & (1 << (i%8)) ? 1 : 0;
512 return ERROR_OK;
516 static int psoc4_mass_erase(struct flash_bank *bank)
518 int i;
519 int retval = psoc4_flash_prepare(bank);
520 if (retval != ERROR_OK)
521 return retval;
523 /* Call "Erase All" system ROM API */
524 uint32_t param = 0;
525 retval = psoc4_sysreq(bank, PSOC4_CMD_ERASE_ALL,
527 &param, sizeof(param), NULL);
529 if (retval == ERROR_OK)
530 /* set all sectors as erased */
531 for (i = 0; i < bank->num_sectors; i++)
532 bank->sectors[i].is_erased = 1;
534 return retval;
538 static int psoc4_erase(struct flash_bank *bank, int first, int last)
540 struct psoc4_flash_bank *psoc4_info = bank->driver_priv;
541 if (psoc4_info->cmd_program_row == PSOC4_CMD_WRITE_ROW) {
542 LOG_INFO("Autoerase enabled, erase command ignored");
543 return ERROR_OK;
546 if ((first == 0) && (last == (bank->num_sectors - 1)))
547 return psoc4_mass_erase(bank);
549 LOG_ERROR("Only mass erase available! Consider using 'psoc4 flash_autoerase 0 on'");
551 return ERROR_FAIL;
555 static int psoc4_protect(struct flash_bank *bank, int set, int first, int last)
557 struct target *target = bank->target;
558 struct psoc4_flash_bank *psoc4_info = bank->driver_priv;
560 if (!psoc4_info->probed)
561 return ERROR_FAIL;
563 int retval = psoc4_flash_prepare(bank);
564 if (retval != ERROR_OK)
565 return retval;
567 uint32_t *sysrq_buffer = NULL;
568 const int param_sz = 8;
569 int chip_prot = PSOC4_CHIP_PROT_OPEN;
570 int i, m, sect;
571 int num_bits = bank->num_sectors;
573 if (num_bits > PSOC4_ROWS_PER_MACRO)
574 num_bits = PSOC4_ROWS_PER_MACRO;
576 int prot_sz = num_bits / 8;
578 sysrq_buffer = malloc(param_sz + prot_sz);
579 if (sysrq_buffer == NULL) {
580 LOG_ERROR("no memory for row buffer");
581 return ERROR_FAIL;
584 for (i = first; i <= last && i < bank->num_sectors; i++)
585 bank->sectors[i].is_protected = set;
587 for (m = 0, sect = 0; m < psoc4_info->num_macros; m++) {
588 uint8_t *p = (uint8_t *)(sysrq_buffer + 2);
589 memset(p, 0, prot_sz);
590 for (i = 0; i < num_bits && sect < bank->num_sectors; i++, sect++) {
591 if (bank->sectors[sect].is_protected)
592 p[i/8] |= 1 << (i%8);
595 /* Call "Load Latch" system ROM API */
596 target_buffer_set_u32(target, (uint8_t *)(sysrq_buffer + 1),
597 prot_sz - 1);
598 retval = psoc4_sysreq(bank, PSOC4_CMD_LOAD_LATCH,
599 0 /* Byte number in latch from what to write */
600 | (m << 8), /* flash macro index */
601 sysrq_buffer, param_sz + prot_sz,
602 NULL);
603 if (retval != ERROR_OK)
604 break;
606 /* Call "Write Protection" system ROM API */
607 retval = psoc4_sysreq(bank, PSOC4_CMD_WRITE_PROTECTION,
608 chip_prot | (m << 8), NULL, 0, NULL);
609 if (retval != ERROR_OK)
610 break;
613 if (sysrq_buffer)
614 free(sysrq_buffer);
616 psoc4_protect_check(bank);
617 return retval;
621 COMMAND_HANDLER(psoc4_handle_flash_autoerase_command)
623 if (CMD_ARGC < 1)
624 return ERROR_COMMAND_SYNTAX_ERROR;
626 struct flash_bank *bank;
627 int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
628 if (ERROR_OK != retval)
629 return retval;
631 struct psoc4_flash_bank *psoc4_info = bank->driver_priv;
632 bool enable = psoc4_info->cmd_program_row == PSOC4_CMD_WRITE_ROW;
634 if (CMD_ARGC >= 2)
635 COMMAND_PARSE_ON_OFF(CMD_ARGV[1], enable);
637 if (enable) {
638 psoc4_info->cmd_program_row = PSOC4_CMD_WRITE_ROW;
639 LOG_INFO("Flash auto-erase enabled, non mass erase commands will be ignored.");
640 } else {
641 psoc4_info->cmd_program_row = PSOC4_CMD_PROGRAM_ROW;
642 LOG_INFO("Flash auto-erase disabled. Use psoc mass_erase before flash programming.");
645 return retval;
649 static int psoc4_write(struct flash_bank *bank, const uint8_t *buffer,
650 uint32_t offset, uint32_t count)
652 struct target *target = bank->target;
653 struct psoc4_flash_bank *psoc4_info = bank->driver_priv;
654 uint32_t *sysrq_buffer = NULL;
655 const int param_sz = 8;
657 int retval = psoc4_flash_prepare(bank);
658 if (retval != ERROR_OK)
659 return retval;
661 sysrq_buffer = malloc(param_sz + psoc4_info->row_size);
662 if (sysrq_buffer == NULL) {
663 LOG_ERROR("no memory for row buffer");
664 return ERROR_FAIL;
667 uint8_t *row_buffer = (uint8_t *)sysrq_buffer + param_sz;
668 uint32_t row_num = offset / psoc4_info->row_size;
669 uint32_t row_offset = offset - row_num * psoc4_info->row_size;
670 if (row_offset)
671 memset(row_buffer, bank->default_padded_value, row_offset);
673 bool save_poll = jtag_poll_get_enabled();
674 jtag_poll_set_enabled(false);
676 while (count) {
677 uint32_t chunk_size = psoc4_info->row_size - row_offset;
678 if (chunk_size > count) {
679 chunk_size = count;
680 memset(row_buffer + chunk_size, bank->default_padded_value, psoc4_info->row_size - chunk_size);
682 memcpy(row_buffer + row_offset, buffer, chunk_size);
683 LOG_DEBUG("offset / row: 0x%08" PRIx32 " / %" PRIu32 ", size %" PRIu32 "",
684 offset, row_offset, chunk_size);
686 uint32_t macro_idx = row_num / PSOC4_ROWS_PER_MACRO;
688 /* Call "Load Latch" system ROM API */
689 target_buffer_set_u32(target, (uint8_t *)(sysrq_buffer + 1),
690 psoc4_info->row_size - 1);
691 retval = psoc4_sysreq(bank, PSOC4_CMD_LOAD_LATCH,
692 0 /* Byte number in latch from what to write */
693 | (macro_idx << 8),
694 sysrq_buffer, param_sz + psoc4_info->row_size,
695 NULL);
696 if (retval != ERROR_OK)
697 goto cleanup;
699 /* Call "Program Row" or "Write Row" system ROM API */
700 uint32_t sysrq_param;
701 retval = psoc4_sysreq(bank, psoc4_info->cmd_program_row,
702 row_num & 0xffff,
703 &sysrq_param, sizeof(sysrq_param),
704 NULL);
705 if (retval != ERROR_OK)
706 goto cleanup;
708 buffer += chunk_size;
709 row_num++;
710 row_offset = 0;
711 count -= chunk_size;
714 cleanup:
715 jtag_poll_set_enabled(save_poll);
717 if (sysrq_buffer)
718 free(sysrq_buffer);
720 return retval;
724 /* Due to Cypress's method of market segmentation some devices
725 * have accessible only 1/2, 1/4 or 1/8 of SPCIF described flash */
726 static int psoc4_test_flash_wounding(struct target *target, uint32_t flash_size)
728 int retval, i;
729 for (i = 3; i >= 1; i--) {
730 uint32_t addr = flash_size >> i;
731 uint32_t dummy;
732 retval = target_read_u32(target, addr, &dummy);
733 if (retval != ERROR_OK)
734 return i;
736 return 0;
740 static int psoc4_probe(struct flash_bank *bank)
742 struct psoc4_flash_bank *psoc4_info = bank->driver_priv;
743 struct target *target = bank->target;
745 int retval;
746 uint16_t family_id;
748 psoc4_info->probed = false;
750 retval = psoc4_get_family(target, &family_id);
751 if (retval != ERROR_OK)
752 return retval;
754 const struct psoc4_chip_family *family = psoc4_family_by_id(family_id);
756 if (family->id == 0) {
757 LOG_ERROR("Cannot identify PSoC 4 family.");
758 return ERROR_FAIL;
761 if (family->flags & PSOC4_FAMILY_FLAG_LEGACY) {
762 LOG_INFO("%s legacy family detected.", family->name);
763 psoc4_info->legacy_family = true;
764 psoc4_info->cpuss_sysreq_addr = PSOC4_CPUSS_SYSREQ_LEGACY;
765 psoc4_info->cpuss_sysarg_addr = PSOC4_CPUSS_SYSARG_LEGACY;
766 psoc4_info->spcif_geometry_addr = PSOC4_SPCIF_GEOMETRY_LEGACY;
767 } else {
768 LOG_INFO("%s family detected.", family->name);
769 psoc4_info->legacy_family = false;
770 psoc4_info->cpuss_sysreq_addr = PSOC4_CPUSS_SYSREQ_NEW;
771 psoc4_info->cpuss_sysarg_addr = PSOC4_CPUSS_SYSARG_NEW;
772 psoc4_info->spcif_geometry_addr = PSOC4_SPCIF_GEOMETRY_NEW;
775 uint32_t spcif_geometry;
776 retval = target_read_u32(target, psoc4_info->spcif_geometry_addr, &spcif_geometry);
777 if (retval != ERROR_OK)
778 return retval;
780 uint32_t flash_size_in_kb = spcif_geometry & 0x3fff;
781 /* TRM of legacy, M and L version describes FLASH field as 16-bit.
782 * S-series and PSoC Analog Coprocessor changes spec to 14-bit only.
783 * Impose PSoC Analog Coprocessor limit to all devices as it
784 * does not make any harm: flash size is safely below 4 MByte limit
786 uint32_t row_size = (spcif_geometry >> 22) & 3;
787 uint32_t num_macros = (spcif_geometry >> 20) & 3;
789 if (psoc4_info->legacy_family) {
790 flash_size_in_kb = flash_size_in_kb * 256 / 1024;
791 row_size *= 128;
792 } else {
793 flash_size_in_kb = (flash_size_in_kb + 1) * 256 / 1024;
794 row_size = 64 * (row_size + 1);
795 num_macros++;
798 LOG_DEBUG("SPCIF geometry: %" PRIu32 " kb flash, row %" PRIu32 " bytes.",
799 flash_size_in_kb, row_size);
801 /* if the user sets the size manually then ignore the probed value
802 * this allows us to work around devices that have a invalid flash size register value */
803 if (psoc4_info->user_bank_size) {
804 LOG_INFO("ignoring flash probed value, using configured bank size");
805 flash_size_in_kb = psoc4_info->user_bank_size / 1024;
808 char macros_txt[20] = "";
809 if (num_macros > 1)
810 snprintf(macros_txt, sizeof(macros_txt), " in %" PRIu32 " macros", num_macros);
812 LOG_INFO("flash size = %" PRIu32 " kbytes%s", flash_size_in_kb, macros_txt);
814 /* calculate number of pages */
815 uint32_t num_rows = flash_size_in_kb * 1024 / row_size;
817 /* check number of flash macros */
818 if (num_macros != (num_rows + PSOC4_ROWS_PER_MACRO - 1) / PSOC4_ROWS_PER_MACRO)
819 LOG_WARNING("Number of macros does not correspond with flash size!");
821 if (!psoc4_info->legacy_family) {
822 int wounding = psoc4_test_flash_wounding(target, num_rows * row_size);
823 if (wounding > 0) {
824 flash_size_in_kb = flash_size_in_kb >> wounding;
825 num_rows = num_rows >> wounding;
826 LOG_INFO("WOUNDING detected: accessible flash size %" PRIu32 " kbytes", flash_size_in_kb);
830 if (bank->sectors) {
831 free(bank->sectors);
834 psoc4_info->family_id = family_id;
835 psoc4_info->num_macros = num_macros;
836 psoc4_info->row_size = row_size;
837 bank->base = 0x00000000;
838 bank->size = num_rows * row_size;
839 bank->num_sectors = num_rows;
840 bank->sectors = alloc_block_array(0, row_size, num_rows);
841 if (bank->sectors == NULL)
842 return ERROR_FAIL;
844 LOG_DEBUG("flash bank set %" PRIu32 " rows", num_rows);
845 psoc4_info->probed = true;
847 return ERROR_OK;
850 static int psoc4_auto_probe(struct flash_bank *bank)
852 struct psoc4_flash_bank *psoc4_info = bank->driver_priv;
853 if (psoc4_info->probed)
854 return ERROR_OK;
855 return psoc4_probe(bank);
859 static int get_psoc4_info(struct flash_bank *bank, char *buf, int buf_size)
861 struct target *target = bank->target;
862 struct psoc4_flash_bank *psoc4_info = bank->driver_priv;
864 if (!psoc4_info->probed)
865 return ERROR_FAIL;
867 const struct psoc4_chip_family *family = psoc4_family_by_id(psoc4_info->family_id);
868 uint32_t size_in_kb = bank->size / 1024;
870 if (target->state != TARGET_HALTED) {
871 snprintf(buf, buf_size, "%s, flash %" PRIu32 " kb"
872 " (halt target to see details)", family->name, size_in_kb);
873 return ERROR_OK;
876 int retval;
877 int printed = 0;
878 uint32_t silicon_id;
879 uint16_t family_id;
880 uint8_t protection;
882 retval = psoc4_get_silicon_id(bank, &silicon_id, &family_id, &protection);
883 if (retval != ERROR_OK)
884 return retval;
886 if (family_id != psoc4_info->family_id)
887 printed = snprintf(buf, buf_size, "Family id mismatch 0x%02" PRIx16
888 "/0x%02" PRIx16 ", silicon id 0x%08" PRIx32,
889 psoc4_info->family_id, family_id, silicon_id);
890 else {
891 printed = snprintf(buf, buf_size, "%s silicon id 0x%08" PRIx32 "",
892 family->name, silicon_id);
895 buf += printed;
896 buf_size -= printed;
898 const char *prot_txt = psoc4_decode_chip_protection(protection);
899 snprintf(buf, buf_size, ", flash %" PRIu32 " kb %s", size_in_kb, prot_txt);
900 return ERROR_OK;
904 COMMAND_HANDLER(psoc4_handle_mass_erase_command)
906 if (CMD_ARGC < 1)
907 return ERROR_COMMAND_SYNTAX_ERROR;
909 struct flash_bank *bank;
910 int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
911 if (ERROR_OK != retval)
912 return retval;
914 retval = psoc4_mass_erase(bank);
915 if (retval == ERROR_OK)
916 command_print(CMD, "psoc mass erase complete");
917 else
918 command_print(CMD, "psoc mass erase failed");
920 return retval;
924 static const struct command_registration psoc4_exec_command_handlers[] = {
926 .name = "mass_erase",
927 .handler = psoc4_handle_mass_erase_command,
928 .mode = COMMAND_EXEC,
929 .usage = "bank_id",
930 .help = "Erase entire flash device.",
933 .name = "flash_autoerase",
934 .handler = psoc4_handle_flash_autoerase_command,
935 .mode = COMMAND_EXEC,
936 .usage = "bank_id on|off",
937 .help = "Set autoerase mode for flash bank.",
939 COMMAND_REGISTRATION_DONE
942 static const struct command_registration psoc4_command_handlers[] = {
944 .name = "psoc4",
945 .mode = COMMAND_ANY,
946 .help = "PSoC 4 flash command group",
947 .usage = "",
948 .chain = psoc4_exec_command_handlers,
950 COMMAND_REGISTRATION_DONE
953 const struct flash_driver psoc4_flash = {
954 .name = "psoc4",
955 .commands = psoc4_command_handlers,
956 .flash_bank_command = psoc4_flash_bank_command,
957 .erase = psoc4_erase,
958 .protect = psoc4_protect,
959 .write = psoc4_write,
960 .read = default_flash_read,
961 .probe = psoc4_probe,
962 .auto_probe = psoc4_auto_probe,
963 .erase_check = default_flash_blank_check,
964 .protect_check = psoc4_protect_check,
965 .info = get_psoc4_info,
966 .free_driver_priv = default_flash_free_driver_priv,