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

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)