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

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)