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

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)