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

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)