target/xtensa: avoid IHI for writes to non-executable memory
[openocd.git] / src / flash / nor / psoc4.c
blob1064fa93d3e9197624b383adccd73405afd2a703
1 // SPDX-License-Identifier: GPL-2.0-or-later
3 /***************************************************************************
4 * Copyright (C) 2005 by Dominic Rath *
5 * Dominic.Rath@gmx.de *
6 * *
7 * Copyright (C) 2008 by Spencer Oliver *
8 * spen@spen-soft.co.uk *
9 * *
10 * Copyright (C) 2011 by Andreas Fritiofson *
11 * andreas.fritiofson@gmail.com *
12 * *
13 * Copyright (C) 2014 by Tomas Vanek (PSoC 4 support derived from STM32) *
14 * vanekt@fbl.cz *
15 ***************************************************************************/
17 #ifdef HAVE_CONFIG_H
18 #include "config.h"
19 #endif
21 #include "imp.h"
22 #include <helper/binarybuffer.h>
23 #include <jtag/jtag.h>
24 #include <target/algorithm.h>
25 #include <target/armv7m.h>
27 /* device documents:
29 PSoC(R) 4: PSoC 4200 Family Datasheet
30 Document Number: 001-87197 Rev. *B Revised August 29, 2013
32 PSoC 4100/4200 Family PSoC(R) 4 Architecture TRM
33 Document No. 001-85634 Rev. *E June 28, 2016
35 PSoC(R) 4 Registers TRM Spec.
36 Document No. 001-85847 Rev. *A June 25, 2013
38 PSoC 4000 Family PSoC(R) 4 Technical Reference Manual
39 Document No. 001-89309 Rev. *B May 9, 2016
41 PSoC 41XX_BLE/42XX_BLE Family PSoC 4 BLE Architecture TRM
42 Document No. 001-92738 Rev. *C February 12, 2016
44 PSoC 4200L Family PSoC 4 Architecture TRM
45 Document No. 001-97952 Rev. *A December 15, 2015
47 PSoC 4200L Family PSoC 4 Registers TRM
48 Document No. 001-98126 Rev. *A December 16, 2015
50 PSoC 4100M/4200M Family PSoC 4 Architecture TRM
51 Document No. 001-95223 Rev. *B July 29, 2015
53 PSoC 4100S Family PSoC 4 Architecture TRM
54 Document No. 002-10621 Rev. *A July 29, 2016
56 PSoC 4100S Family PSoC 4 Registers TRM
57 Document No. 002-10523 Rev. *A July 20, 2016
59 PSoC Analog Coprocessor Architecture TRM
60 Document No. 002-10404 Rev. ** December 18, 2015
62 CY8C4Axx PSoC Analog Coprocessor Registers TRM
63 Document No. 002-10405 Rev. ** December 18, 2015
65 CY8C41xx, CY8C42xx Programming Specifications
66 Document No. 001-81799 Rev. *C March 4, 2014
68 CYBL10x6x, CY8C4127_BL, CY8C4247_BL Programming Specifications
69 Document No. 001-91508 Rev. *B September 22, 2014
71 http://dmitry.gr/index.php?r=05.Projects&proj=24.%20PSoC4%20confidential
74 /* register locations */
75 #define PSOC4_SFLASH_MACRO0 0x0FFFF000
77 #define PSOC4_CPUSS_SYSREQ_LEGACY 0x40000004
78 #define PSOC4_CPUSS_SYSARG_LEGACY 0x40000008
79 #define PSOC4_SPCIF_GEOMETRY_LEGACY 0x400E0000
81 #define PSOC4_CPUSS_SYSREQ_NEW 0x40100004
82 #define PSOC4_CPUSS_SYSARG_NEW 0x40100008
83 #define PSOC4_SPCIF_GEOMETRY_NEW 0x40110000
85 #define PSOC4_TEST_MODE 0x40030014
87 #define PSOC4_ROMTABLE_PID0 0xF0000FE0
90 /* constants */
91 #define PSOC4_SFLASH_MACRO_SIZE 0x800
92 #define PSOC4_ROWS_PER_MACRO 512
94 #define PSOC4_SROM_KEY1 0xb6
95 #define PSOC4_SROM_KEY2 0xd3
96 #define PSOC4_SROM_SYSREQ_BIT (1<<31)
97 #define PSOC4_SROM_HMASTER_BIT (1<<30)
98 #define PSOC4_SROM_PRIVILEGED_BIT (1<<28)
99 #define PSOC4_SROM_STATUS_SUCCEEDED 0xa0000000
100 #define PSOC4_SROM_STATUS_FAILED 0xf0000000
101 #define PSOC4_SROM_STATUS_MASK 0xf0000000
103 /* not documented in any TRM */
104 #define PSOC4_SROM_ERR_IMO_NOT_IMPLEM 0xf0000013
106 #define PSOC4_CMD_GET_SILICON_ID 0
107 #define PSOC4_CMD_LOAD_LATCH 4
108 #define PSOC4_CMD_WRITE_ROW 5
109 #define PSOC4_CMD_PROGRAM_ROW 6
110 #define PSOC4_CMD_ERASE_ALL 0xa
111 #define PSOC4_CMD_CHECKSUM 0xb
112 #define PSOC4_CMD_WRITE_PROTECTION 0xd
113 #define PSOC4_CMD_SET_IMO48 0x15
114 #define PSOC4_CMD_WRITE_SFLASH_ROW 0x18
116 #define PSOC4_CHIP_PROT_VIRGIN 0x0
117 #define PSOC4_CHIP_PROT_OPEN 0x1
118 #define PSOC4_CHIP_PROT_PROTECTED 0x2
119 #define PSOC4_CHIP_PROT_KILL 0x4
121 #define PSOC4_ROMTABLE_DESIGNER_CHECK 0xb4
123 #define PSOC4_FAMILY_FLAG_LEGACY 1
125 struct psoc4_chip_family {
126 uint16_t id;
127 const char *name;
128 uint32_t flags;
131 static const struct psoc4_chip_family psoc4_families[] = {
132 { 0x93, "PSoC4100/4200", .flags = PSOC4_FAMILY_FLAG_LEGACY },
133 { 0x9A, "PSoC4000", .flags = 0 },
134 { 0x9E, "PSoC/PRoC BLE (119E)", .flags = 0 },
135 { 0xA0, "PSoC4200L", .flags = 0 },
136 { 0xA1, "PSoC4100M/4200M", .flags = 0 },
137 { 0xA3, "PSoC/PRoC BLE (11A3)", .flags = 0 },
138 { 0xA9, "PSoC4000S", .flags = 0 },
139 { 0xAA, "PSoC/PRoC BLE (11AA)", .flags = 0 },
140 { 0xAB, "PSoC4100S", .flags = 0 },
141 { 0xAC, "PSoC Analog Coprocessor", .flags = 0 },
142 { 0, "Unknown", .flags = 0 }
146 struct psoc4_flash_bank {
147 uint32_t row_size;
148 uint32_t user_bank_size;
149 unsigned int num_macros;
150 bool probed;
151 uint8_t cmd_program_row;
152 uint16_t family_id;
153 bool legacy_family;
154 uint32_t cpuss_sysreq_addr;
155 uint32_t cpuss_sysarg_addr;
156 uint32_t spcif_geometry_addr;
160 static const struct psoc4_chip_family *psoc4_family_by_id(uint16_t family_id)
162 const struct psoc4_chip_family *p = psoc4_families;
163 while (p->id && p->id != family_id)
164 p++;
166 return p;
169 static const char *psoc4_decode_chip_protection(uint8_t protection)
171 switch (protection) {
172 case PSOC4_CHIP_PROT_VIRGIN:
173 return "protection VIRGIN";
174 case PSOC4_CHIP_PROT_OPEN:
175 return "protection open";
176 case PSOC4_CHIP_PROT_PROTECTED:
177 return "PROTECTED";
178 case PSOC4_CHIP_PROT_KILL:
179 return "protection KILL";
180 default:
181 LOG_WARNING("Unknown protection state 0x%02" PRIx8 "", protection);
182 return "";
187 /* flash bank <name> psoc <base> <size> 0 0 <target#>
189 FLASH_BANK_COMMAND_HANDLER(psoc4_flash_bank_command)
191 struct psoc4_flash_bank *psoc4_info;
193 if (CMD_ARGC < 6)
194 return ERROR_COMMAND_SYNTAX_ERROR;
196 psoc4_info = calloc(1, sizeof(struct psoc4_flash_bank));
198 bank->driver_priv = psoc4_info;
199 bank->default_padded_value = bank->erased_value = 0x00;
200 psoc4_info->user_bank_size = bank->size;
201 psoc4_info->cmd_program_row = PSOC4_CMD_WRITE_ROW;
203 return ERROR_OK;
207 /* PSoC 4 system ROM request
208 * Setting SROM_SYSREQ_BIT in CPUSS_SYSREQ register runs NMI service
209 * in sysrem ROM. Algorithm just waits for NMI to finish.
210 * When sysreq_params_size == 0 only one parameter is passed in CPUSS_SYSARG register.
211 * Otherwise address of memory parameter block is set in CPUSS_SYSARG
212 * and the first parameter is written to the first word of parameter block
214 static int psoc4_sysreq(struct flash_bank *bank, uint8_t cmd,
215 uint16_t cmd_param,
216 uint32_t *sysreq_params, uint32_t sysreq_params_size,
217 uint32_t *sysarg_out)
219 struct target *target = bank->target;
220 struct psoc4_flash_bank *psoc4_info = bank->driver_priv;
222 struct working_area *sysreq_wait_algorithm;
223 struct working_area *sysreq_mem;
225 struct reg_param reg_params[1];
226 struct armv7m_algorithm armv7m_info;
228 int retval = ERROR_OK;
230 uint32_t param1 = PSOC4_SROM_KEY1
231 | ((PSOC4_SROM_KEY2 + cmd) << 8)
232 | (cmd_param << 16);
234 static uint8_t psoc4_sysreq_wait_code[] = {
235 /* system request NMI is served immediately after algo run
236 now we are done: break */
237 0x00, 0xbe, /* bkpt 0 */
240 const int code_words = (sizeof(psoc4_sysreq_wait_code) + 3) / 4;
241 /* stack must be aligned */
242 const int stack_size = 256;
243 /* tested stack sizes on PSoC4200:
244 ERASE_ALL 144
245 PROGRAM_ROW 112
246 other sysreq 68
249 /* allocate area for sysreq wait code and stack */
250 if (target_alloc_working_area(target, code_words * 4 + stack_size,
251 &sysreq_wait_algorithm) != ERROR_OK) {
252 LOG_DEBUG("no working area for sysreq code");
253 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
256 /* Write the code */
257 retval = target_write_buffer(target,
258 sysreq_wait_algorithm->address,
259 sizeof(psoc4_sysreq_wait_code),
260 psoc4_sysreq_wait_code);
261 if (retval != ERROR_OK) {
262 /* we already allocated the writing code, but failed to get a
263 * buffer, free the algorithm */
264 goto cleanup_algo;
267 if (sysreq_params_size) {
268 LOG_DEBUG("SYSREQ %02" PRIx8 " %04" PRIx16 " %08" PRIx32 " size %" PRIu32,
269 cmd, cmd_param, param1, sysreq_params_size);
270 /* Allocate memory for sysreq_params */
271 retval = target_alloc_working_area(target, sysreq_params_size, &sysreq_mem);
272 if (retval != ERROR_OK) {
273 LOG_WARNING("no working area for sysreq parameters");
275 /* we already allocated the writing code, but failed to get a
276 * buffer, free the algorithm */
277 retval = ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
278 goto cleanup_algo;
281 /* Write sysreq_params */
282 target_buffer_set_u32(target, (uint8_t *)sysreq_params, param1);
283 retval = target_write_buffer(target, sysreq_mem->address,
284 sysreq_params_size, (uint8_t *)sysreq_params);
285 if (retval != ERROR_OK)
286 goto cleanup_mem;
288 /* Set address of sysreq parameters block */
289 retval = target_write_u32(target, psoc4_info->cpuss_sysarg_addr, sysreq_mem->address);
290 if (retval != ERROR_OK)
291 goto cleanup_mem;
293 } else {
294 /* Sysreq without memory block of parameters */
295 LOG_DEBUG("SYSREQ %02" PRIx8 " %04" PRIx16 " %08" PRIx32,
296 cmd, cmd_param, param1);
297 /* Set register parameter */
298 retval = target_write_u32(target, psoc4_info->cpuss_sysarg_addr, param1);
299 if (retval != ERROR_OK)
300 goto cleanup_mem;
303 armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
304 armv7m_info.core_mode = ARM_MODE_THREAD;
306 /* sysreq stack */
307 init_reg_param(&reg_params[0], "sp", 32, PARAM_OUT);
308 buf_set_u32(reg_params[0].value, 0, 32,
309 sysreq_wait_algorithm->address + sysreq_wait_algorithm->size);
311 struct armv7m_common *armv7m = target_to_armv7m(target);
312 if (!armv7m) {
313 /* something is very wrong if armv7m is NULL */
314 LOG_ERROR("unable to get armv7m target");
315 retval = ERROR_FAIL;
316 goto cleanup;
319 /* Set SROM request */
320 retval = target_write_u32(target, psoc4_info->cpuss_sysreq_addr,
321 PSOC4_SROM_SYSREQ_BIT | PSOC4_SROM_HMASTER_BIT | cmd);
322 if (retval != ERROR_OK)
323 goto cleanup;
325 /* Execute wait code */
326 retval = target_run_algorithm(target, 0, NULL,
327 ARRAY_SIZE(reg_params), reg_params,
328 sysreq_wait_algorithm->address, 0, 1000, &armv7m_info);
329 if (retval != ERROR_OK) {
330 LOG_ERROR("sysreq wait code execution failed");
331 goto cleanup;
334 uint32_t sysarg_out_tmp;
335 retval = target_read_u32(target, psoc4_info->cpuss_sysarg_addr, &sysarg_out_tmp);
336 if (retval != ERROR_OK)
337 goto cleanup;
339 if (sysarg_out) {
340 *sysarg_out = sysarg_out_tmp;
341 /* If result is an error, do not show now, let caller to decide */
342 } else if ((sysarg_out_tmp & PSOC4_SROM_STATUS_MASK) != PSOC4_SROM_STATUS_SUCCEEDED) {
343 LOG_ERROR("sysreq error 0x%" PRIx32, sysarg_out_tmp);
344 retval = ERROR_FAIL;
346 cleanup:
347 destroy_reg_param(&reg_params[0]);
349 cleanup_mem:
350 if (sysreq_params_size)
351 target_free_working_area(target, sysreq_mem);
353 cleanup_algo:
354 target_free_working_area(target, sysreq_wait_algorithm);
356 return retval;
360 /* helper routine to get silicon ID from a PSoC 4 chip */
361 static int psoc4_get_silicon_id(struct flash_bank *bank, uint32_t *silicon_id, uint16_t *family_id, uint8_t *protection)
363 struct target *target = bank->target;
364 struct psoc4_flash_bank *psoc4_info = bank->driver_priv;
366 uint32_t part0, part1;
368 int retval = psoc4_sysreq(bank, PSOC4_CMD_GET_SILICON_ID, 0, NULL, 0, &part0);
369 if (retval != ERROR_OK)
370 return retval;
372 if ((part0 & PSOC4_SROM_STATUS_MASK) != PSOC4_SROM_STATUS_SUCCEEDED) {
373 LOG_ERROR("sysreq error 0x%" PRIx32, part0);
374 return ERROR_FAIL;
377 retval = target_read_u32(target, psoc4_info->cpuss_sysreq_addr, &part1);
378 if (retval != ERROR_OK)
379 return retval;
381 /* build ID as Cypress sw does:
382 * bit 31..16 silicon ID
383 * bit 15..8 revision ID (so far 0x11 for all devices)
384 * bit 7..0 family ID (lowest 8 bits)
386 if (silicon_id)
387 *silicon_id = ((part0 & 0x0000ffff) << 16)
388 | ((part0 & 0x00ff0000) >> 8)
389 | (part1 & 0x000000ff);
391 if (family_id)
392 *family_id = part1 & 0x0fff;
394 if (protection)
395 *protection = (part1 >> 12) & 0x0f;
397 return ERROR_OK;
401 static int psoc4_get_family(struct target *target, uint16_t *family_id)
403 int retval, i;
404 uint32_t pidbf[3];
405 uint8_t pid[3];
407 retval = target_read_memory(target, PSOC4_ROMTABLE_PID0, 4, 3, (uint8_t *)pidbf);
408 if (retval != ERROR_OK)
409 return retval;
411 for (i = 0; i < 3; i++) {
412 uint32_t tmp = target_buffer_get_u32(target, (uint8_t *)(pidbf + i));
413 if (tmp & 0xffffff00) {
414 LOG_ERROR("Unexpected data in ROMTABLE");
415 return ERROR_FAIL;
417 pid[i] = tmp & 0xff;
420 uint16_t family = pid[0] | ((pid[1] & 0xf) << 8);
421 uint32_t designer = ((pid[1] & 0xf0) >> 4) | ((pid[2] & 0xf) << 4);
423 if (designer != PSOC4_ROMTABLE_DESIGNER_CHECK) {
424 LOG_ERROR("ROMTABLE designer is not Cypress");
425 return ERROR_FAIL;
428 *family_id = family;
429 return ERROR_OK;
433 static int psoc4_flash_prepare(struct flash_bank *bank)
435 struct target *target = bank->target;
436 struct psoc4_flash_bank *psoc4_info = bank->driver_priv;
438 if (target->state != TARGET_HALTED) {
439 LOG_ERROR("Target not halted");
440 return ERROR_TARGET_NOT_HALTED;
443 uint16_t family_id;
444 int retval;
446 /* get family ID from SROM call */
447 retval = psoc4_get_silicon_id(bank, NULL, &family_id, NULL);
448 if (retval != ERROR_OK)
449 return retval;
451 /* and check with family ID from ROMTABLE */
452 if (family_id != psoc4_info->family_id) {
453 LOG_ERROR("Family mismatch");
454 return ERROR_FAIL;
457 if (!psoc4_info->legacy_family) {
458 uint32_t sysreq_status;
459 retval = psoc4_sysreq(bank, PSOC4_CMD_SET_IMO48, 0, NULL, 0, &sysreq_status);
460 if (retval != ERROR_OK)
461 return retval;
463 if ((sysreq_status & PSOC4_SROM_STATUS_MASK) != PSOC4_SROM_STATUS_SUCCEEDED) {
464 /* This undocumented error code is returned probably when
465 * PSOC4_CMD_SET_IMO48 command is not implemented.
466 * Can be safely ignored, programming works.
468 if (sysreq_status == PSOC4_SROM_ERR_IMO_NOT_IMPLEM)
469 LOG_INFO("PSOC4_CMD_SET_IMO48 is not implemented on this device.");
470 else {
471 LOG_ERROR("sysreq error 0x%" PRIx32, sysreq_status);
472 return ERROR_FAIL;
477 return ERROR_OK;
481 static int psoc4_protect_check(struct flash_bank *bank)
483 struct target *target = bank->target;
484 struct psoc4_flash_bank *psoc4_info = bank->driver_priv;
486 uint32_t prot_addr = PSOC4_SFLASH_MACRO0;
487 int retval;
488 uint8_t bf[PSOC4_ROWS_PER_MACRO/8];
489 unsigned int s = 0;
491 for (unsigned int m = 0; m < psoc4_info->num_macros; m++, prot_addr += PSOC4_SFLASH_MACRO_SIZE) {
492 retval = target_read_memory(target, prot_addr, 4, PSOC4_ROWS_PER_MACRO/32, bf);
493 if (retval != ERROR_OK)
494 return retval;
496 for (unsigned int i = 0; i < PSOC4_ROWS_PER_MACRO && s < bank->num_sectors; i++, s++)
497 bank->sectors[s].is_protected = bf[i/8] & (1 << (i%8)) ? 1 : 0;
500 return ERROR_OK;
504 static int psoc4_mass_erase(struct flash_bank *bank)
506 int retval = psoc4_flash_prepare(bank);
507 if (retval != ERROR_OK)
508 return retval;
510 /* Call "Erase All" system ROM API */
511 uint32_t param = 0;
512 return psoc4_sysreq(bank, PSOC4_CMD_ERASE_ALL,
514 &param, sizeof(param), NULL);
518 static int psoc4_erase(struct flash_bank *bank, unsigned int first,
519 unsigned int last)
521 struct psoc4_flash_bank *psoc4_info = bank->driver_priv;
522 if (psoc4_info->cmd_program_row == PSOC4_CMD_WRITE_ROW) {
523 LOG_INFO("Autoerase enabled, erase command ignored");
524 return ERROR_OK;
527 if ((first == 0) && (last == (bank->num_sectors - 1)))
528 return psoc4_mass_erase(bank);
530 LOG_ERROR("Only mass erase available! Consider using 'psoc4 flash_autoerase 0 on'");
532 return ERROR_FAIL;
536 static int psoc4_protect(struct flash_bank *bank, int set, unsigned int first,
537 unsigned int last)
539 struct target *target = bank->target;
540 struct psoc4_flash_bank *psoc4_info = bank->driver_priv;
542 if (!psoc4_info->probed)
543 return ERROR_FAIL;
545 int retval = psoc4_flash_prepare(bank);
546 if (retval != ERROR_OK)
547 return retval;
549 uint32_t *sysrq_buffer = NULL;
550 const int param_sz = 8;
551 int chip_prot = PSOC4_CHIP_PROT_OPEN;
552 unsigned int i;
553 unsigned int num_bits = bank->num_sectors;
555 if (num_bits > PSOC4_ROWS_PER_MACRO)
556 num_bits = PSOC4_ROWS_PER_MACRO;
558 int prot_sz = num_bits / 8;
560 sysrq_buffer = malloc(param_sz + prot_sz);
561 if (!sysrq_buffer) {
562 LOG_ERROR("no memory for row buffer");
563 return ERROR_FAIL;
566 for (i = first; i <= last && i < bank->num_sectors; i++)
567 bank->sectors[i].is_protected = set;
569 for (unsigned int m = 0, sect = 0; m < psoc4_info->num_macros; m++) {
570 uint8_t *p = (uint8_t *)(sysrq_buffer + 2);
571 memset(p, 0, prot_sz);
572 for (i = 0; i < num_bits && sect < bank->num_sectors; i++, sect++) {
573 if (bank->sectors[sect].is_protected)
574 p[i/8] |= 1 << (i%8);
577 /* Call "Load Latch" system ROM API */
578 target_buffer_set_u32(target, (uint8_t *)(sysrq_buffer + 1),
579 prot_sz - 1);
580 retval = psoc4_sysreq(bank, PSOC4_CMD_LOAD_LATCH,
581 0 /* Byte number in latch from what to write */
582 | (m << 8), /* flash macro index */
583 sysrq_buffer, param_sz + prot_sz,
584 NULL);
585 if (retval != ERROR_OK)
586 break;
588 /* Call "Write Protection" system ROM API */
589 retval = psoc4_sysreq(bank, PSOC4_CMD_WRITE_PROTECTION,
590 chip_prot | (m << 8), NULL, 0, NULL);
591 if (retval != ERROR_OK)
592 break;
595 free(sysrq_buffer);
597 psoc4_protect_check(bank);
598 return retval;
602 COMMAND_HANDLER(psoc4_handle_flash_autoerase_command)
604 if (CMD_ARGC < 1)
605 return ERROR_COMMAND_SYNTAX_ERROR;
607 struct flash_bank *bank;
608 int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
609 if (retval != ERROR_OK)
610 return retval;
612 struct psoc4_flash_bank *psoc4_info = bank->driver_priv;
613 bool enable = psoc4_info->cmd_program_row == PSOC4_CMD_WRITE_ROW;
615 if (CMD_ARGC >= 2)
616 COMMAND_PARSE_ON_OFF(CMD_ARGV[1], enable);
618 if (enable) {
619 psoc4_info->cmd_program_row = PSOC4_CMD_WRITE_ROW;
620 LOG_INFO("Flash auto-erase enabled, non mass erase commands will be ignored.");
621 } else {
622 psoc4_info->cmd_program_row = PSOC4_CMD_PROGRAM_ROW;
623 LOG_INFO("Flash auto-erase disabled. Use psoc mass_erase before flash programming.");
626 return retval;
630 static int psoc4_write(struct flash_bank *bank, const uint8_t *buffer,
631 uint32_t offset, uint32_t count)
633 struct target *target = bank->target;
634 struct psoc4_flash_bank *psoc4_info = bank->driver_priv;
635 uint32_t *sysrq_buffer = NULL;
636 const int param_sz = 8;
638 int retval = psoc4_flash_prepare(bank);
639 if (retval != ERROR_OK)
640 return retval;
642 sysrq_buffer = malloc(param_sz + psoc4_info->row_size);
643 if (!sysrq_buffer) {
644 LOG_ERROR("no memory for row buffer");
645 return ERROR_FAIL;
648 uint8_t *row_buffer = (uint8_t *)sysrq_buffer + param_sz;
649 uint32_t row_num = offset / psoc4_info->row_size;
650 uint32_t row_offset = offset - row_num * psoc4_info->row_size;
651 if (row_offset)
652 memset(row_buffer, bank->default_padded_value, row_offset);
654 while (count) {
655 uint32_t chunk_size = psoc4_info->row_size - row_offset;
656 if (chunk_size > count) {
657 chunk_size = count;
658 memset(row_buffer + chunk_size, bank->default_padded_value, psoc4_info->row_size - chunk_size);
660 memcpy(row_buffer + row_offset, buffer, chunk_size);
661 LOG_DEBUG("offset / row: 0x%08" PRIx32 " / %" PRIu32 ", size %" PRIu32 "",
662 offset, row_offset, chunk_size);
664 uint32_t macro_idx = row_num / PSOC4_ROWS_PER_MACRO;
666 /* Call "Load Latch" system ROM API */
667 target_buffer_set_u32(target, (uint8_t *)(sysrq_buffer + 1),
668 psoc4_info->row_size - 1);
669 retval = psoc4_sysreq(bank, PSOC4_CMD_LOAD_LATCH,
670 0 /* Byte number in latch from what to write */
671 | (macro_idx << 8),
672 sysrq_buffer, param_sz + psoc4_info->row_size,
673 NULL);
674 if (retval != ERROR_OK)
675 goto cleanup;
677 /* Call "Program Row" or "Write Row" system ROM API */
678 uint32_t sysrq_param;
679 retval = psoc4_sysreq(bank, psoc4_info->cmd_program_row,
680 row_num & 0xffff,
681 &sysrq_param, sizeof(sysrq_param),
682 NULL);
683 if (retval != ERROR_OK)
684 goto cleanup;
686 buffer += chunk_size;
687 row_num++;
688 row_offset = 0;
689 count -= chunk_size;
692 cleanup:
693 free(sysrq_buffer);
694 return retval;
698 /* Due to Cypress's method of market segmentation some devices
699 * have accessible only 1/2, 1/4 or 1/8 of SPCIF described flash */
700 static int psoc4_test_flash_wounding(struct target *target, uint32_t flash_size)
702 int retval, i;
703 for (i = 3; i >= 1; i--) {
704 uint32_t addr = flash_size >> i;
705 uint32_t dummy;
706 retval = target_read_u32(target, addr, &dummy);
707 if (retval != ERROR_OK)
708 return i;
710 return 0;
714 static int psoc4_probe(struct flash_bank *bank)
716 struct psoc4_flash_bank *psoc4_info = bank->driver_priv;
717 struct target *target = bank->target;
719 int retval;
720 uint16_t family_id;
722 psoc4_info->probed = false;
724 retval = psoc4_get_family(target, &family_id);
725 if (retval != ERROR_OK)
726 return retval;
728 const struct psoc4_chip_family *family = psoc4_family_by_id(family_id);
730 if (family->id == 0) {
731 LOG_ERROR("Cannot identify PSoC 4 family.");
732 return ERROR_FAIL;
735 if (family->flags & PSOC4_FAMILY_FLAG_LEGACY) {
736 LOG_INFO("%s legacy family detected.", family->name);
737 psoc4_info->legacy_family = true;
738 psoc4_info->cpuss_sysreq_addr = PSOC4_CPUSS_SYSREQ_LEGACY;
739 psoc4_info->cpuss_sysarg_addr = PSOC4_CPUSS_SYSARG_LEGACY;
740 psoc4_info->spcif_geometry_addr = PSOC4_SPCIF_GEOMETRY_LEGACY;
741 } else {
742 LOG_INFO("%s family detected.", family->name);
743 psoc4_info->legacy_family = false;
744 psoc4_info->cpuss_sysreq_addr = PSOC4_CPUSS_SYSREQ_NEW;
745 psoc4_info->cpuss_sysarg_addr = PSOC4_CPUSS_SYSARG_NEW;
746 psoc4_info->spcif_geometry_addr = PSOC4_SPCIF_GEOMETRY_NEW;
749 uint32_t spcif_geometry;
750 retval = target_read_u32(target, psoc4_info->spcif_geometry_addr, &spcif_geometry);
751 if (retval != ERROR_OK)
752 return retval;
754 uint32_t flash_size_in_kb = spcif_geometry & 0x3fff;
755 /* TRM of legacy, M and L version describes FLASH field as 16-bit.
756 * S-series and PSoC Analog Coprocessor changes spec to 14-bit only.
757 * Impose PSoC Analog Coprocessor limit to all devices as it
758 * does not make any harm: flash size is safely below 4 MByte limit
760 uint32_t row_size = (spcif_geometry >> 22) & 3;
761 uint32_t num_macros = (spcif_geometry >> 20) & 3;
763 if (psoc4_info->legacy_family) {
764 flash_size_in_kb = flash_size_in_kb * 256 / 1024;
765 row_size *= 128;
766 } else {
767 flash_size_in_kb = (flash_size_in_kb + 1) * 256 / 1024;
768 row_size = 64 * (row_size + 1);
769 num_macros++;
772 LOG_DEBUG("SPCIF geometry: %" PRIu32 " KiB flash, row %" PRIu32 " bytes.",
773 flash_size_in_kb, row_size);
775 /* if the user sets the size manually then ignore the probed value
776 * this allows us to work around devices that have a invalid flash size register value */
777 if (psoc4_info->user_bank_size) {
778 LOG_INFO("ignoring flash probed value, using configured bank size");
779 flash_size_in_kb = psoc4_info->user_bank_size / 1024;
782 char macros_txt[22] = "";
783 if (num_macros > 1)
784 snprintf(macros_txt, sizeof(macros_txt), " in %" PRIu32 " macros", num_macros);
786 LOG_INFO("flash size = %" PRIu32 " KiB%s", flash_size_in_kb, macros_txt);
788 /* calculate number of pages */
789 uint32_t num_rows = flash_size_in_kb * 1024 / row_size;
791 /* check number of flash macros */
792 if (num_macros != (num_rows + PSOC4_ROWS_PER_MACRO - 1) / PSOC4_ROWS_PER_MACRO)
793 LOG_WARNING("Number of macros does not correspond with flash size!");
795 if (!psoc4_info->legacy_family) {
796 int wounding = psoc4_test_flash_wounding(target, num_rows * row_size);
797 if (wounding > 0) {
798 flash_size_in_kb = flash_size_in_kb >> wounding;
799 num_rows = num_rows >> wounding;
800 LOG_INFO("WOUNDING detected: accessible flash size %" PRIu32 " kbytes", flash_size_in_kb);
804 free(bank->sectors);
806 psoc4_info->family_id = family_id;
807 psoc4_info->num_macros = num_macros;
808 psoc4_info->row_size = row_size;
809 bank->base = 0x00000000;
810 bank->size = num_rows * row_size;
811 bank->num_sectors = num_rows;
812 bank->sectors = alloc_block_array(0, row_size, num_rows);
813 if (!bank->sectors)
814 return ERROR_FAIL;
816 LOG_DEBUG("flash bank set %" PRIu32 " rows", num_rows);
817 psoc4_info->probed = true;
819 return ERROR_OK;
822 static int psoc4_auto_probe(struct flash_bank *bank)
824 struct psoc4_flash_bank *psoc4_info = bank->driver_priv;
825 if (psoc4_info->probed)
826 return ERROR_OK;
827 return psoc4_probe(bank);
831 static int get_psoc4_info(struct flash_bank *bank, struct command_invocation *cmd)
833 struct target *target = bank->target;
834 struct psoc4_flash_bank *psoc4_info = bank->driver_priv;
836 if (!psoc4_info->probed)
837 return ERROR_FAIL;
839 const struct psoc4_chip_family *family = psoc4_family_by_id(psoc4_info->family_id);
840 uint32_t size_in_kb = bank->size / 1024;
842 if (target->state != TARGET_HALTED) {
843 command_print_sameline(cmd, "%s, flash %" PRIu32 " kb"
844 " (halt target to see details)", family->name, size_in_kb);
845 return ERROR_OK;
848 uint32_t silicon_id;
849 uint16_t family_id;
850 uint8_t protection;
852 int retval = psoc4_get_silicon_id(bank, &silicon_id, &family_id, &protection);
853 if (retval != ERROR_OK)
854 return retval;
856 if (family_id != psoc4_info->family_id)
857 command_print_sameline(cmd, "Family id mismatch 0x%02" PRIx16
858 "/0x%02" PRIx16 ", silicon id 0x%08" PRIx32,
859 psoc4_info->family_id, family_id, silicon_id);
860 else {
861 command_print_sameline(cmd, "%s silicon id 0x%08" PRIx32 "",
862 family->name, silicon_id);
865 const char *prot_txt = psoc4_decode_chip_protection(protection);
866 command_print_sameline(cmd, ", flash %" PRIu32 " kb %s", size_in_kb, prot_txt);
867 return ERROR_OK;
871 COMMAND_HANDLER(psoc4_handle_mass_erase_command)
873 if (CMD_ARGC < 1)
874 return ERROR_COMMAND_SYNTAX_ERROR;
876 struct flash_bank *bank;
877 int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
878 if (retval != ERROR_OK)
879 return retval;
881 retval = psoc4_mass_erase(bank);
882 if (retval == ERROR_OK)
883 command_print(CMD, "psoc mass erase complete");
884 else
885 command_print(CMD, "psoc mass erase failed");
887 return retval;
891 static const struct command_registration psoc4_exec_command_handlers[] = {
893 .name = "mass_erase",
894 .handler = psoc4_handle_mass_erase_command,
895 .mode = COMMAND_EXEC,
896 .usage = "bank_id",
897 .help = "Erase entire flash device.",
900 .name = "flash_autoerase",
901 .handler = psoc4_handle_flash_autoerase_command,
902 .mode = COMMAND_EXEC,
903 .usage = "bank_id on|off",
904 .help = "Set autoerase mode for flash bank.",
906 COMMAND_REGISTRATION_DONE
909 static const struct command_registration psoc4_command_handlers[] = {
911 .name = "psoc4",
912 .mode = COMMAND_ANY,
913 .help = "PSoC 4 flash command group",
914 .usage = "",
915 .chain = psoc4_exec_command_handlers,
917 COMMAND_REGISTRATION_DONE
920 const struct flash_driver psoc4_flash = {
921 .name = "psoc4",
922 .commands = psoc4_command_handlers,
923 .flash_bank_command = psoc4_flash_bank_command,
924 .erase = psoc4_erase,
925 .protect = psoc4_protect,
926 .write = psoc4_write,
927 .read = default_flash_read,
928 .probe = psoc4_probe,
929 .auto_probe = psoc4_auto_probe,
930 .erase_check = default_flash_blank_check,
931 .protect_check = psoc4_protect_check,
932 .info = get_psoc4_info,
933 .free_driver_priv = default_flash_free_driver_priv,