1b46020a65c6eaea4c9a9b983ae7004cc064ed85
[openocd.git] / src / flash / nor / psoc5lp.c
1 /*
2 * PSoC 5LP flash driver
3 *
4 * Copyright (c) 2016 Andreas Färber
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23
24 #include "imp.h"
25 #include <helper/time_support.h>
26 #include <target/armv7m.h>
27
28 #define PM_ACT_CFG0 0x400043A0
29 #define PM_ACT_CFG12 0x400043AC
30 #define SPC_CPU_DATA 0x40004720
31 #define SPC_SR 0x40004722
32 #define PHUB_CH0_BASIC_CFG 0x40007010
33 #define PHUB_CH0_ACTION 0x40007014
34 #define PHUB_CH0_BASIC_STATUS 0x40007018
35 #define PHUB_CH1_BASIC_CFG 0x40007020
36 #define PHUB_CH1_ACTION 0x40007024
37 #define PHUB_CH1_BASIC_STATUS 0x40007028
38 #define PHUB_CFGMEM0_CFG0 0x40007600
39 #define PHUB_CFGMEM0_CFG1 0x40007604
40 #define PHUB_CFGMEM1_CFG0 0x40007608
41 #define PHUB_CFGMEM1_CFG1 0x4000760C
42 #define PHUB_TDMEM0_ORIG_TD0 0x40007800
43 #define PHUB_TDMEM0_ORIG_TD1 0x40007804
44 #define PHUB_TDMEM1_ORIG_TD0 0x40007808
45 #define PHUB_TDMEM1_ORIG_TD1 0x4000780C
46 #define PANTHER_DEVICE_ID 0x4008001C
47
48 #define PM_ACT_CFG12_EN_EE (1 << 4)
49
50 #define SPC_KEY1 0xB6
51 #define SPC_KEY2 0xD3
52
53 #define SPC_LOAD_BYTE 0x00
54 #define SPC_LOAD_MULTI_BYTE 0x01
55 #define SPC_LOAD_ROW 0x02
56 #define SPC_READ_BYTE 0x03
57 #define SPC_READ_MULTI_BYTE 0x04
58 #define SPC_WRITE_ROW 0x05
59 #define SPC_WRITE_USER_NVL 0x06
60 #define SPC_PRG_ROW 0x07
61 #define SPC_ERASE_SECTOR 0x08
62 #define SPC_ERASE_ALL 0x09
63 #define SPC_READ_HIDDEN_ROW 0x0A
64 #define SPC_PROGRAM_PROTECT_ROW 0x0B
65 #define SPC_GET_CHECKSUM 0x0C
66 #define SPC_GET_TEMP 0x0E
67 #define SPC_READ_VOLATILE_BYTE 0x10
68
69 #define SPC_ARRAY_ALL 0x3F
70 #define SPC_ARRAY_EEPROM 0x40
71 #define SPC_ARRAY_NVL_USER 0x80
72 #define SPC_ARRAY_NVL_WO 0xF8
73
74 #define SPC_ROW_PROTECTION 0
75
76 #define SPC_OPCODE_LEN 3
77
78 #define SPC_SR_DATA_READY (1 << 0)
79 #define SPC_SR_IDLE (1 << 1)
80
81 #define PM_ACT_CFG0_EN_CLK_SPC (1 << 3)
82
83 #define PHUB_CHx_BASIC_CFG_EN (1 << 0)
84 #define PHUB_CHx_BASIC_CFG_WORK_SEP (1 << 5)
85
86 #define PHUB_CHx_ACTION_CPU_REQ (1 << 0)
87
88 #define PHUB_CFGMEMx_CFG0 (1 << 7)
89
90 #define PHUB_TDMEMx_ORIG_TD0_NEXT_TD_PTR_LAST (0xff << 16)
91 #define PHUB_TDMEMx_ORIG_TD0_INC_SRC_ADDR (1 << 24)
92
93 #define NVL_3_ECCEN (1 << 3)
94
95 #define ROW_SIZE 256
96 #define ROW_ECC_SIZE 32
97 #define ROWS_PER_SECTOR 64
98 #define SECTOR_SIZE (ROWS_PER_SECTOR * ROW_SIZE)
99 #define ROWS_PER_BLOCK 256
100 #define BLOCK_SIZE (ROWS_PER_BLOCK * ROW_SIZE)
101 #define SECTORS_PER_BLOCK (BLOCK_SIZE / SECTOR_SIZE)
102 #define EEPROM_ROW_SIZE 16
103 #define EEPROM_SECTOR_SIZE (ROWS_PER_SECTOR * EEPROM_ROW_SIZE)
104 #define EEPROM_BLOCK_SIZE (ROWS_PER_BLOCK * EEPROM_ROW_SIZE)
105
106 #define PART_NUMBER_LEN (17 + 1)
107
108 struct psoc5lp_device {
109 uint32_t id;
110 unsigned fam;
111 unsigned speed_mhz;
112 unsigned flash_kb;
113 unsigned eeprom_kb;
114 };
115
116 /*
117 * Device information collected from datasheets.
118 * Different temperature ranges (C/I/Q/A) may share IDs, not differing otherwise.
119 */
120 static const struct psoc5lp_device psoc5lp_devices[] = {
121 /* CY8C58LP Family Datasheet */
122 { .id = 0x2E11F069, .fam = 8, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 },
123 { .id = 0x2E120069, .fam = 8, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 },
124 { .id = 0x2E123069, .fam = 8, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 },
125 { .id = 0x2E124069, .fam = 8, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 },
126 { .id = 0x2E126069, .fam = 8, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 },
127 { .id = 0x2E127069, .fam = 8, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 },
128 { .id = 0x2E117069, .fam = 8, .speed_mhz = 67, .flash_kb = 128, .eeprom_kb = 2 },
129 { .id = 0x2E118069, .fam = 8, .speed_mhz = 67, .flash_kb = 128, .eeprom_kb = 2 },
130 { .id = 0x2E119069, .fam = 8, .speed_mhz = 67, .flash_kb = 128, .eeprom_kb = 2 },
131 { .id = 0x2E11C069, .fam = 8, .speed_mhz = 67, .flash_kb = 128, .eeprom_kb = 2 },
132 { .id = 0x2E114069, .fam = 8, .speed_mhz = 67, .flash_kb = 64, .eeprom_kb = 2 },
133 { .id = 0x2E115069, .fam = 8, .speed_mhz = 67, .flash_kb = 64, .eeprom_kb = 2 },
134 { .id = 0x2E116069, .fam = 8, .speed_mhz = 67, .flash_kb = 64, .eeprom_kb = 2 },
135 { .id = 0x2E160069, .fam = 8, .speed_mhz = 80, .flash_kb = 256, .eeprom_kb = 2 },
136 /* '' */
137 { .id = 0x2E161069, .fam = 8, .speed_mhz = 80, .flash_kb = 256, .eeprom_kb = 2 },
138 /* '' */
139 { .id = 0x2E1D2069, .fam = 8, .speed_mhz = 80, .flash_kb = 256, .eeprom_kb = 2 },
140 { .id = 0x2E1D6069, .fam = 8, .speed_mhz = 80, .flash_kb = 256, .eeprom_kb = 2 },
141
142 /* CY8C56LP Family Datasheet */
143 { .id = 0x2E10A069, .fam = 6, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 },
144 { .id = 0x2E10D069, .fam = 6, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 },
145 { .id = 0x2E10E069, .fam = 6, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 },
146 { .id = 0x2E106069, .fam = 6, .speed_mhz = 67, .flash_kb = 128, .eeprom_kb = 2 },
147 { .id = 0x2E108069, .fam = 6, .speed_mhz = 67, .flash_kb = 128, .eeprom_kb = 2 },
148 { .id = 0x2E109069, .fam = 6, .speed_mhz = 67, .flash_kb = 128, .eeprom_kb = 2 },
149 { .id = 0x2E101069, .fam = 6, .speed_mhz = 67, .flash_kb = 64, .eeprom_kb = 2 },
150 { .id = 0x2E104069, .fam = 6, .speed_mhz = 67, .flash_kb = 64, .eeprom_kb = 2 },
151 /* '' */
152 { .id = 0x2E105069, .fam = 6, .speed_mhz = 67, .flash_kb = 64, .eeprom_kb = 2 },
153 { .id = 0x2E128069, .fam = 6, .speed_mhz = 67, .flash_kb = 128, .eeprom_kb = 2 },
154 /* '' */
155 { .id = 0x2E122069, .fam = 6, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 },
156 { .id = 0x2E129069, .fam = 6, .speed_mhz = 67, .flash_kb = 128, .eeprom_kb = 2 },
157 { .id = 0x2E163069, .fam = 6, .speed_mhz = 80, .flash_kb = 256, .eeprom_kb = 2 },
158 { .id = 0x2E156069, .fam = 6, .speed_mhz = 80, .flash_kb = 256, .eeprom_kb = 2 },
159 { .id = 0x2E1D3069, .fam = 6, .speed_mhz = 80, .flash_kb = 256, .eeprom_kb = 2 },
160
161 /* CY8C54LP Family Datasheet */
162 { .id = 0x2E11A069, .fam = 4, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 },
163 { .id = 0x2E16A069, .fam = 4, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 },
164 { .id = 0x2E12A069, .fam = 4, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 },
165 { .id = 0x2E103069, .fam = 4, .speed_mhz = 67, .flash_kb = 128, .eeprom_kb = 2 },
166 { .id = 0x2E16C069, .fam = 4, .speed_mhz = 67, .flash_kb = 128, .eeprom_kb = 2 },
167 { .id = 0x2E102069, .fam = 4, .speed_mhz = 67, .flash_kb = 64, .eeprom_kb = 2 },
168 { .id = 0x2E148069, .fam = 4, .speed_mhz = 67, .flash_kb = 64, .eeprom_kb = 2 },
169 { .id = 0x2E155069, .fam = 4, .speed_mhz = 67, .flash_kb = 64, .eeprom_kb = 2 },
170 { .id = 0x2E16B069, .fam = 4, .speed_mhz = 67, .flash_kb = 64, .eeprom_kb = 2 },
171 { .id = 0x2E12B069, .fam = 4, .speed_mhz = 67, .flash_kb = 32, .eeprom_kb = 2 },
172 { .id = 0x2E168069, .fam = 4, .speed_mhz = 67, .flash_kb = 32, .eeprom_kb = 2 },
173 { .id = 0x2E178069, .fam = 4, .speed_mhz = 80, .flash_kb = 256, .eeprom_kb = 2 },
174 { .id = 0x2E15D069, .fam = 4, .speed_mhz = 80, .flash_kb = 256, .eeprom_kb = 2 },
175 { .id = 0x2E1D4069, .fam = 4, .speed_mhz = 80, .flash_kb = 256, .eeprom_kb = 2 },
176
177 /* CY8C52LP Family Datasheet */
178 { .id = 0x2E11E069, .fam = 2, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 },
179 { .id = 0x2E12F069, .fam = 2, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 },
180 { .id = 0x2E133069, .fam = 2, .speed_mhz = 67, .flash_kb = 128, .eeprom_kb = 2 },
181 { .id = 0x2E159069, .fam = 2, .speed_mhz = 67, .flash_kb = 128, .eeprom_kb = 2 },
182 { .id = 0x2E11D069, .fam = 2, .speed_mhz = 67, .flash_kb = 64, .eeprom_kb = 2 },
183 { .id = 0x2E121069, .fam = 2, .speed_mhz = 67, .flash_kb = 64, .eeprom_kb = 2 },
184 { .id = 0x2E184069, .fam = 2, .speed_mhz = 67, .flash_kb = 64, .eeprom_kb = 2 },
185 { .id = 0x2E196069, .fam = 2, .speed_mhz = 67, .flash_kb = 64, .eeprom_kb = 2 },
186 { .id = 0x2E132069, .fam = 2, .speed_mhz = 67, .flash_kb = 32, .eeprom_kb = 2 },
187 { .id = 0x2E138069, .fam = 2, .speed_mhz = 67, .flash_kb = 32, .eeprom_kb = 2 },
188 { .id = 0x2E13A069, .fam = 2, .speed_mhz = 67, .flash_kb = 32, .eeprom_kb = 2 },
189 { .id = 0x2E152069, .fam = 2, .speed_mhz = 67, .flash_kb = 32, .eeprom_kb = 2 },
190 { .id = 0x2E15F069, .fam = 2, .speed_mhz = 80, .flash_kb = 256, .eeprom_kb = 2 },
191 { .id = 0x2E15A069, .fam = 2, .speed_mhz = 80, .flash_kb = 256, .eeprom_kb = 2 },
192 { .id = 0x2E1D5069, .fam = 2, .speed_mhz = 80, .flash_kb = 256, .eeprom_kb = 2 },
193 };
194
195 static void psoc5lp_get_part_number(const struct psoc5lp_device *dev, char *str)
196 {
197 strcpy(str, "CY8Cabcdefg-LPxxx");
198
199 str[4] = '5';
200 str[5] = '0' + dev->fam;
201
202 switch (dev->speed_mhz) {
203 case 67:
204 str[6] = '6';
205 break;
206 case 80:
207 str[6] = '8';
208 break;
209 default:
210 str[6] = '?';
211 }
212
213 switch (dev->flash_kb) {
214 case 32:
215 str[7] = '5';
216 break;
217 case 64:
218 str[7] = '6';
219 break;
220 case 128:
221 str[7] = '7';
222 break;
223 case 256:
224 str[7] = '8';
225 break;
226 default:
227 str[7] = '?';
228 }
229
230 /* Package does not matter. */
231 strncpy(str + 8, "xx", 2);
232
233 /* Temperate range cannot uniquely be identified. */
234 str[10] = 'x';
235 }
236
237 static int psoc5lp_get_device_id(struct target *target, uint32_t *id)
238 {
239 int retval;
240
241 retval = target_read_u32(target, PANTHER_DEVICE_ID, id); /* dummy read */
242 if (retval != ERROR_OK)
243 return retval;
244 retval = target_read_u32(target, PANTHER_DEVICE_ID, id);
245 return retval;
246 }
247
248 static int psoc5lp_find_device(struct target *target,
249 const struct psoc5lp_device **device)
250 {
251 uint32_t device_id;
252 unsigned i;
253 int retval;
254
255 *device = NULL;
256
257 retval = psoc5lp_get_device_id(target, &device_id);
258 if (retval != ERROR_OK)
259 return retval;
260 LOG_DEBUG("PANTHER_DEVICE_ID = 0x%08" PRIX32, device_id);
261
262 for (i = 0; i < ARRAY_SIZE(psoc5lp_devices); i++) {
263 if (psoc5lp_devices[i].id == device_id) {
264 *device = &psoc5lp_devices[i];
265 return ERROR_OK;
266 }
267 }
268
269 LOG_ERROR("Device 0x%08" PRIX32 " not supported", device_id);
270 return ERROR_FLASH_OPER_UNSUPPORTED;
271 }
272
273 static int psoc5lp_spc_enable_clock(struct target *target)
274 {
275 int retval;
276 uint8_t pm_act_cfg0;
277
278 retval = target_read_u8(target, PM_ACT_CFG0, &pm_act_cfg0);
279 if (retval != ERROR_OK) {
280 LOG_ERROR("Cannot read PM_ACT_CFG0");
281 return retval;
282 }
283
284 if (pm_act_cfg0 & PM_ACT_CFG0_EN_CLK_SPC)
285 return ERROR_OK; /* clock already enabled */
286
287 retval = target_write_u8(target, PM_ACT_CFG0, pm_act_cfg0 | PM_ACT_CFG0_EN_CLK_SPC);
288 if (retval != ERROR_OK)
289 LOG_ERROR("Cannot enable SPC clock");
290
291 return retval;
292 }
293
294 static int psoc5lp_spc_write_opcode(struct target *target, uint8_t opcode)
295 {
296 int retval;
297
298 retval = target_write_u8(target, SPC_CPU_DATA, SPC_KEY1);
299 if (retval != ERROR_OK)
300 return retval;
301 retval = target_write_u8(target, SPC_CPU_DATA, SPC_KEY2 + opcode);
302 if (retval != ERROR_OK)
303 return retval;
304 retval = target_write_u8(target, SPC_CPU_DATA, opcode);
305 return retval;
306 }
307
308 static void psoc5lp_spc_write_opcode_buffer(struct target *target,
309 uint8_t *buf, uint8_t opcode)
310 {
311 buf[0] = SPC_KEY1;
312 buf[1] = SPC_KEY2 + opcode;
313 buf[2] = opcode;
314 }
315
316 static int psoc5lp_spc_busy_wait_data(struct target *target)
317 {
318 int64_t endtime;
319 uint8_t sr;
320 int retval;
321
322 retval = target_read_u8(target, SPC_SR, &sr); /* dummy read */
323 if (retval != ERROR_OK)
324 return retval;
325
326 endtime = timeval_ms() + 1000; /* 1 second timeout */
327 do {
328 alive_sleep(1);
329 retval = target_read_u8(target, SPC_SR, &sr);
330 if (retval != ERROR_OK)
331 return retval;
332 if (sr == SPC_SR_DATA_READY)
333 return ERROR_OK;
334 } while (timeval_ms() < endtime);
335
336 return ERROR_FLASH_OPERATION_FAILED;
337 }
338
339 static int psoc5lp_spc_busy_wait_idle(struct target *target)
340 {
341 int64_t endtime;
342 uint8_t sr;
343 int retval;
344
345 retval = target_read_u8(target, SPC_SR, &sr); /* dummy read */
346 if (retval != ERROR_OK)
347 return retval;
348
349 endtime = timeval_ms() + 1000; /* 1 second timeout */
350 do {
351 alive_sleep(1);
352 retval = target_read_u8(target, SPC_SR, &sr);
353 if (retval != ERROR_OK)
354 return retval;
355 if (sr == SPC_SR_IDLE)
356 return ERROR_OK;
357 } while (timeval_ms() < endtime);
358
359 return ERROR_FLASH_OPERATION_FAILED;
360 }
361
362 static int psoc5lp_spc_load_row(struct target *target,
363 uint8_t array_id, const uint8_t *data, unsigned row_size)
364 {
365 unsigned i;
366 int retval;
367
368 retval = psoc5lp_spc_write_opcode(target, SPC_LOAD_ROW);
369 if (retval != ERROR_OK)
370 return retval;
371 retval = target_write_u8(target, SPC_CPU_DATA, array_id);
372 if (retval != ERROR_OK)
373 return retval;
374
375 for (i = 0; i < row_size; i++) {
376 retval = target_write_u8(target, SPC_CPU_DATA, data[i]);
377 if (retval != ERROR_OK)
378 return retval;
379 }
380
381 retval = psoc5lp_spc_busy_wait_idle(target);
382 if (retval != ERROR_OK)
383 return retval;
384
385 return ERROR_OK;
386 }
387
388 static int psoc5lp_spc_read_byte(struct target *target,
389 uint8_t array_id, uint8_t offset, uint8_t *data)
390 {
391 int retval;
392
393 retval = psoc5lp_spc_write_opcode(target, SPC_READ_BYTE);
394 if (retval != ERROR_OK)
395 return retval;
396 retval = target_write_u8(target, SPC_CPU_DATA, array_id);
397 if (retval != ERROR_OK)
398 return retval;
399 retval = target_write_u8(target, SPC_CPU_DATA, offset);
400 if (retval != ERROR_OK)
401 return retval;
402
403 retval = psoc5lp_spc_busy_wait_data(target);
404 if (retval != ERROR_OK)
405 return retval;
406
407 retval = target_read_u8(target, SPC_CPU_DATA, data);
408 if (retval != ERROR_OK)
409 return retval;
410
411 retval = psoc5lp_spc_busy_wait_idle(target);
412 if (retval != ERROR_OK)
413 return retval;
414
415 return ERROR_OK;
416 }
417
418 static int psoc5lp_spc_write_row(struct target *target,
419 uint8_t array_id, uint16_t row_id, const uint8_t *temp)
420 {
421 int retval;
422
423 retval = psoc5lp_spc_write_opcode(target, SPC_WRITE_ROW);
424 if (retval != ERROR_OK)
425 return retval;
426 retval = target_write_u8(target, SPC_CPU_DATA, array_id);
427 if (retval != ERROR_OK)
428 return retval;
429 retval = target_write_u8(target, SPC_CPU_DATA, row_id >> 8);
430 if (retval != ERROR_OK)
431 return retval;
432 retval = target_write_u8(target, SPC_CPU_DATA, row_id & 0xff);
433 if (retval != ERROR_OK)
434 return retval;
435 retval = target_write_u8(target, SPC_CPU_DATA, temp[0]);
436 if (retval != ERROR_OK)
437 return retval;
438 retval = target_write_u8(target, SPC_CPU_DATA, temp[1]);
439 if (retval != ERROR_OK)
440 return retval;
441
442 retval = psoc5lp_spc_busy_wait_idle(target);
443 if (retval != ERROR_OK)
444 return retval;
445
446 return ERROR_OK;
447 }
448
449 static int psoc5lp_spc_erase_sector(struct target *target,
450 uint8_t array_id, uint8_t row_id)
451 {
452 int retval;
453
454 retval = psoc5lp_spc_write_opcode(target, SPC_ERASE_SECTOR);
455 if (retval != ERROR_OK)
456 return retval;
457 retval = target_write_u8(target, SPC_CPU_DATA, array_id);
458 if (retval != ERROR_OK)
459 return retval;
460 retval = target_write_u8(target, SPC_CPU_DATA, row_id);
461 if (retval != ERROR_OK)
462 return retval;
463
464 retval = psoc5lp_spc_busy_wait_idle(target);
465 if (retval != ERROR_OK)
466 return retval;
467
468 return ERROR_OK;
469 }
470
471 static int psoc5lp_spc_erase_all(struct target *target)
472 {
473 int retval;
474
475 retval = psoc5lp_spc_write_opcode(target, SPC_ERASE_ALL);
476 if (retval != ERROR_OK)
477 return retval;
478
479 retval = psoc5lp_spc_busy_wait_idle(target);
480 if (retval != ERROR_OK)
481 return retval;
482
483 return ERROR_OK;
484 }
485
486 static int psoc5lp_spc_read_hidden_row(struct target *target,
487 uint8_t array_id, uint8_t row_id, uint8_t *data)
488 {
489 int i, retval;
490
491 retval = psoc5lp_spc_write_opcode(target, SPC_READ_HIDDEN_ROW);
492 if (retval != ERROR_OK)
493 return retval;
494 retval = target_write_u8(target, SPC_CPU_DATA, array_id);
495 if (retval != ERROR_OK)
496 return retval;
497 retval = target_write_u8(target, SPC_CPU_DATA, row_id);
498 if (retval != ERROR_OK)
499 return retval;
500
501 retval = psoc5lp_spc_busy_wait_data(target);
502 if (retval != ERROR_OK)
503 return retval;
504
505 for (i = 0; i < ROW_SIZE; i++) {
506 retval = target_read_u8(target, SPC_CPU_DATA, &data[i]);
507 if (retval != ERROR_OK)
508 return retval;
509 }
510
511 retval = psoc5lp_spc_busy_wait_idle(target);
512 if (retval != ERROR_OK)
513 return retval;
514
515 return ERROR_OK;
516 }
517
518 static int psoc5lp_spc_get_temp(struct target *target, uint8_t samples,
519 uint8_t *data)
520 {
521 int retval;
522
523 retval = psoc5lp_spc_write_opcode(target, SPC_GET_TEMP);
524 if (retval != ERROR_OK)
525 return retval;
526 retval = target_write_u8(target, SPC_CPU_DATA, samples);
527 if (retval != ERROR_OK)
528 return retval;
529
530 retval = psoc5lp_spc_busy_wait_data(target);
531 if (retval != ERROR_OK)
532 return retval;
533
534 retval = target_read_u8(target, SPC_CPU_DATA, &data[0]);
535 if (retval != ERROR_OK)
536 return retval;
537 retval = target_read_u8(target, SPC_CPU_DATA, &data[1]);
538 if (retval != ERROR_OK)
539 return retval;
540
541 retval = psoc5lp_spc_busy_wait_idle(target);
542 if (retval != ERROR_OK)
543 return retval;
544
545 return ERROR_OK;
546 }
547
548 /*
549 * EEPROM
550 */
551
552 struct psoc5lp_eeprom_flash_bank {
553 bool probed;
554 const struct psoc5lp_device *device;
555 };
556
557 static int psoc5lp_eeprom_erase(struct flash_bank *bank, int first, int last)
558 {
559 int i, retval;
560
561 for (i = first; i <= last; i++) {
562 retval = psoc5lp_spc_erase_sector(bank->target,
563 SPC_ARRAY_EEPROM, i);
564 if (retval != ERROR_OK)
565 return retval;
566 }
567
568 return ERROR_OK;
569 }
570
571 static int psoc5lp_eeprom_write(struct flash_bank *bank,
572 const uint8_t *buffer, uint32_t offset, uint32_t byte_count)
573 {
574 struct target *target = bank->target;
575 uint8_t temp[2];
576 unsigned row;
577 int retval;
578
579 if (offset % EEPROM_ROW_SIZE != 0) {
580 LOG_ERROR("Writes must be row-aligned, got offset 0x%08" PRIx32,
581 offset);
582 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
583 }
584
585 retval = psoc5lp_spc_get_temp(target, 3, temp);
586 if (retval != ERROR_OK) {
587 LOG_ERROR("Unable to read Die temperature");
588 return retval;
589 }
590 LOG_DEBUG("Get_Temp: sign 0x%02" PRIx8 ", magnitude 0x%02" PRIx8,
591 temp[0], temp[1]);
592
593 for (row = offset / EEPROM_ROW_SIZE; byte_count >= EEPROM_ROW_SIZE; row++) {
594 retval = psoc5lp_spc_load_row(target, SPC_ARRAY_EEPROM,
595 buffer, EEPROM_ROW_SIZE);
596 if (retval != ERROR_OK)
597 return retval;
598
599 retval = psoc5lp_spc_write_row(target, SPC_ARRAY_EEPROM,
600 row, temp);
601 if (retval != ERROR_OK)
602 return retval;
603
604 buffer += EEPROM_ROW_SIZE;
605 byte_count -= EEPROM_ROW_SIZE;
606 offset += EEPROM_ROW_SIZE;
607 }
608 if (byte_count > 0) {
609 uint8_t buf[EEPROM_ROW_SIZE];
610
611 memcpy(buf, buffer, byte_count);
612 memset(buf + byte_count, bank->default_padded_value,
613 EEPROM_ROW_SIZE - byte_count);
614
615 LOG_DEBUG("Padding %d bytes", EEPROM_ROW_SIZE - byte_count);
616 retval = psoc5lp_spc_load_row(target, SPC_ARRAY_EEPROM,
617 buf, EEPROM_ROW_SIZE);
618 if (retval != ERROR_OK)
619 return retval;
620
621 retval = psoc5lp_spc_write_row(target, SPC_ARRAY_EEPROM,
622 row, temp);
623 if (retval != ERROR_OK)
624 return retval;
625 }
626
627 return ERROR_OK;
628 }
629
630 static int psoc5lp_eeprom_protect_check(struct flash_bank *bank)
631 {
632 int i;
633
634 for (i = 0; i < bank->num_sectors; i++)
635 bank->sectors[i].is_protected = -1;
636
637 return ERROR_OK;
638 }
639
640 static int psoc5lp_eeprom_get_info_command(struct flash_bank *bank, char *buf, int buf_size)
641 {
642 struct psoc5lp_eeprom_flash_bank *psoc_eeprom_bank = bank->driver_priv;
643 char part_number[PART_NUMBER_LEN];
644
645 psoc5lp_get_part_number(psoc_eeprom_bank->device, part_number);
646
647 snprintf(buf, buf_size, "%s", part_number);
648
649 return ERROR_OK;
650 }
651
652 static int psoc5lp_eeprom_probe(struct flash_bank *bank)
653 {
654 struct psoc5lp_eeprom_flash_bank *psoc_eeprom_bank = bank->driver_priv;
655 uint32_t flash_addr = bank->base;
656 uint32_t val;
657 int i, retval;
658
659 if (psoc_eeprom_bank->probed)
660 return ERROR_OK;
661
662 if (bank->target->state != TARGET_HALTED) {
663 LOG_ERROR("Target not halted");
664 return ERROR_TARGET_NOT_HALTED;
665 }
666
667 retval = psoc5lp_find_device(bank->target, &psoc_eeprom_bank->device);
668 if (retval != ERROR_OK)
669 return retval;
670
671 retval = target_read_u32(bank->target, PM_ACT_CFG12, &val);
672 if (retval != ERROR_OK)
673 return retval;
674 if (!(val & PM_ACT_CFG12_EN_EE)) {
675 val |= PM_ACT_CFG12_EN_EE;
676 retval = target_write_u32(bank->target, PM_ACT_CFG12, val);
677 if (retval != ERROR_OK)
678 return retval;
679 }
680
681 bank->size = psoc_eeprom_bank->device->eeprom_kb * 1024;
682 bank->num_sectors = DIV_ROUND_UP(bank->size, EEPROM_SECTOR_SIZE);
683 bank->sectors = calloc(bank->num_sectors,
684 sizeof(struct flash_sector));
685 for (i = 0; i < bank->num_sectors; i++) {
686 bank->sectors[i].size = EEPROM_SECTOR_SIZE;
687 bank->sectors[i].offset = flash_addr - bank->base;
688 bank->sectors[i].is_erased = -1;
689 bank->sectors[i].is_protected = -1;
690
691 flash_addr += bank->sectors[i].size;
692 }
693
694 bank->default_padded_value = bank->erased_value = 0x00;
695
696 psoc_eeprom_bank->probed = true;
697
698 return ERROR_OK;
699 }
700
701 static int psoc5lp_eeprom_auto_probe(struct flash_bank *bank)
702 {
703 struct psoc5lp_eeprom_flash_bank *psoc_eeprom_bank = bank->driver_priv;
704
705 if (psoc_eeprom_bank->probed)
706 return ERROR_OK;
707
708 return psoc5lp_eeprom_probe(bank);
709 }
710
711 FLASH_BANK_COMMAND_HANDLER(psoc5lp_eeprom_flash_bank_command)
712 {
713 struct psoc5lp_eeprom_flash_bank *psoc_eeprom_bank;
714
715 psoc_eeprom_bank = malloc(sizeof(struct psoc5lp_eeprom_flash_bank));
716 if (!psoc_eeprom_bank)
717 return ERROR_FLASH_OPERATION_FAILED;
718
719 psoc_eeprom_bank->probed = false;
720 psoc_eeprom_bank->device = NULL;
721
722 bank->driver_priv = psoc_eeprom_bank;
723
724 return ERROR_OK;
725 }
726
727 static const struct command_registration psoc5lp_eeprom_exec_command_handlers[] = {
728 COMMAND_REGISTRATION_DONE
729 };
730
731 static const struct command_registration psoc5lp_eeprom_command_handlers[] = {
732 {
733 .name = "psoc5lp_eeprom",
734 .mode = COMMAND_ANY,
735 .help = "PSoC 5LP EEPROM command group",
736 .usage = "",
737 .chain = psoc5lp_eeprom_exec_command_handlers,
738 },
739 COMMAND_REGISTRATION_DONE
740 };
741
742 struct flash_driver psoc5lp_eeprom_flash = {
743 .name = "psoc5lp_eeprom",
744 .commands = psoc5lp_eeprom_command_handlers,
745 .flash_bank_command = psoc5lp_eeprom_flash_bank_command,
746 .info = psoc5lp_eeprom_get_info_command,
747 .probe = psoc5lp_eeprom_probe,
748 .auto_probe = psoc5lp_eeprom_auto_probe,
749 .protect_check = psoc5lp_eeprom_protect_check,
750 .read = default_flash_read,
751 .erase = psoc5lp_eeprom_erase,
752 .erase_check = default_flash_blank_check,
753 .write = psoc5lp_eeprom_write,
754 };
755
756 /*
757 * Program Flash
758 */
759
760 struct psoc5lp_flash_bank {
761 bool probed;
762 const struct psoc5lp_device *device;
763 bool ecc_enabled;
764 };
765
766 static int psoc5lp_erase(struct flash_bank *bank, int first, int last)
767 {
768 struct psoc5lp_flash_bank *psoc_bank = bank->driver_priv;
769 int i, retval;
770
771 if (!psoc_bank->ecc_enabled) {
772 /* Silently avoid erasing sectors twice */
773 if (last >= first + bank->num_sectors / 2) {
774 LOG_DEBUG("Skipping duplicate erase of sectors %d to %d",
775 first + bank->num_sectors / 2, last);
776 last = first + (bank->num_sectors / 2) - 1;
777 }
778 /* Check for any remaining ECC sectors */
779 if (last >= bank->num_sectors / 2) {
780 LOG_WARNING("Skipping erase of ECC region sectors %d to %d",
781 bank->num_sectors / 2, last);
782 last = (bank->num_sectors / 2) - 1;
783 }
784 }
785
786 for (i = first; i <= last; i++) {
787 retval = psoc5lp_spc_erase_sector(bank->target,
788 i / SECTORS_PER_BLOCK, i % SECTORS_PER_BLOCK);
789 if (retval != ERROR_OK)
790 return retval;
791 }
792
793 return ERROR_OK;
794 }
795
796 /* Derived from core.c:default_flash_blank_check() */
797 static int psoc5lp_erase_check(struct flash_bank *bank)
798 {
799 struct psoc5lp_flash_bank *psoc_bank = bank->driver_priv;
800 struct target *target = bank->target;
801 int i, retval;
802
803 if (target->state != TARGET_HALTED) {
804 LOG_ERROR("Target not halted");
805 return ERROR_TARGET_NOT_HALTED;
806 }
807
808 struct target_memory_check_block *block_array;
809 block_array = malloc(bank->num_sectors * sizeof(struct target_memory_check_block));
810 if (block_array == NULL)
811 return ERROR_FAIL;
812
813 for (i = 0; i < bank->num_sectors; i++) {
814 block_array[i].address = bank->base + bank->sectors[i].offset;
815 block_array[i].size = bank->sectors[i].size;
816 block_array[i].result = UINT32_MAX; /* erase state unknown */
817 }
818
819 bool fast_check = true;
820 for (i = 0; i < bank->num_sectors; ) {
821 retval = armv7m_blank_check_memory(target,
822 block_array + i, bank->num_sectors - i,
823 bank->erased_value);
824 if (retval < 1) {
825 /* Run slow fallback if the first run gives no result
826 * otherwise use possibly incomplete results */
827 if (i == 0)
828 fast_check = false;
829 break;
830 }
831 i += retval; /* add number of blocks done this round */
832 }
833
834 if (fast_check) {
835 if (!psoc_bank->ecc_enabled) {
836 int half_sectors = bank->num_sectors / 2;
837 for (i = 0; i < half_sectors / 2; i++)
838 bank->sectors[i].is_erased =
839 (block_array[i].result != 1)
840 ? block_array[i + half_sectors].result
841 : block_array[i].result;
842 } else {
843 for (i = 0; i < bank->num_sectors; i++)
844 bank->sectors[i].is_erased = block_array[i].result;
845 }
846 retval = ERROR_OK;
847 } else {
848 LOG_ERROR("Can't run erase check - add working memory");
849 retval = ERROR_FAIL;
850 }
851 free(block_array);
852
853 return retval;
854 }
855
856 static int psoc5lp_write(struct flash_bank *bank, const uint8_t *buffer,
857 uint32_t offset, uint32_t byte_count)
858 {
859 struct psoc5lp_flash_bank *psoc_bank = bank->driver_priv;
860 struct target *target = bank->target;
861 struct working_area *code_area, *even_row_area, *odd_row_area;
862 uint32_t row_size;
863 uint8_t temp[2], buf[12], ecc_bytes[ROW_ECC_SIZE];
864 unsigned array_id, row;
865 int i, retval;
866
867 if (offset + byte_count > bank->size) {
868 LOG_ERROR("Writing to ECC not supported");
869 return ERROR_FLASH_DST_OUT_OF_BANK;
870 }
871
872 if (offset % ROW_SIZE != 0) {
873 LOG_ERROR("Writes must be row-aligned, got offset 0x%08" PRIx32,
874 offset);
875 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
876 }
877
878 row_size = ROW_SIZE;
879 if (!psoc_bank->ecc_enabled) {
880 row_size += ROW_ECC_SIZE;
881 memset(ecc_bytes, bank->default_padded_value, ROW_ECC_SIZE);
882 }
883
884 retval = psoc5lp_spc_get_temp(target, 3, temp);
885 if (retval != ERROR_OK) {
886 LOG_ERROR("Unable to read Die temperature");
887 return retval;
888 }
889 LOG_DEBUG("Get_Temp: sign 0x%02" PRIx8 ", magnitude 0x%02" PRIx8,
890 temp[0], temp[1]);
891
892 assert(target_get_working_area_avail(target) == target->working_area_size);
893 retval = target_alloc_working_area(target,
894 target_get_working_area_avail(target) / 2, &code_area);
895 if (retval != ERROR_OK) {
896 LOG_ERROR("Could not allocate working area for program SRAM");
897 return retval;
898 }
899 assert(code_area->address < 0x20000000);
900
901 retval = target_alloc_working_area(target,
902 SPC_OPCODE_LEN + 1 + row_size + 3 + SPC_OPCODE_LEN + 6,
903 &even_row_area);
904 if (retval != ERROR_OK) {
905 LOG_ERROR("Could not allocate working area for even row");
906 goto err_alloc_even;
907 }
908 assert(even_row_area->address >= 0x20000000);
909
910 retval = target_alloc_working_area(target, even_row_area->size,
911 &odd_row_area);
912 if (retval != ERROR_OK) {
913 LOG_ERROR("Could not allocate working area for odd row");
914 goto err_alloc_odd;
915 }
916 assert(odd_row_area->address >= 0x20000000);
917
918 for (array_id = offset / BLOCK_SIZE; byte_count > 0; array_id++) {
919 for (row = (offset / ROW_SIZE) % ROWS_PER_BLOCK;
920 row < ROWS_PER_BLOCK && byte_count > 0; row++) {
921 bool even_row = (row % 2 == 0);
922 struct working_area *data_area = even_row ? even_row_area : odd_row_area;
923 unsigned len = MIN(ROW_SIZE, byte_count);
924
925 LOG_DEBUG("Writing load command for array %u row %u at 0x%08" TARGET_PRIxADDR,
926 array_id, row, data_area->address);
927
928 psoc5lp_spc_write_opcode_buffer(target, buf, SPC_LOAD_ROW);
929 buf[SPC_OPCODE_LEN] = array_id;
930 retval = target_write_buffer(target, data_area->address, 4, buf);
931 if (retval != ERROR_OK)
932 goto err_write;
933
934 retval = target_write_buffer(target,
935 data_area->address + SPC_OPCODE_LEN + 1,
936 len, buffer);
937 if (retval != ERROR_OK)
938 goto err_write;
939 buffer += len;
940 byte_count -= len;
941 offset += len;
942
943 if (len < ROW_SIZE) {
944 uint8_t padding[ROW_SIZE];
945
946 memset(padding, bank->default_padded_value, ROW_SIZE);
947
948 LOG_DEBUG("Padding %d bytes", ROW_SIZE - len);
949 retval = target_write_buffer(target,
950 data_area->address + SPC_OPCODE_LEN + 1 + len,
951 ROW_SIZE - len, padding);
952 if (retval != ERROR_OK)
953 goto err_write;
954 }
955
956 if (!psoc_bank->ecc_enabled) {
957 retval = target_write_buffer(target,
958 data_area->address + SPC_OPCODE_LEN + 1 + ROW_SIZE,
959 sizeof(ecc_bytes), ecc_bytes);
960 if (retval != ERROR_OK)
961 goto err_write;
962 }
963
964 for (i = 0; i < 3; i++)
965 buf[i] = 0x00; /* 3 NOPs for short delay */
966 psoc5lp_spc_write_opcode_buffer(target, buf + 3, SPC_PRG_ROW);
967 buf[3 + SPC_OPCODE_LEN] = array_id;
968 buf[3 + SPC_OPCODE_LEN + 1] = row >> 8;
969 buf[3 + SPC_OPCODE_LEN + 2] = row & 0xff;
970 memcpy(buf + 3 + SPC_OPCODE_LEN + 3, temp, 2);
971 buf[3 + SPC_OPCODE_LEN + 5] = 0x00; /* padding */
972 retval = target_write_buffer(target,
973 data_area->address + SPC_OPCODE_LEN + 1 + row_size,
974 12, buf);
975 if (retval != ERROR_OK)
976 goto err_write;
977
978 retval = target_write_u32(target,
979 even_row ? PHUB_CH0_BASIC_STATUS : PHUB_CH1_BASIC_STATUS,
980 (even_row ? 0 : 1) << 8);
981 if (retval != ERROR_OK)
982 goto err_dma;
983
984 retval = target_write_u32(target,
985 even_row ? PHUB_CH0_BASIC_CFG : PHUB_CH1_BASIC_CFG,
986 PHUB_CHx_BASIC_CFG_WORK_SEP | PHUB_CHx_BASIC_CFG_EN);
987 if (retval != ERROR_OK)
988 goto err_dma;
989
990 retval = target_write_u32(target,
991 even_row ? PHUB_CFGMEM0_CFG0 : PHUB_CFGMEM1_CFG0,
992 PHUB_CFGMEMx_CFG0);
993 if (retval != ERROR_OK)
994 goto err_dma;
995
996 retval = target_write_u32(target,
997 even_row ? PHUB_CFGMEM0_CFG1 : PHUB_CFGMEM1_CFG1,
998 ((SPC_CPU_DATA >> 16) << 16) | (data_area->address >> 16));
999 if (retval != ERROR_OK)
1000 goto err_dma;
1001
1002 retval = target_write_u32(target,
1003 even_row ? PHUB_TDMEM0_ORIG_TD0 : PHUB_TDMEM1_ORIG_TD0,
1004 PHUB_TDMEMx_ORIG_TD0_INC_SRC_ADDR |
1005 PHUB_TDMEMx_ORIG_TD0_NEXT_TD_PTR_LAST |
1006 ((SPC_OPCODE_LEN + 1 + row_size + 3 + SPC_OPCODE_LEN + 5) & 0xfff));
1007 if (retval != ERROR_OK)
1008 goto err_dma;
1009
1010 retval = target_write_u32(target,
1011 even_row ? PHUB_TDMEM0_ORIG_TD1 : PHUB_TDMEM1_ORIG_TD1,
1012 ((SPC_CPU_DATA & 0xffff) << 16) | (data_area->address & 0xffff));
1013 if (retval != ERROR_OK)
1014 goto err_dma;
1015
1016 retval = psoc5lp_spc_busy_wait_idle(target);
1017 if (retval != ERROR_OK)
1018 goto err_idle;
1019
1020 retval = target_write_u32(target,
1021 even_row ? PHUB_CH0_ACTION : PHUB_CH1_ACTION,
1022 PHUB_CHx_ACTION_CPU_REQ);
1023 if (retval != ERROR_OK)
1024 goto err_dma_action;
1025 }
1026 }
1027
1028 retval = psoc5lp_spc_busy_wait_idle(target);
1029
1030 err_dma_action:
1031 err_idle:
1032 err_dma:
1033 err_write:
1034 target_free_working_area(target, odd_row_area);
1035 err_alloc_odd:
1036 target_free_working_area(target, even_row_area);
1037 err_alloc_even:
1038 target_free_working_area(target, code_area);
1039
1040 return retval;
1041 }
1042
1043 static int psoc5lp_protect_check(struct flash_bank *bank)
1044 {
1045 struct psoc5lp_flash_bank *psoc_bank = bank->driver_priv;
1046 uint8_t row_data[ROW_SIZE];
1047 const unsigned protection_bytes_per_sector = ROWS_PER_SECTOR * 2 / 8;
1048 unsigned i, j, k, num_sectors;
1049 int retval;
1050
1051 if (bank->target->state != TARGET_HALTED) {
1052 LOG_ERROR("Target not halted");
1053 return ERROR_TARGET_NOT_HALTED;
1054 }
1055
1056 for (i = 0; i < DIV_ROUND_UP(bank->size, BLOCK_SIZE); i++) {
1057 retval = psoc5lp_spc_read_hidden_row(bank->target, i,
1058 SPC_ROW_PROTECTION, row_data);
1059 if (retval != ERROR_OK)
1060 return retval;
1061
1062 /* Last flash array may have less rows, but in practice full sectors. */
1063 if (i == bank->size / BLOCK_SIZE)
1064 num_sectors = (bank->size % BLOCK_SIZE) / SECTOR_SIZE;
1065 else
1066 num_sectors = SECTORS_PER_BLOCK;
1067
1068 for (j = 0; j < num_sectors; j++) {
1069 int sector_nr = i * SECTORS_PER_BLOCK + j;
1070 struct flash_sector *sector = &bank->sectors[sector_nr];
1071 struct flash_sector *ecc_sector;
1072
1073 if (psoc_bank->ecc_enabled)
1074 ecc_sector = &bank->sectors[bank->num_sectors + sector_nr];
1075 else
1076 ecc_sector = &bank->sectors[bank->num_sectors / 2 + sector_nr];
1077
1078 sector->is_protected = ecc_sector->is_protected = 0;
1079 for (k = protection_bytes_per_sector * j;
1080 k < protection_bytes_per_sector * (j + 1); k++) {
1081 assert(k < protection_bytes_per_sector * SECTORS_PER_BLOCK);
1082 LOG_DEBUG("row[%u][%02u] = 0x%02" PRIx8, i, k, row_data[k]);
1083 if (row_data[k] != 0x00) {
1084 sector->is_protected = ecc_sector->is_protected = 1;
1085 break;
1086 }
1087 }
1088 }
1089 }
1090
1091 return ERROR_OK;
1092 }
1093
1094 static int psoc5lp_get_info_command(struct flash_bank *bank, char *buf, int buf_size)
1095 {
1096 struct psoc5lp_flash_bank *psoc_bank = bank->driver_priv;
1097 char part_number[PART_NUMBER_LEN];
1098 const char *ecc;
1099
1100 psoc5lp_get_part_number(psoc_bank->device, part_number);
1101 ecc = psoc_bank->ecc_enabled ? "ECC enabled" : "ECC disabled";
1102
1103 snprintf(buf, buf_size, "%s %s", part_number, ecc);
1104
1105 return ERROR_OK;
1106 }
1107
1108 static int psoc5lp_probe(struct flash_bank *bank)
1109 {
1110 struct target *target = bank->target;
1111 struct psoc5lp_flash_bank *psoc_bank = bank->driver_priv;
1112 uint32_t flash_addr = bank->base;
1113 uint8_t nvl[4], temp[2];
1114 int i, retval;
1115
1116 if (target->state != TARGET_HALTED) {
1117 LOG_ERROR("Target not halted");
1118 return ERROR_TARGET_NOT_HALTED;
1119 }
1120
1121 if (!psoc_bank->device) {
1122 retval = psoc5lp_find_device(target, &psoc_bank->device);
1123 if (retval != ERROR_OK)
1124 return retval;
1125
1126 bank->size = psoc_bank->device->flash_kb * 1024;
1127 }
1128
1129 bank->num_sectors = DIV_ROUND_UP(bank->size, SECTOR_SIZE);
1130
1131 if (!psoc_bank->probed) {
1132 retval = psoc5lp_spc_enable_clock(target);
1133 if (retval != ERROR_OK)
1134 return retval;
1135
1136 /* First values read are inaccurate, so do it once now. */
1137 retval = psoc5lp_spc_get_temp(target, 3, temp);
1138 if (retval != ERROR_OK) {
1139 LOG_ERROR("Unable to read Die temperature");
1140 return retval;
1141 }
1142
1143 bank->sectors = calloc(bank->num_sectors * 2,
1144 sizeof(struct flash_sector));
1145 for (i = 0; i < bank->num_sectors; i++) {
1146 bank->sectors[i].size = SECTOR_SIZE;
1147 bank->sectors[i].offset = flash_addr - bank->base;
1148 bank->sectors[i].is_erased = -1;
1149 bank->sectors[i].is_protected = -1;
1150
1151 flash_addr += bank->sectors[i].size;
1152 }
1153 flash_addr = 0x48000000;
1154 for (i = bank->num_sectors; i < bank->num_sectors * 2; i++) {
1155 bank->sectors[i].size = ROWS_PER_SECTOR * ROW_ECC_SIZE;
1156 bank->sectors[i].offset = flash_addr - bank->base;
1157 bank->sectors[i].is_erased = -1;
1158 bank->sectors[i].is_protected = -1;
1159
1160 flash_addr += bank->sectors[i].size;
1161 }
1162
1163 bank->default_padded_value = bank->erased_value = 0x00;
1164
1165 psoc_bank->probed = true;
1166 }
1167
1168 retval = psoc5lp_spc_read_byte(target, SPC_ARRAY_NVL_USER, 3, &nvl[3]);
1169 if (retval != ERROR_OK)
1170 return retval;
1171 LOG_DEBUG("NVL[%d] = 0x%02" PRIx8, 3, nvl[3]);
1172 psoc_bank->ecc_enabled = nvl[3] & NVL_3_ECCEN;
1173
1174 if (!psoc_bank->ecc_enabled)
1175 bank->num_sectors *= 2;
1176
1177 return ERROR_OK;
1178 }
1179
1180 static int psoc5lp_auto_probe(struct flash_bank *bank)
1181 {
1182 return psoc5lp_probe(bank);
1183 }
1184
1185 COMMAND_HANDLER(psoc5lp_handle_mass_erase_command)
1186 {
1187 struct flash_bank *bank;
1188 int retval;
1189
1190 if (CMD_ARGC < 1)
1191 return ERROR_COMMAND_SYNTAX_ERROR;
1192
1193 retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
1194 if (retval != ERROR_OK)
1195 return retval;
1196
1197 retval = psoc5lp_spc_erase_all(bank->target);
1198 if (retval == ERROR_OK)
1199 command_print(CMD_CTX, "PSoC 5LP erase succeeded");
1200 else
1201 command_print(CMD_CTX, "PSoC 5LP erase failed");
1202
1203 return retval;
1204 }
1205
1206 FLASH_BANK_COMMAND_HANDLER(psoc5lp_flash_bank_command)
1207 {
1208 struct psoc5lp_flash_bank *psoc_bank;
1209
1210 psoc_bank = malloc(sizeof(struct psoc5lp_flash_bank));
1211 if (!psoc_bank)
1212 return ERROR_FLASH_OPERATION_FAILED;
1213
1214 psoc_bank->probed = false;
1215 psoc_bank->device = NULL;
1216
1217 bank->driver_priv = psoc_bank;
1218
1219 return ERROR_OK;
1220 }
1221
1222 static const struct command_registration psoc5lp_exec_command_handlers[] = {
1223 {
1224 .name = "mass_erase",
1225 .handler = psoc5lp_handle_mass_erase_command,
1226 .mode = COMMAND_EXEC,
1227 .usage = "bank_id",
1228 .help = "Erase all flash data and ECC/configuration bytes, "
1229 "all flash protection rows, "
1230 "and all row latches in all flash arrays on the device.",
1231 },
1232 COMMAND_REGISTRATION_DONE
1233 };
1234
1235 static const struct command_registration psoc5lp_command_handlers[] = {
1236 {
1237 .name = "psoc5lp",
1238 .mode = COMMAND_ANY,
1239 .help = "PSoC 5LP flash command group",
1240 .usage = "",
1241 .chain = psoc5lp_exec_command_handlers,
1242 },
1243 COMMAND_REGISTRATION_DONE
1244 };
1245
1246 struct flash_driver psoc5lp_flash = {
1247 .name = "psoc5lp",
1248 .commands = psoc5lp_command_handlers,
1249 .flash_bank_command = psoc5lp_flash_bank_command,
1250 .info = psoc5lp_get_info_command,
1251 .probe = psoc5lp_probe,
1252 .auto_probe = psoc5lp_auto_probe,
1253 .protect_check = psoc5lp_protect_check,
1254 .read = default_flash_read,
1255 .erase = psoc5lp_erase,
1256 .erase_check = psoc5lp_erase_check,
1257 .write = psoc5lp_write,
1258 };

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)