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