jtag: linuxgpiod: drop extra parenthesis
[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 const struct flash_driver psoc5lp_nvl_flash = {
815 .name = "psoc5lp_nvl",
816 .flash_bank_command = psoc5lp_nvl_flash_bank_command,
817 .info = psoc5lp_nvl_get_info_command,
818 .probe = psoc5lp_nvl_probe,
819 .auto_probe = psoc5lp_nvl_auto_probe,
820 .read = psoc5lp_nvl_read,
821 .erase = psoc5lp_nvl_erase,
822 .erase_check = psoc5lp_nvl_erase_check,
823 .write = psoc5lp_nvl_write,
824 .free_driver_priv = default_flash_free_driver_priv,
825 };
826
827 /*
828 * EEPROM
829 */
830
831 struct psoc5lp_eeprom_flash_bank {
832 bool probed;
833 const struct psoc5lp_device *device;
834 };
835
836 static int psoc5lp_eeprom_erase(struct flash_bank *bank, unsigned int first,
837 unsigned int last)
838 {
839 int retval;
840
841 for (unsigned int i = first; i <= last; i++) {
842 retval = psoc5lp_spc_erase_sector(bank->target,
843 SPC_ARRAY_EEPROM, i);
844 if (retval != ERROR_OK)
845 return retval;
846 }
847
848 return ERROR_OK;
849 }
850
851 static int psoc5lp_eeprom_write(struct flash_bank *bank,
852 const uint8_t *buffer, uint32_t offset, uint32_t byte_count)
853 {
854 struct target *target = bank->target;
855 uint8_t temp[2];
856 unsigned row;
857 int retval;
858
859 if (offset % EEPROM_ROW_SIZE != 0) {
860 LOG_ERROR("Writes must be row-aligned, got offset 0x%08" PRIx32,
861 offset);
862 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
863 }
864
865 retval = psoc5lp_spc_get_temp(target, 3, temp);
866 if (retval != ERROR_OK) {
867 LOG_ERROR("Unable to read Die temperature");
868 return retval;
869 }
870 LOG_DEBUG("Get_Temp: sign 0x%02" PRIx8 ", magnitude 0x%02" PRIx8,
871 temp[0], temp[1]);
872
873 for (row = offset / EEPROM_ROW_SIZE; byte_count >= EEPROM_ROW_SIZE; row++) {
874 retval = psoc5lp_spc_load_row(target, SPC_ARRAY_EEPROM,
875 buffer, EEPROM_ROW_SIZE);
876 if (retval != ERROR_OK)
877 return retval;
878
879 retval = psoc5lp_spc_write_row(target, SPC_ARRAY_EEPROM,
880 row, temp);
881 if (retval != ERROR_OK)
882 return retval;
883
884 buffer += EEPROM_ROW_SIZE;
885 byte_count -= EEPROM_ROW_SIZE;
886 offset += EEPROM_ROW_SIZE;
887 }
888 if (byte_count > 0) {
889 uint8_t buf[EEPROM_ROW_SIZE];
890
891 memcpy(buf, buffer, byte_count);
892 memset(buf + byte_count, bank->default_padded_value,
893 EEPROM_ROW_SIZE - byte_count);
894
895 LOG_DEBUG("Padding %" PRIu32 " bytes", EEPROM_ROW_SIZE - byte_count);
896 retval = psoc5lp_spc_load_row(target, SPC_ARRAY_EEPROM,
897 buf, EEPROM_ROW_SIZE);
898 if (retval != ERROR_OK)
899 return retval;
900
901 retval = psoc5lp_spc_write_row(target, SPC_ARRAY_EEPROM,
902 row, temp);
903 if (retval != ERROR_OK)
904 return retval;
905 }
906
907 return ERROR_OK;
908 }
909
910 static int psoc5lp_eeprom_get_info_command(struct flash_bank *bank, struct command_invocation *cmd)
911 {
912 struct psoc5lp_eeprom_flash_bank *psoc_eeprom_bank = bank->driver_priv;
913 char part_number[PART_NUMBER_LEN];
914
915 psoc5lp_get_part_number(psoc_eeprom_bank->device, part_number);
916
917 command_print_sameline(cmd, "%s", part_number);
918
919 return ERROR_OK;
920 }
921
922 static int psoc5lp_eeprom_probe(struct flash_bank *bank)
923 {
924 struct psoc5lp_eeprom_flash_bank *psoc_eeprom_bank = bank->driver_priv;
925 uint32_t flash_addr = bank->base;
926 uint32_t val;
927 int retval;
928
929 if (psoc_eeprom_bank->probed)
930 return ERROR_OK;
931
932 if (bank->target->state != TARGET_HALTED) {
933 LOG_ERROR("Target not halted");
934 return ERROR_TARGET_NOT_HALTED;
935 }
936
937 retval = psoc5lp_find_device(bank->target, &psoc_eeprom_bank->device);
938 if (retval != ERROR_OK)
939 return retval;
940
941 retval = target_read_u32(bank->target, PM_ACT_CFG12, &val);
942 if (retval != ERROR_OK)
943 return retval;
944 if (!(val & PM_ACT_CFG12_EN_EE)) {
945 val |= PM_ACT_CFG12_EN_EE;
946 retval = target_write_u32(bank->target, PM_ACT_CFG12, val);
947 if (retval != ERROR_OK)
948 return retval;
949 }
950
951 bank->size = psoc_eeprom_bank->device->eeprom_kb * 1024;
952 bank->num_sectors = DIV_ROUND_UP(bank->size, EEPROM_SECTOR_SIZE);
953 bank->sectors = calloc(bank->num_sectors,
954 sizeof(struct flash_sector));
955 for (unsigned int i = 0; i < bank->num_sectors; i++) {
956 bank->sectors[i].size = EEPROM_SECTOR_SIZE;
957 bank->sectors[i].offset = flash_addr - bank->base;
958 bank->sectors[i].is_erased = -1;
959 bank->sectors[i].is_protected = -1;
960
961 flash_addr += bank->sectors[i].size;
962 }
963
964 bank->default_padded_value = bank->erased_value = 0x00;
965
966 psoc_eeprom_bank->probed = true;
967
968 return ERROR_OK;
969 }
970
971 static int psoc5lp_eeprom_auto_probe(struct flash_bank *bank)
972 {
973 struct psoc5lp_eeprom_flash_bank *psoc_eeprom_bank = bank->driver_priv;
974
975 if (psoc_eeprom_bank->probed)
976 return ERROR_OK;
977
978 return psoc5lp_eeprom_probe(bank);
979 }
980
981 FLASH_BANK_COMMAND_HANDLER(psoc5lp_eeprom_flash_bank_command)
982 {
983 struct psoc5lp_eeprom_flash_bank *psoc_eeprom_bank;
984
985 psoc_eeprom_bank = malloc(sizeof(struct psoc5lp_eeprom_flash_bank));
986 if (!psoc_eeprom_bank)
987 return ERROR_FLASH_OPERATION_FAILED;
988
989 psoc_eeprom_bank->probed = false;
990 psoc_eeprom_bank->device = NULL;
991
992 bank->driver_priv = psoc_eeprom_bank;
993
994 return ERROR_OK;
995 }
996
997 const struct flash_driver psoc5lp_eeprom_flash = {
998 .name = "psoc5lp_eeprom",
999 .flash_bank_command = psoc5lp_eeprom_flash_bank_command,
1000 .info = psoc5lp_eeprom_get_info_command,
1001 .probe = psoc5lp_eeprom_probe,
1002 .auto_probe = psoc5lp_eeprom_auto_probe,
1003 .read = default_flash_read,
1004 .erase = psoc5lp_eeprom_erase,
1005 .erase_check = default_flash_blank_check,
1006 .write = psoc5lp_eeprom_write,
1007 .free_driver_priv = default_flash_free_driver_priv,
1008 };
1009
1010 /*
1011 * Program Flash
1012 */
1013
1014 struct psoc5lp_flash_bank {
1015 bool probed;
1016 const struct psoc5lp_device *device;
1017 bool ecc_enabled;
1018 /* If ecc is disabled, num_sectors counts both std and ecc sectors.
1019 * If ecc is enabled, num_sectors indicates just the number of std sectors.
1020 * However ecc sector descriptors bank->sector[num_sectors..2*num_sectors-1]
1021 * are used for driver private flash operations */
1022 };
1023
1024 static int psoc5lp_erase(struct flash_bank *bank, unsigned int first,
1025 unsigned int last)
1026 {
1027 struct psoc5lp_flash_bank *psoc_bank = bank->driver_priv;
1028 int retval;
1029
1030 if (!psoc_bank->ecc_enabled) {
1031 /* Silently avoid erasing sectors twice */
1032 if (last >= first + bank->num_sectors / 2) {
1033 LOG_DEBUG("Skipping duplicate erase of sectors %u to %u",
1034 first + bank->num_sectors / 2, last);
1035 last = first + (bank->num_sectors / 2) - 1;
1036 }
1037 /* Check for any remaining ECC sectors */
1038 if (last >= bank->num_sectors / 2) {
1039 LOG_WARNING("Skipping erase of ECC region sectors %u to %u",
1040 bank->num_sectors / 2, last);
1041 last = (bank->num_sectors / 2) - 1;
1042 }
1043 }
1044
1045 for (unsigned int i = first; i <= last; i++) {
1046 retval = psoc5lp_spc_erase_sector(bank->target,
1047 i / SECTORS_PER_BLOCK, i % SECTORS_PER_BLOCK);
1048 if (retval != ERROR_OK)
1049 return retval;
1050 }
1051
1052 return ERROR_OK;
1053 }
1054
1055 /* Derived from core.c:default_flash_blank_check() */
1056 static int psoc5lp_erase_check(struct flash_bank *bank)
1057 {
1058 struct psoc5lp_flash_bank *psoc_bank = bank->driver_priv;
1059 struct target *target = bank->target;
1060 int retval;
1061
1062 if (target->state != TARGET_HALTED) {
1063 LOG_ERROR("Target not halted");
1064 return ERROR_TARGET_NOT_HALTED;
1065 }
1066
1067 unsigned int num_sectors = bank->num_sectors;
1068 if (psoc_bank->ecc_enabled)
1069 num_sectors *= 2; /* count both std and ecc sector always */
1070
1071 struct target_memory_check_block *block_array;
1072 block_array = malloc(num_sectors * sizeof(struct target_memory_check_block));
1073 if (!block_array)
1074 return ERROR_FAIL;
1075
1076 for (unsigned int i = 0; i < num_sectors; i++) {
1077 block_array[i].address = bank->base + bank->sectors[i].offset;
1078 block_array[i].size = bank->sectors[i].size;
1079 block_array[i].result = UINT32_MAX; /* erase state unknown */
1080 }
1081
1082 bool fast_check = true;
1083 for (unsigned int i = 0; i < num_sectors; ) {
1084 retval = armv7m_blank_check_memory(target,
1085 block_array + i, num_sectors - i,
1086 bank->erased_value);
1087 if (retval < 1) {
1088 /* Run slow fallback if the first run gives no result
1089 * otherwise use possibly incomplete results */
1090 if (i == 0)
1091 fast_check = false;
1092 break;
1093 }
1094 i += retval; /* add number of blocks done this round */
1095 }
1096
1097 if (fast_check) {
1098 if (psoc_bank->ecc_enabled) {
1099 for (unsigned int i = 0; i < bank->num_sectors; i++)
1100 bank->sectors[i].is_erased =
1101 (block_array[i].result != 1)
1102 ? block_array[i].result
1103 : block_array[i + bank->num_sectors].result;
1104 /* if std sector is erased, use status of ecc sector */
1105 } else {
1106 for (unsigned int i = 0; i < num_sectors; i++)
1107 bank->sectors[i].is_erased = block_array[i].result;
1108 }
1109 retval = ERROR_OK;
1110 } else {
1111 LOG_ERROR("Can't run erase check - add working memory");
1112 retval = ERROR_FAIL;
1113 }
1114 free(block_array);
1115
1116 return retval;
1117 }
1118
1119 static int psoc5lp_write(struct flash_bank *bank, const uint8_t *buffer,
1120 uint32_t offset, uint32_t byte_count)
1121 {
1122 struct psoc5lp_flash_bank *psoc_bank = bank->driver_priv;
1123 struct target *target = bank->target;
1124 struct working_area *code_area, *even_row_area, *odd_row_area;
1125 uint32_t row_size;
1126 uint8_t temp[2], buf[12], ecc_bytes[ROW_ECC_SIZE];
1127 unsigned array_id, row;
1128 int i, retval;
1129
1130 if (offset + byte_count > bank->size) {
1131 LOG_ERROR("Writing to ECC not supported");
1132 return ERROR_FLASH_DST_OUT_OF_BANK;
1133 }
1134
1135 if (offset % ROW_SIZE != 0) {
1136 LOG_ERROR("Writes must be row-aligned, got offset 0x%08" PRIx32,
1137 offset);
1138 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
1139 }
1140
1141 row_size = ROW_SIZE;
1142 if (!psoc_bank->ecc_enabled) {
1143 row_size += ROW_ECC_SIZE;
1144 memset(ecc_bytes, bank->default_padded_value, ROW_ECC_SIZE);
1145 }
1146
1147 retval = psoc5lp_spc_get_temp(target, 3, temp);
1148 if (retval != ERROR_OK) {
1149 LOG_ERROR("Unable to read Die temperature");
1150 return retval;
1151 }
1152 LOG_DEBUG("Get_Temp: sign 0x%02" PRIx8 ", magnitude 0x%02" PRIx8,
1153 temp[0], temp[1]);
1154
1155 assert(target_get_working_area_avail(target) == target->working_area_size);
1156 retval = target_alloc_working_area(target,
1157 target_get_working_area_avail(target) / 2, &code_area);
1158 if (retval != ERROR_OK) {
1159 LOG_ERROR("Could not allocate working area for program SRAM");
1160 return retval;
1161 }
1162 assert(code_area->address < 0x20000000);
1163
1164 retval = target_alloc_working_area(target,
1165 SPC_OPCODE_LEN + 1 + row_size + 3 + SPC_OPCODE_LEN + 6,
1166 &even_row_area);
1167 if (retval != ERROR_OK) {
1168 LOG_ERROR("Could not allocate working area for even row");
1169 goto err_alloc_even;
1170 }
1171 assert(even_row_area->address >= 0x20000000);
1172
1173 retval = target_alloc_working_area(target, even_row_area->size,
1174 &odd_row_area);
1175 if (retval != ERROR_OK) {
1176 LOG_ERROR("Could not allocate working area for odd row");
1177 goto err_alloc_odd;
1178 }
1179 assert(odd_row_area->address >= 0x20000000);
1180
1181 for (array_id = offset / BLOCK_SIZE; byte_count > 0; array_id++) {
1182 for (row = (offset / ROW_SIZE) % ROWS_PER_BLOCK;
1183 row < ROWS_PER_BLOCK && byte_count > 0; row++) {
1184 bool even_row = (row % 2 == 0);
1185 struct working_area *data_area = even_row ? even_row_area : odd_row_area;
1186 unsigned len = MIN(ROW_SIZE, byte_count);
1187
1188 LOG_DEBUG("Writing load command for array %u row %u at " TARGET_ADDR_FMT,
1189 array_id, row, data_area->address);
1190
1191 psoc5lp_spc_write_opcode_buffer(target, buf, SPC_LOAD_ROW);
1192 buf[SPC_OPCODE_LEN] = array_id;
1193 retval = target_write_buffer(target, data_area->address, 4, buf);
1194 if (retval != ERROR_OK)
1195 goto err_write;
1196
1197 retval = target_write_buffer(target,
1198 data_area->address + SPC_OPCODE_LEN + 1,
1199 len, buffer);
1200 if (retval != ERROR_OK)
1201 goto err_write;
1202 buffer += len;
1203 byte_count -= len;
1204 offset += len;
1205
1206 if (len < ROW_SIZE) {
1207 uint8_t padding[ROW_SIZE];
1208
1209 memset(padding, bank->default_padded_value, ROW_SIZE);
1210
1211 LOG_DEBUG("Padding %d bytes", ROW_SIZE - len);
1212 retval = target_write_buffer(target,
1213 data_area->address + SPC_OPCODE_LEN + 1 + len,
1214 ROW_SIZE - len, padding);
1215 if (retval != ERROR_OK)
1216 goto err_write;
1217 }
1218
1219 if (!psoc_bank->ecc_enabled) {
1220 retval = target_write_buffer(target,
1221 data_area->address + SPC_OPCODE_LEN + 1 + ROW_SIZE,
1222 sizeof(ecc_bytes), ecc_bytes);
1223 if (retval != ERROR_OK)
1224 goto err_write;
1225 }
1226
1227 for (i = 0; i < 3; i++)
1228 buf[i] = 0x00; /* 3 NOPs for short delay */
1229 psoc5lp_spc_write_opcode_buffer(target, buf + 3, SPC_PRG_ROW);
1230 buf[3 + SPC_OPCODE_LEN] = array_id;
1231 buf[3 + SPC_OPCODE_LEN + 1] = row >> 8;
1232 buf[3 + SPC_OPCODE_LEN + 2] = row & 0xff;
1233 memcpy(buf + 3 + SPC_OPCODE_LEN + 3, temp, 2);
1234 buf[3 + SPC_OPCODE_LEN + 5] = 0x00; /* padding */
1235 retval = target_write_buffer(target,
1236 data_area->address + SPC_OPCODE_LEN + 1 + row_size,
1237 12, buf);
1238 if (retval != ERROR_OK)
1239 goto err_write;
1240
1241 retval = target_write_u32(target,
1242 even_row ? PHUB_CH0_BASIC_STATUS : PHUB_CH1_BASIC_STATUS,
1243 (even_row ? 0 : 1) << 8);
1244 if (retval != ERROR_OK)
1245 goto err_dma;
1246
1247 retval = target_write_u32(target,
1248 even_row ? PHUB_CH0_BASIC_CFG : PHUB_CH1_BASIC_CFG,
1249 PHUB_CHX_BASIC_CFG_WORK_SEP | PHUB_CHX_BASIC_CFG_EN);
1250 if (retval != ERROR_OK)
1251 goto err_dma;
1252
1253 retval = target_write_u32(target,
1254 even_row ? PHUB_CFGMEM0_CFG0 : PHUB_CFGMEM1_CFG0,
1255 PHUB_CFGMEMX_CFG0);
1256 if (retval != ERROR_OK)
1257 goto err_dma;
1258
1259 retval = target_write_u32(target,
1260 even_row ? PHUB_CFGMEM0_CFG1 : PHUB_CFGMEM1_CFG1,
1261 ((SPC_CPU_DATA >> 16) << 16) | (data_area->address >> 16));
1262 if (retval != ERROR_OK)
1263 goto err_dma;
1264
1265 retval = target_write_u32(target,
1266 even_row ? PHUB_TDMEM0_ORIG_TD0 : PHUB_TDMEM1_ORIG_TD0,
1267 PHUB_TDMEMX_ORIG_TD0_INC_SRC_ADDR |
1268 PHUB_TDMEMX_ORIG_TD0_NEXT_TD_PTR_LAST |
1269 ((SPC_OPCODE_LEN + 1 + row_size + 3 + SPC_OPCODE_LEN + 5) & 0xfff));
1270 if (retval != ERROR_OK)
1271 goto err_dma;
1272
1273 retval = target_write_u32(target,
1274 even_row ? PHUB_TDMEM0_ORIG_TD1 : PHUB_TDMEM1_ORIG_TD1,
1275 ((SPC_CPU_DATA & 0xffff) << 16) | (data_area->address & 0xffff));
1276 if (retval != ERROR_OK)
1277 goto err_dma;
1278
1279 retval = psoc5lp_spc_busy_wait_idle(target);
1280 if (retval != ERROR_OK)
1281 goto err_idle;
1282
1283 retval = target_write_u32(target,
1284 even_row ? PHUB_CH0_ACTION : PHUB_CH1_ACTION,
1285 PHUB_CHX_ACTION_CPU_REQ);
1286 if (retval != ERROR_OK)
1287 goto err_dma_action;
1288 }
1289 }
1290
1291 retval = psoc5lp_spc_busy_wait_idle(target);
1292
1293 err_dma_action:
1294 err_idle:
1295 err_dma:
1296 err_write:
1297 target_free_working_area(target, odd_row_area);
1298 err_alloc_odd:
1299 target_free_working_area(target, even_row_area);
1300 err_alloc_even:
1301 target_free_working_area(target, code_area);
1302
1303 return retval;
1304 }
1305
1306 static int psoc5lp_protect_check(struct flash_bank *bank)
1307 {
1308 struct psoc5lp_flash_bank *psoc_bank = bank->driver_priv;
1309 uint8_t row_data[ROW_SIZE];
1310 const unsigned protection_bytes_per_sector = ROWS_PER_SECTOR * 2 / 8;
1311 unsigned i, k, num_sectors;
1312 int retval;
1313
1314 if (bank->target->state != TARGET_HALTED) {
1315 LOG_ERROR("Target not halted");
1316 return ERROR_TARGET_NOT_HALTED;
1317 }
1318
1319 for (i = 0; i < DIV_ROUND_UP(bank->size, BLOCK_SIZE); i++) {
1320 retval = psoc5lp_spc_read_hidden_row(bank->target, i,
1321 SPC_ROW_PROTECTION, row_data);
1322 if (retval != ERROR_OK)
1323 return retval;
1324
1325 /* Last flash array may have less rows, but in practice full sectors. */
1326 if (i == bank->size / BLOCK_SIZE)
1327 num_sectors = (bank->size % BLOCK_SIZE) / SECTOR_SIZE;
1328 else
1329 num_sectors = SECTORS_PER_BLOCK;
1330
1331 for (unsigned int j = 0; j < num_sectors; j++) {
1332 int sector_nr = i * SECTORS_PER_BLOCK + j;
1333 struct flash_sector *sector = &bank->sectors[sector_nr];
1334 struct flash_sector *ecc_sector;
1335
1336 if (psoc_bank->ecc_enabled)
1337 ecc_sector = &bank->sectors[bank->num_sectors + sector_nr];
1338 else
1339 ecc_sector = &bank->sectors[bank->num_sectors / 2 + sector_nr];
1340
1341 sector->is_protected = ecc_sector->is_protected = 0;
1342 for (k = protection_bytes_per_sector * j;
1343 k < protection_bytes_per_sector * (j + 1); k++) {
1344 assert(k < protection_bytes_per_sector * SECTORS_PER_BLOCK);
1345 LOG_DEBUG("row[%u][%02u] = 0x%02" PRIx8, i, k, row_data[k]);
1346 if (row_data[k] != 0x00) {
1347 sector->is_protected = ecc_sector->is_protected = 1;
1348 break;
1349 }
1350 }
1351 }
1352 }
1353
1354 return ERROR_OK;
1355 }
1356
1357 static int psoc5lp_get_info_command(struct flash_bank *bank, struct command_invocation *cmd)
1358 {
1359 struct psoc5lp_flash_bank *psoc_bank = bank->driver_priv;
1360 char part_number[PART_NUMBER_LEN];
1361 const char *ecc;
1362
1363 psoc5lp_get_part_number(psoc_bank->device, part_number);
1364 ecc = psoc_bank->ecc_enabled ? "ECC enabled" : "ECC disabled";
1365
1366 command_print_sameline(cmd, "%s %s", part_number, ecc);
1367
1368 return ERROR_OK;
1369 }
1370
1371 static int psoc5lp_probe(struct flash_bank *bank)
1372 {
1373 struct target *target = bank->target;
1374 struct psoc5lp_flash_bank *psoc_bank = bank->driver_priv;
1375 uint32_t flash_addr = bank->base;
1376 uint8_t nvl[4], temp[2];
1377 int retval;
1378
1379 if (target->state != TARGET_HALTED) {
1380 LOG_ERROR("Target not halted");
1381 return ERROR_TARGET_NOT_HALTED;
1382 }
1383
1384 if (!psoc_bank->device) {
1385 retval = psoc5lp_find_device(target, &psoc_bank->device);
1386 if (retval != ERROR_OK)
1387 return retval;
1388
1389 bank->size = psoc_bank->device->flash_kb * 1024;
1390 }
1391
1392 bank->num_sectors = DIV_ROUND_UP(bank->size, SECTOR_SIZE);
1393
1394 if (!psoc_bank->probed) {
1395 retval = psoc5lp_spc_enable_clock(target);
1396 if (retval != ERROR_OK)
1397 return retval;
1398
1399 /* First values read are inaccurate, so do it once now. */
1400 retval = psoc5lp_spc_get_temp(target, 3, temp);
1401 if (retval != ERROR_OK) {
1402 LOG_ERROR("Unable to read Die temperature");
1403 return retval;
1404 }
1405
1406 bank->sectors = calloc(bank->num_sectors * 2,
1407 sizeof(struct flash_sector));
1408 for (unsigned int i = 0; i < bank->num_sectors; i++) {
1409 bank->sectors[i].size = SECTOR_SIZE;
1410 bank->sectors[i].offset = flash_addr - bank->base;
1411 bank->sectors[i].is_erased = -1;
1412 bank->sectors[i].is_protected = -1;
1413
1414 flash_addr += bank->sectors[i].size;
1415 }
1416 flash_addr = 0x48000000;
1417 for (unsigned int i = bank->num_sectors; i < bank->num_sectors * 2; i++) {
1418 bank->sectors[i].size = ROWS_PER_SECTOR * ROW_ECC_SIZE;
1419 bank->sectors[i].offset = flash_addr - bank->base;
1420 bank->sectors[i].is_erased = -1;
1421 bank->sectors[i].is_protected = -1;
1422
1423 flash_addr += bank->sectors[i].size;
1424 }
1425
1426 bank->default_padded_value = bank->erased_value = 0x00;
1427
1428 psoc_bank->probed = true;
1429 }
1430
1431 retval = psoc5lp_spc_read_byte(target, SPC_ARRAY_NVL_USER, 3, &nvl[3]);
1432 if (retval != ERROR_OK)
1433 return retval;
1434 LOG_DEBUG("NVL[%d] = 0x%02" PRIx8, 3, nvl[3]);
1435 psoc_bank->ecc_enabled = nvl[3] & NVL_3_ECCEN;
1436
1437 if (!psoc_bank->ecc_enabled)
1438 bank->num_sectors *= 2;
1439
1440 return ERROR_OK;
1441 }
1442
1443 static int psoc5lp_auto_probe(struct flash_bank *bank)
1444 {
1445 return psoc5lp_probe(bank);
1446 }
1447
1448 COMMAND_HANDLER(psoc5lp_handle_mass_erase_command)
1449 {
1450 struct flash_bank *bank;
1451 int retval;
1452
1453 if (CMD_ARGC < 1)
1454 return ERROR_COMMAND_SYNTAX_ERROR;
1455
1456 retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
1457 if (retval != ERROR_OK)
1458 return retval;
1459
1460 retval = psoc5lp_spc_erase_all(bank->target);
1461 if (retval == ERROR_OK)
1462 command_print(CMD, "PSoC 5LP erase succeeded");
1463 else
1464 command_print(CMD, "PSoC 5LP erase failed");
1465
1466 return retval;
1467 }
1468
1469 FLASH_BANK_COMMAND_HANDLER(psoc5lp_flash_bank_command)
1470 {
1471 struct psoc5lp_flash_bank *psoc_bank;
1472
1473 psoc_bank = malloc(sizeof(struct psoc5lp_flash_bank));
1474 if (!psoc_bank)
1475 return ERROR_FLASH_OPERATION_FAILED;
1476
1477 psoc_bank->probed = false;
1478 psoc_bank->device = NULL;
1479
1480 bank->driver_priv = psoc_bank;
1481
1482 return ERROR_OK;
1483 }
1484
1485 static const struct command_registration psoc5lp_exec_command_handlers[] = {
1486 {
1487 .name = "mass_erase",
1488 .handler = psoc5lp_handle_mass_erase_command,
1489 .mode = COMMAND_EXEC,
1490 .usage = "bank_id",
1491 .help = "Erase all flash data and ECC/configuration bytes, "
1492 "all flash protection rows, "
1493 "and all row latches in all flash arrays on the device.",
1494 },
1495 COMMAND_REGISTRATION_DONE
1496 };
1497
1498 static const struct command_registration psoc5lp_command_handlers[] = {
1499 {
1500 .name = "psoc5lp",
1501 .mode = COMMAND_ANY,
1502 .help = "PSoC 5LP flash command group",
1503 .usage = "",
1504 .chain = psoc5lp_exec_command_handlers,
1505 },
1506 COMMAND_REGISTRATION_DONE
1507 };
1508
1509 const struct flash_driver psoc5lp_flash = {
1510 .name = "psoc5lp",
1511 .commands = psoc5lp_command_handlers,
1512 .flash_bank_command = psoc5lp_flash_bank_command,
1513 .info = psoc5lp_get_info_command,
1514 .probe = psoc5lp_probe,
1515 .auto_probe = psoc5lp_auto_probe,
1516 .protect_check = psoc5lp_protect_check,
1517 .read = default_flash_read,
1518 .erase = psoc5lp_erase,
1519 .erase_check = psoc5lp_erase_check,
1520 .write = psoc5lp_write,
1521 .free_driver_priv = default_flash_free_driver_priv,
1522 };

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)