openocd: fix simple cases of NULL comparison
[fw/openocd] / 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 documents:
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. *E June 28, 2016
45
46  PSoC(R) 4 Registers TRM Spec.
47         Document No. 001-85847 Rev. *A June 25, 2013
48
49  PSoC 4000 Family PSoC(R) 4 Technical Reference Manual
50         Document No. 001-89309 Rev. *B May 9, 2016
51
52  PSoC 41XX_BLE/42XX_BLE Family PSoC 4 BLE Architecture TRM
53         Document No. 001-92738 Rev. *C February 12, 2016
54
55  PSoC 4200L Family PSoC 4 Architecture TRM
56         Document No. 001-97952 Rev. *A December 15, 2015
57
58  PSoC 4200L Family PSoC 4 Registers TRM
59         Document No. 001-98126 Rev. *A December 16, 2015
60
61  PSoC 4100M/4200M Family PSoC 4 Architecture TRM
62         Document No. 001-95223 Rev. *B July 29, 2015
63
64  PSoC 4100S Family PSoC 4 Architecture TRM
65         Document No. 002-10621 Rev. *A July 29, 2016
66
67  PSoC 4100S Family PSoC 4 Registers TRM
68         Document No. 002-10523 Rev. *A July 20, 2016
69
70  PSoC Analog Coprocessor Architecture TRM
71         Document No. 002-10404 Rev. ** December 18, 2015
72
73  CY8C4Axx PSoC Analog Coprocessor Registers TRM
74         Document No. 002-10405 Rev. ** December 18, 2015
75
76  CY8C41xx, CY8C42xx Programming Specifications
77         Document No. 001-81799 Rev. *C March 4, 2014
78
79  CYBL10x6x, CY8C4127_BL, CY8C4247_BL Programming Specifications
80         Document No. 001-91508 Rev. *B September 22, 2014
81
82  http://dmitry.gr/index.php?r=05.Projects&proj=24.%20PSoC4%20confidential
83 */
84
85 /* register locations */
86 #define PSOC4_SFLASH_MACRO0             0x0FFFF000
87
88 #define PSOC4_CPUSS_SYSREQ_LEGACY       0x40000004
89 #define PSOC4_CPUSS_SYSARG_LEGACY       0x40000008
90 #define PSOC4_SPCIF_GEOMETRY_LEGACY     0x400E0000
91
92 #define PSOC4_CPUSS_SYSREQ_NEW          0x40100004
93 #define PSOC4_CPUSS_SYSARG_NEW          0x40100008
94 #define PSOC4_SPCIF_GEOMETRY_NEW        0x40110000
95
96 #define PSOC4_TEST_MODE                 0x40030014
97
98 #define PSOC4_ROMTABLE_PID0             0xF0000FE0
99
100
101 /* constants */
102 #define PSOC4_SFLASH_MACRO_SIZE         0x800
103 #define PSOC4_ROWS_PER_MACRO            512
104
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
113
114 /* not documented in any TRM */
115 #define PSOC4_SROM_ERR_IMO_NOT_IMPLEM   0xf0000013
116
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
126
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
131
132 #define PSOC4_ROMTABLE_DESIGNER_CHECK   0xb4
133
134 #define PSOC4_FAMILY_FLAG_LEGACY        1
135
136 struct psoc4_chip_family {
137         uint16_t id;
138         const char *name;
139         uint32_t flags;
140 };
141
142 static 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 }
154 };
155
156
157 struct psoc4_flash_bank {
158         uint32_t row_size;
159         uint32_t user_bank_size;
160         unsigned 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;
168 };
169
170
171 static const struct psoc4_chip_family *psoc4_family_by_id(uint16_t family_id)
172 {
173         const struct psoc4_chip_family *p = psoc4_families;
174         while (p->id && p->id != family_id)
175                 p++;
176
177         return p;
178 }
179
180 static const char *psoc4_decode_chip_protection(uint8_t protection)
181 {
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 "";
194         }
195 }
196
197
198 /* flash bank <name> psoc <base> <size> 0 0 <target#>
199  */
200 FLASH_BANK_COMMAND_HANDLER(psoc4_flash_bank_command)
201 {
202         struct psoc4_flash_bank *psoc4_info;
203
204         if (CMD_ARGC < 6)
205                 return ERROR_COMMAND_SYNTAX_ERROR;
206
207         psoc4_info = calloc(1, sizeof(struct psoc4_flash_bank));
208
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;
213
214         return ERROR_OK;
215 }
216
217
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
224  */
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)
229 {
230         struct target *target = bank->target;
231         struct psoc4_flash_bank *psoc4_info = bank->driver_priv;
232
233         struct working_area *sysreq_wait_algorithm;
234         struct working_area *sysreq_mem;
235
236         struct reg_param reg_params[1];
237         struct armv7m_algorithm armv7m_info;
238
239         int retval = ERROR_OK;
240
241         uint32_t param1 = PSOC4_SROM_KEY1
242                          | ((PSOC4_SROM_KEY2 + cmd) << 8)
243                          | (cmd_param << 16);
244
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 */
249         };
250
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
258         */
259
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;
265         }
266
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;
276         }
277
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");
285
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;
290                 }
291
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;
298
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;
303
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;
312         }
313
314         armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
315         armv7m_info.core_mode = ARM_MODE_THREAD;
316
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);
321
322         struct armv7m_common *armv7m = target_to_armv7m(target);
323         if (!armv7m) {
324                 /* something is very wrong if armv7m is NULL */
325                 LOG_ERROR("unable to get armv7m target");
326                 retval = ERROR_FAIL;
327                 goto cleanup;
328         }
329
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;
335
336         /* Execute wait code */
337         retval = target_run_algorithm(target, 0, NULL,
338                                 ARRAY_SIZE(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;
343         }
344
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;
349
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;
356         }
357 cleanup:
358         destroy_reg_param(&reg_params[0]);
359
360 cleanup_mem:
361         if (sysreq_params_size)
362                 target_free_working_area(target, sysreq_mem);
363
364 cleanup_algo:
365         target_free_working_area(target, sysreq_wait_algorithm);
366
367         return retval;
368 }
369
370
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)
373 {
374         struct target *target = bank->target;
375         struct psoc4_flash_bank *psoc4_info = bank->driver_priv;
376
377         uint32_t part0, part1;
378
379         int retval = psoc4_sysreq(bank, PSOC4_CMD_GET_SILICON_ID, 0, NULL, 0, &part0);
380         if (retval != ERROR_OK)
381                 return retval;
382
383         if ((part0 & PSOC4_SROM_STATUS_MASK) != PSOC4_SROM_STATUS_SUCCEEDED) {
384                 LOG_ERROR("sysreq error 0x%" PRIx32, part0);
385                 return ERROR_FAIL;
386         }
387
388         retval = target_read_u32(target, psoc4_info->cpuss_sysreq_addr, &part1);
389         if (retval != ERROR_OK)
390                 return retval;
391
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 (lowest 8 bits)
396          */
397         if (silicon_id)
398                         *silicon_id = ((part0 & 0x0000ffff) << 16)
399                                     | ((part0 & 0x00ff0000) >> 8)
400                                     | (part1 & 0x000000ff);
401
402         if (family_id)
403                         *family_id = part1 & 0x0fff;
404
405         if (protection)
406                         *protection = (part1 >> 12) & 0x0f;
407
408         return ERROR_OK;
409 }
410
411
412 static int psoc4_get_family(struct target *target, uint16_t *family_id)
413 {
414         int retval, i;
415         uint32_t pidbf[3];
416         uint8_t pid[3];
417
418         retval = target_read_memory(target, PSOC4_ROMTABLE_PID0, 4, 3, (uint8_t *)pidbf);
419         if (retval != ERROR_OK)
420                 return retval;
421
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;
427                 }
428                 pid[i] = tmp & 0xff;
429         }
430
431         uint16_t family = pid[0] | ((pid[1] & 0xf) << 8);
432         uint32_t designer = ((pid[1] & 0xf0) >> 4) | ((pid[2] & 0xf) << 4);
433
434         if (designer != PSOC4_ROMTABLE_DESIGNER_CHECK) {
435                 LOG_ERROR("ROMTABLE designer is not Cypress");
436                 return ERROR_FAIL;
437         }
438
439         *family_id = family;
440         return ERROR_OK;
441 }
442
443
444 static int psoc4_flash_prepare(struct flash_bank *bank)
445 {
446         struct target *target = bank->target;
447         struct psoc4_flash_bank *psoc4_info = bank->driver_priv;
448
449         if (target->state != TARGET_HALTED) {
450                 LOG_ERROR("Target not halted");
451                 return ERROR_TARGET_NOT_HALTED;
452         }
453
454         uint16_t family_id;
455         int retval;
456
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;
461
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;
466         }
467
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;
473
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.
478                          */
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;
484                         }
485                 }
486         }
487
488         return ERROR_OK;
489 }
490
491
492 static int psoc4_protect_check(struct flash_bank *bank)
493 {
494         struct target *target = bank->target;
495         struct psoc4_flash_bank *psoc4_info = bank->driver_priv;
496
497         uint32_t prot_addr = PSOC4_SFLASH_MACRO0;
498         int retval;
499         uint8_t bf[PSOC4_ROWS_PER_MACRO/8];
500         unsigned int s = 0;
501
502         for (unsigned int m = 0; m < psoc4_info->num_macros; m++, prot_addr += PSOC4_SFLASH_MACRO_SIZE) {
503                 retval = target_read_memory(target, prot_addr, 4, PSOC4_ROWS_PER_MACRO/32, bf);
504                 if (retval != ERROR_OK)
505                         return retval;
506
507                 for (unsigned int i = 0; i < PSOC4_ROWS_PER_MACRO && s < bank->num_sectors; i++, s++)
508                         bank->sectors[s].is_protected = bf[i/8] & (1 << (i%8)) ? 1 : 0;
509         }
510
511         return ERROR_OK;
512 }
513
514
515 static int psoc4_mass_erase(struct flash_bank *bank)
516 {
517         int retval = psoc4_flash_prepare(bank);
518         if (retval != ERROR_OK)
519                 return retval;
520
521         /* Call "Erase All" system ROM API */
522         uint32_t param = 0;
523         retval = psoc4_sysreq(bank, PSOC4_CMD_ERASE_ALL,
524                         0,
525                         &param, sizeof(param), NULL);
526
527         if (retval == ERROR_OK)
528                 /* set all sectors as erased */
529                 for (unsigned int i = 0; i < bank->num_sectors; i++)
530                         bank->sectors[i].is_erased = 1;
531
532         return retval;
533 }
534
535
536 static int psoc4_erase(struct flash_bank *bank, unsigned int first,
537                 unsigned int last)
538 {
539         struct psoc4_flash_bank *psoc4_info = bank->driver_priv;
540         if (psoc4_info->cmd_program_row == PSOC4_CMD_WRITE_ROW) {
541                 LOG_INFO("Autoerase enabled, erase command ignored");
542                 return ERROR_OK;
543         }
544
545         if ((first == 0) && (last == (bank->num_sectors - 1)))
546                 return psoc4_mass_erase(bank);
547
548         LOG_ERROR("Only mass erase available! Consider using 'psoc4 flash_autoerase 0 on'");
549
550         return ERROR_FAIL;
551 }
552
553
554 static int psoc4_protect(struct flash_bank *bank, int set, unsigned int first,
555                 unsigned int last)
556 {
557         struct target *target = bank->target;
558         struct psoc4_flash_bank *psoc4_info = bank->driver_priv;
559
560         if (!psoc4_info->probed)
561                 return ERROR_FAIL;
562
563         int retval = psoc4_flash_prepare(bank);
564         if (retval != ERROR_OK)
565                 return retval;
566
567         uint32_t *sysrq_buffer = NULL;
568         const int param_sz = 8;
569         int chip_prot = PSOC4_CHIP_PROT_OPEN;
570         unsigned int i;
571         unsigned int num_bits = bank->num_sectors;
572
573         if (num_bits > PSOC4_ROWS_PER_MACRO)
574                 num_bits = PSOC4_ROWS_PER_MACRO;
575
576         int prot_sz = num_bits / 8;
577
578         sysrq_buffer = malloc(param_sz + prot_sz);
579         if (!sysrq_buffer) {
580                 LOG_ERROR("no memory for row buffer");
581                 return ERROR_FAIL;
582         }
583
584         for (i = first; i <= last && i < bank->num_sectors; i++)
585                 bank->sectors[i].is_protected = set;
586
587         for (unsigned int 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);
593                 }
594
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;
605
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;
611         }
612
613         free(sysrq_buffer);
614
615         psoc4_protect_check(bank);
616         return retval;
617 }
618
619
620 COMMAND_HANDLER(psoc4_handle_flash_autoerase_command)
621 {
622         if (CMD_ARGC < 1)
623                 return ERROR_COMMAND_SYNTAX_ERROR;
624
625         struct flash_bank *bank;
626         int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
627         if (retval != ERROR_OK)
628                 return retval;
629
630         struct psoc4_flash_bank *psoc4_info = bank->driver_priv;
631         bool enable = psoc4_info->cmd_program_row == PSOC4_CMD_WRITE_ROW;
632
633         if (CMD_ARGC >= 2)
634                 COMMAND_PARSE_ON_OFF(CMD_ARGV[1], enable);
635
636         if (enable) {
637                 psoc4_info->cmd_program_row = PSOC4_CMD_WRITE_ROW;
638                 LOG_INFO("Flash auto-erase enabled, non mass erase commands will be ignored.");
639         } else {
640                 psoc4_info->cmd_program_row = PSOC4_CMD_PROGRAM_ROW;
641                 LOG_INFO("Flash auto-erase disabled. Use psoc mass_erase before flash programming.");
642         }
643
644         return retval;
645 }
646
647
648 static int psoc4_write(struct flash_bank *bank, const uint8_t *buffer,
649                 uint32_t offset, uint32_t count)
650 {
651         struct target *target = bank->target;
652         struct psoc4_flash_bank *psoc4_info = bank->driver_priv;
653         uint32_t *sysrq_buffer = NULL;
654         const int param_sz = 8;
655
656         int retval = psoc4_flash_prepare(bank);
657         if (retval != ERROR_OK)
658                 return retval;
659
660         sysrq_buffer = malloc(param_sz + psoc4_info->row_size);
661         if (!sysrq_buffer) {
662                 LOG_ERROR("no memory for row buffer");
663                 return ERROR_FAIL;
664         }
665
666         uint8_t *row_buffer = (uint8_t *)sysrq_buffer + param_sz;
667         uint32_t row_num = offset / psoc4_info->row_size;
668         uint32_t row_offset = offset - row_num * psoc4_info->row_size;
669         if (row_offset)
670                 memset(row_buffer, bank->default_padded_value, row_offset);
671
672         bool save_poll = jtag_poll_get_enabled();
673         jtag_poll_set_enabled(false);
674
675         while (count) {
676                 uint32_t chunk_size = psoc4_info->row_size - row_offset;
677                 if (chunk_size > count) {
678                         chunk_size = count;
679                         memset(row_buffer + chunk_size, bank->default_padded_value, psoc4_info->row_size - chunk_size);
680                 }
681                 memcpy(row_buffer + row_offset, buffer, chunk_size);
682                 LOG_DEBUG("offset / row: 0x%08" PRIx32 " / %" PRIu32 ", size %" PRIu32 "",
683                                 offset, row_offset, chunk_size);
684
685                 uint32_t macro_idx = row_num / PSOC4_ROWS_PER_MACRO;
686
687                 /* Call "Load Latch" system ROM API */
688                 target_buffer_set_u32(target, (uint8_t *)(sysrq_buffer + 1),
689                                         psoc4_info->row_size - 1);
690                 retval = psoc4_sysreq(bank, PSOC4_CMD_LOAD_LATCH,
691                                 0       /* Byte number in latch from what to write */
692                                   | (macro_idx << 8),
693                                 sysrq_buffer, param_sz + psoc4_info->row_size,
694                                 NULL);
695                 if (retval != ERROR_OK)
696                         goto cleanup;
697
698                 /* Call "Program Row" or "Write Row" system ROM API */
699                 uint32_t sysrq_param;
700                 retval = psoc4_sysreq(bank, psoc4_info->cmd_program_row,
701                                 row_num & 0xffff,
702                                 &sysrq_param, sizeof(sysrq_param),
703                                 NULL);
704                 if (retval != ERROR_OK)
705                         goto cleanup;
706
707                 buffer += chunk_size;
708                 row_num++;
709                 row_offset = 0;
710                 count -= chunk_size;
711         }
712
713 cleanup:
714         jtag_poll_set_enabled(save_poll);
715
716         free(sysrq_buffer);
717         return retval;
718 }
719
720
721 /* Due to Cypress's method of market segmentation some devices
722  * have accessible only 1/2, 1/4 or 1/8 of SPCIF described flash */
723 static int psoc4_test_flash_wounding(struct target *target, uint32_t flash_size)
724 {
725         int retval, i;
726         for (i = 3; i >= 1; i--) {
727                 uint32_t addr = flash_size >> i;
728                 uint32_t dummy;
729                 retval = target_read_u32(target, addr, &dummy);
730                 if (retval != ERROR_OK)
731                         return i;
732         }
733         return 0;
734 }
735
736
737 static int psoc4_probe(struct flash_bank *bank)
738 {
739         struct psoc4_flash_bank *psoc4_info = bank->driver_priv;
740         struct target *target = bank->target;
741
742         int retval;
743         uint16_t family_id;
744
745         psoc4_info->probed = false;
746
747         retval = psoc4_get_family(target, &family_id);
748         if (retval != ERROR_OK)
749                 return retval;
750
751         const struct psoc4_chip_family *family = psoc4_family_by_id(family_id);
752
753         if (family->id == 0) {
754                 LOG_ERROR("Cannot identify PSoC 4 family.");
755                 return ERROR_FAIL;
756         }
757
758         if (family->flags & PSOC4_FAMILY_FLAG_LEGACY) {
759                 LOG_INFO("%s legacy family detected.", family->name);
760                 psoc4_info->legacy_family = true;
761                 psoc4_info->cpuss_sysreq_addr = PSOC4_CPUSS_SYSREQ_LEGACY;
762                 psoc4_info->cpuss_sysarg_addr = PSOC4_CPUSS_SYSARG_LEGACY;
763                 psoc4_info->spcif_geometry_addr = PSOC4_SPCIF_GEOMETRY_LEGACY;
764         } else {
765                 LOG_INFO("%s family detected.", family->name);
766                 psoc4_info->legacy_family = false;
767                 psoc4_info->cpuss_sysreq_addr = PSOC4_CPUSS_SYSREQ_NEW;
768                 psoc4_info->cpuss_sysarg_addr = PSOC4_CPUSS_SYSARG_NEW;
769                 psoc4_info->spcif_geometry_addr = PSOC4_SPCIF_GEOMETRY_NEW;
770         }
771
772         uint32_t spcif_geometry;
773         retval = target_read_u32(target, psoc4_info->spcif_geometry_addr, &spcif_geometry);
774         if (retval != ERROR_OK)
775                 return retval;
776
777         uint32_t flash_size_in_kb = spcif_geometry & 0x3fff;
778         /* TRM of legacy, M and L version describes FLASH field as 16-bit.
779          * S-series and PSoC Analog Coprocessor changes spec to 14-bit only.
780          * Impose PSoC Analog Coprocessor limit to all devices as it
781          * does not make any harm: flash size is safely below 4 MByte limit
782          */
783         uint32_t row_size = (spcif_geometry >> 22) & 3;
784         uint32_t num_macros = (spcif_geometry >> 20) & 3;
785
786         if (psoc4_info->legacy_family) {
787                 flash_size_in_kb = flash_size_in_kb * 256 / 1024;
788                 row_size *= 128;
789         } else {
790                 flash_size_in_kb = (flash_size_in_kb + 1) * 256 / 1024;
791                 row_size = 64 * (row_size + 1);
792                 num_macros++;
793         }
794
795         LOG_DEBUG("SPCIF geometry: %" PRIu32 " kb flash, row %" PRIu32 " bytes.",
796                  flash_size_in_kb, row_size);
797
798         /* if the user sets the size manually then ignore the probed value
799          * this allows us to work around devices that have a invalid flash size register value */
800         if (psoc4_info->user_bank_size) {
801                 LOG_INFO("ignoring flash probed value, using configured bank size");
802                 flash_size_in_kb = psoc4_info->user_bank_size / 1024;
803         }
804
805         char macros_txt[20] = "";
806         if (num_macros > 1)
807                 snprintf(macros_txt, sizeof(macros_txt), " in %" PRIu32 " macros", num_macros);
808
809         LOG_INFO("flash size = %" PRIu32 " kbytes%s", flash_size_in_kb, macros_txt);
810
811         /* calculate number of pages */
812         uint32_t num_rows = flash_size_in_kb * 1024 / row_size;
813
814         /* check number of flash macros */
815         if (num_macros != (num_rows + PSOC4_ROWS_PER_MACRO - 1) / PSOC4_ROWS_PER_MACRO)
816                 LOG_WARNING("Number of macros does not correspond with flash size!");
817
818         if (!psoc4_info->legacy_family) {
819                 int wounding = psoc4_test_flash_wounding(target, num_rows * row_size);
820                 if (wounding > 0) {
821                         flash_size_in_kb = flash_size_in_kb >> wounding;
822                         num_rows = num_rows >> wounding;
823                         LOG_INFO("WOUNDING detected: accessible flash size %" PRIu32 " kbytes", flash_size_in_kb);
824                 }
825         }
826
827         free(bank->sectors);
828
829         psoc4_info->family_id = family_id;
830         psoc4_info->num_macros = num_macros;
831         psoc4_info->row_size = row_size;
832         bank->base = 0x00000000;
833         bank->size = num_rows * row_size;
834         bank->num_sectors = num_rows;
835         bank->sectors = alloc_block_array(0, row_size, num_rows);
836         if (!bank->sectors)
837                 return ERROR_FAIL;
838
839         LOG_DEBUG("flash bank set %" PRIu32 " rows", num_rows);
840         psoc4_info->probed = true;
841
842         return ERROR_OK;
843 }
844
845 static int psoc4_auto_probe(struct flash_bank *bank)
846 {
847         struct psoc4_flash_bank *psoc4_info = bank->driver_priv;
848         if (psoc4_info->probed)
849                 return ERROR_OK;
850         return psoc4_probe(bank);
851 }
852
853
854 static int get_psoc4_info(struct flash_bank *bank, struct command_invocation *cmd)
855 {
856         struct target *target = bank->target;
857         struct psoc4_flash_bank *psoc4_info = bank->driver_priv;
858
859         if (!psoc4_info->probed)
860                 return ERROR_FAIL;
861
862         const struct psoc4_chip_family *family = psoc4_family_by_id(psoc4_info->family_id);
863         uint32_t size_in_kb = bank->size / 1024;
864
865         if (target->state != TARGET_HALTED) {
866                 command_print_sameline(cmd, "%s, flash %" PRIu32 " kb"
867                         " (halt target to see details)", family->name, size_in_kb);
868                 return ERROR_OK;
869         }
870
871         uint32_t silicon_id;
872         uint16_t family_id;
873         uint8_t protection;
874
875         int retval = psoc4_get_silicon_id(bank, &silicon_id, &family_id, &protection);
876         if (retval != ERROR_OK)
877                 return retval;
878
879         if (family_id != psoc4_info->family_id)
880                 command_print_sameline(cmd, "Family id mismatch 0x%02" PRIx16
881                         "/0x%02" PRIx16 ", silicon id 0x%08" PRIx32,
882                         psoc4_info->family_id, family_id, silicon_id);
883         else {
884                 command_print_sameline(cmd, "%s silicon id 0x%08" PRIx32 "",
885                         family->name, silicon_id);
886         }
887
888         const char *prot_txt = psoc4_decode_chip_protection(protection);
889         command_print_sameline(cmd, ", flash %" PRIu32 " kb %s", size_in_kb, prot_txt);
890         return ERROR_OK;
891 }
892
893
894 COMMAND_HANDLER(psoc4_handle_mass_erase_command)
895 {
896         if (CMD_ARGC < 1)
897                 return ERROR_COMMAND_SYNTAX_ERROR;
898
899         struct flash_bank *bank;
900         int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
901         if (retval != ERROR_OK)
902                 return retval;
903
904         retval = psoc4_mass_erase(bank);
905         if (retval == ERROR_OK)
906                 command_print(CMD, "psoc mass erase complete");
907         else
908                 command_print(CMD, "psoc mass erase failed");
909
910         return retval;
911 }
912
913
914 static const struct command_registration psoc4_exec_command_handlers[] = {
915         {
916                 .name = "mass_erase",
917                 .handler = psoc4_handle_mass_erase_command,
918                 .mode = COMMAND_EXEC,
919                 .usage = "bank_id",
920                 .help = "Erase entire flash device.",
921         },
922         {
923                 .name = "flash_autoerase",
924                 .handler = psoc4_handle_flash_autoerase_command,
925                 .mode = COMMAND_EXEC,
926                 .usage = "bank_id on|off",
927                 .help = "Set autoerase mode for flash bank.",
928         },
929         COMMAND_REGISTRATION_DONE
930 };
931
932 static const struct command_registration psoc4_command_handlers[] = {
933         {
934                 .name = "psoc4",
935                 .mode = COMMAND_ANY,
936                 .help = "PSoC 4 flash command group",
937                 .usage = "",
938                 .chain = psoc4_exec_command_handlers,
939         },
940         COMMAND_REGISTRATION_DONE
941 };
942
943 const struct flash_driver psoc4_flash = {
944         .name = "psoc4",
945         .commands = psoc4_command_handlers,
946         .flash_bank_command = psoc4_flash_bank_command,
947         .erase = psoc4_erase,
948         .protect = psoc4_protect,
949         .write = psoc4_write,
950         .read = default_flash_read,
951         .probe = psoc4_probe,
952         .auto_probe = psoc4_auto_probe,
953         .erase_check = default_flash_blank_check,
954         .protect_check = psoc4_protect_check,
955         .info = get_psoc4_info,
956         .free_driver_priv = default_flash_free_driver_priv,
957 };