target/xtensa: avoid IHI for writes to non-executable memory
[openocd.git] / src / flash / nor / psoc5lp.c
blob407efbcab312e28f359d06808ec152824a05f55f
1 // SPDX-License-Identifier: GPL-2.0-or-later
3 /*
4 * PSoC 5LP flash driver
6 * Copyright (c) 2016 Andreas Färber
7 */
9 #ifdef HAVE_CONFIG_H
10 #include "config.h"
11 #endif
13 #include "imp.h"
14 #include <helper/time_support.h>
15 #include <target/armv7m.h>
17 #define PM_ACT_CFG0 0x400043A0
18 #define PM_ACT_CFG12 0x400043AC
19 #define SPC_CPU_DATA 0x40004720
20 #define SPC_SR 0x40004722
21 #define PRT1_PC2 0x4000500A
22 #define PHUB_CH0_BASIC_CFG 0x40007010
23 #define PHUB_CH0_ACTION 0x40007014
24 #define PHUB_CH0_BASIC_STATUS 0x40007018
25 #define PHUB_CH1_BASIC_CFG 0x40007020
26 #define PHUB_CH1_ACTION 0x40007024
27 #define PHUB_CH1_BASIC_STATUS 0x40007028
28 #define PHUB_CFGMEM0_CFG0 0x40007600
29 #define PHUB_CFGMEM0_CFG1 0x40007604
30 #define PHUB_CFGMEM1_CFG0 0x40007608
31 #define PHUB_CFGMEM1_CFG1 0x4000760C
32 #define PHUB_TDMEM0_ORIG_TD0 0x40007800
33 #define PHUB_TDMEM0_ORIG_TD1 0x40007804
34 #define PHUB_TDMEM1_ORIG_TD0 0x40007808
35 #define PHUB_TDMEM1_ORIG_TD1 0x4000780C
36 #define PANTHER_DEVICE_ID 0x4008001C
38 /* NVL is not actually mapped to the Cortex-M address space
39 * As we need a base address different from other banks in the device
40 * we use the address of NVL programming data in Cypress images */
41 #define NVL_META_BASE 0x90000000
43 #define PM_ACT_CFG12_EN_EE (1 << 4)
45 #define SPC_KEY1 0xB6
46 #define SPC_KEY2 0xD3
48 #define SPC_LOAD_BYTE 0x00
49 #define SPC_LOAD_MULTI_BYTE 0x01
50 #define SPC_LOAD_ROW 0x02
51 #define SPC_READ_BYTE 0x03
52 #define SPC_READ_MULTI_BYTE 0x04
53 #define SPC_WRITE_ROW 0x05
54 #define SPC_WRITE_USER_NVL 0x06
55 #define SPC_PRG_ROW 0x07
56 #define SPC_ERASE_SECTOR 0x08
57 #define SPC_ERASE_ALL 0x09
58 #define SPC_READ_HIDDEN_ROW 0x0A
59 #define SPC_PROGRAM_PROTECT_ROW 0x0B
60 #define SPC_GET_CHECKSUM 0x0C
61 #define SPC_GET_TEMP 0x0E
62 #define SPC_READ_VOLATILE_BYTE 0x10
64 #define SPC_ARRAY_ALL 0x3F
65 #define SPC_ARRAY_EEPROM 0x40
66 #define SPC_ARRAY_NVL_USER 0x80
67 #define SPC_ARRAY_NVL_WO 0xF8
69 #define SPC_ROW_PROTECTION 0
71 #define SPC_OPCODE_LEN 3
73 #define SPC_SR_DATA_READY (1 << 0)
74 #define SPC_SR_IDLE (1 << 1)
76 #define PM_ACT_CFG0_EN_CLK_SPC (1 << 3)
78 #define PHUB_CHX_BASIC_CFG_EN (1 << 0)
79 #define PHUB_CHX_BASIC_CFG_WORK_SEP (1 << 5)
81 #define PHUB_CHX_ACTION_CPU_REQ (1 << 0)
83 #define PHUB_CFGMEMX_CFG0 (1 << 7)
85 #define PHUB_TDMEMX_ORIG_TD0_NEXT_TD_PTR_LAST (0xff << 16)
86 #define PHUB_TDMEMX_ORIG_TD0_INC_SRC_ADDR (1 << 24)
88 #define NVL_3_ECCEN (1 << 3)
90 #define ROW_SIZE 256
91 #define ROW_ECC_SIZE 32
92 #define ROWS_PER_SECTOR 64
93 #define SECTOR_SIZE (ROWS_PER_SECTOR * ROW_SIZE)
94 #define ROWS_PER_BLOCK 256
95 #define BLOCK_SIZE (ROWS_PER_BLOCK * ROW_SIZE)
96 #define SECTORS_PER_BLOCK (BLOCK_SIZE / SECTOR_SIZE)
97 #define EEPROM_ROW_SIZE 16
98 #define EEPROM_SECTOR_SIZE (ROWS_PER_SECTOR * EEPROM_ROW_SIZE)
99 #define EEPROM_BLOCK_SIZE (ROWS_PER_BLOCK * EEPROM_ROW_SIZE)
101 #define PART_NUMBER_LEN (17 + 1)
103 struct psoc5lp_device {
104 uint32_t id;
105 unsigned fam;
106 unsigned speed_mhz;
107 unsigned flash_kb;
108 unsigned eeprom_kb;
112 * Device information collected from datasheets.
113 * Different temperature ranges (C/I/Q/A) may share IDs, not differing otherwise.
115 static const struct psoc5lp_device psoc5lp_devices[] = {
116 /* CY8C58LP Family Datasheet */
117 { .id = 0x2E11F069, .fam = 8, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 },
118 { .id = 0x2E120069, .fam = 8, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 },
119 { .id = 0x2E123069, .fam = 8, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 },
120 { .id = 0x2E124069, .fam = 8, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 },
121 { .id = 0x2E126069, .fam = 8, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 },
122 { .id = 0x2E127069, .fam = 8, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 },
123 { .id = 0x2E117069, .fam = 8, .speed_mhz = 67, .flash_kb = 128, .eeprom_kb = 2 },
124 { .id = 0x2E118069, .fam = 8, .speed_mhz = 67, .flash_kb = 128, .eeprom_kb = 2 },
125 { .id = 0x2E119069, .fam = 8, .speed_mhz = 67, .flash_kb = 128, .eeprom_kb = 2 },
126 { .id = 0x2E11C069, .fam = 8, .speed_mhz = 67, .flash_kb = 128, .eeprom_kb = 2 },
127 { .id = 0x2E114069, .fam = 8, .speed_mhz = 67, .flash_kb = 64, .eeprom_kb = 2 },
128 { .id = 0x2E115069, .fam = 8, .speed_mhz = 67, .flash_kb = 64, .eeprom_kb = 2 },
129 { .id = 0x2E116069, .fam = 8, .speed_mhz = 67, .flash_kb = 64, .eeprom_kb = 2 },
130 { .id = 0x2E160069, .fam = 8, .speed_mhz = 80, .flash_kb = 256, .eeprom_kb = 2 },
131 /* '' */
132 { .id = 0x2E161069, .fam = 8, .speed_mhz = 80, .flash_kb = 256, .eeprom_kb = 2 },
133 /* '' */
134 { .id = 0x2E1D2069, .fam = 8, .speed_mhz = 80, .flash_kb = 256, .eeprom_kb = 2 },
135 { .id = 0x2E1D6069, .fam = 8, .speed_mhz = 80, .flash_kb = 256, .eeprom_kb = 2 },
137 /* CY8C56LP Family Datasheet */
138 { .id = 0x2E10A069, .fam = 6, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 },
139 { .id = 0x2E10D069, .fam = 6, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 },
140 { .id = 0x2E10E069, .fam = 6, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 },
141 { .id = 0x2E106069, .fam = 6, .speed_mhz = 67, .flash_kb = 128, .eeprom_kb = 2 },
142 { .id = 0x2E108069, .fam = 6, .speed_mhz = 67, .flash_kb = 128, .eeprom_kb = 2 },
143 { .id = 0x2E109069, .fam = 6, .speed_mhz = 67, .flash_kb = 128, .eeprom_kb = 2 },
144 { .id = 0x2E101069, .fam = 6, .speed_mhz = 67, .flash_kb = 64, .eeprom_kb = 2 },
145 { .id = 0x2E104069, .fam = 6, .speed_mhz = 67, .flash_kb = 64, .eeprom_kb = 2 },
146 /* '' */
147 { .id = 0x2E105069, .fam = 6, .speed_mhz = 67, .flash_kb = 64, .eeprom_kb = 2 },
148 { .id = 0x2E128069, .fam = 6, .speed_mhz = 67, .flash_kb = 128, .eeprom_kb = 2 },
149 /* '' */
150 { .id = 0x2E122069, .fam = 6, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 },
151 { .id = 0x2E129069, .fam = 6, .speed_mhz = 67, .flash_kb = 128, .eeprom_kb = 2 },
152 { .id = 0x2E163069, .fam = 6, .speed_mhz = 80, .flash_kb = 256, .eeprom_kb = 2 },
153 { .id = 0x2E156069, .fam = 6, .speed_mhz = 80, .flash_kb = 256, .eeprom_kb = 2 },
154 { .id = 0x2E1D3069, .fam = 6, .speed_mhz = 80, .flash_kb = 256, .eeprom_kb = 2 },
156 /* CY8C54LP Family Datasheet */
157 { .id = 0x2E11A069, .fam = 4, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 },
158 { .id = 0x2E16A069, .fam = 4, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 },
159 { .id = 0x2E12A069, .fam = 4, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 },
160 { .id = 0x2E103069, .fam = 4, .speed_mhz = 67, .flash_kb = 128, .eeprom_kb = 2 },
161 { .id = 0x2E16C069, .fam = 4, .speed_mhz = 67, .flash_kb = 128, .eeprom_kb = 2 },
162 { .id = 0x2E102069, .fam = 4, .speed_mhz = 67, .flash_kb = 64, .eeprom_kb = 2 },
163 { .id = 0x2E148069, .fam = 4, .speed_mhz = 67, .flash_kb = 64, .eeprom_kb = 2 },
164 { .id = 0x2E155069, .fam = 4, .speed_mhz = 67, .flash_kb = 64, .eeprom_kb = 2 },
165 { .id = 0x2E16B069, .fam = 4, .speed_mhz = 67, .flash_kb = 64, .eeprom_kb = 2 },
166 { .id = 0x2E12B069, .fam = 4, .speed_mhz = 67, .flash_kb = 32, .eeprom_kb = 2 },
167 { .id = 0x2E168069, .fam = 4, .speed_mhz = 67, .flash_kb = 32, .eeprom_kb = 2 },
168 { .id = 0x2E178069, .fam = 4, .speed_mhz = 80, .flash_kb = 256, .eeprom_kb = 2 },
169 { .id = 0x2E15D069, .fam = 4, .speed_mhz = 80, .flash_kb = 256, .eeprom_kb = 2 },
170 { .id = 0x2E1D4069, .fam = 4, .speed_mhz = 80, .flash_kb = 256, .eeprom_kb = 2 },
172 /* CY8C52LP Family Datasheet */
173 { .id = 0x2E11E069, .fam = 2, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 },
174 { .id = 0x2E12F069, .fam = 2, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 },
175 { .id = 0x2E133069, .fam = 2, .speed_mhz = 67, .flash_kb = 128, .eeprom_kb = 2 },
176 { .id = 0x2E159069, .fam = 2, .speed_mhz = 67, .flash_kb = 128, .eeprom_kb = 2 },
177 { .id = 0x2E11D069, .fam = 2, .speed_mhz = 67, .flash_kb = 64, .eeprom_kb = 2 },
178 { .id = 0x2E121069, .fam = 2, .speed_mhz = 67, .flash_kb = 64, .eeprom_kb = 2 },
179 { .id = 0x2E184069, .fam = 2, .speed_mhz = 67, .flash_kb = 64, .eeprom_kb = 2 },
180 { .id = 0x2E196069, .fam = 2, .speed_mhz = 67, .flash_kb = 64, .eeprom_kb = 2 },
181 { .id = 0x2E132069, .fam = 2, .speed_mhz = 67, .flash_kb = 32, .eeprom_kb = 2 },
182 { .id = 0x2E138069, .fam = 2, .speed_mhz = 67, .flash_kb = 32, .eeprom_kb = 2 },
183 { .id = 0x2E13A069, .fam = 2, .speed_mhz = 67, .flash_kb = 32, .eeprom_kb = 2 },
184 { .id = 0x2E152069, .fam = 2, .speed_mhz = 67, .flash_kb = 32, .eeprom_kb = 2 },
185 { .id = 0x2E15F069, .fam = 2, .speed_mhz = 80, .flash_kb = 256, .eeprom_kb = 2 },
186 { .id = 0x2E15A069, .fam = 2, .speed_mhz = 80, .flash_kb = 256, .eeprom_kb = 2 },
187 { .id = 0x2E1D5069, .fam = 2, .speed_mhz = 80, .flash_kb = 256, .eeprom_kb = 2 },
190 static void psoc5lp_get_part_number(const struct psoc5lp_device *dev, char *str)
192 strcpy(str, "CY8Cabcdefg-LPxxx");
194 str[4] = '5';
195 str[5] = '0' + dev->fam;
197 switch (dev->speed_mhz) {
198 case 67:
199 str[6] = '6';
200 break;
201 case 80:
202 str[6] = '8';
203 break;
204 default:
205 str[6] = '?';
208 switch (dev->flash_kb) {
209 case 32:
210 str[7] = '5';
211 break;
212 case 64:
213 str[7] = '6';
214 break;
215 case 128:
216 str[7] = '7';
217 break;
218 case 256:
219 str[7] = '8';
220 break;
221 default:
222 str[7] = '?';
225 /* Package does not matter. */
226 str[8] = 'x';
227 str[9] = 'x';
229 /* Temperate range cannot uniquely be identified. */
230 str[10] = 'x';
233 static int psoc5lp_get_device_id(struct target *target, uint32_t *id)
235 int retval;
237 retval = target_read_u32(target, PANTHER_DEVICE_ID, id); /* dummy read */
238 if (retval != ERROR_OK)
239 return retval;
240 retval = target_read_u32(target, PANTHER_DEVICE_ID, id);
241 return retval;
244 static int psoc5lp_find_device(struct target *target,
245 const struct psoc5lp_device **device)
247 uint32_t device_id;
248 unsigned i;
249 int retval;
251 *device = NULL;
253 retval = psoc5lp_get_device_id(target, &device_id);
254 if (retval != ERROR_OK)
255 return retval;
256 LOG_DEBUG("PANTHER_DEVICE_ID = 0x%08" PRIX32, device_id);
258 for (i = 0; i < ARRAY_SIZE(psoc5lp_devices); i++) {
259 if (psoc5lp_devices[i].id == device_id) {
260 *device = &psoc5lp_devices[i];
261 return ERROR_OK;
265 LOG_ERROR("Device 0x%08" PRIX32 " not supported", device_id);
266 return ERROR_FLASH_OPER_UNSUPPORTED;
269 static int psoc5lp_spc_enable_clock(struct target *target)
271 int retval;
272 uint8_t pm_act_cfg0;
274 retval = target_read_u8(target, PM_ACT_CFG0, &pm_act_cfg0);
275 if (retval != ERROR_OK) {
276 LOG_ERROR("Cannot read PM_ACT_CFG0");
277 return retval;
280 if (pm_act_cfg0 & PM_ACT_CFG0_EN_CLK_SPC)
281 return ERROR_OK; /* clock already enabled */
283 retval = target_write_u8(target, PM_ACT_CFG0, pm_act_cfg0 | PM_ACT_CFG0_EN_CLK_SPC);
284 if (retval != ERROR_OK)
285 LOG_ERROR("Cannot enable SPC clock");
287 return retval;
290 static int psoc5lp_spc_write_opcode(struct target *target, uint8_t opcode)
292 int retval;
294 retval = target_write_u8(target, SPC_CPU_DATA, SPC_KEY1);
295 if (retval != ERROR_OK)
296 return retval;
297 retval = target_write_u8(target, SPC_CPU_DATA, SPC_KEY2 + opcode);
298 if (retval != ERROR_OK)
299 return retval;
300 retval = target_write_u8(target, SPC_CPU_DATA, opcode);
301 return retval;
304 static void psoc5lp_spc_write_opcode_buffer(struct target *target,
305 uint8_t *buf, uint8_t opcode)
307 buf[0] = SPC_KEY1;
308 buf[1] = SPC_KEY2 + opcode;
309 buf[2] = opcode;
312 static int psoc5lp_spc_busy_wait_data(struct target *target)
314 int64_t endtime;
315 uint8_t sr;
316 int retval;
318 retval = target_read_u8(target, SPC_SR, &sr); /* dummy read */
319 if (retval != ERROR_OK)
320 return retval;
322 endtime = timeval_ms() + 1000; /* 1 second timeout */
323 do {
324 alive_sleep(1);
325 retval = target_read_u8(target, SPC_SR, &sr);
326 if (retval != ERROR_OK)
327 return retval;
328 if (sr == SPC_SR_DATA_READY)
329 return ERROR_OK;
330 } while (timeval_ms() < endtime);
332 return ERROR_FLASH_OPERATION_FAILED;
335 static int psoc5lp_spc_busy_wait_idle(struct target *target)
337 int64_t endtime;
338 uint8_t sr;
339 int retval;
341 retval = target_read_u8(target, SPC_SR, &sr); /* dummy read */
342 if (retval != ERROR_OK)
343 return retval;
345 endtime = timeval_ms() + 1000; /* 1 second timeout */
346 do {
347 alive_sleep(1);
348 retval = target_read_u8(target, SPC_SR, &sr);
349 if (retval != ERROR_OK)
350 return retval;
351 if (sr == SPC_SR_IDLE)
352 return ERROR_OK;
353 } while (timeval_ms() < endtime);
355 return ERROR_FLASH_OPERATION_FAILED;
358 static int psoc5lp_spc_load_byte(struct target *target,
359 uint8_t array_id, uint8_t offset, uint8_t value)
361 int retval;
363 retval = psoc5lp_spc_write_opcode(target, SPC_LOAD_BYTE);
364 if (retval != ERROR_OK)
365 return retval;
366 retval = target_write_u8(target, SPC_CPU_DATA, array_id);
367 if (retval != ERROR_OK)
368 return retval;
369 retval = target_write_u8(target, SPC_CPU_DATA, offset);
370 if (retval != ERROR_OK)
371 return retval;
372 retval = target_write_u8(target, SPC_CPU_DATA, value);
373 if (retval != ERROR_OK)
374 return retval;
376 retval = psoc5lp_spc_busy_wait_idle(target);
377 if (retval != ERROR_OK)
378 return retval;
380 return ERROR_OK;
383 static int psoc5lp_spc_load_row(struct target *target,
384 uint8_t array_id, const uint8_t *data, unsigned row_size)
386 unsigned i;
387 int retval;
389 retval = psoc5lp_spc_write_opcode(target, SPC_LOAD_ROW);
390 if (retval != ERROR_OK)
391 return retval;
392 retval = target_write_u8(target, SPC_CPU_DATA, array_id);
393 if (retval != ERROR_OK)
394 return retval;
396 for (i = 0; i < row_size; i++) {
397 retval = target_write_u8(target, SPC_CPU_DATA, data[i]);
398 if (retval != ERROR_OK)
399 return retval;
402 retval = psoc5lp_spc_busy_wait_idle(target);
403 if (retval != ERROR_OK)
404 return retval;
406 return ERROR_OK;
409 static int psoc5lp_spc_read_byte(struct target *target,
410 uint8_t array_id, uint8_t offset, uint8_t *data)
412 int retval;
414 retval = psoc5lp_spc_write_opcode(target, SPC_READ_BYTE);
415 if (retval != ERROR_OK)
416 return retval;
417 retval = target_write_u8(target, SPC_CPU_DATA, array_id);
418 if (retval != ERROR_OK)
419 return retval;
420 retval = target_write_u8(target, SPC_CPU_DATA, offset);
421 if (retval != ERROR_OK)
422 return retval;
424 retval = psoc5lp_spc_busy_wait_data(target);
425 if (retval != ERROR_OK)
426 return retval;
428 retval = target_read_u8(target, SPC_CPU_DATA, data);
429 if (retval != ERROR_OK)
430 return retval;
432 retval = psoc5lp_spc_busy_wait_idle(target);
433 if (retval != ERROR_OK)
434 return retval;
436 return ERROR_OK;
439 static int psoc5lp_spc_write_row(struct target *target,
440 uint8_t array_id, uint16_t row_id, const uint8_t *temp)
442 int retval;
444 retval = psoc5lp_spc_write_opcode(target, SPC_WRITE_ROW);
445 if (retval != ERROR_OK)
446 return retval;
447 retval = target_write_u8(target, SPC_CPU_DATA, array_id);
448 if (retval != ERROR_OK)
449 return retval;
450 retval = target_write_u8(target, SPC_CPU_DATA, row_id >> 8);
451 if (retval != ERROR_OK)
452 return retval;
453 retval = target_write_u8(target, SPC_CPU_DATA, row_id & 0xff);
454 if (retval != ERROR_OK)
455 return retval;
456 retval = target_write_u8(target, SPC_CPU_DATA, temp[0]);
457 if (retval != ERROR_OK)
458 return retval;
459 retval = target_write_u8(target, SPC_CPU_DATA, temp[1]);
460 if (retval != ERROR_OK)
461 return retval;
463 retval = psoc5lp_spc_busy_wait_idle(target);
464 if (retval != ERROR_OK)
465 return retval;
467 return ERROR_OK;
470 static int psoc5lp_spc_write_user_nvl(struct target *target,
471 uint8_t array_id)
473 int retval;
475 retval = psoc5lp_spc_write_opcode(target, SPC_WRITE_USER_NVL);
476 if (retval != ERROR_OK)
477 return retval;
478 retval = target_write_u8(target, SPC_CPU_DATA, array_id);
479 if (retval != ERROR_OK)
480 return retval;
482 retval = psoc5lp_spc_busy_wait_idle(target);
483 if (retval != ERROR_OK)
484 return retval;
486 return ERROR_OK;
489 static int psoc5lp_spc_erase_sector(struct target *target,
490 uint8_t array_id, uint8_t row_id)
492 int retval;
494 retval = psoc5lp_spc_write_opcode(target, SPC_ERASE_SECTOR);
495 if (retval != ERROR_OK)
496 return retval;
497 retval = target_write_u8(target, SPC_CPU_DATA, array_id);
498 if (retval != ERROR_OK)
499 return retval;
500 retval = target_write_u8(target, SPC_CPU_DATA, row_id);
501 if (retval != ERROR_OK)
502 return retval;
504 retval = psoc5lp_spc_busy_wait_idle(target);
505 if (retval != ERROR_OK)
506 return retval;
508 return ERROR_OK;
511 static int psoc5lp_spc_erase_all(struct target *target)
513 int retval;
515 retval = psoc5lp_spc_write_opcode(target, SPC_ERASE_ALL);
516 if (retval != ERROR_OK)
517 return retval;
519 retval = psoc5lp_spc_busy_wait_idle(target);
520 if (retval != ERROR_OK)
521 return retval;
523 return ERROR_OK;
526 static int psoc5lp_spc_read_hidden_row(struct target *target,
527 uint8_t array_id, uint8_t row_id, uint8_t *data)
529 int i, retval;
531 retval = psoc5lp_spc_write_opcode(target, SPC_READ_HIDDEN_ROW);
532 if (retval != ERROR_OK)
533 return retval;
534 retval = target_write_u8(target, SPC_CPU_DATA, array_id);
535 if (retval != ERROR_OK)
536 return retval;
537 retval = target_write_u8(target, SPC_CPU_DATA, row_id);
538 if (retval != ERROR_OK)
539 return retval;
541 retval = psoc5lp_spc_busy_wait_data(target);
542 if (retval != ERROR_OK)
543 return retval;
545 for (i = 0; i < ROW_SIZE; i++) {
546 retval = target_read_u8(target, SPC_CPU_DATA, &data[i]);
547 if (retval != ERROR_OK)
548 return retval;
551 retval = psoc5lp_spc_busy_wait_idle(target);
552 if (retval != ERROR_OK)
553 return retval;
555 return ERROR_OK;
558 static int psoc5lp_spc_get_temp(struct target *target, uint8_t samples,
559 uint8_t *data)
561 int retval;
563 retval = psoc5lp_spc_write_opcode(target, SPC_GET_TEMP);
564 if (retval != ERROR_OK)
565 return retval;
566 retval = target_write_u8(target, SPC_CPU_DATA, samples);
567 if (retval != ERROR_OK)
568 return retval;
570 retval = psoc5lp_spc_busy_wait_data(target);
571 if (retval != ERROR_OK)
572 return retval;
574 retval = target_read_u8(target, SPC_CPU_DATA, &data[0]);
575 if (retval != ERROR_OK)
576 return retval;
577 retval = target_read_u8(target, SPC_CPU_DATA, &data[1]);
578 if (retval != ERROR_OK)
579 return retval;
581 retval = psoc5lp_spc_busy_wait_idle(target);
582 if (retval != ERROR_OK)
583 return retval;
585 return ERROR_OK;
588 static int psoc5lp_spc_read_volatile_byte(struct target *target,
589 uint8_t array_id, uint8_t offset, uint8_t *data)
591 int retval;
593 retval = psoc5lp_spc_write_opcode(target, SPC_READ_VOLATILE_BYTE);
594 if (retval != ERROR_OK)
595 return retval;
596 retval = target_write_u8(target, SPC_CPU_DATA, array_id);
597 if (retval != ERROR_OK)
598 return retval;
599 retval = target_write_u8(target, SPC_CPU_DATA, offset);
600 if (retval != ERROR_OK)
601 return retval;
603 retval = psoc5lp_spc_busy_wait_data(target);
604 if (retval != ERROR_OK)
605 return retval;
607 retval = target_read_u8(target, SPC_CPU_DATA, data);
608 if (retval != ERROR_OK)
609 return retval;
611 retval = psoc5lp_spc_busy_wait_idle(target);
612 if (retval != ERROR_OK)
613 return retval;
615 return ERROR_OK;
619 * NV Latch
622 struct psoc5lp_nvl_flash_bank {
623 bool probed;
624 const struct psoc5lp_device *device;
627 static int psoc5lp_nvl_read(struct flash_bank *bank,
628 uint8_t *buffer, uint32_t offset, uint32_t count)
630 int retval;
632 retval = psoc5lp_spc_enable_clock(bank->target);
633 if (retval != ERROR_OK)
634 return retval;
636 while (count > 0) {
637 retval = psoc5lp_spc_read_byte(bank->target,
638 SPC_ARRAY_NVL_USER, offset, buffer);
639 if (retval != ERROR_OK)
640 return retval;
641 buffer++;
642 offset++;
643 count--;
646 return ERROR_OK;
649 static int psoc5lp_nvl_erase(struct flash_bank *bank, unsigned int first,
650 unsigned int last)
652 LOG_WARNING("There is no erase operation for NV Latches");
653 return ERROR_FLASH_OPER_UNSUPPORTED;
656 static int psoc5lp_nvl_erase_check(struct flash_bank *bank)
658 for (unsigned int i = 0; i < bank->num_sectors; i++)
659 bank->sectors[i].is_erased = 0;
661 return ERROR_OK;
664 static int psoc5lp_nvl_write(struct flash_bank *bank,
665 const uint8_t *buffer, uint32_t offset, uint32_t byte_count)
667 struct target *target = bank->target;
668 uint8_t *current_data, val;
669 bool write_required = false, pullup_needed = false, ecc_changed = false;
670 uint32_t i;
671 int retval;
673 if (offset != 0 || byte_count != bank->size) {
674 LOG_ERROR("NVL can only be written in whole");
675 return ERROR_FLASH_OPER_UNSUPPORTED;
678 current_data = calloc(1, bank->size);
679 if (!current_data)
680 return ERROR_FAIL;
681 retval = psoc5lp_nvl_read(bank, current_data, offset, byte_count);
682 if (retval != ERROR_OK) {
683 free(current_data);
684 return retval;
686 for (i = offset; i < byte_count; i++) {
687 if (current_data[i] != buffer[i]) {
688 write_required = true;
689 break;
692 if (((buffer[2] & 0x80) == 0x80) && ((current_data[0] & 0x0C) != 0x08))
693 pullup_needed = true;
694 if (((buffer[3] ^ current_data[3]) & 0x08) == 0x08)
695 ecc_changed = true;
696 free(current_data);
698 if (!write_required) {
699 LOG_INFO("Unchanged, skipping NVL write");
700 return ERROR_OK;
702 if (pullup_needed) {
703 retval = target_read_u8(target, PRT1_PC2, &val);
704 if (retval != ERROR_OK)
705 return retval;
706 val &= 0xF0;
707 val |= 0x05;
708 retval = target_write_u8(target, PRT1_PC2, val);
709 if (retval != ERROR_OK)
710 return retval;
713 for (i = offset; i < byte_count; i++) {
714 retval = psoc5lp_spc_load_byte(target,
715 SPC_ARRAY_NVL_USER, i, buffer[i]);
716 if (retval != ERROR_OK)
717 return retval;
719 retval = psoc5lp_spc_read_volatile_byte(target,
720 SPC_ARRAY_NVL_USER, i, &val);
721 if (retval != ERROR_OK)
722 return retval;
723 if (val != buffer[i]) {
724 LOG_ERROR("Failed to load NVL byte %" PRIu32 ": "
725 "expected 0x%02" PRIx8 ", read 0x%02" PRIx8,
726 i, buffer[i], val);
727 return ERROR_FLASH_OPERATION_FAILED;
731 retval = psoc5lp_spc_write_user_nvl(target, SPC_ARRAY_NVL_USER);
732 if (retval != ERROR_OK)
733 return retval;
735 if (ecc_changed) {
736 retval = target_call_reset_callbacks(target, RESET_INIT);
737 if (retval != ERROR_OK)
738 LOG_WARNING("Reset failed after enabling or disabling ECC");
741 return ERROR_OK;
744 static int psoc5lp_nvl_get_info_command(struct flash_bank *bank,
745 struct command_invocation *cmd)
747 struct psoc5lp_nvl_flash_bank *psoc_nvl_bank = bank->driver_priv;
748 char part_number[PART_NUMBER_LEN];
750 psoc5lp_get_part_number(psoc_nvl_bank->device, part_number);
752 command_print_sameline(cmd, "%s", part_number);
754 return ERROR_OK;
757 static int psoc5lp_nvl_probe(struct flash_bank *bank)
759 struct psoc5lp_nvl_flash_bank *psoc_nvl_bank = bank->driver_priv;
760 int retval;
762 if (psoc_nvl_bank->probed)
763 return ERROR_OK;
765 if (bank->target->state != TARGET_HALTED) {
766 LOG_ERROR("Target not halted");
767 return ERROR_TARGET_NOT_HALTED;
770 retval = psoc5lp_find_device(bank->target, &psoc_nvl_bank->device);
771 if (retval != ERROR_OK)
772 return retval;
774 bank->base = NVL_META_BASE;
775 bank->size = 4;
776 bank->num_sectors = 1;
777 bank->sectors = calloc(bank->num_sectors,
778 sizeof(struct flash_sector));
779 bank->sectors[0].offset = 0;
780 bank->sectors[0].size = 4;
781 bank->sectors[0].is_erased = -1;
782 bank->sectors[0].is_protected = -1;
784 psoc_nvl_bank->probed = true;
786 return ERROR_OK;
789 static int psoc5lp_nvl_auto_probe(struct flash_bank *bank)
791 struct psoc5lp_nvl_flash_bank *psoc_nvl_bank = bank->driver_priv;
793 if (psoc_nvl_bank->probed)
794 return ERROR_OK;
796 return psoc5lp_nvl_probe(bank);
799 FLASH_BANK_COMMAND_HANDLER(psoc5lp_nvl_flash_bank_command)
801 struct psoc5lp_nvl_flash_bank *psoc_nvl_bank;
803 psoc_nvl_bank = malloc(sizeof(struct psoc5lp_nvl_flash_bank));
804 if (!psoc_nvl_bank)
805 return ERROR_FLASH_OPERATION_FAILED;
807 psoc_nvl_bank->probed = false;
809 bank->driver_priv = psoc_nvl_bank;
811 return ERROR_OK;
814 const struct flash_driver psoc5lp_nvl_flash = {
815 .name = "psoc5lp_nvl",
816 .flash_bank_command = psoc5lp_nvl_flash_bank_command,
817 .info = psoc5lp_nvl_get_info_command,
818 .probe = psoc5lp_nvl_probe,
819 .auto_probe = psoc5lp_nvl_auto_probe,
820 .read = psoc5lp_nvl_read,
821 .erase = psoc5lp_nvl_erase,
822 .erase_check = psoc5lp_nvl_erase_check,
823 .write = psoc5lp_nvl_write,
824 .free_driver_priv = default_flash_free_driver_priv,
828 * EEPROM
831 struct psoc5lp_eeprom_flash_bank {
832 bool probed;
833 const struct psoc5lp_device *device;
836 static int psoc5lp_eeprom_erase(struct flash_bank *bank, unsigned int first,
837 unsigned int last)
839 int retval;
841 for (unsigned int i = first; i <= last; i++) {
842 retval = psoc5lp_spc_erase_sector(bank->target,
843 SPC_ARRAY_EEPROM, i);
844 if (retval != ERROR_OK)
845 return retval;
848 return ERROR_OK;
851 static int psoc5lp_eeprom_write(struct flash_bank *bank,
852 const uint8_t *buffer, uint32_t offset, uint32_t byte_count)
854 struct target *target = bank->target;
855 uint8_t temp[2];
856 unsigned row;
857 int retval;
859 if (offset % EEPROM_ROW_SIZE != 0) {
860 LOG_ERROR("Writes must be row-aligned, got offset 0x%08" PRIx32,
861 offset);
862 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
865 retval = psoc5lp_spc_get_temp(target, 3, temp);
866 if (retval != ERROR_OK) {
867 LOG_ERROR("Unable to read Die temperature");
868 return retval;
870 LOG_DEBUG("Get_Temp: sign 0x%02" PRIx8 ", magnitude 0x%02" PRIx8,
871 temp[0], temp[1]);
873 for (row = offset / EEPROM_ROW_SIZE; byte_count >= EEPROM_ROW_SIZE; row++) {
874 retval = psoc5lp_spc_load_row(target, SPC_ARRAY_EEPROM,
875 buffer, EEPROM_ROW_SIZE);
876 if (retval != ERROR_OK)
877 return retval;
879 retval = psoc5lp_spc_write_row(target, SPC_ARRAY_EEPROM,
880 row, temp);
881 if (retval != ERROR_OK)
882 return retval;
884 buffer += EEPROM_ROW_SIZE;
885 byte_count -= EEPROM_ROW_SIZE;
886 offset += EEPROM_ROW_SIZE;
888 if (byte_count > 0) {
889 uint8_t buf[EEPROM_ROW_SIZE];
891 memcpy(buf, buffer, byte_count);
892 memset(buf + byte_count, bank->default_padded_value,
893 EEPROM_ROW_SIZE - byte_count);
895 LOG_DEBUG("Padding %" PRIu32 " bytes", EEPROM_ROW_SIZE - byte_count);
896 retval = psoc5lp_spc_load_row(target, SPC_ARRAY_EEPROM,
897 buf, EEPROM_ROW_SIZE);
898 if (retval != ERROR_OK)
899 return retval;
901 retval = psoc5lp_spc_write_row(target, SPC_ARRAY_EEPROM,
902 row, temp);
903 if (retval != ERROR_OK)
904 return retval;
907 return ERROR_OK;
910 static int psoc5lp_eeprom_get_info_command(struct flash_bank *bank, struct command_invocation *cmd)
912 struct psoc5lp_eeprom_flash_bank *psoc_eeprom_bank = bank->driver_priv;
913 char part_number[PART_NUMBER_LEN];
915 psoc5lp_get_part_number(psoc_eeprom_bank->device, part_number);
917 command_print_sameline(cmd, "%s", part_number);
919 return ERROR_OK;
922 static int psoc5lp_eeprom_probe(struct flash_bank *bank)
924 struct psoc5lp_eeprom_flash_bank *psoc_eeprom_bank = bank->driver_priv;
925 uint32_t flash_addr = bank->base;
926 uint32_t val;
927 int retval;
929 if (psoc_eeprom_bank->probed)
930 return ERROR_OK;
932 if (bank->target->state != TARGET_HALTED) {
933 LOG_ERROR("Target not halted");
934 return ERROR_TARGET_NOT_HALTED;
937 retval = psoc5lp_find_device(bank->target, &psoc_eeprom_bank->device);
938 if (retval != ERROR_OK)
939 return retval;
941 retval = target_read_u32(bank->target, PM_ACT_CFG12, &val);
942 if (retval != ERROR_OK)
943 return retval;
944 if (!(val & PM_ACT_CFG12_EN_EE)) {
945 val |= PM_ACT_CFG12_EN_EE;
946 retval = target_write_u32(bank->target, PM_ACT_CFG12, val);
947 if (retval != ERROR_OK)
948 return retval;
951 bank->size = psoc_eeprom_bank->device->eeprom_kb * 1024;
952 bank->num_sectors = DIV_ROUND_UP(bank->size, EEPROM_SECTOR_SIZE);
953 bank->sectors = calloc(bank->num_sectors,
954 sizeof(struct flash_sector));
955 for (unsigned int i = 0; i < bank->num_sectors; i++) {
956 bank->sectors[i].size = EEPROM_SECTOR_SIZE;
957 bank->sectors[i].offset = flash_addr - bank->base;
958 bank->sectors[i].is_erased = -1;
959 bank->sectors[i].is_protected = -1;
961 flash_addr += bank->sectors[i].size;
964 bank->default_padded_value = bank->erased_value = 0x00;
966 psoc_eeprom_bank->probed = true;
968 return ERROR_OK;
971 static int psoc5lp_eeprom_auto_probe(struct flash_bank *bank)
973 struct psoc5lp_eeprom_flash_bank *psoc_eeprom_bank = bank->driver_priv;
975 if (psoc_eeprom_bank->probed)
976 return ERROR_OK;
978 return psoc5lp_eeprom_probe(bank);
981 FLASH_BANK_COMMAND_HANDLER(psoc5lp_eeprom_flash_bank_command)
983 struct psoc5lp_eeprom_flash_bank *psoc_eeprom_bank;
985 psoc_eeprom_bank = malloc(sizeof(struct psoc5lp_eeprom_flash_bank));
986 if (!psoc_eeprom_bank)
987 return ERROR_FLASH_OPERATION_FAILED;
989 psoc_eeprom_bank->probed = false;
990 psoc_eeprom_bank->device = NULL;
992 bank->driver_priv = psoc_eeprom_bank;
994 return ERROR_OK;
997 const struct flash_driver psoc5lp_eeprom_flash = {
998 .name = "psoc5lp_eeprom",
999 .flash_bank_command = psoc5lp_eeprom_flash_bank_command,
1000 .info = psoc5lp_eeprom_get_info_command,
1001 .probe = psoc5lp_eeprom_probe,
1002 .auto_probe = psoc5lp_eeprom_auto_probe,
1003 .read = default_flash_read,
1004 .erase = psoc5lp_eeprom_erase,
1005 .erase_check = default_flash_blank_check,
1006 .write = psoc5lp_eeprom_write,
1007 .free_driver_priv = default_flash_free_driver_priv,
1011 * Program Flash
1014 struct psoc5lp_flash_bank {
1015 bool probed;
1016 const struct psoc5lp_device *device;
1017 bool ecc_enabled;
1018 /* If ecc is disabled, num_sectors counts both std and ecc sectors.
1019 * If ecc is enabled, num_sectors indicates just the number of std sectors.
1020 * However ecc sector descriptors bank->sector[num_sectors..2*num_sectors-1]
1021 * are used for driver private flash operations */
1024 static int psoc5lp_erase(struct flash_bank *bank, unsigned int first,
1025 unsigned int last)
1027 struct psoc5lp_flash_bank *psoc_bank = bank->driver_priv;
1028 int retval;
1030 if (!psoc_bank->ecc_enabled) {
1031 /* Silently avoid erasing sectors twice */
1032 if (last >= first + bank->num_sectors / 2) {
1033 LOG_DEBUG("Skipping duplicate erase of sectors %u to %u",
1034 first + bank->num_sectors / 2, last);
1035 last = first + (bank->num_sectors / 2) - 1;
1037 /* Check for any remaining ECC sectors */
1038 if (last >= bank->num_sectors / 2) {
1039 LOG_WARNING("Skipping erase of ECC region sectors %u to %u",
1040 bank->num_sectors / 2, last);
1041 last = (bank->num_sectors / 2) - 1;
1045 for (unsigned int i = first; i <= last; i++) {
1046 retval = psoc5lp_spc_erase_sector(bank->target,
1047 i / SECTORS_PER_BLOCK, i % SECTORS_PER_BLOCK);
1048 if (retval != ERROR_OK)
1049 return retval;
1052 return ERROR_OK;
1055 /* Derived from core.c:default_flash_blank_check() */
1056 static int psoc5lp_erase_check(struct flash_bank *bank)
1058 struct psoc5lp_flash_bank *psoc_bank = bank->driver_priv;
1059 struct target *target = bank->target;
1060 int retval;
1062 if (target->state != TARGET_HALTED) {
1063 LOG_ERROR("Target not halted");
1064 return ERROR_TARGET_NOT_HALTED;
1067 unsigned int num_sectors = bank->num_sectors;
1068 if (psoc_bank->ecc_enabled)
1069 num_sectors *= 2; /* count both std and ecc sector always */
1071 struct target_memory_check_block *block_array;
1072 block_array = malloc(num_sectors * sizeof(struct target_memory_check_block));
1073 if (!block_array)
1074 return ERROR_FAIL;
1076 for (unsigned int i = 0; i < num_sectors; i++) {
1077 block_array[i].address = bank->base + bank->sectors[i].offset;
1078 block_array[i].size = bank->sectors[i].size;
1079 block_array[i].result = UINT32_MAX; /* erase state unknown */
1082 bool fast_check = true;
1083 for (unsigned int i = 0; i < num_sectors; ) {
1084 retval = armv7m_blank_check_memory(target,
1085 block_array + i, num_sectors - i,
1086 bank->erased_value);
1087 if (retval < 1) {
1088 /* Run slow fallback if the first run gives no result
1089 * otherwise use possibly incomplete results */
1090 if (i == 0)
1091 fast_check = false;
1092 break;
1094 i += retval; /* add number of blocks done this round */
1097 if (fast_check) {
1098 if (psoc_bank->ecc_enabled) {
1099 for (unsigned int i = 0; i < bank->num_sectors; i++)
1100 bank->sectors[i].is_erased =
1101 (block_array[i].result != 1)
1102 ? block_array[i].result
1103 : block_array[i + bank->num_sectors].result;
1104 /* if std sector is erased, use status of ecc sector */
1105 } else {
1106 for (unsigned int i = 0; i < num_sectors; i++)
1107 bank->sectors[i].is_erased = block_array[i].result;
1109 retval = ERROR_OK;
1110 } else {
1111 LOG_ERROR("Can't run erase check - add working memory");
1112 retval = ERROR_FAIL;
1114 free(block_array);
1116 return retval;
1119 static int psoc5lp_write(struct flash_bank *bank, const uint8_t *buffer,
1120 uint32_t offset, uint32_t byte_count)
1122 struct psoc5lp_flash_bank *psoc_bank = bank->driver_priv;
1123 struct target *target = bank->target;
1124 struct working_area *code_area, *even_row_area, *odd_row_area;
1125 uint32_t row_size;
1126 uint8_t temp[2], buf[12], ecc_bytes[ROW_ECC_SIZE];
1127 unsigned array_id, row;
1128 int i, retval;
1130 if (offset + byte_count > bank->size) {
1131 LOG_ERROR("Writing to ECC not supported");
1132 return ERROR_FLASH_DST_OUT_OF_BANK;
1135 if (offset % ROW_SIZE != 0) {
1136 LOG_ERROR("Writes must be row-aligned, got offset 0x%08" PRIx32,
1137 offset);
1138 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
1141 row_size = ROW_SIZE;
1142 if (!psoc_bank->ecc_enabled) {
1143 row_size += ROW_ECC_SIZE;
1144 memset(ecc_bytes, bank->default_padded_value, ROW_ECC_SIZE);
1147 retval = psoc5lp_spc_get_temp(target, 3, temp);
1148 if (retval != ERROR_OK) {
1149 LOG_ERROR("Unable to read Die temperature");
1150 return retval;
1152 LOG_DEBUG("Get_Temp: sign 0x%02" PRIx8 ", magnitude 0x%02" PRIx8,
1153 temp[0], temp[1]);
1155 assert(target_get_working_area_avail(target) == target->working_area_size);
1156 retval = target_alloc_working_area(target,
1157 target_get_working_area_avail(target) / 2, &code_area);
1158 if (retval != ERROR_OK) {
1159 LOG_ERROR("Could not allocate working area for program SRAM");
1160 return retval;
1162 assert(code_area->address < 0x20000000);
1164 retval = target_alloc_working_area(target,
1165 SPC_OPCODE_LEN + 1 + row_size + 3 + SPC_OPCODE_LEN + 6,
1166 &even_row_area);
1167 if (retval != ERROR_OK) {
1168 LOG_ERROR("Could not allocate working area for even row");
1169 goto err_alloc_even;
1171 assert(even_row_area->address >= 0x20000000);
1173 retval = target_alloc_working_area(target, even_row_area->size,
1174 &odd_row_area);
1175 if (retval != ERROR_OK) {
1176 LOG_ERROR("Could not allocate working area for odd row");
1177 goto err_alloc_odd;
1179 assert(odd_row_area->address >= 0x20000000);
1181 for (array_id = offset / BLOCK_SIZE; byte_count > 0; array_id++) {
1182 for (row = (offset / ROW_SIZE) % ROWS_PER_BLOCK;
1183 row < ROWS_PER_BLOCK && byte_count > 0; row++) {
1184 bool even_row = (row % 2 == 0);
1185 struct working_area *data_area = even_row ? even_row_area : odd_row_area;
1186 unsigned len = MIN(ROW_SIZE, byte_count);
1188 LOG_DEBUG("Writing load command for array %u row %u at " TARGET_ADDR_FMT,
1189 array_id, row, data_area->address);
1191 psoc5lp_spc_write_opcode_buffer(target, buf, SPC_LOAD_ROW);
1192 buf[SPC_OPCODE_LEN] = array_id;
1193 retval = target_write_buffer(target, data_area->address, 4, buf);
1194 if (retval != ERROR_OK)
1195 goto err_write;
1197 retval = target_write_buffer(target,
1198 data_area->address + SPC_OPCODE_LEN + 1,
1199 len, buffer);
1200 if (retval != ERROR_OK)
1201 goto err_write;
1202 buffer += len;
1203 byte_count -= len;
1204 offset += len;
1206 if (len < ROW_SIZE) {
1207 uint8_t padding[ROW_SIZE];
1209 memset(padding, bank->default_padded_value, ROW_SIZE);
1211 LOG_DEBUG("Padding %d bytes", ROW_SIZE - len);
1212 retval = target_write_buffer(target,
1213 data_area->address + SPC_OPCODE_LEN + 1 + len,
1214 ROW_SIZE - len, padding);
1215 if (retval != ERROR_OK)
1216 goto err_write;
1219 if (!psoc_bank->ecc_enabled) {
1220 retval = target_write_buffer(target,
1221 data_area->address + SPC_OPCODE_LEN + 1 + ROW_SIZE,
1222 sizeof(ecc_bytes), ecc_bytes);
1223 if (retval != ERROR_OK)
1224 goto err_write;
1227 for (i = 0; i < 3; i++)
1228 buf[i] = 0x00; /* 3 NOPs for short delay */
1229 psoc5lp_spc_write_opcode_buffer(target, buf + 3, SPC_PRG_ROW);
1230 buf[3 + SPC_OPCODE_LEN] = array_id;
1231 buf[3 + SPC_OPCODE_LEN + 1] = row >> 8;
1232 buf[3 + SPC_OPCODE_LEN + 2] = row & 0xff;
1233 memcpy(buf + 3 + SPC_OPCODE_LEN + 3, temp, 2);
1234 buf[3 + SPC_OPCODE_LEN + 5] = 0x00; /* padding */
1235 retval = target_write_buffer(target,
1236 data_area->address + SPC_OPCODE_LEN + 1 + row_size,
1237 12, buf);
1238 if (retval != ERROR_OK)
1239 goto err_write;
1241 retval = target_write_u32(target,
1242 even_row ? PHUB_CH0_BASIC_STATUS : PHUB_CH1_BASIC_STATUS,
1243 (even_row ? 0 : 1) << 8);
1244 if (retval != ERROR_OK)
1245 goto err_dma;
1247 retval = target_write_u32(target,
1248 even_row ? PHUB_CH0_BASIC_CFG : PHUB_CH1_BASIC_CFG,
1249 PHUB_CHX_BASIC_CFG_WORK_SEP | PHUB_CHX_BASIC_CFG_EN);
1250 if (retval != ERROR_OK)
1251 goto err_dma;
1253 retval = target_write_u32(target,
1254 even_row ? PHUB_CFGMEM0_CFG0 : PHUB_CFGMEM1_CFG0,
1255 PHUB_CFGMEMX_CFG0);
1256 if (retval != ERROR_OK)
1257 goto err_dma;
1259 retval = target_write_u32(target,
1260 even_row ? PHUB_CFGMEM0_CFG1 : PHUB_CFGMEM1_CFG1,
1261 ((SPC_CPU_DATA >> 16) << 16) | (data_area->address >> 16));
1262 if (retval != ERROR_OK)
1263 goto err_dma;
1265 retval = target_write_u32(target,
1266 even_row ? PHUB_TDMEM0_ORIG_TD0 : PHUB_TDMEM1_ORIG_TD0,
1267 PHUB_TDMEMX_ORIG_TD0_INC_SRC_ADDR |
1268 PHUB_TDMEMX_ORIG_TD0_NEXT_TD_PTR_LAST |
1269 ((SPC_OPCODE_LEN + 1 + row_size + 3 + SPC_OPCODE_LEN + 5) & 0xfff));
1270 if (retval != ERROR_OK)
1271 goto err_dma;
1273 retval = target_write_u32(target,
1274 even_row ? PHUB_TDMEM0_ORIG_TD1 : PHUB_TDMEM1_ORIG_TD1,
1275 ((SPC_CPU_DATA & 0xffff) << 16) | (data_area->address & 0xffff));
1276 if (retval != ERROR_OK)
1277 goto err_dma;
1279 retval = psoc5lp_spc_busy_wait_idle(target);
1280 if (retval != ERROR_OK)
1281 goto err_idle;
1283 retval = target_write_u32(target,
1284 even_row ? PHUB_CH0_ACTION : PHUB_CH1_ACTION,
1285 PHUB_CHX_ACTION_CPU_REQ);
1286 if (retval != ERROR_OK)
1287 goto err_dma_action;
1291 retval = psoc5lp_spc_busy_wait_idle(target);
1293 err_dma_action:
1294 err_idle:
1295 err_dma:
1296 err_write:
1297 target_free_working_area(target, odd_row_area);
1298 err_alloc_odd:
1299 target_free_working_area(target, even_row_area);
1300 err_alloc_even:
1301 target_free_working_area(target, code_area);
1303 return retval;
1306 static int psoc5lp_protect_check(struct flash_bank *bank)
1308 struct psoc5lp_flash_bank *psoc_bank = bank->driver_priv;
1309 uint8_t row_data[ROW_SIZE];
1310 const unsigned protection_bytes_per_sector = ROWS_PER_SECTOR * 2 / 8;
1311 unsigned i, k, num_sectors;
1312 int retval;
1314 if (bank->target->state != TARGET_HALTED) {
1315 LOG_ERROR("Target not halted");
1316 return ERROR_TARGET_NOT_HALTED;
1319 for (i = 0; i < DIV_ROUND_UP(bank->size, BLOCK_SIZE); i++) {
1320 retval = psoc5lp_spc_read_hidden_row(bank->target, i,
1321 SPC_ROW_PROTECTION, row_data);
1322 if (retval != ERROR_OK)
1323 return retval;
1325 /* Last flash array may have less rows, but in practice full sectors. */
1326 if (i == bank->size / BLOCK_SIZE)
1327 num_sectors = (bank->size % BLOCK_SIZE) / SECTOR_SIZE;
1328 else
1329 num_sectors = SECTORS_PER_BLOCK;
1331 for (unsigned int j = 0; j < num_sectors; j++) {
1332 int sector_nr = i * SECTORS_PER_BLOCK + j;
1333 struct flash_sector *sector = &bank->sectors[sector_nr];
1334 struct flash_sector *ecc_sector;
1336 if (psoc_bank->ecc_enabled)
1337 ecc_sector = &bank->sectors[bank->num_sectors + sector_nr];
1338 else
1339 ecc_sector = &bank->sectors[bank->num_sectors / 2 + sector_nr];
1341 sector->is_protected = ecc_sector->is_protected = 0;
1342 for (k = protection_bytes_per_sector * j;
1343 k < protection_bytes_per_sector * (j + 1); k++) {
1344 assert(k < protection_bytes_per_sector * SECTORS_PER_BLOCK);
1345 LOG_DEBUG("row[%u][%02u] = 0x%02" PRIx8, i, k, row_data[k]);
1346 if (row_data[k] != 0x00) {
1347 sector->is_protected = ecc_sector->is_protected = 1;
1348 break;
1354 return ERROR_OK;
1357 static int psoc5lp_get_info_command(struct flash_bank *bank, struct command_invocation *cmd)
1359 struct psoc5lp_flash_bank *psoc_bank = bank->driver_priv;
1360 char part_number[PART_NUMBER_LEN];
1361 const char *ecc;
1363 psoc5lp_get_part_number(psoc_bank->device, part_number);
1364 ecc = psoc_bank->ecc_enabled ? "ECC enabled" : "ECC disabled";
1366 command_print_sameline(cmd, "%s %s", part_number, ecc);
1368 return ERROR_OK;
1371 static int psoc5lp_probe(struct flash_bank *bank)
1373 struct target *target = bank->target;
1374 struct psoc5lp_flash_bank *psoc_bank = bank->driver_priv;
1375 uint32_t flash_addr = bank->base;
1376 uint8_t nvl[4], temp[2];
1377 int retval;
1379 if (target->state != TARGET_HALTED) {
1380 LOG_ERROR("Target not halted");
1381 return ERROR_TARGET_NOT_HALTED;
1384 if (!psoc_bank->device) {
1385 retval = psoc5lp_find_device(target, &psoc_bank->device);
1386 if (retval != ERROR_OK)
1387 return retval;
1389 bank->size = psoc_bank->device->flash_kb * 1024;
1392 bank->num_sectors = DIV_ROUND_UP(bank->size, SECTOR_SIZE);
1394 if (!psoc_bank->probed) {
1395 retval = psoc5lp_spc_enable_clock(target);
1396 if (retval != ERROR_OK)
1397 return retval;
1399 /* First values read are inaccurate, so do it once now. */
1400 retval = psoc5lp_spc_get_temp(target, 3, temp);
1401 if (retval != ERROR_OK) {
1402 LOG_ERROR("Unable to read Die temperature");
1403 return retval;
1406 bank->sectors = calloc(bank->num_sectors * 2,
1407 sizeof(struct flash_sector));
1408 for (unsigned int i = 0; i < bank->num_sectors; i++) {
1409 bank->sectors[i].size = SECTOR_SIZE;
1410 bank->sectors[i].offset = flash_addr - bank->base;
1411 bank->sectors[i].is_erased = -1;
1412 bank->sectors[i].is_protected = -1;
1414 flash_addr += bank->sectors[i].size;
1416 flash_addr = 0x48000000;
1417 for (unsigned int i = bank->num_sectors; i < bank->num_sectors * 2; i++) {
1418 bank->sectors[i].size = ROWS_PER_SECTOR * ROW_ECC_SIZE;
1419 bank->sectors[i].offset = flash_addr - bank->base;
1420 bank->sectors[i].is_erased = -1;
1421 bank->sectors[i].is_protected = -1;
1423 flash_addr += bank->sectors[i].size;
1426 bank->default_padded_value = bank->erased_value = 0x00;
1428 psoc_bank->probed = true;
1431 retval = psoc5lp_spc_read_byte(target, SPC_ARRAY_NVL_USER, 3, &nvl[3]);
1432 if (retval != ERROR_OK)
1433 return retval;
1434 LOG_DEBUG("NVL[%d] = 0x%02" PRIx8, 3, nvl[3]);
1435 psoc_bank->ecc_enabled = nvl[3] & NVL_3_ECCEN;
1437 if (!psoc_bank->ecc_enabled)
1438 bank->num_sectors *= 2;
1440 return ERROR_OK;
1443 static int psoc5lp_auto_probe(struct flash_bank *bank)
1445 return psoc5lp_probe(bank);
1448 COMMAND_HANDLER(psoc5lp_handle_mass_erase_command)
1450 struct flash_bank *bank;
1451 int retval;
1453 if (CMD_ARGC < 1)
1454 return ERROR_COMMAND_SYNTAX_ERROR;
1456 retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
1457 if (retval != ERROR_OK)
1458 return retval;
1460 retval = psoc5lp_spc_erase_all(bank->target);
1461 if (retval == ERROR_OK)
1462 command_print(CMD, "PSoC 5LP erase succeeded");
1463 else
1464 command_print(CMD, "PSoC 5LP erase failed");
1466 return retval;
1469 FLASH_BANK_COMMAND_HANDLER(psoc5lp_flash_bank_command)
1471 struct psoc5lp_flash_bank *psoc_bank;
1473 psoc_bank = malloc(sizeof(struct psoc5lp_flash_bank));
1474 if (!psoc_bank)
1475 return ERROR_FLASH_OPERATION_FAILED;
1477 psoc_bank->probed = false;
1478 psoc_bank->device = NULL;
1480 bank->driver_priv = psoc_bank;
1482 return ERROR_OK;
1485 static const struct command_registration psoc5lp_exec_command_handlers[] = {
1487 .name = "mass_erase",
1488 .handler = psoc5lp_handle_mass_erase_command,
1489 .mode = COMMAND_EXEC,
1490 .usage = "bank_id",
1491 .help = "Erase all flash data and ECC/configuration bytes, "
1492 "all flash protection rows, "
1493 "and all row latches in all flash arrays on the device.",
1495 COMMAND_REGISTRATION_DONE
1498 static const struct command_registration psoc5lp_command_handlers[] = {
1500 .name = "psoc5lp",
1501 .mode = COMMAND_ANY,
1502 .help = "PSoC 5LP flash command group",
1503 .usage = "",
1504 .chain = psoc5lp_exec_command_handlers,
1506 COMMAND_REGISTRATION_DONE
1509 const struct flash_driver psoc5lp_flash = {
1510 .name = "psoc5lp",
1511 .commands = psoc5lp_command_handlers,
1512 .flash_bank_command = psoc5lp_flash_bank_command,
1513 .info = psoc5lp_get_info_command,
1514 .probe = psoc5lp_probe,
1515 .auto_probe = psoc5lp_auto_probe,
1516 .protect_check = psoc5lp_protect_check,
1517 .read = default_flash_read,
1518 .erase = psoc5lp_erase,
1519 .erase_check = psoc5lp_erase_check,
1520 .write = psoc5lp_write,
1521 .free_driver_priv = default_flash_free_driver_priv,