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