ae8e3d3bc17a5370fed494fdd302cf8fb00a1570
[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 strncpy(str + 8, "xx", 2);
238
239 /* Temperate range cannot uniquely be identified. */
240 str[10] = 'x';
241 }
242
243 static int psoc5lp_get_device_id(struct target *target, uint32_t *id)
244 {
245 int retval;
246
247 retval = target_read_u32(target, PANTHER_DEVICE_ID, id); /* dummy read */
248 if (retval != ERROR_OK)
249 return retval;
250 retval = target_read_u32(target, PANTHER_DEVICE_ID, id);
251 return retval;
252 }
253
254 static int psoc5lp_find_device(struct target *target,
255 const struct psoc5lp_device **device)
256 {
257 uint32_t device_id;
258 unsigned i;
259 int retval;
260
261 *device = NULL;
262
263 retval = psoc5lp_get_device_id(target, &device_id);
264 if (retval != ERROR_OK)
265 return retval;
266 LOG_DEBUG("PANTHER_DEVICE_ID = 0x%08" PRIX32, device_id);
267
268 for (i = 0; i < ARRAY_SIZE(psoc5lp_devices); i++) {
269 if (psoc5lp_devices[i].id == device_id) {
270 *device = &psoc5lp_devices[i];
271 return ERROR_OK;
272 }
273 }
274
275 LOG_ERROR("Device 0x%08" PRIX32 " not supported", device_id);
276 return ERROR_FLASH_OPER_UNSUPPORTED;
277 }
278
279 static int psoc5lp_spc_enable_clock(struct target *target)
280 {
281 int retval;
282 uint8_t pm_act_cfg0;
283
284 retval = target_read_u8(target, PM_ACT_CFG0, &pm_act_cfg0);
285 if (retval != ERROR_OK) {
286 LOG_ERROR("Cannot read PM_ACT_CFG0");
287 return retval;
288 }
289
290 if (pm_act_cfg0 & PM_ACT_CFG0_EN_CLK_SPC)
291 return ERROR_OK; /* clock already enabled */
292
293 retval = target_write_u8(target, PM_ACT_CFG0, pm_act_cfg0 | PM_ACT_CFG0_EN_CLK_SPC);
294 if (retval != ERROR_OK)
295 LOG_ERROR("Cannot enable SPC clock");
296
297 return retval;
298 }
299
300 static int psoc5lp_spc_write_opcode(struct target *target, uint8_t opcode)
301 {
302 int retval;
303
304 retval = target_write_u8(target, SPC_CPU_DATA, SPC_KEY1);
305 if (retval != ERROR_OK)
306 return retval;
307 retval = target_write_u8(target, SPC_CPU_DATA, SPC_KEY2 + opcode);
308 if (retval != ERROR_OK)
309 return retval;
310 retval = target_write_u8(target, SPC_CPU_DATA, opcode);
311 return retval;
312 }
313
314 static void psoc5lp_spc_write_opcode_buffer(struct target *target,
315 uint8_t *buf, uint8_t opcode)
316 {
317 buf[0] = SPC_KEY1;
318 buf[1] = SPC_KEY2 + opcode;
319 buf[2] = opcode;
320 }
321
322 static int psoc5lp_spc_busy_wait_data(struct target *target)
323 {
324 int64_t endtime;
325 uint8_t sr;
326 int retval;
327
328 retval = target_read_u8(target, SPC_SR, &sr); /* dummy read */
329 if (retval != ERROR_OK)
330 return retval;
331
332 endtime = timeval_ms() + 1000; /* 1 second timeout */
333 do {
334 alive_sleep(1);
335 retval = target_read_u8(target, SPC_SR, &sr);
336 if (retval != ERROR_OK)
337 return retval;
338 if (sr == SPC_SR_DATA_READY)
339 return ERROR_OK;
340 } while (timeval_ms() < endtime);
341
342 return ERROR_FLASH_OPERATION_FAILED;
343 }
344
345 static int psoc5lp_spc_busy_wait_idle(struct target *target)
346 {
347 int64_t endtime;
348 uint8_t sr;
349 int retval;
350
351 retval = target_read_u8(target, SPC_SR, &sr); /* dummy read */
352 if (retval != ERROR_OK)
353 return retval;
354
355 endtime = timeval_ms() + 1000; /* 1 second timeout */
356 do {
357 alive_sleep(1);
358 retval = target_read_u8(target, SPC_SR, &sr);
359 if (retval != ERROR_OK)
360 return retval;
361 if (sr == SPC_SR_IDLE)
362 return ERROR_OK;
363 } while (timeval_ms() < endtime);
364
365 return ERROR_FLASH_OPERATION_FAILED;
366 }
367
368 static int psoc5lp_spc_load_byte(struct target *target,
369 uint8_t array_id, uint8_t offset, uint8_t value)
370 {
371 int retval;
372
373 retval = psoc5lp_spc_write_opcode(target, SPC_LOAD_BYTE);
374 if (retval != ERROR_OK)
375 return retval;
376 retval = target_write_u8(target, SPC_CPU_DATA, array_id);
377 if (retval != ERROR_OK)
378 return retval;
379 retval = target_write_u8(target, SPC_CPU_DATA, offset);
380 if (retval != ERROR_OK)
381 return retval;
382 retval = target_write_u8(target, SPC_CPU_DATA, value);
383 if (retval != ERROR_OK)
384 return retval;
385
386 retval = psoc5lp_spc_busy_wait_idle(target);
387 if (retval != ERROR_OK)
388 return retval;
389
390 return ERROR_OK;
391 }
392
393 static int psoc5lp_spc_load_row(struct target *target,
394 uint8_t array_id, const uint8_t *data, unsigned row_size)
395 {
396 unsigned i;
397 int retval;
398
399 retval = psoc5lp_spc_write_opcode(target, SPC_LOAD_ROW);
400 if (retval != ERROR_OK)
401 return retval;
402 retval = target_write_u8(target, SPC_CPU_DATA, array_id);
403 if (retval != ERROR_OK)
404 return retval;
405
406 for (i = 0; i < row_size; i++) {
407 retval = target_write_u8(target, SPC_CPU_DATA, data[i]);
408 if (retval != ERROR_OK)
409 return retval;
410 }
411
412 retval = psoc5lp_spc_busy_wait_idle(target);
413 if (retval != ERROR_OK)
414 return retval;
415
416 return ERROR_OK;
417 }
418
419 static int psoc5lp_spc_read_byte(struct target *target,
420 uint8_t array_id, uint8_t offset, uint8_t *data)
421 {
422 int retval;
423
424 retval = psoc5lp_spc_write_opcode(target, SPC_READ_BYTE);
425 if (retval != ERROR_OK)
426 return retval;
427 retval = target_write_u8(target, SPC_CPU_DATA, array_id);
428 if (retval != ERROR_OK)
429 return retval;
430 retval = target_write_u8(target, SPC_CPU_DATA, offset);
431 if (retval != ERROR_OK)
432 return retval;
433
434 retval = psoc5lp_spc_busy_wait_data(target);
435 if (retval != ERROR_OK)
436 return retval;
437
438 retval = target_read_u8(target, SPC_CPU_DATA, data);
439 if (retval != ERROR_OK)
440 return retval;
441
442 retval = psoc5lp_spc_busy_wait_idle(target);
443 if (retval != ERROR_OK)
444 return retval;
445
446 return ERROR_OK;
447 }
448
449 static int psoc5lp_spc_write_row(struct target *target,
450 uint8_t array_id, uint16_t row_id, const uint8_t *temp)
451 {
452 int retval;
453
454 retval = psoc5lp_spc_write_opcode(target, SPC_WRITE_ROW);
455 if (retval != ERROR_OK)
456 return retval;
457 retval = target_write_u8(target, SPC_CPU_DATA, array_id);
458 if (retval != ERROR_OK)
459 return retval;
460 retval = target_write_u8(target, SPC_CPU_DATA, row_id >> 8);
461 if (retval != ERROR_OK)
462 return retval;
463 retval = target_write_u8(target, SPC_CPU_DATA, row_id & 0xff);
464 if (retval != ERROR_OK)
465 return retval;
466 retval = target_write_u8(target, SPC_CPU_DATA, temp[0]);
467 if (retval != ERROR_OK)
468 return retval;
469 retval = target_write_u8(target, SPC_CPU_DATA, temp[1]);
470 if (retval != ERROR_OK)
471 return retval;
472
473 retval = psoc5lp_spc_busy_wait_idle(target);
474 if (retval != ERROR_OK)
475 return retval;
476
477 return ERROR_OK;
478 }
479
480 static int psoc5lp_spc_write_user_nvl(struct target *target,
481 uint8_t array_id)
482 {
483 int retval;
484
485 retval = psoc5lp_spc_write_opcode(target, SPC_WRITE_USER_NVL);
486 if (retval != ERROR_OK)
487 return retval;
488 retval = target_write_u8(target, SPC_CPU_DATA, array_id);
489 if (retval != ERROR_OK)
490 return retval;
491
492 retval = psoc5lp_spc_busy_wait_idle(target);
493 if (retval != ERROR_OK)
494 return retval;
495
496 return ERROR_OK;
497 }
498
499 static int psoc5lp_spc_erase_sector(struct target *target,
500 uint8_t array_id, uint8_t row_id)
501 {
502 int retval;
503
504 retval = psoc5lp_spc_write_opcode(target, SPC_ERASE_SECTOR);
505 if (retval != ERROR_OK)
506 return retval;
507 retval = target_write_u8(target, SPC_CPU_DATA, array_id);
508 if (retval != ERROR_OK)
509 return retval;
510 retval = target_write_u8(target, SPC_CPU_DATA, row_id);
511 if (retval != ERROR_OK)
512 return retval;
513
514 retval = psoc5lp_spc_busy_wait_idle(target);
515 if (retval != ERROR_OK)
516 return retval;
517
518 return ERROR_OK;
519 }
520
521 static int psoc5lp_spc_erase_all(struct target *target)
522 {
523 int retval;
524
525 retval = psoc5lp_spc_write_opcode(target, SPC_ERASE_ALL);
526 if (retval != ERROR_OK)
527 return retval;
528
529 retval = psoc5lp_spc_busy_wait_idle(target);
530 if (retval != ERROR_OK)
531 return retval;
532
533 return ERROR_OK;
534 }
535
536 static int psoc5lp_spc_read_hidden_row(struct target *target,
537 uint8_t array_id, uint8_t row_id, uint8_t *data)
538 {
539 int i, retval;
540
541 retval = psoc5lp_spc_write_opcode(target, SPC_READ_HIDDEN_ROW);
542 if (retval != ERROR_OK)
543 return retval;
544 retval = target_write_u8(target, SPC_CPU_DATA, array_id);
545 if (retval != ERROR_OK)
546 return retval;
547 retval = target_write_u8(target, SPC_CPU_DATA, row_id);
548 if (retval != ERROR_OK)
549 return retval;
550
551 retval = psoc5lp_spc_busy_wait_data(target);
552 if (retval != ERROR_OK)
553 return retval;
554
555 for (i = 0; i < ROW_SIZE; i++) {
556 retval = target_read_u8(target, SPC_CPU_DATA, &data[i]);
557 if (retval != ERROR_OK)
558 return retval;
559 }
560
561 retval = psoc5lp_spc_busy_wait_idle(target);
562 if (retval != ERROR_OK)
563 return retval;
564
565 return ERROR_OK;
566 }
567
568 static int psoc5lp_spc_get_temp(struct target *target, uint8_t samples,
569 uint8_t *data)
570 {
571 int retval;
572
573 retval = psoc5lp_spc_write_opcode(target, SPC_GET_TEMP);
574 if (retval != ERROR_OK)
575 return retval;
576 retval = target_write_u8(target, SPC_CPU_DATA, samples);
577 if (retval != ERROR_OK)
578 return retval;
579
580 retval = psoc5lp_spc_busy_wait_data(target);
581 if (retval != ERROR_OK)
582 return retval;
583
584 retval = target_read_u8(target, SPC_CPU_DATA, &data[0]);
585 if (retval != ERROR_OK)
586 return retval;
587 retval = target_read_u8(target, SPC_CPU_DATA, &data[1]);
588 if (retval != ERROR_OK)
589 return retval;
590
591 retval = psoc5lp_spc_busy_wait_idle(target);
592 if (retval != ERROR_OK)
593 return retval;
594
595 return ERROR_OK;
596 }
597
598 static int psoc5lp_spc_read_volatile_byte(struct target *target,
599 uint8_t array_id, uint8_t offset, uint8_t *data)
600 {
601 int retval;
602
603 retval = psoc5lp_spc_write_opcode(target, SPC_READ_VOLATILE_BYTE);
604 if (retval != ERROR_OK)
605 return retval;
606 retval = target_write_u8(target, SPC_CPU_DATA, array_id);
607 if (retval != ERROR_OK)
608 return retval;
609 retval = target_write_u8(target, SPC_CPU_DATA, offset);
610 if (retval != ERROR_OK)
611 return retval;
612
613 retval = psoc5lp_spc_busy_wait_data(target);
614 if (retval != ERROR_OK)
615 return retval;
616
617 retval = target_read_u8(target, SPC_CPU_DATA, data);
618 if (retval != ERROR_OK)
619 return retval;
620
621 retval = psoc5lp_spc_busy_wait_idle(target);
622 if (retval != ERROR_OK)
623 return retval;
624
625 return ERROR_OK;
626 }
627
628 /*
629 * NV Latch
630 */
631
632 struct psoc5lp_nvl_flash_bank {
633 bool probed;
634 const struct psoc5lp_device *device;
635 };
636
637 static int psoc5lp_nvl_read(struct flash_bank *bank,
638 uint8_t *buffer, uint32_t offset, uint32_t count)
639 {
640 int retval;
641
642 retval = psoc5lp_spc_enable_clock(bank->target);
643 if (retval != ERROR_OK)
644 return retval;
645
646 while (count > 0) {
647 retval = psoc5lp_spc_read_byte(bank->target,
648 SPC_ARRAY_NVL_USER, offset, buffer);
649 if (retval != ERROR_OK)
650 return retval;
651 buffer++;
652 offset++;
653 count--;
654 }
655
656 return ERROR_OK;
657 }
658
659 static int psoc5lp_nvl_erase(struct flash_bank *bank, int first, int last)
660 {
661 LOG_WARNING("There is no erase operation for NV Latches");
662 return ERROR_FLASH_OPER_UNSUPPORTED;
663 }
664
665 static int psoc5lp_nvl_erase_check(struct flash_bank *bank)
666 {
667 int i;
668
669 for (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_protect_check(struct flash_bank *bank)
756 {
757 int i;
758
759 for (i = 0; i < bank->num_sectors; i++)
760 bank->sectors[i].is_protected = -1;
761
762 return ERROR_OK;
763 }
764
765 static int psoc5lp_nvl_get_info_command(struct flash_bank *bank,
766 char *buf, int buf_size)
767 {
768 struct psoc5lp_nvl_flash_bank *psoc_nvl_bank = bank->driver_priv;
769 char part_number[PART_NUMBER_LEN];
770
771 psoc5lp_get_part_number(psoc_nvl_bank->device, part_number);
772
773 snprintf(buf, buf_size, "%s", part_number);
774
775 return ERROR_OK;
776 }
777
778 static int psoc5lp_nvl_probe(struct flash_bank *bank)
779 {
780 struct psoc5lp_nvl_flash_bank *psoc_nvl_bank = bank->driver_priv;
781 int retval;
782
783 if (psoc_nvl_bank->probed)
784 return ERROR_OK;
785
786 if (bank->target->state != TARGET_HALTED) {
787 LOG_ERROR("Target not halted");
788 return ERROR_TARGET_NOT_HALTED;
789 }
790
791 retval = psoc5lp_find_device(bank->target, &psoc_nvl_bank->device);
792 if (retval != ERROR_OK)
793 return retval;
794
795 bank->base = NVL_META_BASE;
796 bank->size = 4;
797 bank->num_sectors = 1;
798 bank->sectors = calloc(bank->num_sectors,
799 sizeof(struct flash_sector));
800 bank->sectors[0].offset = 0;
801 bank->sectors[0].size = 4;
802 bank->sectors[0].is_erased = -1;
803 bank->sectors[0].is_protected = -1;
804
805 psoc_nvl_bank->probed = true;
806
807 return ERROR_OK;
808 }
809
810 static int psoc5lp_nvl_auto_probe(struct flash_bank *bank)
811 {
812 struct psoc5lp_nvl_flash_bank *psoc_nvl_bank = bank->driver_priv;
813
814 if (psoc_nvl_bank->probed)
815 return ERROR_OK;
816
817 return psoc5lp_nvl_probe(bank);
818 }
819
820 FLASH_BANK_COMMAND_HANDLER(psoc5lp_nvl_flash_bank_command)
821 {
822 struct psoc5lp_nvl_flash_bank *psoc_nvl_bank;
823
824 psoc_nvl_bank = malloc(sizeof(struct psoc5lp_nvl_flash_bank));
825 if (!psoc_nvl_bank)
826 return ERROR_FLASH_OPERATION_FAILED;
827
828 psoc_nvl_bank->probed = false;
829
830 bank->driver_priv = psoc_nvl_bank;
831
832 return ERROR_OK;
833 }
834
835 static const struct command_registration psoc5lp_nvl_exec_command_handlers[] = {
836 COMMAND_REGISTRATION_DONE
837 };
838
839 static const struct command_registration psoc5lp_nvl_command_handlers[] = {
840 {
841 .name = "psoc5lp_nvl",
842 .mode = COMMAND_ANY,
843 .help = "PSoC 5LP NV Latch command group",
844 .usage = "",
845 .chain = psoc5lp_nvl_exec_command_handlers,
846 },
847 COMMAND_REGISTRATION_DONE
848 };
849
850 struct flash_driver psoc5lp_nvl_flash = {
851 .name = "psoc5lp_nvl",
852 .commands = psoc5lp_nvl_command_handlers,
853 .flash_bank_command = psoc5lp_nvl_flash_bank_command,
854 .info = psoc5lp_nvl_get_info_command,
855 .probe = psoc5lp_nvl_probe,
856 .auto_probe = psoc5lp_nvl_auto_probe,
857 .protect_check = psoc5lp_nvl_protect_check,
858 .read = psoc5lp_nvl_read,
859 .erase = psoc5lp_nvl_erase,
860 .erase_check = psoc5lp_nvl_erase_check,
861 .write = psoc5lp_nvl_write,
862 };
863
864 /*
865 * EEPROM
866 */
867
868 struct psoc5lp_eeprom_flash_bank {
869 bool probed;
870 const struct psoc5lp_device *device;
871 };
872
873 static int psoc5lp_eeprom_erase(struct flash_bank *bank, int first, int last)
874 {
875 int i, retval;
876
877 for (i = first; i <= last; i++) {
878 retval = psoc5lp_spc_erase_sector(bank->target,
879 SPC_ARRAY_EEPROM, i);
880 if (retval != ERROR_OK)
881 return retval;
882 }
883
884 return ERROR_OK;
885 }
886
887 static int psoc5lp_eeprom_write(struct flash_bank *bank,
888 const uint8_t *buffer, uint32_t offset, uint32_t byte_count)
889 {
890 struct target *target = bank->target;
891 uint8_t temp[2];
892 unsigned row;
893 int retval;
894
895 if (offset % EEPROM_ROW_SIZE != 0) {
896 LOG_ERROR("Writes must be row-aligned, got offset 0x%08" PRIx32,
897 offset);
898 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
899 }
900
901 retval = psoc5lp_spc_get_temp(target, 3, temp);
902 if (retval != ERROR_OK) {
903 LOG_ERROR("Unable to read Die temperature");
904 return retval;
905 }
906 LOG_DEBUG("Get_Temp: sign 0x%02" PRIx8 ", magnitude 0x%02" PRIx8,
907 temp[0], temp[1]);
908
909 for (row = offset / EEPROM_ROW_SIZE; byte_count >= EEPROM_ROW_SIZE; row++) {
910 retval = psoc5lp_spc_load_row(target, SPC_ARRAY_EEPROM,
911 buffer, EEPROM_ROW_SIZE);
912 if (retval != ERROR_OK)
913 return retval;
914
915 retval = psoc5lp_spc_write_row(target, SPC_ARRAY_EEPROM,
916 row, temp);
917 if (retval != ERROR_OK)
918 return retval;
919
920 buffer += EEPROM_ROW_SIZE;
921 byte_count -= EEPROM_ROW_SIZE;
922 offset += EEPROM_ROW_SIZE;
923 }
924 if (byte_count > 0) {
925 uint8_t buf[EEPROM_ROW_SIZE];
926
927 memcpy(buf, buffer, byte_count);
928 memset(buf + byte_count, bank->default_padded_value,
929 EEPROM_ROW_SIZE - byte_count);
930
931 LOG_DEBUG("Padding %d bytes", EEPROM_ROW_SIZE - byte_count);
932 retval = psoc5lp_spc_load_row(target, SPC_ARRAY_EEPROM,
933 buf, EEPROM_ROW_SIZE);
934 if (retval != ERROR_OK)
935 return retval;
936
937 retval = psoc5lp_spc_write_row(target, SPC_ARRAY_EEPROM,
938 row, temp);
939 if (retval != ERROR_OK)
940 return retval;
941 }
942
943 return ERROR_OK;
944 }
945
946 static int psoc5lp_eeprom_protect_check(struct flash_bank *bank)
947 {
948 int i;
949
950 for (i = 0; i < bank->num_sectors; i++)
951 bank->sectors[i].is_protected = -1;
952
953 return ERROR_OK;
954 }
955
956 static int psoc5lp_eeprom_get_info_command(struct flash_bank *bank, char *buf, int buf_size)
957 {
958 struct psoc5lp_eeprom_flash_bank *psoc_eeprom_bank = bank->driver_priv;
959 char part_number[PART_NUMBER_LEN];
960
961 psoc5lp_get_part_number(psoc_eeprom_bank->device, part_number);
962
963 snprintf(buf, buf_size, "%s", part_number);
964
965 return ERROR_OK;
966 }
967
968 static int psoc5lp_eeprom_probe(struct flash_bank *bank)
969 {
970 struct psoc5lp_eeprom_flash_bank *psoc_eeprom_bank = bank->driver_priv;
971 uint32_t flash_addr = bank->base;
972 uint32_t val;
973 int i, retval;
974
975 if (psoc_eeprom_bank->probed)
976 return ERROR_OK;
977
978 if (bank->target->state != TARGET_HALTED) {
979 LOG_ERROR("Target not halted");
980 return ERROR_TARGET_NOT_HALTED;
981 }
982
983 retval = psoc5lp_find_device(bank->target, &psoc_eeprom_bank->device);
984 if (retval != ERROR_OK)
985 return retval;
986
987 retval = target_read_u32(bank->target, PM_ACT_CFG12, &val);
988 if (retval != ERROR_OK)
989 return retval;
990 if (!(val & PM_ACT_CFG12_EN_EE)) {
991 val |= PM_ACT_CFG12_EN_EE;
992 retval = target_write_u32(bank->target, PM_ACT_CFG12, val);
993 if (retval != ERROR_OK)
994 return retval;
995 }
996
997 bank->size = psoc_eeprom_bank->device->eeprom_kb * 1024;
998 bank->num_sectors = DIV_ROUND_UP(bank->size, EEPROM_SECTOR_SIZE);
999 bank->sectors = calloc(bank->num_sectors,
1000 sizeof(struct flash_sector));
1001 for (i = 0; i < bank->num_sectors; i++) {
1002 bank->sectors[i].size = EEPROM_SECTOR_SIZE;
1003 bank->sectors[i].offset = flash_addr - bank->base;
1004 bank->sectors[i].is_erased = -1;
1005 bank->sectors[i].is_protected = -1;
1006
1007 flash_addr += bank->sectors[i].size;
1008 }
1009
1010 bank->default_padded_value = bank->erased_value = 0x00;
1011
1012 psoc_eeprom_bank->probed = true;
1013
1014 return ERROR_OK;
1015 }
1016
1017 static int psoc5lp_eeprom_auto_probe(struct flash_bank *bank)
1018 {
1019 struct psoc5lp_eeprom_flash_bank *psoc_eeprom_bank = bank->driver_priv;
1020
1021 if (psoc_eeprom_bank->probed)
1022 return ERROR_OK;
1023
1024 return psoc5lp_eeprom_probe(bank);
1025 }
1026
1027 FLASH_BANK_COMMAND_HANDLER(psoc5lp_eeprom_flash_bank_command)
1028 {
1029 struct psoc5lp_eeprom_flash_bank *psoc_eeprom_bank;
1030
1031 psoc_eeprom_bank = malloc(sizeof(struct psoc5lp_eeprom_flash_bank));
1032 if (!psoc_eeprom_bank)
1033 return ERROR_FLASH_OPERATION_FAILED;
1034
1035 psoc_eeprom_bank->probed = false;
1036 psoc_eeprom_bank->device = NULL;
1037
1038 bank->driver_priv = psoc_eeprom_bank;
1039
1040 return ERROR_OK;
1041 }
1042
1043 static const struct command_registration psoc5lp_eeprom_exec_command_handlers[] = {
1044 COMMAND_REGISTRATION_DONE
1045 };
1046
1047 static const struct command_registration psoc5lp_eeprom_command_handlers[] = {
1048 {
1049 .name = "psoc5lp_eeprom",
1050 .mode = COMMAND_ANY,
1051 .help = "PSoC 5LP EEPROM command group",
1052 .usage = "",
1053 .chain = psoc5lp_eeprom_exec_command_handlers,
1054 },
1055 COMMAND_REGISTRATION_DONE
1056 };
1057
1058 struct flash_driver psoc5lp_eeprom_flash = {
1059 .name = "psoc5lp_eeprom",
1060 .commands = psoc5lp_eeprom_command_handlers,
1061 .flash_bank_command = psoc5lp_eeprom_flash_bank_command,
1062 .info = psoc5lp_eeprom_get_info_command,
1063 .probe = psoc5lp_eeprom_probe,
1064 .auto_probe = psoc5lp_eeprom_auto_probe,
1065 .protect_check = psoc5lp_eeprom_protect_check,
1066 .read = default_flash_read,
1067 .erase = psoc5lp_eeprom_erase,
1068 .erase_check = default_flash_blank_check,
1069 .write = psoc5lp_eeprom_write,
1070 };
1071
1072 /*
1073 * Program Flash
1074 */
1075
1076 struct psoc5lp_flash_bank {
1077 bool probed;
1078 const struct psoc5lp_device *device;
1079 bool ecc_enabled;
1080 };
1081
1082 static int psoc5lp_erase(struct flash_bank *bank, int first, int last)
1083 {
1084 struct psoc5lp_flash_bank *psoc_bank = bank->driver_priv;
1085 int i, retval;
1086
1087 if (!psoc_bank->ecc_enabled) {
1088 /* Silently avoid erasing sectors twice */
1089 if (last >= first + bank->num_sectors / 2) {
1090 LOG_DEBUG("Skipping duplicate erase of sectors %d to %d",
1091 first + bank->num_sectors / 2, last);
1092 last = first + (bank->num_sectors / 2) - 1;
1093 }
1094 /* Check for any remaining ECC sectors */
1095 if (last >= bank->num_sectors / 2) {
1096 LOG_WARNING("Skipping erase of ECC region sectors %d to %d",
1097 bank->num_sectors / 2, last);
1098 last = (bank->num_sectors / 2) - 1;
1099 }
1100 }
1101
1102 for (i = first; i <= last; i++) {
1103 retval = psoc5lp_spc_erase_sector(bank->target,
1104 i / SECTORS_PER_BLOCK, i % SECTORS_PER_BLOCK);
1105 if (retval != ERROR_OK)
1106 return retval;
1107 }
1108
1109 return ERROR_OK;
1110 }
1111
1112 /* Derived from core.c:default_flash_blank_check() */
1113 static int psoc5lp_erase_check(struct flash_bank *bank)
1114 {
1115 struct psoc5lp_flash_bank *psoc_bank = bank->driver_priv;
1116 struct target *target = bank->target;
1117 int i, retval;
1118
1119 if (target->state != TARGET_HALTED) {
1120 LOG_ERROR("Target not halted");
1121 return ERROR_TARGET_NOT_HALTED;
1122 }
1123
1124 struct target_memory_check_block *block_array;
1125 block_array = malloc(bank->num_sectors * sizeof(struct target_memory_check_block));
1126 if (block_array == NULL)
1127 return ERROR_FAIL;
1128
1129 for (i = 0; i < bank->num_sectors; i++) {
1130 block_array[i].address = bank->base + bank->sectors[i].offset;
1131 block_array[i].size = bank->sectors[i].size;
1132 block_array[i].result = UINT32_MAX; /* erase state unknown */
1133 }
1134
1135 bool fast_check = true;
1136 for (i = 0; i < bank->num_sectors; ) {
1137 retval = armv7m_blank_check_memory(target,
1138 block_array + i, bank->num_sectors - i,
1139 bank->erased_value);
1140 if (retval < 1) {
1141 /* Run slow fallback if the first run gives no result
1142 * otherwise use possibly incomplete results */
1143 if (i == 0)
1144 fast_check = false;
1145 break;
1146 }
1147 i += retval; /* add number of blocks done this round */
1148 }
1149
1150 if (fast_check) {
1151 if (!psoc_bank->ecc_enabled) {
1152 int half_sectors = bank->num_sectors / 2;
1153 for (i = 0; i < half_sectors / 2; i++)
1154 bank->sectors[i].is_erased =
1155 (block_array[i].result != 1)
1156 ? block_array[i + half_sectors].result
1157 : block_array[i].result;
1158 } else {
1159 for (i = 0; i < bank->num_sectors; i++)
1160 bank->sectors[i].is_erased = block_array[i].result;
1161 }
1162 retval = ERROR_OK;
1163 } else {
1164 LOG_ERROR("Can't run erase check - add working memory");
1165 retval = ERROR_FAIL;
1166 }
1167 free(block_array);
1168
1169 return retval;
1170 }
1171
1172 static int psoc5lp_write(struct flash_bank *bank, const uint8_t *buffer,
1173 uint32_t offset, uint32_t byte_count)
1174 {
1175 struct psoc5lp_flash_bank *psoc_bank = bank->driver_priv;
1176 struct target *target = bank->target;
1177 struct working_area *code_area, *even_row_area, *odd_row_area;
1178 uint32_t row_size;
1179 uint8_t temp[2], buf[12], ecc_bytes[ROW_ECC_SIZE];
1180 unsigned array_id, row;
1181 int i, retval;
1182
1183 if (offset + byte_count > bank->size) {
1184 LOG_ERROR("Writing to ECC not supported");
1185 return ERROR_FLASH_DST_OUT_OF_BANK;
1186 }
1187
1188 if (offset % ROW_SIZE != 0) {
1189 LOG_ERROR("Writes must be row-aligned, got offset 0x%08" PRIx32,
1190 offset);
1191 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
1192 }
1193
1194 row_size = ROW_SIZE;
1195 if (!psoc_bank->ecc_enabled) {
1196 row_size += ROW_ECC_SIZE;
1197 memset(ecc_bytes, bank->default_padded_value, ROW_ECC_SIZE);
1198 }
1199
1200 retval = psoc5lp_spc_get_temp(target, 3, temp);
1201 if (retval != ERROR_OK) {
1202 LOG_ERROR("Unable to read Die temperature");
1203 return retval;
1204 }
1205 LOG_DEBUG("Get_Temp: sign 0x%02" PRIx8 ", magnitude 0x%02" PRIx8,
1206 temp[0], temp[1]);
1207
1208 assert(target_get_working_area_avail(target) == target->working_area_size);
1209 retval = target_alloc_working_area(target,
1210 target_get_working_area_avail(target) / 2, &code_area);
1211 if (retval != ERROR_OK) {
1212 LOG_ERROR("Could not allocate working area for program SRAM");
1213 return retval;
1214 }
1215 assert(code_area->address < 0x20000000);
1216
1217 retval = target_alloc_working_area(target,
1218 SPC_OPCODE_LEN + 1 + row_size + 3 + SPC_OPCODE_LEN + 6,
1219 &even_row_area);
1220 if (retval != ERROR_OK) {
1221 LOG_ERROR("Could not allocate working area for even row");
1222 goto err_alloc_even;
1223 }
1224 assert(even_row_area->address >= 0x20000000);
1225
1226 retval = target_alloc_working_area(target, even_row_area->size,
1227 &odd_row_area);
1228 if (retval != ERROR_OK) {
1229 LOG_ERROR("Could not allocate working area for odd row");
1230 goto err_alloc_odd;
1231 }
1232 assert(odd_row_area->address >= 0x20000000);
1233
1234 for (array_id = offset / BLOCK_SIZE; byte_count > 0; array_id++) {
1235 for (row = (offset / ROW_SIZE) % ROWS_PER_BLOCK;
1236 row < ROWS_PER_BLOCK && byte_count > 0; row++) {
1237 bool even_row = (row % 2 == 0);
1238 struct working_area *data_area = even_row ? even_row_area : odd_row_area;
1239 unsigned len = MIN(ROW_SIZE, byte_count);
1240
1241 LOG_DEBUG("Writing load command for array %u row %u at 0x%08" TARGET_PRIxADDR,
1242 array_id, row, data_area->address);
1243
1244 psoc5lp_spc_write_opcode_buffer(target, buf, SPC_LOAD_ROW);
1245 buf[SPC_OPCODE_LEN] = array_id;
1246 retval = target_write_buffer(target, data_area->address, 4, buf);
1247 if (retval != ERROR_OK)
1248 goto err_write;
1249
1250 retval = target_write_buffer(target,
1251 data_area->address + SPC_OPCODE_LEN + 1,
1252 len, buffer);
1253 if (retval != ERROR_OK)
1254 goto err_write;
1255 buffer += len;
1256 byte_count -= len;
1257 offset += len;
1258
1259 if (len < ROW_SIZE) {
1260 uint8_t padding[ROW_SIZE];
1261
1262 memset(padding, bank->default_padded_value, ROW_SIZE);
1263
1264 LOG_DEBUG("Padding %d bytes", ROW_SIZE - len);
1265 retval = target_write_buffer(target,
1266 data_area->address + SPC_OPCODE_LEN + 1 + len,
1267 ROW_SIZE - len, padding);
1268 if (retval != ERROR_OK)
1269 goto err_write;
1270 }
1271
1272 if (!psoc_bank->ecc_enabled) {
1273 retval = target_write_buffer(target,
1274 data_area->address + SPC_OPCODE_LEN + 1 + ROW_SIZE,
1275 sizeof(ecc_bytes), ecc_bytes);
1276 if (retval != ERROR_OK)
1277 goto err_write;
1278 }
1279
1280 for (i = 0; i < 3; i++)
1281 buf[i] = 0x00; /* 3 NOPs for short delay */
1282 psoc5lp_spc_write_opcode_buffer(target, buf + 3, SPC_PRG_ROW);
1283 buf[3 + SPC_OPCODE_LEN] = array_id;
1284 buf[3 + SPC_OPCODE_LEN + 1] = row >> 8;
1285 buf[3 + SPC_OPCODE_LEN + 2] = row & 0xff;
1286 memcpy(buf + 3 + SPC_OPCODE_LEN + 3, temp, 2);
1287 buf[3 + SPC_OPCODE_LEN + 5] = 0x00; /* padding */
1288 retval = target_write_buffer(target,
1289 data_area->address + SPC_OPCODE_LEN + 1 + row_size,
1290 12, buf);
1291 if (retval != ERROR_OK)
1292 goto err_write;
1293
1294 retval = target_write_u32(target,
1295 even_row ? PHUB_CH0_BASIC_STATUS : PHUB_CH1_BASIC_STATUS,
1296 (even_row ? 0 : 1) << 8);
1297 if (retval != ERROR_OK)
1298 goto err_dma;
1299
1300 retval = target_write_u32(target,
1301 even_row ? PHUB_CH0_BASIC_CFG : PHUB_CH1_BASIC_CFG,
1302 PHUB_CHx_BASIC_CFG_WORK_SEP | PHUB_CHx_BASIC_CFG_EN);
1303 if (retval != ERROR_OK)
1304 goto err_dma;
1305
1306 retval = target_write_u32(target,
1307 even_row ? PHUB_CFGMEM0_CFG0 : PHUB_CFGMEM1_CFG0,
1308 PHUB_CFGMEMx_CFG0);
1309 if (retval != ERROR_OK)
1310 goto err_dma;
1311
1312 retval = target_write_u32(target,
1313 even_row ? PHUB_CFGMEM0_CFG1 : PHUB_CFGMEM1_CFG1,
1314 ((SPC_CPU_DATA >> 16) << 16) | (data_area->address >> 16));
1315 if (retval != ERROR_OK)
1316 goto err_dma;
1317
1318 retval = target_write_u32(target,
1319 even_row ? PHUB_TDMEM0_ORIG_TD0 : PHUB_TDMEM1_ORIG_TD0,
1320 PHUB_TDMEMx_ORIG_TD0_INC_SRC_ADDR |
1321 PHUB_TDMEMx_ORIG_TD0_NEXT_TD_PTR_LAST |
1322 ((SPC_OPCODE_LEN + 1 + row_size + 3 + SPC_OPCODE_LEN + 5) & 0xfff));
1323 if (retval != ERROR_OK)
1324 goto err_dma;
1325
1326 retval = target_write_u32(target,
1327 even_row ? PHUB_TDMEM0_ORIG_TD1 : PHUB_TDMEM1_ORIG_TD1,
1328 ((SPC_CPU_DATA & 0xffff) << 16) | (data_area->address & 0xffff));
1329 if (retval != ERROR_OK)
1330 goto err_dma;
1331
1332 retval = psoc5lp_spc_busy_wait_idle(target);
1333 if (retval != ERROR_OK)
1334 goto err_idle;
1335
1336 retval = target_write_u32(target,
1337 even_row ? PHUB_CH0_ACTION : PHUB_CH1_ACTION,
1338 PHUB_CHx_ACTION_CPU_REQ);
1339 if (retval != ERROR_OK)
1340 goto err_dma_action;
1341 }
1342 }
1343
1344 retval = psoc5lp_spc_busy_wait_idle(target);
1345
1346 err_dma_action:
1347 err_idle:
1348 err_dma:
1349 err_write:
1350 target_free_working_area(target, odd_row_area);
1351 err_alloc_odd:
1352 target_free_working_area(target, even_row_area);
1353 err_alloc_even:
1354 target_free_working_area(target, code_area);
1355
1356 return retval;
1357 }
1358
1359 static int psoc5lp_protect_check(struct flash_bank *bank)
1360 {
1361 struct psoc5lp_flash_bank *psoc_bank = bank->driver_priv;
1362 uint8_t row_data[ROW_SIZE];
1363 const unsigned protection_bytes_per_sector = ROWS_PER_SECTOR * 2 / 8;
1364 unsigned i, j, k, num_sectors;
1365 int retval;
1366
1367 if (bank->target->state != TARGET_HALTED) {
1368 LOG_ERROR("Target not halted");
1369 return ERROR_TARGET_NOT_HALTED;
1370 }
1371
1372 for (i = 0; i < DIV_ROUND_UP(bank->size, BLOCK_SIZE); i++) {
1373 retval = psoc5lp_spc_read_hidden_row(bank->target, i,
1374 SPC_ROW_PROTECTION, row_data);
1375 if (retval != ERROR_OK)
1376 return retval;
1377
1378 /* Last flash array may have less rows, but in practice full sectors. */
1379 if (i == bank->size / BLOCK_SIZE)
1380 num_sectors = (bank->size % BLOCK_SIZE) / SECTOR_SIZE;
1381 else
1382 num_sectors = SECTORS_PER_BLOCK;
1383
1384 for (j = 0; j < num_sectors; j++) {
1385 int sector_nr = i * SECTORS_PER_BLOCK + j;
1386 struct flash_sector *sector = &bank->sectors[sector_nr];
1387 struct flash_sector *ecc_sector;
1388
1389 if (psoc_bank->ecc_enabled)
1390 ecc_sector = &bank->sectors[bank->num_sectors + sector_nr];
1391 else
1392 ecc_sector = &bank->sectors[bank->num_sectors / 2 + sector_nr];
1393
1394 sector->is_protected = ecc_sector->is_protected = 0;
1395 for (k = protection_bytes_per_sector * j;
1396 k < protection_bytes_per_sector * (j + 1); k++) {
1397 assert(k < protection_bytes_per_sector * SECTORS_PER_BLOCK);
1398 LOG_DEBUG("row[%u][%02u] = 0x%02" PRIx8, i, k, row_data[k]);
1399 if (row_data[k] != 0x00) {
1400 sector->is_protected = ecc_sector->is_protected = 1;
1401 break;
1402 }
1403 }
1404 }
1405 }
1406
1407 return ERROR_OK;
1408 }
1409
1410 static int psoc5lp_get_info_command(struct flash_bank *bank, char *buf, int buf_size)
1411 {
1412 struct psoc5lp_flash_bank *psoc_bank = bank->driver_priv;
1413 char part_number[PART_NUMBER_LEN];
1414 const char *ecc;
1415
1416 psoc5lp_get_part_number(psoc_bank->device, part_number);
1417 ecc = psoc_bank->ecc_enabled ? "ECC enabled" : "ECC disabled";
1418
1419 snprintf(buf, buf_size, "%s %s", part_number, ecc);
1420
1421 return ERROR_OK;
1422 }
1423
1424 static int psoc5lp_probe(struct flash_bank *bank)
1425 {
1426 struct target *target = bank->target;
1427 struct psoc5lp_flash_bank *psoc_bank = bank->driver_priv;
1428 uint32_t flash_addr = bank->base;
1429 uint8_t nvl[4], temp[2];
1430 int i, retval;
1431
1432 if (target->state != TARGET_HALTED) {
1433 LOG_ERROR("Target not halted");
1434 return ERROR_TARGET_NOT_HALTED;
1435 }
1436
1437 if (!psoc_bank->device) {
1438 retval = psoc5lp_find_device(target, &psoc_bank->device);
1439 if (retval != ERROR_OK)
1440 return retval;
1441
1442 bank->size = psoc_bank->device->flash_kb * 1024;
1443 }
1444
1445 bank->num_sectors = DIV_ROUND_UP(bank->size, SECTOR_SIZE);
1446
1447 if (!psoc_bank->probed) {
1448 retval = psoc5lp_spc_enable_clock(target);
1449 if (retval != ERROR_OK)
1450 return retval;
1451
1452 /* First values read are inaccurate, so do it once now. */
1453 retval = psoc5lp_spc_get_temp(target, 3, temp);
1454 if (retval != ERROR_OK) {
1455 LOG_ERROR("Unable to read Die temperature");
1456 return retval;
1457 }
1458
1459 bank->sectors = calloc(bank->num_sectors * 2,
1460 sizeof(struct flash_sector));
1461 for (i = 0; i < bank->num_sectors; i++) {
1462 bank->sectors[i].size = SECTOR_SIZE;
1463 bank->sectors[i].offset = flash_addr - bank->base;
1464 bank->sectors[i].is_erased = -1;
1465 bank->sectors[i].is_protected = -1;
1466
1467 flash_addr += bank->sectors[i].size;
1468 }
1469 flash_addr = 0x48000000;
1470 for (i = bank->num_sectors; i < bank->num_sectors * 2; i++) {
1471 bank->sectors[i].size = ROWS_PER_SECTOR * ROW_ECC_SIZE;
1472 bank->sectors[i].offset = flash_addr - bank->base;
1473 bank->sectors[i].is_erased = -1;
1474 bank->sectors[i].is_protected = -1;
1475
1476 flash_addr += bank->sectors[i].size;
1477 }
1478
1479 bank->default_padded_value = bank->erased_value = 0x00;
1480
1481 psoc_bank->probed = true;
1482 }
1483
1484 retval = psoc5lp_spc_read_byte(target, SPC_ARRAY_NVL_USER, 3, &nvl[3]);
1485 if (retval != ERROR_OK)
1486 return retval;
1487 LOG_DEBUG("NVL[%d] = 0x%02" PRIx8, 3, nvl[3]);
1488 psoc_bank->ecc_enabled = nvl[3] & NVL_3_ECCEN;
1489
1490 if (!psoc_bank->ecc_enabled)
1491 bank->num_sectors *= 2;
1492
1493 return ERROR_OK;
1494 }
1495
1496 static int psoc5lp_auto_probe(struct flash_bank *bank)
1497 {
1498 return psoc5lp_probe(bank);
1499 }
1500
1501 COMMAND_HANDLER(psoc5lp_handle_mass_erase_command)
1502 {
1503 struct flash_bank *bank;
1504 int retval;
1505
1506 if (CMD_ARGC < 1)
1507 return ERROR_COMMAND_SYNTAX_ERROR;
1508
1509 retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
1510 if (retval != ERROR_OK)
1511 return retval;
1512
1513 retval = psoc5lp_spc_erase_all(bank->target);
1514 if (retval == ERROR_OK)
1515 command_print(CMD_CTX, "PSoC 5LP erase succeeded");
1516 else
1517 command_print(CMD_CTX, "PSoC 5LP erase failed");
1518
1519 return retval;
1520 }
1521
1522 FLASH_BANK_COMMAND_HANDLER(psoc5lp_flash_bank_command)
1523 {
1524 struct psoc5lp_flash_bank *psoc_bank;
1525
1526 psoc_bank = malloc(sizeof(struct psoc5lp_flash_bank));
1527 if (!psoc_bank)
1528 return ERROR_FLASH_OPERATION_FAILED;
1529
1530 psoc_bank->probed = false;
1531 psoc_bank->device = NULL;
1532
1533 bank->driver_priv = psoc_bank;
1534
1535 return ERROR_OK;
1536 }
1537
1538 static const struct command_registration psoc5lp_exec_command_handlers[] = {
1539 {
1540 .name = "mass_erase",
1541 .handler = psoc5lp_handle_mass_erase_command,
1542 .mode = COMMAND_EXEC,
1543 .usage = "bank_id",
1544 .help = "Erase all flash data and ECC/configuration bytes, "
1545 "all flash protection rows, "
1546 "and all row latches in all flash arrays on the device.",
1547 },
1548 COMMAND_REGISTRATION_DONE
1549 };
1550
1551 static const struct command_registration psoc5lp_command_handlers[] = {
1552 {
1553 .name = "psoc5lp",
1554 .mode = COMMAND_ANY,
1555 .help = "PSoC 5LP flash command group",
1556 .usage = "",
1557 .chain = psoc5lp_exec_command_handlers,
1558 },
1559 COMMAND_REGISTRATION_DONE
1560 };
1561
1562 struct flash_driver psoc5lp_flash = {
1563 .name = "psoc5lp",
1564 .commands = psoc5lp_command_handlers,
1565 .flash_bank_command = psoc5lp_flash_bank_command,
1566 .info = psoc5lp_get_info_command,
1567 .probe = psoc5lp_probe,
1568 .auto_probe = psoc5lp_auto_probe,
1569 .protect_check = psoc5lp_protect_check,
1570 .read = default_flash_read,
1571 .erase = psoc5lp_erase,
1572 .erase_check = psoc5lp_erase_check,
1573 .write = psoc5lp_write,
1574 };

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)