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

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)