psoc5lp: Add EEPROM flash driver
[openocd.git] / src / flash / nor / psoc5lp.c
blob87e130fb717ae1ae1ad54b8ba88084ee59b6f174
1 /*
2 * PSoC 5LP flash driver
4 * Copyright (c) 2016 Andreas Färber
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.
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.
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/>.
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
24 #include "imp.h"
25 #include <helper/time_support.h>
26 #include <target/armv7m.h>
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 PHUB_CH0_BASIC_CFG 0x40007010
33 #define PHUB_CH0_ACTION 0x40007014
34 #define PHUB_CH0_BASIC_STATUS 0x40007018
35 #define PHUB_CH1_BASIC_CFG 0x40007020
36 #define PHUB_CH1_ACTION 0x40007024
37 #define PHUB_CH1_BASIC_STATUS 0x40007028
38 #define PHUB_CFGMEM0_CFG0 0x40007600
39 #define PHUB_CFGMEM0_CFG1 0x40007604
40 #define PHUB_CFGMEM1_CFG0 0x40007608
41 #define PHUB_CFGMEM1_CFG1 0x4000760C
42 #define PHUB_TDMEM0_ORIG_TD0 0x40007800
43 #define PHUB_TDMEM0_ORIG_TD1 0x40007804
44 #define PHUB_TDMEM1_ORIG_TD0 0x40007808
45 #define PHUB_TDMEM1_ORIG_TD1 0x4000780C
46 #define PANTHER_DEVICE_ID 0x4008001C
48 #define PM_ACT_CFG12_EN_EE (1 << 4)
50 #define SPC_KEY1 0xB6
51 #define SPC_KEY2 0xD3
53 #define SPC_LOAD_BYTE 0x00
54 #define SPC_LOAD_MULTI_BYTE 0x01
55 #define SPC_LOAD_ROW 0x02
56 #define SPC_READ_BYTE 0x03
57 #define SPC_READ_MULTI_BYTE 0x04
58 #define SPC_WRITE_ROW 0x05
59 #define SPC_WRITE_USER_NVL 0x06
60 #define SPC_PRG_ROW 0x07
61 #define SPC_ERASE_SECTOR 0x08
62 #define SPC_ERASE_ALL 0x09
63 #define SPC_READ_HIDDEN_ROW 0x0A
64 #define SPC_PROGRAM_PROTECT_ROW 0x0B
65 #define SPC_GET_CHECKSUM 0x0C
66 #define SPC_GET_TEMP 0x0E
67 #define SPC_READ_VOLATILE_BYTE 0x10
69 #define SPC_ARRAY_ALL 0x3F
70 #define SPC_ARRAY_EEPROM 0x40
71 #define SPC_ARRAY_NVL_USER 0x80
72 #define SPC_ARRAY_NVL_WO 0xF8
74 #define SPC_ROW_PROTECTION 0
76 #define SPC_OPCODE_LEN 3
78 #define SPC_SR_DATA_READY (1 << 0)
79 #define SPC_SR_IDLE (1 << 1)
81 #define PM_ACT_CFG0_EN_CLK_SPC (1 << 3)
83 #define PHUB_CHx_BASIC_CFG_EN (1 << 0)
84 #define PHUB_CHx_BASIC_CFG_WORK_SEP (1 << 5)
86 #define PHUB_CHx_ACTION_CPU_REQ (1 << 0)
88 #define PHUB_CFGMEMx_CFG0 (1 << 7)
90 #define PHUB_TDMEMx_ORIG_TD0_NEXT_TD_PTR_LAST (0xff << 16)
91 #define PHUB_TDMEMx_ORIG_TD0_INC_SRC_ADDR (1 << 24)
93 #define NVL_3_ECCEN (1 << 3)
95 #define ROW_SIZE 256
96 #define ROW_ECC_SIZE 32
97 #define ROWS_PER_SECTOR 64
98 #define SECTOR_SIZE (ROWS_PER_SECTOR * ROW_SIZE)
99 #define ROWS_PER_BLOCK 256
100 #define BLOCK_SIZE (ROWS_PER_BLOCK * ROW_SIZE)
101 #define SECTORS_PER_BLOCK (BLOCK_SIZE / SECTOR_SIZE)
102 #define EEPROM_ROW_SIZE 16
103 #define EEPROM_SECTOR_SIZE (ROWS_PER_SECTOR * EEPROM_ROW_SIZE)
104 #define EEPROM_BLOCK_SIZE (ROWS_PER_BLOCK * EEPROM_ROW_SIZE)
106 #define PART_NUMBER_LEN (17 + 1)
108 struct psoc5lp_device {
109 uint32_t id;
110 unsigned fam;
111 unsigned speed_mhz;
112 unsigned flash_kb;
113 unsigned eeprom_kb;
117 * Device information collected from datasheets.
118 * Different temperature ranges (C/I/Q/A) may share IDs, not differing otherwise.
120 static const struct psoc5lp_device psoc5lp_devices[] = {
121 /* CY8C58LP Family Datasheet */
122 { .id = 0x2E11F069, .fam = 8, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 },
123 { .id = 0x2E120069, .fam = 8, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 },
124 { .id = 0x2E123069, .fam = 8, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 },
125 { .id = 0x2E124069, .fam = 8, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 },
126 { .id = 0x2E126069, .fam = 8, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 },
127 { .id = 0x2E127069, .fam = 8, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 },
128 { .id = 0x2E117069, .fam = 8, .speed_mhz = 67, .flash_kb = 128, .eeprom_kb = 2 },
129 { .id = 0x2E118069, .fam = 8, .speed_mhz = 67, .flash_kb = 128, .eeprom_kb = 2 },
130 { .id = 0x2E119069, .fam = 8, .speed_mhz = 67, .flash_kb = 128, .eeprom_kb = 2 },
131 { .id = 0x2E11C069, .fam = 8, .speed_mhz = 67, .flash_kb = 128, .eeprom_kb = 2 },
132 { .id = 0x2E114069, .fam = 8, .speed_mhz = 67, .flash_kb = 64, .eeprom_kb = 2 },
133 { .id = 0x2E115069, .fam = 8, .speed_mhz = 67, .flash_kb = 64, .eeprom_kb = 2 },
134 { .id = 0x2E116069, .fam = 8, .speed_mhz = 67, .flash_kb = 64, .eeprom_kb = 2 },
135 { .id = 0x2E160069, .fam = 8, .speed_mhz = 80, .flash_kb = 256, .eeprom_kb = 2 },
136 /* '' */
137 { .id = 0x2E161069, .fam = 8, .speed_mhz = 80, .flash_kb = 256, .eeprom_kb = 2 },
138 /* '' */
139 { .id = 0x2E1D2069, .fam = 8, .speed_mhz = 80, .flash_kb = 256, .eeprom_kb = 2 },
140 { .id = 0x2E1D6069, .fam = 8, .speed_mhz = 80, .flash_kb = 256, .eeprom_kb = 2 },
142 /* CY8C56LP Family Datasheet */
143 { .id = 0x2E10A069, .fam = 6, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 },
144 { .id = 0x2E10D069, .fam = 6, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 },
145 { .id = 0x2E10E069, .fam = 6, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 },
146 { .id = 0x2E106069, .fam = 6, .speed_mhz = 67, .flash_kb = 128, .eeprom_kb = 2 },
147 { .id = 0x2E108069, .fam = 6, .speed_mhz = 67, .flash_kb = 128, .eeprom_kb = 2 },
148 { .id = 0x2E109069, .fam = 6, .speed_mhz = 67, .flash_kb = 128, .eeprom_kb = 2 },
149 { .id = 0x2E101069, .fam = 6, .speed_mhz = 67, .flash_kb = 64, .eeprom_kb = 2 },
150 { .id = 0x2E104069, .fam = 6, .speed_mhz = 67, .flash_kb = 64, .eeprom_kb = 2 },
151 /* '' */
152 { .id = 0x2E105069, .fam = 6, .speed_mhz = 67, .flash_kb = 64, .eeprom_kb = 2 },
153 { .id = 0x2E128069, .fam = 6, .speed_mhz = 67, .flash_kb = 128, .eeprom_kb = 2 },
154 /* '' */
155 { .id = 0x2E122069, .fam = 6, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 },
156 { .id = 0x2E129069, .fam = 6, .speed_mhz = 67, .flash_kb = 128, .eeprom_kb = 2 },
157 { .id = 0x2E163069, .fam = 6, .speed_mhz = 80, .flash_kb = 256, .eeprom_kb = 2 },
158 { .id = 0x2E156069, .fam = 6, .speed_mhz = 80, .flash_kb = 256, .eeprom_kb = 2 },
159 { .id = 0x2E1D3069, .fam = 6, .speed_mhz = 80, .flash_kb = 256, .eeprom_kb = 2 },
161 /* CY8C54LP Family Datasheet */
162 { .id = 0x2E11A069, .fam = 4, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 },
163 { .id = 0x2E16A069, .fam = 4, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 },
164 { .id = 0x2E12A069, .fam = 4, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 },
165 { .id = 0x2E103069, .fam = 4, .speed_mhz = 67, .flash_kb = 128, .eeprom_kb = 2 },
166 { .id = 0x2E16C069, .fam = 4, .speed_mhz = 67, .flash_kb = 128, .eeprom_kb = 2 },
167 { .id = 0x2E102069, .fam = 4, .speed_mhz = 67, .flash_kb = 64, .eeprom_kb = 2 },
168 { .id = 0x2E148069, .fam = 4, .speed_mhz = 67, .flash_kb = 64, .eeprom_kb = 2 },
169 { .id = 0x2E155069, .fam = 4, .speed_mhz = 67, .flash_kb = 64, .eeprom_kb = 2 },
170 { .id = 0x2E16B069, .fam = 4, .speed_mhz = 67, .flash_kb = 64, .eeprom_kb = 2 },
171 { .id = 0x2E12B069, .fam = 4, .speed_mhz = 67, .flash_kb = 32, .eeprom_kb = 2 },
172 { .id = 0x2E168069, .fam = 4, .speed_mhz = 67, .flash_kb = 32, .eeprom_kb = 2 },
173 { .id = 0x2E178069, .fam = 4, .speed_mhz = 80, .flash_kb = 256, .eeprom_kb = 2 },
174 { .id = 0x2E15D069, .fam = 4, .speed_mhz = 80, .flash_kb = 256, .eeprom_kb = 2 },
175 { .id = 0x2E1D4069, .fam = 4, .speed_mhz = 80, .flash_kb = 256, .eeprom_kb = 2 },
177 /* CY8C52LP Family Datasheet */
178 { .id = 0x2E11E069, .fam = 2, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 },
179 { .id = 0x2E12F069, .fam = 2, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 },
180 { .id = 0x2E133069, .fam = 2, .speed_mhz = 67, .flash_kb = 128, .eeprom_kb = 2 },
181 { .id = 0x2E159069, .fam = 2, .speed_mhz = 67, .flash_kb = 128, .eeprom_kb = 2 },
182 { .id = 0x2E11D069, .fam = 2, .speed_mhz = 67, .flash_kb = 64, .eeprom_kb = 2 },
183 { .id = 0x2E121069, .fam = 2, .speed_mhz = 67, .flash_kb = 64, .eeprom_kb = 2 },
184 { .id = 0x2E184069, .fam = 2, .speed_mhz = 67, .flash_kb = 64, .eeprom_kb = 2 },
185 { .id = 0x2E196069, .fam = 2, .speed_mhz = 67, .flash_kb = 64, .eeprom_kb = 2 },
186 { .id = 0x2E132069, .fam = 2, .speed_mhz = 67, .flash_kb = 32, .eeprom_kb = 2 },
187 { .id = 0x2E138069, .fam = 2, .speed_mhz = 67, .flash_kb = 32, .eeprom_kb = 2 },
188 { .id = 0x2E13A069, .fam = 2, .speed_mhz = 67, .flash_kb = 32, .eeprom_kb = 2 },
189 { .id = 0x2E152069, .fam = 2, .speed_mhz = 67, .flash_kb = 32, .eeprom_kb = 2 },
190 { .id = 0x2E15F069, .fam = 2, .speed_mhz = 80, .flash_kb = 256, .eeprom_kb = 2 },
191 { .id = 0x2E15A069, .fam = 2, .speed_mhz = 80, .flash_kb = 256, .eeprom_kb = 2 },
192 { .id = 0x2E1D5069, .fam = 2, .speed_mhz = 80, .flash_kb = 256, .eeprom_kb = 2 },
195 static void psoc5lp_get_part_number(const struct psoc5lp_device *dev, char *str)
197 strcpy(str, "CY8Cabcdefg-LPxxx");
199 str[4] = '5';
200 str[5] = '0' + dev->fam;
202 switch (dev->speed_mhz) {
203 case 67:
204 str[6] = '6';
205 break;
206 case 80:
207 str[6] = '8';
208 break;
209 default:
210 str[6] = '?';
213 switch (dev->flash_kb) {
214 case 32:
215 str[7] = '5';
216 break;
217 case 64:
218 str[7] = '6';
219 break;
220 case 128:
221 str[7] = '7';
222 break;
223 case 256:
224 str[7] = '8';
225 break;
226 default:
227 str[7] = '?';
230 /* Package does not matter. */
231 strncpy(str + 8, "xx", 2);
233 /* Temperate range cannot uniquely be identified. */
234 str[10] = 'x';
237 static int psoc5lp_get_device_id(struct target *target, uint32_t *id)
239 int retval;
241 retval = target_read_u32(target, PANTHER_DEVICE_ID, id); /* dummy read */
242 if (retval != ERROR_OK)
243 return retval;
244 retval = target_read_u32(target, PANTHER_DEVICE_ID, id);
245 return retval;
248 static int psoc5lp_find_device(struct target *target,
249 const struct psoc5lp_device **device)
251 uint32_t device_id;
252 unsigned i;
253 int retval;
255 *device = NULL;
257 retval = psoc5lp_get_device_id(target, &device_id);
258 if (retval != ERROR_OK)
259 return retval;
260 LOG_DEBUG("PANTHER_DEVICE_ID = 0x%08" PRIX32, device_id);
262 for (i = 0; i < ARRAY_SIZE(psoc5lp_devices); i++) {
263 if (psoc5lp_devices[i].id == device_id) {
264 *device = &psoc5lp_devices[i];
265 return ERROR_OK;
269 LOG_ERROR("Device 0x%08" PRIX32 " not supported", device_id);
270 return ERROR_FLASH_OPER_UNSUPPORTED;
273 static int psoc5lp_spc_enable_clock(struct target *target)
275 int retval;
276 uint8_t pm_act_cfg0;
278 retval = target_read_u8(target, PM_ACT_CFG0, &pm_act_cfg0);
279 if (retval != ERROR_OK) {
280 LOG_ERROR("Cannot read PM_ACT_CFG0");
281 return retval;
284 if (pm_act_cfg0 & PM_ACT_CFG0_EN_CLK_SPC)
285 return ERROR_OK; /* clock already enabled */
287 retval = target_write_u8(target, PM_ACT_CFG0, pm_act_cfg0 | PM_ACT_CFG0_EN_CLK_SPC);
288 if (retval != ERROR_OK)
289 LOG_ERROR("Cannot enable SPC clock");
291 return retval;
294 static int psoc5lp_spc_write_opcode(struct target *target, uint8_t opcode)
296 int retval;
298 retval = target_write_u8(target, SPC_CPU_DATA, SPC_KEY1);
299 if (retval != ERROR_OK)
300 return retval;
301 retval = target_write_u8(target, SPC_CPU_DATA, SPC_KEY2 + opcode);
302 if (retval != ERROR_OK)
303 return retval;
304 retval = target_write_u8(target, SPC_CPU_DATA, opcode);
305 return retval;
308 static void psoc5lp_spc_write_opcode_buffer(struct target *target,
309 uint8_t *buf, uint8_t opcode)
311 buf[0] = SPC_KEY1;
312 buf[1] = SPC_KEY2 + opcode;
313 buf[2] = opcode;
316 static int psoc5lp_spc_busy_wait_data(struct target *target)
318 int64_t endtime;
319 uint8_t sr;
320 int retval;
322 retval = target_read_u8(target, SPC_SR, &sr); /* dummy read */
323 if (retval != ERROR_OK)
324 return retval;
326 endtime = timeval_ms() + 1000; /* 1 second timeout */
327 do {
328 alive_sleep(1);
329 retval = target_read_u8(target, SPC_SR, &sr);
330 if (retval != ERROR_OK)
331 return retval;
332 if (sr == SPC_SR_DATA_READY)
333 return ERROR_OK;
334 } while (timeval_ms() < endtime);
336 return ERROR_FLASH_OPERATION_FAILED;
339 static int psoc5lp_spc_busy_wait_idle(struct target *target)
341 int64_t endtime;
342 uint8_t sr;
343 int retval;
345 retval = target_read_u8(target, SPC_SR, &sr); /* dummy read */
346 if (retval != ERROR_OK)
347 return retval;
349 endtime = timeval_ms() + 1000; /* 1 second timeout */
350 do {
351 alive_sleep(1);
352 retval = target_read_u8(target, SPC_SR, &sr);
353 if (retval != ERROR_OK)
354 return retval;
355 if (sr == SPC_SR_IDLE)
356 return ERROR_OK;
357 } while (timeval_ms() < endtime);
359 return ERROR_FLASH_OPERATION_FAILED;
362 static int psoc5lp_spc_load_row(struct target *target,
363 uint8_t array_id, const uint8_t *data, unsigned row_size)
365 unsigned i;
366 int retval;
368 retval = psoc5lp_spc_write_opcode(target, SPC_LOAD_ROW);
369 if (retval != ERROR_OK)
370 return retval;
371 retval = target_write_u8(target, SPC_CPU_DATA, array_id);
372 if (retval != ERROR_OK)
373 return retval;
375 for (i = 0; i < row_size; i++) {
376 retval = target_write_u8(target, SPC_CPU_DATA, data[i]);
377 if (retval != ERROR_OK)
378 return retval;
381 retval = psoc5lp_spc_busy_wait_idle(target);
382 if (retval != ERROR_OK)
383 return retval;
385 return ERROR_OK;
388 static int psoc5lp_spc_read_byte(struct target *target,
389 uint8_t array_id, uint8_t offset, uint8_t *data)
391 int retval;
393 retval = psoc5lp_spc_write_opcode(target, SPC_READ_BYTE);
394 if (retval != ERROR_OK)
395 return retval;
396 retval = target_write_u8(target, SPC_CPU_DATA, array_id);
397 if (retval != ERROR_OK)
398 return retval;
399 retval = target_write_u8(target, SPC_CPU_DATA, offset);
400 if (retval != ERROR_OK)
401 return retval;
403 retval = psoc5lp_spc_busy_wait_data(target);
404 if (retval != ERROR_OK)
405 return retval;
407 retval = target_read_u8(target, SPC_CPU_DATA, data);
408 if (retval != ERROR_OK)
409 return retval;
411 retval = psoc5lp_spc_busy_wait_idle(target);
412 if (retval != ERROR_OK)
413 return retval;
415 return ERROR_OK;
418 static int psoc5lp_spc_write_row(struct target *target,
419 uint8_t array_id, uint16_t row_id, const uint8_t *temp)
421 int retval;
423 retval = psoc5lp_spc_write_opcode(target, SPC_WRITE_ROW);
424 if (retval != ERROR_OK)
425 return retval;
426 retval = target_write_u8(target, SPC_CPU_DATA, array_id);
427 if (retval != ERROR_OK)
428 return retval;
429 retval = target_write_u8(target, SPC_CPU_DATA, row_id >> 8);
430 if (retval != ERROR_OK)
431 return retval;
432 retval = target_write_u8(target, SPC_CPU_DATA, row_id & 0xff);
433 if (retval != ERROR_OK)
434 return retval;
435 retval = target_write_u8(target, SPC_CPU_DATA, temp[0]);
436 if (retval != ERROR_OK)
437 return retval;
438 retval = target_write_u8(target, SPC_CPU_DATA, temp[1]);
439 if (retval != ERROR_OK)
440 return retval;
442 retval = psoc5lp_spc_busy_wait_idle(target);
443 if (retval != ERROR_OK)
444 return retval;
446 return ERROR_OK;
449 static int psoc5lp_spc_erase_sector(struct target *target,
450 uint8_t array_id, uint8_t row_id)
452 int retval;
454 retval = psoc5lp_spc_write_opcode(target, SPC_ERASE_SECTOR);
455 if (retval != ERROR_OK)
456 return retval;
457 retval = target_write_u8(target, SPC_CPU_DATA, array_id);
458 if (retval != ERROR_OK)
459 return retval;
460 retval = target_write_u8(target, SPC_CPU_DATA, row_id);
461 if (retval != ERROR_OK)
462 return retval;
464 retval = psoc5lp_spc_busy_wait_idle(target);
465 if (retval != ERROR_OK)
466 return retval;
468 return ERROR_OK;
471 static int psoc5lp_spc_erase_all(struct target *target)
473 int retval;
475 retval = psoc5lp_spc_write_opcode(target, SPC_ERASE_ALL);
476 if (retval != ERROR_OK)
477 return retval;
479 retval = psoc5lp_spc_busy_wait_idle(target);
480 if (retval != ERROR_OK)
481 return retval;
483 return ERROR_OK;
486 static int psoc5lp_spc_read_hidden_row(struct target *target,
487 uint8_t array_id, uint8_t row_id, uint8_t *data)
489 int i, retval;
491 retval = psoc5lp_spc_write_opcode(target, SPC_READ_HIDDEN_ROW);
492 if (retval != ERROR_OK)
493 return retval;
494 retval = target_write_u8(target, SPC_CPU_DATA, array_id);
495 if (retval != ERROR_OK)
496 return retval;
497 retval = target_write_u8(target, SPC_CPU_DATA, row_id);
498 if (retval != ERROR_OK)
499 return retval;
501 retval = psoc5lp_spc_busy_wait_data(target);
502 if (retval != ERROR_OK)
503 return retval;
505 for (i = 0; i < ROW_SIZE; i++) {
506 retval = target_read_u8(target, SPC_CPU_DATA, &data[i]);
507 if (retval != ERROR_OK)
508 return retval;
511 retval = psoc5lp_spc_busy_wait_idle(target);
512 if (retval != ERROR_OK)
513 return retval;
515 return ERROR_OK;
518 static int psoc5lp_spc_get_temp(struct target *target, uint8_t samples,
519 uint8_t *data)
521 int retval;
523 retval = psoc5lp_spc_write_opcode(target, SPC_GET_TEMP);
524 if (retval != ERROR_OK)
525 return retval;
526 retval = target_write_u8(target, SPC_CPU_DATA, samples);
527 if (retval != ERROR_OK)
528 return retval;
530 retval = psoc5lp_spc_busy_wait_data(target);
531 if (retval != ERROR_OK)
532 return retval;
534 retval = target_read_u8(target, SPC_CPU_DATA, &data[0]);
535 if (retval != ERROR_OK)
536 return retval;
537 retval = target_read_u8(target, SPC_CPU_DATA, &data[1]);
538 if (retval != ERROR_OK)
539 return retval;
541 retval = psoc5lp_spc_busy_wait_idle(target);
542 if (retval != ERROR_OK)
543 return retval;
545 return ERROR_OK;
549 * EEPROM
552 struct psoc5lp_eeprom_flash_bank {
553 bool probed;
554 const struct psoc5lp_device *device;
557 static int psoc5lp_eeprom_erase(struct flash_bank *bank, int first, int last)
559 int i, retval;
561 for (i = first; i <= last; i++) {
562 retval = psoc5lp_spc_erase_sector(bank->target,
563 SPC_ARRAY_EEPROM, i);
564 if (retval != ERROR_OK)
565 return retval;
568 return ERROR_OK;
571 static int psoc5lp_eeprom_write(struct flash_bank *bank,
572 const uint8_t *buffer, uint32_t offset, uint32_t byte_count)
574 struct target *target = bank->target;
575 uint8_t temp[2];
576 unsigned row;
577 int retval;
579 if (offset % EEPROM_ROW_SIZE != 0) {
580 LOG_ERROR("Writes must be row-aligned, got offset 0x%08" PRIx32,
581 offset);
582 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
585 retval = psoc5lp_spc_get_temp(target, 3, temp);
586 if (retval != ERROR_OK) {
587 LOG_ERROR("Unable to read Die temperature");
588 return retval;
590 LOG_DEBUG("Get_Temp: sign 0x%02" PRIx8 ", magnitude 0x%02" PRIx8,
591 temp[0], temp[1]);
593 for (row = offset / EEPROM_ROW_SIZE; byte_count >= EEPROM_ROW_SIZE; row++) {
594 retval = psoc5lp_spc_load_row(target, SPC_ARRAY_EEPROM,
595 buffer, EEPROM_ROW_SIZE);
596 if (retval != ERROR_OK)
597 return retval;
599 retval = psoc5lp_spc_write_row(target, SPC_ARRAY_EEPROM,
600 row, temp);
601 if (retval != ERROR_OK)
602 return retval;
604 buffer += EEPROM_ROW_SIZE;
605 byte_count -= EEPROM_ROW_SIZE;
606 offset += EEPROM_ROW_SIZE;
608 if (byte_count > 0) {
609 uint8_t buf[EEPROM_ROW_SIZE];
611 memcpy(buf, buffer, byte_count);
612 memset(buf + byte_count, bank->default_padded_value,
613 EEPROM_ROW_SIZE - byte_count);
615 LOG_DEBUG("Padding %d bytes", EEPROM_ROW_SIZE - byte_count);
616 retval = psoc5lp_spc_load_row(target, SPC_ARRAY_EEPROM,
617 buf, EEPROM_ROW_SIZE);
618 if (retval != ERROR_OK)
619 return retval;
621 retval = psoc5lp_spc_write_row(target, SPC_ARRAY_EEPROM,
622 row, temp);
623 if (retval != ERROR_OK)
624 return retval;
627 return ERROR_OK;
630 static int psoc5lp_eeprom_protect_check(struct flash_bank *bank)
632 int i;
634 for (i = 0; i < bank->num_sectors; i++)
635 bank->sectors[i].is_protected = -1;
637 return ERROR_OK;
640 static int psoc5lp_eeprom_get_info_command(struct flash_bank *bank, char *buf, int buf_size)
642 struct psoc5lp_eeprom_flash_bank *psoc_eeprom_bank = bank->driver_priv;
643 char part_number[PART_NUMBER_LEN];
645 psoc5lp_get_part_number(psoc_eeprom_bank->device, part_number);
647 snprintf(buf, buf_size, "%s", part_number);
649 return ERROR_OK;
652 static int psoc5lp_eeprom_probe(struct flash_bank *bank)
654 struct psoc5lp_eeprom_flash_bank *psoc_eeprom_bank = bank->driver_priv;
655 uint32_t flash_addr = bank->base;
656 uint32_t val;
657 int i, retval;
659 if (psoc_eeprom_bank->probed)
660 return ERROR_OK;
662 if (bank->target->state != TARGET_HALTED) {
663 LOG_ERROR("Target not halted");
664 return ERROR_TARGET_NOT_HALTED;
667 retval = psoc5lp_find_device(bank->target, &psoc_eeprom_bank->device);
668 if (retval != ERROR_OK)
669 return retval;
671 retval = target_read_u32(bank->target, PM_ACT_CFG12, &val);
672 if (retval != ERROR_OK)
673 return retval;
674 if (!(val & PM_ACT_CFG12_EN_EE)) {
675 val |= PM_ACT_CFG12_EN_EE;
676 retval = target_write_u32(bank->target, PM_ACT_CFG12, val);
677 if (retval != ERROR_OK)
678 return retval;
681 bank->size = psoc_eeprom_bank->device->eeprom_kb * 1024;
682 bank->num_sectors = DIV_ROUND_UP(bank->size, EEPROM_SECTOR_SIZE);
683 bank->sectors = calloc(bank->num_sectors,
684 sizeof(struct flash_sector));
685 for (i = 0; i < bank->num_sectors; i++) {
686 bank->sectors[i].size = EEPROM_SECTOR_SIZE;
687 bank->sectors[i].offset = flash_addr - bank->base;
688 bank->sectors[i].is_erased = -1;
689 bank->sectors[i].is_protected = -1;
691 flash_addr += bank->sectors[i].size;
694 bank->default_padded_value = bank->erased_value = 0x00;
696 psoc_eeprom_bank->probed = true;
698 return ERROR_OK;
701 static int psoc5lp_eeprom_auto_probe(struct flash_bank *bank)
703 struct psoc5lp_eeprom_flash_bank *psoc_eeprom_bank = bank->driver_priv;
705 if (psoc_eeprom_bank->probed)
706 return ERROR_OK;
708 return psoc5lp_eeprom_probe(bank);
711 FLASH_BANK_COMMAND_HANDLER(psoc5lp_eeprom_flash_bank_command)
713 struct psoc5lp_eeprom_flash_bank *psoc_eeprom_bank;
715 psoc_eeprom_bank = malloc(sizeof(struct psoc5lp_eeprom_flash_bank));
716 if (!psoc_eeprom_bank)
717 return ERROR_FLASH_OPERATION_FAILED;
719 psoc_eeprom_bank->probed = false;
720 psoc_eeprom_bank->device = NULL;
722 bank->driver_priv = psoc_eeprom_bank;
724 return ERROR_OK;
727 static const struct command_registration psoc5lp_eeprom_exec_command_handlers[] = {
728 COMMAND_REGISTRATION_DONE
731 static const struct command_registration psoc5lp_eeprom_command_handlers[] = {
733 .name = "psoc5lp_eeprom",
734 .mode = COMMAND_ANY,
735 .help = "PSoC 5LP EEPROM command group",
736 .usage = "",
737 .chain = psoc5lp_eeprom_exec_command_handlers,
739 COMMAND_REGISTRATION_DONE
742 struct flash_driver psoc5lp_eeprom_flash = {
743 .name = "psoc5lp_eeprom",
744 .commands = psoc5lp_eeprom_command_handlers,
745 .flash_bank_command = psoc5lp_eeprom_flash_bank_command,
746 .info = psoc5lp_eeprom_get_info_command,
747 .probe = psoc5lp_eeprom_probe,
748 .auto_probe = psoc5lp_eeprom_auto_probe,
749 .protect_check = psoc5lp_eeprom_protect_check,
750 .read = default_flash_read,
751 .erase = psoc5lp_eeprom_erase,
752 .erase_check = default_flash_blank_check,
753 .write = psoc5lp_eeprom_write,
757 * Program Flash
760 struct psoc5lp_flash_bank {
761 bool probed;
762 const struct psoc5lp_device *device;
763 bool ecc_enabled;
766 static int psoc5lp_erase(struct flash_bank *bank, int first, int last)
768 struct psoc5lp_flash_bank *psoc_bank = bank->driver_priv;
769 int i, retval;
771 if (!psoc_bank->ecc_enabled) {
772 /* Silently avoid erasing sectors twice */
773 if (last >= first + bank->num_sectors / 2) {
774 LOG_DEBUG("Skipping duplicate erase of sectors %d to %d",
775 first + bank->num_sectors / 2, last);
776 last = first + (bank->num_sectors / 2) - 1;
778 /* Check for any remaining ECC sectors */
779 if (last >= bank->num_sectors / 2) {
780 LOG_WARNING("Skipping erase of ECC region sectors %d to %d",
781 bank->num_sectors / 2, last);
782 last = (bank->num_sectors / 2) - 1;
786 for (i = first; i <= last; i++) {
787 retval = psoc5lp_spc_erase_sector(bank->target,
788 i / SECTORS_PER_BLOCK, i % SECTORS_PER_BLOCK);
789 if (retval != ERROR_OK)
790 return retval;
793 return ERROR_OK;
796 /* Derived from core.c:default_flash_blank_check() */
797 static int psoc5lp_erase_check(struct flash_bank *bank)
799 struct psoc5lp_flash_bank *psoc_bank = bank->driver_priv;
800 struct target *target = bank->target;
801 uint32_t blank;
802 int i, num_sectors, retval;
804 if (target->state != TARGET_HALTED) {
805 LOG_ERROR("Target not halted");
806 return ERROR_TARGET_NOT_HALTED;
809 num_sectors = bank->num_sectors;
810 if (!psoc_bank->ecc_enabled)
811 num_sectors /= 2;
813 for (i = 0; i < num_sectors; i++) {
814 uint32_t address = bank->base + bank->sectors[i].offset;
815 uint32_t size = bank->sectors[i].size;
817 retval = armv7m_blank_check_memory(target, address, size,
818 &blank, bank->erased_value);
819 if (retval != ERROR_OK)
820 return retval;
822 if (blank == 0x00 && !psoc_bank->ecc_enabled) {
823 address = bank->base + bank->sectors[num_sectors + i].offset;
824 size = bank->sectors[num_sectors + i].size;
826 retval = armv7m_blank_check_memory(target, address, size,
827 &blank, bank->erased_value);
828 if (retval != ERROR_OK)
829 return retval;
832 if (blank == 0x00) {
833 bank->sectors[i].is_erased = 1;
834 bank->sectors[num_sectors + i].is_erased = 1;
835 } else {
836 bank->sectors[i].is_erased = 0;
837 bank->sectors[num_sectors + i].is_erased = 0;
841 return ERROR_OK;
844 static int psoc5lp_write(struct flash_bank *bank, const uint8_t *buffer,
845 uint32_t offset, uint32_t byte_count)
847 struct psoc5lp_flash_bank *psoc_bank = bank->driver_priv;
848 struct target *target = bank->target;
849 struct working_area *code_area, *even_row_area, *odd_row_area;
850 uint32_t row_size;
851 uint8_t temp[2], buf[12], ecc_bytes[ROW_ECC_SIZE];
852 unsigned array_id, row;
853 int i, retval;
855 if (offset + byte_count > bank->size) {
856 LOG_ERROR("Writing to ECC not supported");
857 return ERROR_FLASH_DST_OUT_OF_BANK;
860 if (offset % ROW_SIZE != 0) {
861 LOG_ERROR("Writes must be row-aligned, got offset 0x%08" PRIx32,
862 offset);
863 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
866 row_size = ROW_SIZE;
867 if (!psoc_bank->ecc_enabled) {
868 row_size += ROW_ECC_SIZE;
869 memset(ecc_bytes, bank->default_padded_value, ROW_ECC_SIZE);
872 retval = psoc5lp_spc_get_temp(target, 3, temp);
873 if (retval != ERROR_OK) {
874 LOG_ERROR("Unable to read Die temperature");
875 return retval;
877 LOG_DEBUG("Get_Temp: sign 0x%02" PRIx8 ", magnitude 0x%02" PRIx8,
878 temp[0], temp[1]);
880 assert(target_get_working_area_avail(target) == target->working_area_size);
881 retval = target_alloc_working_area(target,
882 target_get_working_area_avail(target) / 2, &code_area);
883 if (retval != ERROR_OK) {
884 LOG_ERROR("Could not allocate working area for program SRAM");
885 return retval;
887 assert(code_area->address < 0x20000000);
889 retval = target_alloc_working_area(target,
890 SPC_OPCODE_LEN + 1 + row_size + 3 + SPC_OPCODE_LEN + 6,
891 &even_row_area);
892 if (retval != ERROR_OK) {
893 LOG_ERROR("Could not allocate working area for even row");
894 goto err_alloc_even;
896 assert(even_row_area->address >= 0x20000000);
898 retval = target_alloc_working_area(target, even_row_area->size,
899 &odd_row_area);
900 if (retval != ERROR_OK) {
901 LOG_ERROR("Could not allocate working area for odd row");
902 goto err_alloc_odd;
904 assert(odd_row_area->address >= 0x20000000);
906 for (array_id = offset / BLOCK_SIZE; byte_count > 0; array_id++) {
907 for (row = (offset / ROW_SIZE) % ROWS_PER_BLOCK;
908 row < ROWS_PER_BLOCK && byte_count > 0; row++) {
909 bool even_row = (row % 2 == 0);
910 struct working_area *data_area = even_row ? even_row_area : odd_row_area;
911 unsigned len = MIN(ROW_SIZE, byte_count);
913 LOG_DEBUG("Writing load command for array %u row %u at 0x%08" TARGET_PRIxADDR,
914 array_id, row, data_area->address);
916 psoc5lp_spc_write_opcode_buffer(target, buf, SPC_LOAD_ROW);
917 buf[SPC_OPCODE_LEN] = array_id;
918 retval = target_write_buffer(target, data_area->address, 4, buf);
919 if (retval != ERROR_OK)
920 goto err_write;
922 retval = target_write_buffer(target,
923 data_area->address + SPC_OPCODE_LEN + 1,
924 len, buffer);
925 if (retval != ERROR_OK)
926 goto err_write;
927 buffer += len;
928 byte_count -= len;
929 offset += len;
931 if (len < ROW_SIZE) {
932 uint8_t padding[ROW_SIZE];
934 memset(padding, bank->default_padded_value, ROW_SIZE);
936 LOG_DEBUG("Padding %d bytes", ROW_SIZE - len);
937 retval = target_write_buffer(target,
938 data_area->address + SPC_OPCODE_LEN + 1 + len,
939 ROW_SIZE - len, padding);
940 if (retval != ERROR_OK)
941 goto err_write;
944 if (!psoc_bank->ecc_enabled) {
945 retval = target_write_buffer(target,
946 data_area->address + SPC_OPCODE_LEN + 1 + ROW_SIZE,
947 sizeof(ecc_bytes), ecc_bytes);
948 if (retval != ERROR_OK)
949 goto err_write;
952 for (i = 0; i < 3; i++)
953 buf[i] = 0x00; /* 3 NOPs for short delay */
954 psoc5lp_spc_write_opcode_buffer(target, buf + 3, SPC_PRG_ROW);
955 buf[3 + SPC_OPCODE_LEN] = array_id;
956 buf[3 + SPC_OPCODE_LEN + 1] = row >> 8;
957 buf[3 + SPC_OPCODE_LEN + 2] = row & 0xff;
958 memcpy(buf + 3 + SPC_OPCODE_LEN + 3, temp, 2);
959 buf[3 + SPC_OPCODE_LEN + 5] = 0x00; /* padding */
960 retval = target_write_buffer(target,
961 data_area->address + SPC_OPCODE_LEN + 1 + row_size,
962 12, buf);
963 if (retval != ERROR_OK)
964 goto err_write;
966 retval = target_write_u32(target,
967 even_row ? PHUB_CH0_BASIC_STATUS : PHUB_CH1_BASIC_STATUS,
968 (even_row ? 0 : 1) << 8);
969 if (retval != ERROR_OK)
970 goto err_dma;
972 retval = target_write_u32(target,
973 even_row ? PHUB_CH0_BASIC_CFG : PHUB_CH1_BASIC_CFG,
974 PHUB_CHx_BASIC_CFG_WORK_SEP | PHUB_CHx_BASIC_CFG_EN);
975 if (retval != ERROR_OK)
976 goto err_dma;
978 retval = target_write_u32(target,
979 even_row ? PHUB_CFGMEM0_CFG0 : PHUB_CFGMEM1_CFG0,
980 PHUB_CFGMEMx_CFG0);
981 if (retval != ERROR_OK)
982 goto err_dma;
984 retval = target_write_u32(target,
985 even_row ? PHUB_CFGMEM0_CFG1 : PHUB_CFGMEM1_CFG1,
986 ((SPC_CPU_DATA >> 16) << 16) | (data_area->address >> 16));
987 if (retval != ERROR_OK)
988 goto err_dma;
990 retval = target_write_u32(target,
991 even_row ? PHUB_TDMEM0_ORIG_TD0 : PHUB_TDMEM1_ORIG_TD0,
992 PHUB_TDMEMx_ORIG_TD0_INC_SRC_ADDR |
993 PHUB_TDMEMx_ORIG_TD0_NEXT_TD_PTR_LAST |
994 ((SPC_OPCODE_LEN + 1 + row_size + 3 + SPC_OPCODE_LEN + 5) & 0xfff));
995 if (retval != ERROR_OK)
996 goto err_dma;
998 retval = target_write_u32(target,
999 even_row ? PHUB_TDMEM0_ORIG_TD1 : PHUB_TDMEM1_ORIG_TD1,
1000 ((SPC_CPU_DATA & 0xffff) << 16) | (data_area->address & 0xffff));
1001 if (retval != ERROR_OK)
1002 goto err_dma;
1004 retval = psoc5lp_spc_busy_wait_idle(target);
1005 if (retval != ERROR_OK)
1006 goto err_idle;
1008 retval = target_write_u32(target,
1009 even_row ? PHUB_CH0_ACTION : PHUB_CH1_ACTION,
1010 PHUB_CHx_ACTION_CPU_REQ);
1011 if (retval != ERROR_OK)
1012 goto err_dma_action;
1016 retval = psoc5lp_spc_busy_wait_idle(target);
1018 err_dma_action:
1019 err_idle:
1020 err_dma:
1021 err_write:
1022 target_free_working_area(target, odd_row_area);
1023 err_alloc_odd:
1024 target_free_working_area(target, even_row_area);
1025 err_alloc_even:
1026 target_free_working_area(target, code_area);
1028 return retval;
1031 static int psoc5lp_protect_check(struct flash_bank *bank)
1033 struct psoc5lp_flash_bank *psoc_bank = bank->driver_priv;
1034 uint8_t row_data[ROW_SIZE];
1035 const unsigned protection_bytes_per_sector = ROWS_PER_SECTOR * 2 / 8;
1036 unsigned i, j, k, num_sectors;
1037 int retval;
1039 if (bank->target->state != TARGET_HALTED) {
1040 LOG_ERROR("Target not halted");
1041 return ERROR_TARGET_NOT_HALTED;
1044 for (i = 0; i < DIV_ROUND_UP(bank->size, BLOCK_SIZE); i++) {
1045 retval = psoc5lp_spc_read_hidden_row(bank->target, i,
1046 SPC_ROW_PROTECTION, row_data);
1047 if (retval != ERROR_OK)
1048 return retval;
1050 /* Last flash array may have less rows, but in practice full sectors. */
1051 if (i == bank->size / BLOCK_SIZE)
1052 num_sectors = (bank->size % BLOCK_SIZE) / SECTOR_SIZE;
1053 else
1054 num_sectors = SECTORS_PER_BLOCK;
1056 for (j = 0; j < num_sectors; j++) {
1057 int sector_nr = i * SECTORS_PER_BLOCK + j;
1058 struct flash_sector *sector = &bank->sectors[sector_nr];
1059 struct flash_sector *ecc_sector;
1061 if (psoc_bank->ecc_enabled)
1062 ecc_sector = &bank->sectors[bank->num_sectors + sector_nr];
1063 else
1064 ecc_sector = &bank->sectors[bank->num_sectors / 2 + sector_nr];
1066 sector->is_protected = ecc_sector->is_protected = 0;
1067 for (k = protection_bytes_per_sector * j;
1068 k < protection_bytes_per_sector * (j + 1); k++) {
1069 assert(k < protection_bytes_per_sector * SECTORS_PER_BLOCK);
1070 LOG_DEBUG("row[%u][%02u] = 0x%02" PRIx8, i, k, row_data[k]);
1071 if (row_data[k] != 0x00) {
1072 sector->is_protected = ecc_sector->is_protected = 1;
1073 break;
1079 return ERROR_OK;
1082 static int psoc5lp_get_info_command(struct flash_bank *bank, char *buf, int buf_size)
1084 struct psoc5lp_flash_bank *psoc_bank = bank->driver_priv;
1085 char part_number[PART_NUMBER_LEN];
1086 const char *ecc;
1088 psoc5lp_get_part_number(psoc_bank->device, part_number);
1089 ecc = psoc_bank->ecc_enabled ? "ECC enabled" : "ECC disabled";
1091 snprintf(buf, buf_size, "%s %s", part_number, ecc);
1093 return ERROR_OK;
1096 static int psoc5lp_probe(struct flash_bank *bank)
1098 struct target *target = bank->target;
1099 struct psoc5lp_flash_bank *psoc_bank = bank->driver_priv;
1100 uint32_t flash_addr = bank->base;
1101 uint8_t nvl[4], temp[2];
1102 int i, retval;
1104 if (target->state != TARGET_HALTED) {
1105 LOG_ERROR("Target not halted");
1106 return ERROR_TARGET_NOT_HALTED;
1109 if (!psoc_bank->device) {
1110 retval = psoc5lp_find_device(target, &psoc_bank->device);
1111 if (retval != ERROR_OK)
1112 return retval;
1114 bank->size = psoc_bank->device->flash_kb * 1024;
1117 bank->num_sectors = DIV_ROUND_UP(bank->size, SECTOR_SIZE);
1119 if (!psoc_bank->probed) {
1120 retval = psoc5lp_spc_enable_clock(target);
1121 if (retval != ERROR_OK)
1122 return retval;
1124 /* First values read are inaccurate, so do it once now. */
1125 retval = psoc5lp_spc_get_temp(target, 3, temp);
1126 if (retval != ERROR_OK) {
1127 LOG_ERROR("Unable to read Die temperature");
1128 return retval;
1131 bank->sectors = calloc(bank->num_sectors * 2,
1132 sizeof(struct flash_sector));
1133 for (i = 0; i < bank->num_sectors; i++) {
1134 bank->sectors[i].size = SECTOR_SIZE;
1135 bank->sectors[i].offset = flash_addr - bank->base;
1136 bank->sectors[i].is_erased = -1;
1137 bank->sectors[i].is_protected = -1;
1139 flash_addr += bank->sectors[i].size;
1141 flash_addr = 0x48000000;
1142 for (i = bank->num_sectors; i < bank->num_sectors * 2; i++) {
1143 bank->sectors[i].size = ROWS_PER_SECTOR * ROW_ECC_SIZE;
1144 bank->sectors[i].offset = flash_addr - bank->base;
1145 bank->sectors[i].is_erased = -1;
1146 bank->sectors[i].is_protected = -1;
1148 flash_addr += bank->sectors[i].size;
1151 bank->default_padded_value = bank->erased_value = 0x00;
1153 psoc_bank->probed = true;
1156 retval = psoc5lp_spc_read_byte(target, SPC_ARRAY_NVL_USER, 3, &nvl[3]);
1157 if (retval != ERROR_OK)
1158 return retval;
1159 LOG_DEBUG("NVL[%d] = 0x%02" PRIx8, 3, nvl[3]);
1160 psoc_bank->ecc_enabled = nvl[3] & NVL_3_ECCEN;
1162 if (!psoc_bank->ecc_enabled)
1163 bank->num_sectors *= 2;
1165 return ERROR_OK;
1168 static int psoc5lp_auto_probe(struct flash_bank *bank)
1170 return psoc5lp_probe(bank);
1173 COMMAND_HANDLER(psoc5lp_handle_mass_erase_command)
1175 struct flash_bank *bank;
1176 int retval;
1178 if (CMD_ARGC < 1)
1179 return ERROR_COMMAND_SYNTAX_ERROR;
1181 retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
1182 if (retval != ERROR_OK)
1183 return retval;
1185 retval = psoc5lp_spc_erase_all(bank->target);
1186 if (retval == ERROR_OK)
1187 command_print(CMD_CTX, "PSoC 5LP erase succeeded");
1188 else
1189 command_print(CMD_CTX, "PSoC 5LP erase failed");
1191 return retval;
1194 FLASH_BANK_COMMAND_HANDLER(psoc5lp_flash_bank_command)
1196 struct psoc5lp_flash_bank *psoc_bank;
1198 psoc_bank = malloc(sizeof(struct psoc5lp_flash_bank));
1199 if (!psoc_bank)
1200 return ERROR_FLASH_OPERATION_FAILED;
1202 psoc_bank->probed = false;
1203 psoc_bank->device = NULL;
1205 bank->driver_priv = psoc_bank;
1207 return ERROR_OK;
1210 static const struct command_registration psoc5lp_exec_command_handlers[] = {
1212 .name = "mass_erase",
1213 .handler = psoc5lp_handle_mass_erase_command,
1214 .mode = COMMAND_EXEC,
1215 .usage = "bank_id",
1216 .help = "Erase all flash data and ECC/configuration bytes, "
1217 "all flash protection rows, "
1218 "and all row latches in all flash arrays on the device.",
1220 COMMAND_REGISTRATION_DONE
1223 static const struct command_registration psoc5lp_command_handlers[] = {
1225 .name = "psoc5lp",
1226 .mode = COMMAND_ANY,
1227 .help = "PSoC 5LP flash command group",
1228 .usage = "",
1229 .chain = psoc5lp_exec_command_handlers,
1231 COMMAND_REGISTRATION_DONE
1234 struct flash_driver psoc5lp_flash = {
1235 .name = "psoc5lp",
1236 .commands = psoc5lp_command_handlers,
1237 .flash_bank_command = psoc5lp_flash_bank_command,
1238 .info = psoc5lp_get_info_command,
1239 .probe = psoc5lp_probe,
1240 .auto_probe = psoc5lp_auto_probe,
1241 .protect_check = psoc5lp_protect_check,
1242 .read = default_flash_read,
1243 .erase = psoc5lp_erase,
1244 .erase_check = psoc5lp_erase_check,
1245 .write = psoc5lp_write,