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/>.
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 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
49 /* NVL is not actually mapped to the Cortex-M address space
50 * As we need a base address 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
54 #define PM_ACT_CFG12_EN_EE (1 << 4)
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
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
80 #define SPC_ROW_PROTECTION 0
82 #define SPC_OPCODE_LEN 3
84 #define SPC_SR_DATA_READY (1 << 0)
85 #define SPC_SR_IDLE (1 << 1)
87 #define PM_ACT_CFG0_EN_CLK_SPC (1 << 3)
89 #define PHUB_CHx_BASIC_CFG_EN (1 << 0)
90 #define PHUB_CHx_BASIC_CFG_WORK_SEP (1 << 5)
92 #define PHUB_CHx_ACTION_CPU_REQ (1 << 0)
94 #define PHUB_CFGMEMx_CFG0 (1 << 7)
96 #define PHUB_TDMEMx_ORIG_TD0_NEXT_TD_PTR_LAST (0xff << 16)
97 #define PHUB_TDMEMx_ORIG_TD0_INC_SRC_ADDR (1 << 24)
99 #define NVL_3_ECCEN (1 << 3)
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)
112 #define PART_NUMBER_LEN (17 + 1)
114 struct psoc5lp_device {
123 * Device information collected from datasheets.
124 * Different temperature ranges (C/I/Q/A) may share IDs, not differing otherwise.
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 },
143 { .id = 0x2E161069, .fam = 8, .speed_mhz = 80, .flash_kb = 256, .eeprom_kb = 2 },
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 },
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 },
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 },
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 },
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 },
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 },
201 static void psoc5lp_get_part_number(const struct psoc5lp_device *dev, char *str)
203 strcpy(str, "CY8Cabcdefg-LPxxx");
206 str[5] = '0' + dev->fam;
208 switch (dev->speed_mhz) {
219 switch (dev->flash_kb) {
236 /* Package does not matter. */
240 /* Temperate range cannot uniquely be identified. */
244 static int psoc5lp_get_device_id(struct target *target, uint32_t *id)
248 retval = target_read_u32(target, PANTHER_DEVICE_ID, id); /* dummy read */
249 if (retval != ERROR_OK)
251 retval = target_read_u32(target, PANTHER_DEVICE_ID, id);
255 static int psoc5lp_find_device(struct target *target,
256 const struct psoc5lp_device **device)
264 retval = psoc5lp_get_device_id(target, &device_id);
265 if (retval != ERROR_OK)
267 LOG_DEBUG("PANTHER_DEVICE_ID = 0x%08" PRIX32, device_id);
269 for (i = 0; i < ARRAY_SIZE(psoc5lp_devices); i++) {
270 if (psoc5lp_devices[i].id == device_id) {
271 *device = &psoc5lp_devices[i];
276 LOG_ERROR("Device 0x%08" PRIX32 " not supported", device_id);
277 return ERROR_FLASH_OPER_UNSUPPORTED;
280 static int psoc5lp_spc_enable_clock(struct target *target)
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");
291 if (pm_act_cfg0 & PM_ACT_CFG0_EN_CLK_SPC)
292 return ERROR_OK; /* clock already enabled */
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");
301 static int psoc5lp_spc_write_opcode(struct target *target, uint8_t opcode)
305 retval = target_write_u8(target, SPC_CPU_DATA, SPC_KEY1);
306 if (retval != ERROR_OK)
308 retval = target_write_u8(target, SPC_CPU_DATA, SPC_KEY2 + opcode);
309 if (retval != ERROR_OK)
311 retval = target_write_u8(target, SPC_CPU_DATA, opcode);
315 static void psoc5lp_spc_write_opcode_buffer(struct target *target,
316 uint8_t *buf, uint8_t opcode)
319 buf[1] = SPC_KEY2 + opcode;
323 static int psoc5lp_spc_busy_wait_data(struct target *target)
329 retval = target_read_u8(target, SPC_SR, &sr); /* dummy read */
330 if (retval != ERROR_OK)
333 endtime = timeval_ms() + 1000; /* 1 second timeout */
336 retval = target_read_u8(target, SPC_SR, &sr);
337 if (retval != ERROR_OK)
339 if (sr == SPC_SR_DATA_READY)
341 } while (timeval_ms() < endtime);
343 return ERROR_FLASH_OPERATION_FAILED;
346 static int psoc5lp_spc_busy_wait_idle(struct target *target)
352 retval = target_read_u8(target, SPC_SR, &sr); /* dummy read */
353 if (retval != ERROR_OK)
356 endtime = timeval_ms() + 1000; /* 1 second timeout */
359 retval = target_read_u8(target, SPC_SR, &sr);
360 if (retval != ERROR_OK)
362 if (sr == SPC_SR_IDLE)
364 } while (timeval_ms() < endtime);
366 return ERROR_FLASH_OPERATION_FAILED;
369 static int psoc5lp_spc_load_byte(struct target *target,
370 uint8_t array_id, uint8_t offset, uint8_t value)
374 retval = psoc5lp_spc_write_opcode(target, SPC_LOAD_BYTE);
375 if (retval != ERROR_OK)
377 retval = target_write_u8(target, SPC_CPU_DATA, array_id);
378 if (retval != ERROR_OK)
380 retval = target_write_u8(target, SPC_CPU_DATA, offset);
381 if (retval != ERROR_OK)
383 retval = target_write_u8(target, SPC_CPU_DATA, value);
384 if (retval != ERROR_OK)
387 retval = psoc5lp_spc_busy_wait_idle(target);
388 if (retval != ERROR_OK)
394 static int psoc5lp_spc_load_row(struct target *target,
395 uint8_t array_id, const uint8_t *data, unsigned row_size)
400 retval = psoc5lp_spc_write_opcode(target, SPC_LOAD_ROW);
401 if (retval != ERROR_OK)
403 retval = target_write_u8(target, SPC_CPU_DATA, array_id);
404 if (retval != ERROR_OK)
407 for (i = 0; i < row_size; i++) {
408 retval = target_write_u8(target, SPC_CPU_DATA, data[i]);
409 if (retval != ERROR_OK)
413 retval = psoc5lp_spc_busy_wait_idle(target);
414 if (retval != ERROR_OK)
420 static int psoc5lp_spc_read_byte(struct target *target,
421 uint8_t array_id, uint8_t offset, uint8_t *data)
425 retval = psoc5lp_spc_write_opcode(target, SPC_READ_BYTE);
426 if (retval != ERROR_OK)
428 retval = target_write_u8(target, SPC_CPU_DATA, array_id);
429 if (retval != ERROR_OK)
431 retval = target_write_u8(target, SPC_CPU_DATA, offset);
432 if (retval != ERROR_OK)
435 retval = psoc5lp_spc_busy_wait_data(target);
436 if (retval != ERROR_OK)
439 retval = target_read_u8(target, SPC_CPU_DATA, data);
440 if (retval != ERROR_OK)
443 retval = psoc5lp_spc_busy_wait_idle(target);
444 if (retval != ERROR_OK)
450 static int psoc5lp_spc_write_row(struct target *target,
451 uint8_t array_id, uint16_t row_id, const uint8_t *temp)
455 retval = psoc5lp_spc_write_opcode(target, SPC_WRITE_ROW);
456 if (retval != ERROR_OK)
458 retval = target_write_u8(target, SPC_CPU_DATA, array_id);
459 if (retval != ERROR_OK)
461 retval = target_write_u8(target, SPC_CPU_DATA, row_id >> 8);
462 if (retval != ERROR_OK)
464 retval = target_write_u8(target, SPC_CPU_DATA, row_id & 0xff);
465 if (retval != ERROR_OK)
467 retval = target_write_u8(target, SPC_CPU_DATA, temp[0]);
468 if (retval != ERROR_OK)
470 retval = target_write_u8(target, SPC_CPU_DATA, temp[1]);
471 if (retval != ERROR_OK)
474 retval = psoc5lp_spc_busy_wait_idle(target);
475 if (retval != ERROR_OK)
481 static int psoc5lp_spc_write_user_nvl(struct target *target,
486 retval = psoc5lp_spc_write_opcode(target, SPC_WRITE_USER_NVL);
487 if (retval != ERROR_OK)
489 retval = target_write_u8(target, SPC_CPU_DATA, array_id);
490 if (retval != ERROR_OK)
493 retval = psoc5lp_spc_busy_wait_idle(target);
494 if (retval != ERROR_OK)
500 static int psoc5lp_spc_erase_sector(struct target *target,
501 uint8_t array_id, uint8_t row_id)
505 retval = psoc5lp_spc_write_opcode(target, SPC_ERASE_SECTOR);
506 if (retval != ERROR_OK)
508 retval = target_write_u8(target, SPC_CPU_DATA, array_id);
509 if (retval != ERROR_OK)
511 retval = target_write_u8(target, SPC_CPU_DATA, row_id);
512 if (retval != ERROR_OK)
515 retval = psoc5lp_spc_busy_wait_idle(target);
516 if (retval != ERROR_OK)
522 static int psoc5lp_spc_erase_all(struct target *target)
526 retval = psoc5lp_spc_write_opcode(target, SPC_ERASE_ALL);
527 if (retval != ERROR_OK)
530 retval = psoc5lp_spc_busy_wait_idle(target);
531 if (retval != ERROR_OK)
537 static int psoc5lp_spc_read_hidden_row(struct target *target,
538 uint8_t array_id, uint8_t row_id, uint8_t *data)
542 retval = psoc5lp_spc_write_opcode(target, SPC_READ_HIDDEN_ROW);
543 if (retval != ERROR_OK)
545 retval = target_write_u8(target, SPC_CPU_DATA, array_id);
546 if (retval != ERROR_OK)
548 retval = target_write_u8(target, SPC_CPU_DATA, row_id);
549 if (retval != ERROR_OK)
552 retval = psoc5lp_spc_busy_wait_data(target);
553 if (retval != ERROR_OK)
556 for (i = 0; i < ROW_SIZE; i++) {
557 retval = target_read_u8(target, SPC_CPU_DATA, &data[i]);
558 if (retval != ERROR_OK)
562 retval = psoc5lp_spc_busy_wait_idle(target);
563 if (retval != ERROR_OK)
569 static int psoc5lp_spc_get_temp(struct target *target, uint8_t samples,
574 retval = psoc5lp_spc_write_opcode(target, SPC_GET_TEMP);
575 if (retval != ERROR_OK)
577 retval = target_write_u8(target, SPC_CPU_DATA, samples);
578 if (retval != ERROR_OK)
581 retval = psoc5lp_spc_busy_wait_data(target);
582 if (retval != ERROR_OK)
585 retval = target_read_u8(target, SPC_CPU_DATA, &data[0]);
586 if (retval != ERROR_OK)
588 retval = target_read_u8(target, SPC_CPU_DATA, &data[1]);
589 if (retval != ERROR_OK)
592 retval = psoc5lp_spc_busy_wait_idle(target);
593 if (retval != ERROR_OK)
599 static int psoc5lp_spc_read_volatile_byte(struct target *target,
600 uint8_t array_id, uint8_t offset, uint8_t *data)
604 retval = psoc5lp_spc_write_opcode(target, SPC_READ_VOLATILE_BYTE);
605 if (retval != ERROR_OK)
607 retval = target_write_u8(target, SPC_CPU_DATA, array_id);
608 if (retval != ERROR_OK)
610 retval = target_write_u8(target, SPC_CPU_DATA, offset);
611 if (retval != ERROR_OK)
614 retval = psoc5lp_spc_busy_wait_data(target);
615 if (retval != ERROR_OK)
618 retval = target_read_u8(target, SPC_CPU_DATA, data);
619 if (retval != ERROR_OK)
622 retval = psoc5lp_spc_busy_wait_idle(target);
623 if (retval != ERROR_OK)
633 struct psoc5lp_nvl_flash_bank {
635 const struct psoc5lp_device *device;
638 static int psoc5lp_nvl_read(struct flash_bank *bank,
639 uint8_t *buffer, uint32_t offset, uint32_t count)
643 retval = psoc5lp_spc_enable_clock(bank->target);
644 if (retval != ERROR_OK)
648 retval = psoc5lp_spc_read_byte(bank->target,
649 SPC_ARRAY_NVL_USER, offset, buffer);
650 if (retval != ERROR_OK)
660 static int psoc5lp_nvl_erase(struct flash_bank *bank, unsigned int first,
663 LOG_WARNING("There is no erase operation for NV Latches");
664 return ERROR_FLASH_OPER_UNSUPPORTED;
667 static int psoc5lp_nvl_erase_check(struct flash_bank *bank)
669 for (unsigned int i = 0; i < bank->num_sectors; i++)
670 bank->sectors[i].is_erased = 0;
675 static int psoc5lp_nvl_write(struct flash_bank *bank,
676 const uint8_t *buffer, uint32_t offset, uint32_t byte_count)
678 struct target *target = bank->target;
679 uint8_t *current_data, val;
680 bool write_required = false, pullup_needed = false, ecc_changed = false;
684 if (offset != 0 || byte_count != bank->size) {
685 LOG_ERROR("NVL can only be written in whole");
686 return ERROR_FLASH_OPER_UNSUPPORTED;
689 current_data = calloc(1, bank->size);
692 retval = psoc5lp_nvl_read(bank, current_data, offset, byte_count);
693 if (retval != ERROR_OK) {
697 for (i = offset; i < byte_count; i++) {
698 if (current_data[i] != buffer[i]) {
699 write_required = true;
703 if (((buffer[2] & 0x80) == 0x80) && ((current_data[0] & 0x0C) != 0x08))
704 pullup_needed = true;
705 if (((buffer[3] ^ current_data[3]) & 0x08) == 0x08)
709 if (!write_required) {
710 LOG_INFO("Unchanged, skipping NVL write");
714 retval = target_read_u8(target, PRT1_PC2, &val);
715 if (retval != ERROR_OK)
719 retval = target_write_u8(target, PRT1_PC2, val);
720 if (retval != ERROR_OK)
724 for (i = offset; i < byte_count; i++) {
725 retval = psoc5lp_spc_load_byte(target,
726 SPC_ARRAY_NVL_USER, i, buffer[i]);
727 if (retval != ERROR_OK)
730 retval = psoc5lp_spc_read_volatile_byte(target,
731 SPC_ARRAY_NVL_USER, i, &val);
732 if (retval != ERROR_OK)
734 if (val != buffer[i]) {
735 LOG_ERROR("Failed to load NVL byte %" PRIu32 ": "
736 "expected 0x%02" PRIx8 ", read 0x%02" PRIx8,
738 return ERROR_FLASH_OPERATION_FAILED;
742 retval = psoc5lp_spc_write_user_nvl(target, SPC_ARRAY_NVL_USER);
743 if (retval != ERROR_OK)
747 retval = target_call_reset_callbacks(target, RESET_INIT);
748 if (retval != ERROR_OK)
749 LOG_WARNING("Reset failed after enabling or disabling ECC");
755 static int psoc5lp_nvl_get_info_command(struct flash_bank *bank,
756 char *buf, int buf_size)
758 struct psoc5lp_nvl_flash_bank *psoc_nvl_bank = bank->driver_priv;
759 char part_number[PART_NUMBER_LEN];
761 psoc5lp_get_part_number(psoc_nvl_bank->device, part_number);
763 snprintf(buf, buf_size, "%s", part_number);
768 static int psoc5lp_nvl_probe(struct flash_bank *bank)
770 struct psoc5lp_nvl_flash_bank *psoc_nvl_bank = bank->driver_priv;
773 if (psoc_nvl_bank->probed)
776 if (bank->target->state != TARGET_HALTED) {
777 LOG_ERROR("Target not halted");
778 return ERROR_TARGET_NOT_HALTED;
781 retval = psoc5lp_find_device(bank->target, &psoc_nvl_bank->device);
782 if (retval != ERROR_OK)
785 bank->base = NVL_META_BASE;
787 bank->num_sectors = 1;
788 bank->sectors = calloc(bank->num_sectors,
789 sizeof(struct flash_sector));
790 bank->sectors[0].offset = 0;
791 bank->sectors[0].size = 4;
792 bank->sectors[0].is_erased = -1;
793 bank->sectors[0].is_protected = -1;
795 psoc_nvl_bank->probed = true;
800 static int psoc5lp_nvl_auto_probe(struct flash_bank *bank)
802 struct psoc5lp_nvl_flash_bank *psoc_nvl_bank = bank->driver_priv;
804 if (psoc_nvl_bank->probed)
807 return psoc5lp_nvl_probe(bank);
810 FLASH_BANK_COMMAND_HANDLER(psoc5lp_nvl_flash_bank_command)
812 struct psoc5lp_nvl_flash_bank *psoc_nvl_bank;
814 psoc_nvl_bank = malloc(sizeof(struct psoc5lp_nvl_flash_bank));
816 return ERROR_FLASH_OPERATION_FAILED;
818 psoc_nvl_bank->probed = false;
820 bank->driver_priv = psoc_nvl_bank;
825 static const struct command_registration psoc5lp_nvl_exec_command_handlers[] = {
826 COMMAND_REGISTRATION_DONE
829 static const struct command_registration psoc5lp_nvl_command_handlers[] = {
831 .name = "psoc5lp_nvl",
833 .help = "PSoC 5LP NV Latch command group",
835 .chain = psoc5lp_nvl_exec_command_handlers,
837 COMMAND_REGISTRATION_DONE
840 const struct flash_driver psoc5lp_nvl_flash = {
841 .name = "psoc5lp_nvl",
842 .commands = psoc5lp_nvl_command_handlers,
843 .flash_bank_command = psoc5lp_nvl_flash_bank_command,
844 .info = psoc5lp_nvl_get_info_command,
845 .probe = psoc5lp_nvl_probe,
846 .auto_probe = psoc5lp_nvl_auto_probe,
847 .read = psoc5lp_nvl_read,
848 .erase = psoc5lp_nvl_erase,
849 .erase_check = psoc5lp_nvl_erase_check,
850 .write = psoc5lp_nvl_write,
851 .free_driver_priv = default_flash_free_driver_priv,
858 struct psoc5lp_eeprom_flash_bank {
860 const struct psoc5lp_device *device;
863 static int psoc5lp_eeprom_erase(struct flash_bank *bank, unsigned int first,
868 for (unsigned int i = first; i <= last; i++) {
869 retval = psoc5lp_spc_erase_sector(bank->target,
870 SPC_ARRAY_EEPROM, i);
871 if (retval != ERROR_OK)
878 static int psoc5lp_eeprom_write(struct flash_bank *bank,
879 const uint8_t *buffer, uint32_t offset, uint32_t byte_count)
881 struct target *target = bank->target;
886 if (offset % EEPROM_ROW_SIZE != 0) {
887 LOG_ERROR("Writes must be row-aligned, got offset 0x%08" PRIx32,
889 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
892 retval = psoc5lp_spc_get_temp(target, 3, temp);
893 if (retval != ERROR_OK) {
894 LOG_ERROR("Unable to read Die temperature");
897 LOG_DEBUG("Get_Temp: sign 0x%02" PRIx8 ", magnitude 0x%02" PRIx8,
900 for (row = offset / EEPROM_ROW_SIZE; byte_count >= EEPROM_ROW_SIZE; row++) {
901 retval = psoc5lp_spc_load_row(target, SPC_ARRAY_EEPROM,
902 buffer, EEPROM_ROW_SIZE);
903 if (retval != ERROR_OK)
906 retval = psoc5lp_spc_write_row(target, SPC_ARRAY_EEPROM,
908 if (retval != ERROR_OK)
911 buffer += EEPROM_ROW_SIZE;
912 byte_count -= EEPROM_ROW_SIZE;
913 offset += EEPROM_ROW_SIZE;
915 if (byte_count > 0) {
916 uint8_t buf[EEPROM_ROW_SIZE];
918 memcpy(buf, buffer, byte_count);
919 memset(buf + byte_count, bank->default_padded_value,
920 EEPROM_ROW_SIZE - byte_count);
922 LOG_DEBUG("Padding %" PRIu32 " bytes", EEPROM_ROW_SIZE - byte_count);
923 retval = psoc5lp_spc_load_row(target, SPC_ARRAY_EEPROM,
924 buf, EEPROM_ROW_SIZE);
925 if (retval != ERROR_OK)
928 retval = psoc5lp_spc_write_row(target, SPC_ARRAY_EEPROM,
930 if (retval != ERROR_OK)
937 static int psoc5lp_eeprom_get_info_command(struct flash_bank *bank, char *buf, int buf_size)
939 struct psoc5lp_eeprom_flash_bank *psoc_eeprom_bank = bank->driver_priv;
940 char part_number[PART_NUMBER_LEN];
942 psoc5lp_get_part_number(psoc_eeprom_bank->device, part_number);
944 snprintf(buf, buf_size, "%s", part_number);
949 static int psoc5lp_eeprom_probe(struct flash_bank *bank)
951 struct psoc5lp_eeprom_flash_bank *psoc_eeprom_bank = bank->driver_priv;
952 uint32_t flash_addr = bank->base;
956 if (psoc_eeprom_bank->probed)
959 if (bank->target->state != TARGET_HALTED) {
960 LOG_ERROR("Target not halted");
961 return ERROR_TARGET_NOT_HALTED;
964 retval = psoc5lp_find_device(bank->target, &psoc_eeprom_bank->device);
965 if (retval != ERROR_OK)
968 retval = target_read_u32(bank->target, PM_ACT_CFG12, &val);
969 if (retval != ERROR_OK)
971 if (!(val & PM_ACT_CFG12_EN_EE)) {
972 val |= PM_ACT_CFG12_EN_EE;
973 retval = target_write_u32(bank->target, PM_ACT_CFG12, val);
974 if (retval != ERROR_OK)
978 bank->size = psoc_eeprom_bank->device->eeprom_kb * 1024;
979 bank->num_sectors = DIV_ROUND_UP(bank->size, EEPROM_SECTOR_SIZE);
980 bank->sectors = calloc(bank->num_sectors,
981 sizeof(struct flash_sector));
982 for (unsigned int i = 0; i < bank->num_sectors; i++) {
983 bank->sectors[i].size = EEPROM_SECTOR_SIZE;
984 bank->sectors[i].offset = flash_addr - bank->base;
985 bank->sectors[i].is_erased = -1;
986 bank->sectors[i].is_protected = -1;
988 flash_addr += bank->sectors[i].size;
991 bank->default_padded_value = bank->erased_value = 0x00;
993 psoc_eeprom_bank->probed = true;
998 static int psoc5lp_eeprom_auto_probe(struct flash_bank *bank)
1000 struct psoc5lp_eeprom_flash_bank *psoc_eeprom_bank = bank->driver_priv;
1002 if (psoc_eeprom_bank->probed)
1005 return psoc5lp_eeprom_probe(bank);
1008 FLASH_BANK_COMMAND_HANDLER(psoc5lp_eeprom_flash_bank_command)
1010 struct psoc5lp_eeprom_flash_bank *psoc_eeprom_bank;
1012 psoc_eeprom_bank = malloc(sizeof(struct psoc5lp_eeprom_flash_bank));
1013 if (!psoc_eeprom_bank)
1014 return ERROR_FLASH_OPERATION_FAILED;
1016 psoc_eeprom_bank->probed = false;
1017 psoc_eeprom_bank->device = NULL;
1019 bank->driver_priv = psoc_eeprom_bank;
1024 static const struct command_registration psoc5lp_eeprom_exec_command_handlers[] = {
1025 COMMAND_REGISTRATION_DONE
1028 static const struct command_registration psoc5lp_eeprom_command_handlers[] = {
1030 .name = "psoc5lp_eeprom",
1031 .mode = COMMAND_ANY,
1032 .help = "PSoC 5LP EEPROM command group",
1034 .chain = psoc5lp_eeprom_exec_command_handlers,
1036 COMMAND_REGISTRATION_DONE
1039 const struct flash_driver psoc5lp_eeprom_flash = {
1040 .name = "psoc5lp_eeprom",
1041 .commands = psoc5lp_eeprom_command_handlers,
1042 .flash_bank_command = psoc5lp_eeprom_flash_bank_command,
1043 .info = psoc5lp_eeprom_get_info_command,
1044 .probe = psoc5lp_eeprom_probe,
1045 .auto_probe = psoc5lp_eeprom_auto_probe,
1046 .read = default_flash_read,
1047 .erase = psoc5lp_eeprom_erase,
1048 .erase_check = default_flash_blank_check,
1049 .write = psoc5lp_eeprom_write,
1050 .free_driver_priv = default_flash_free_driver_priv,
1057 struct psoc5lp_flash_bank {
1059 const struct psoc5lp_device *device;
1061 /* If ecc is disabled, num_sectors counts both std and ecc sectors.
1062 * If ecc is enabled, num_sectors indicates just the number of std sectors.
1063 * However ecc sector descriptors bank->sector[num_sectors..2*num_sectors-1]
1064 * are used for driver private flash operations */
1067 static int psoc5lp_erase(struct flash_bank *bank, unsigned int first,
1070 struct psoc5lp_flash_bank *psoc_bank = bank->driver_priv;
1073 if (!psoc_bank->ecc_enabled) {
1074 /* Silently avoid erasing sectors twice */
1075 if (last >= first + bank->num_sectors / 2) {
1076 LOG_DEBUG("Skipping duplicate erase of sectors %u to %u",
1077 first + bank->num_sectors / 2, last);
1078 last = first + (bank->num_sectors / 2) - 1;
1080 /* Check for any remaining ECC sectors */
1081 if (last >= bank->num_sectors / 2) {
1082 LOG_WARNING("Skipping erase of ECC region sectors %u to %u",
1083 bank->num_sectors / 2, last);
1084 last = (bank->num_sectors / 2) - 1;
1088 for (unsigned int i = first; i <= last; i++) {
1089 retval = psoc5lp_spc_erase_sector(bank->target,
1090 i / SECTORS_PER_BLOCK, i % SECTORS_PER_BLOCK);
1091 if (retval != ERROR_OK)
1098 /* Derived from core.c:default_flash_blank_check() */
1099 static int psoc5lp_erase_check(struct flash_bank *bank)
1101 struct psoc5lp_flash_bank *psoc_bank = bank->driver_priv;
1102 struct target *target = bank->target;
1105 if (target->state != TARGET_HALTED) {
1106 LOG_ERROR("Target not halted");
1107 return ERROR_TARGET_NOT_HALTED;
1110 unsigned int num_sectors = bank->num_sectors;
1111 if (psoc_bank->ecc_enabled)
1112 num_sectors *= 2; /* count both std and ecc sector always */
1114 struct target_memory_check_block *block_array;
1115 block_array = malloc(num_sectors * sizeof(struct target_memory_check_block));
1116 if (block_array == NULL)
1119 for (unsigned int i = 0; i < num_sectors; i++) {
1120 block_array[i].address = bank->base + bank->sectors[i].offset;
1121 block_array[i].size = bank->sectors[i].size;
1122 block_array[i].result = UINT32_MAX; /* erase state unknown */
1125 bool fast_check = true;
1126 for (unsigned int i = 0; i < num_sectors; ) {
1127 retval = armv7m_blank_check_memory(target,
1128 block_array + i, num_sectors - i,
1129 bank->erased_value);
1131 /* Run slow fallback if the first run gives no result
1132 * otherwise use possibly incomplete results */
1137 i += retval; /* add number of blocks done this round */
1141 if (psoc_bank->ecc_enabled) {
1142 for (unsigned int i = 0; i < bank->num_sectors; i++)
1143 bank->sectors[i].is_erased =
1144 (block_array[i].result != 1)
1145 ? block_array[i].result
1146 : block_array[i + bank->num_sectors].result;
1147 /* if std sector is erased, use status of ecc sector */
1149 for (unsigned int i = 0; i < num_sectors; i++)
1150 bank->sectors[i].is_erased = block_array[i].result;
1154 LOG_ERROR("Can't run erase check - add working memory");
1155 retval = ERROR_FAIL;
1162 static int psoc5lp_write(struct flash_bank *bank, const uint8_t *buffer,
1163 uint32_t offset, uint32_t byte_count)
1165 struct psoc5lp_flash_bank *psoc_bank = bank->driver_priv;
1166 struct target *target = bank->target;
1167 struct working_area *code_area, *even_row_area, *odd_row_area;
1169 uint8_t temp[2], buf[12], ecc_bytes[ROW_ECC_SIZE];
1170 unsigned array_id, row;
1173 if (offset + byte_count > bank->size) {
1174 LOG_ERROR("Writing to ECC not supported");
1175 return ERROR_FLASH_DST_OUT_OF_BANK;
1178 if (offset % ROW_SIZE != 0) {
1179 LOG_ERROR("Writes must be row-aligned, got offset 0x%08" PRIx32,
1181 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
1184 row_size = ROW_SIZE;
1185 if (!psoc_bank->ecc_enabled) {
1186 row_size += ROW_ECC_SIZE;
1187 memset(ecc_bytes, bank->default_padded_value, ROW_ECC_SIZE);
1190 retval = psoc5lp_spc_get_temp(target, 3, temp);
1191 if (retval != ERROR_OK) {
1192 LOG_ERROR("Unable to read Die temperature");
1195 LOG_DEBUG("Get_Temp: sign 0x%02" PRIx8 ", magnitude 0x%02" PRIx8,
1198 assert(target_get_working_area_avail(target) == target->working_area_size);
1199 retval = target_alloc_working_area(target,
1200 target_get_working_area_avail(target) / 2, &code_area);
1201 if (retval != ERROR_OK) {
1202 LOG_ERROR("Could not allocate working area for program SRAM");
1205 assert(code_area->address < 0x20000000);
1207 retval = target_alloc_working_area(target,
1208 SPC_OPCODE_LEN + 1 + row_size + 3 + SPC_OPCODE_LEN + 6,
1210 if (retval != ERROR_OK) {
1211 LOG_ERROR("Could not allocate working area for even row");
1212 goto err_alloc_even;
1214 assert(even_row_area->address >= 0x20000000);
1216 retval = target_alloc_working_area(target, even_row_area->size,
1218 if (retval != ERROR_OK) {
1219 LOG_ERROR("Could not allocate working area for odd row");
1222 assert(odd_row_area->address >= 0x20000000);
1224 for (array_id = offset / BLOCK_SIZE; byte_count > 0; array_id++) {
1225 for (row = (offset / ROW_SIZE) % ROWS_PER_BLOCK;
1226 row < ROWS_PER_BLOCK && byte_count > 0; row++) {
1227 bool even_row = (row % 2 == 0);
1228 struct working_area *data_area = even_row ? even_row_area : odd_row_area;
1229 unsigned len = MIN(ROW_SIZE, byte_count);
1231 LOG_DEBUG("Writing load command for array %u row %u at " TARGET_ADDR_FMT,
1232 array_id, row, data_area->address);
1234 psoc5lp_spc_write_opcode_buffer(target, buf, SPC_LOAD_ROW);
1235 buf[SPC_OPCODE_LEN] = array_id;
1236 retval = target_write_buffer(target, data_area->address, 4, buf);
1237 if (retval != ERROR_OK)
1240 retval = target_write_buffer(target,
1241 data_area->address + SPC_OPCODE_LEN + 1,
1243 if (retval != ERROR_OK)
1249 if (len < ROW_SIZE) {
1250 uint8_t padding[ROW_SIZE];
1252 memset(padding, bank->default_padded_value, ROW_SIZE);
1254 LOG_DEBUG("Padding %d bytes", ROW_SIZE - len);
1255 retval = target_write_buffer(target,
1256 data_area->address + SPC_OPCODE_LEN + 1 + len,
1257 ROW_SIZE - len, padding);
1258 if (retval != ERROR_OK)
1262 if (!psoc_bank->ecc_enabled) {
1263 retval = target_write_buffer(target,
1264 data_area->address + SPC_OPCODE_LEN + 1 + ROW_SIZE,
1265 sizeof(ecc_bytes), ecc_bytes);
1266 if (retval != ERROR_OK)
1270 for (i = 0; i < 3; i++)
1271 buf[i] = 0x00; /* 3 NOPs for short delay */
1272 psoc5lp_spc_write_opcode_buffer(target, buf + 3, SPC_PRG_ROW);
1273 buf[3 + SPC_OPCODE_LEN] = array_id;
1274 buf[3 + SPC_OPCODE_LEN + 1] = row >> 8;
1275 buf[3 + SPC_OPCODE_LEN + 2] = row & 0xff;
1276 memcpy(buf + 3 + SPC_OPCODE_LEN + 3, temp, 2);
1277 buf[3 + SPC_OPCODE_LEN + 5] = 0x00; /* padding */
1278 retval = target_write_buffer(target,
1279 data_area->address + SPC_OPCODE_LEN + 1 + row_size,
1281 if (retval != ERROR_OK)
1284 retval = target_write_u32(target,
1285 even_row ? PHUB_CH0_BASIC_STATUS : PHUB_CH1_BASIC_STATUS,
1286 (even_row ? 0 : 1) << 8);
1287 if (retval != ERROR_OK)
1290 retval = target_write_u32(target,
1291 even_row ? PHUB_CH0_BASIC_CFG : PHUB_CH1_BASIC_CFG,
1292 PHUB_CHx_BASIC_CFG_WORK_SEP | PHUB_CHx_BASIC_CFG_EN);
1293 if (retval != ERROR_OK)
1296 retval = target_write_u32(target,
1297 even_row ? PHUB_CFGMEM0_CFG0 : PHUB_CFGMEM1_CFG0,
1299 if (retval != ERROR_OK)
1302 retval = target_write_u32(target,
1303 even_row ? PHUB_CFGMEM0_CFG1 : PHUB_CFGMEM1_CFG1,
1304 ((SPC_CPU_DATA >> 16) << 16) | (data_area->address >> 16));
1305 if (retval != ERROR_OK)
1308 retval = target_write_u32(target,
1309 even_row ? PHUB_TDMEM0_ORIG_TD0 : PHUB_TDMEM1_ORIG_TD0,
1310 PHUB_TDMEMx_ORIG_TD0_INC_SRC_ADDR |
1311 PHUB_TDMEMx_ORIG_TD0_NEXT_TD_PTR_LAST |
1312 ((SPC_OPCODE_LEN + 1 + row_size + 3 + SPC_OPCODE_LEN + 5) & 0xfff));
1313 if (retval != ERROR_OK)
1316 retval = target_write_u32(target,
1317 even_row ? PHUB_TDMEM0_ORIG_TD1 : PHUB_TDMEM1_ORIG_TD1,
1318 ((SPC_CPU_DATA & 0xffff) << 16) | (data_area->address & 0xffff));
1319 if (retval != ERROR_OK)
1322 retval = psoc5lp_spc_busy_wait_idle(target);
1323 if (retval != ERROR_OK)
1326 retval = target_write_u32(target,
1327 even_row ? PHUB_CH0_ACTION : PHUB_CH1_ACTION,
1328 PHUB_CHx_ACTION_CPU_REQ);
1329 if (retval != ERROR_OK)
1330 goto err_dma_action;
1334 retval = psoc5lp_spc_busy_wait_idle(target);
1340 target_free_working_area(target, odd_row_area);
1342 target_free_working_area(target, even_row_area);
1344 target_free_working_area(target, code_area);
1349 static int psoc5lp_protect_check(struct flash_bank *bank)
1351 struct psoc5lp_flash_bank *psoc_bank = bank->driver_priv;
1352 uint8_t row_data[ROW_SIZE];
1353 const unsigned protection_bytes_per_sector = ROWS_PER_SECTOR * 2 / 8;
1354 unsigned i, k, num_sectors;
1357 if (bank->target->state != TARGET_HALTED) {
1358 LOG_ERROR("Target not halted");
1359 return ERROR_TARGET_NOT_HALTED;
1362 for (i = 0; i < DIV_ROUND_UP(bank->size, BLOCK_SIZE); i++) {
1363 retval = psoc5lp_spc_read_hidden_row(bank->target, i,
1364 SPC_ROW_PROTECTION, row_data);
1365 if (retval != ERROR_OK)
1368 /* Last flash array may have less rows, but in practice full sectors. */
1369 if (i == bank->size / BLOCK_SIZE)
1370 num_sectors = (bank->size % BLOCK_SIZE) / SECTOR_SIZE;
1372 num_sectors = SECTORS_PER_BLOCK;
1374 for (unsigned int j = 0; j < num_sectors; j++) {
1375 int sector_nr = i * SECTORS_PER_BLOCK + j;
1376 struct flash_sector *sector = &bank->sectors[sector_nr];
1377 struct flash_sector *ecc_sector;
1379 if (psoc_bank->ecc_enabled)
1380 ecc_sector = &bank->sectors[bank->num_sectors + sector_nr];
1382 ecc_sector = &bank->sectors[bank->num_sectors / 2 + sector_nr];
1384 sector->is_protected = ecc_sector->is_protected = 0;
1385 for (k = protection_bytes_per_sector * j;
1386 k < protection_bytes_per_sector * (j + 1); k++) {
1387 assert(k < protection_bytes_per_sector * SECTORS_PER_BLOCK);
1388 LOG_DEBUG("row[%u][%02u] = 0x%02" PRIx8, i, k, row_data[k]);
1389 if (row_data[k] != 0x00) {
1390 sector->is_protected = ecc_sector->is_protected = 1;
1400 static int psoc5lp_get_info_command(struct flash_bank *bank, char *buf, int buf_size)
1402 struct psoc5lp_flash_bank *psoc_bank = bank->driver_priv;
1403 char part_number[PART_NUMBER_LEN];
1406 psoc5lp_get_part_number(psoc_bank->device, part_number);
1407 ecc = psoc_bank->ecc_enabled ? "ECC enabled" : "ECC disabled";
1409 snprintf(buf, buf_size, "%s %s", part_number, ecc);
1414 static int psoc5lp_probe(struct flash_bank *bank)
1416 struct target *target = bank->target;
1417 struct psoc5lp_flash_bank *psoc_bank = bank->driver_priv;
1418 uint32_t flash_addr = bank->base;
1419 uint8_t nvl[4], temp[2];
1422 if (target->state != TARGET_HALTED) {
1423 LOG_ERROR("Target not halted");
1424 return ERROR_TARGET_NOT_HALTED;
1427 if (!psoc_bank->device) {
1428 retval = psoc5lp_find_device(target, &psoc_bank->device);
1429 if (retval != ERROR_OK)
1432 bank->size = psoc_bank->device->flash_kb * 1024;
1435 bank->num_sectors = DIV_ROUND_UP(bank->size, SECTOR_SIZE);
1437 if (!psoc_bank->probed) {
1438 retval = psoc5lp_spc_enable_clock(target);
1439 if (retval != ERROR_OK)
1442 /* First values read are inaccurate, so do it once now. */
1443 retval = psoc5lp_spc_get_temp(target, 3, temp);
1444 if (retval != ERROR_OK) {
1445 LOG_ERROR("Unable to read Die temperature");
1449 bank->sectors = calloc(bank->num_sectors * 2,
1450 sizeof(struct flash_sector));
1451 for (unsigned int i = 0; i < bank->num_sectors; i++) {
1452 bank->sectors[i].size = SECTOR_SIZE;
1453 bank->sectors[i].offset = flash_addr - bank->base;
1454 bank->sectors[i].is_erased = -1;
1455 bank->sectors[i].is_protected = -1;
1457 flash_addr += bank->sectors[i].size;
1459 flash_addr = 0x48000000;
1460 for (unsigned int i = bank->num_sectors; i < bank->num_sectors * 2; i++) {
1461 bank->sectors[i].size = ROWS_PER_SECTOR * ROW_ECC_SIZE;
1462 bank->sectors[i].offset = flash_addr - bank->base;
1463 bank->sectors[i].is_erased = -1;
1464 bank->sectors[i].is_protected = -1;
1466 flash_addr += bank->sectors[i].size;
1469 bank->default_padded_value = bank->erased_value = 0x00;
1471 psoc_bank->probed = true;
1474 retval = psoc5lp_spc_read_byte(target, SPC_ARRAY_NVL_USER, 3, &nvl[3]);
1475 if (retval != ERROR_OK)
1477 LOG_DEBUG("NVL[%d] = 0x%02" PRIx8, 3, nvl[3]);
1478 psoc_bank->ecc_enabled = nvl[3] & NVL_3_ECCEN;
1480 if (!psoc_bank->ecc_enabled)
1481 bank->num_sectors *= 2;
1486 static int psoc5lp_auto_probe(struct flash_bank *bank)
1488 return psoc5lp_probe(bank);
1491 COMMAND_HANDLER(psoc5lp_handle_mass_erase_command)
1493 struct flash_bank *bank;
1497 return ERROR_COMMAND_SYNTAX_ERROR;
1499 retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
1500 if (retval != ERROR_OK)
1503 retval = psoc5lp_spc_erase_all(bank->target);
1504 if (retval == ERROR_OK)
1505 command_print(CMD, "PSoC 5LP erase succeeded");
1507 command_print(CMD, "PSoC 5LP erase failed");
1512 FLASH_BANK_COMMAND_HANDLER(psoc5lp_flash_bank_command)
1514 struct psoc5lp_flash_bank *psoc_bank;
1516 psoc_bank = malloc(sizeof(struct psoc5lp_flash_bank));
1518 return ERROR_FLASH_OPERATION_FAILED;
1520 psoc_bank->probed = false;
1521 psoc_bank->device = NULL;
1523 bank->driver_priv = psoc_bank;
1528 static const struct command_registration psoc5lp_exec_command_handlers[] = {
1530 .name = "mass_erase",
1531 .handler = psoc5lp_handle_mass_erase_command,
1532 .mode = COMMAND_EXEC,
1534 .help = "Erase all flash data and ECC/configuration bytes, "
1535 "all flash protection rows, "
1536 "and all row latches in all flash arrays on the device.",
1538 COMMAND_REGISTRATION_DONE
1541 static const struct command_registration psoc5lp_command_handlers[] = {
1544 .mode = COMMAND_ANY,
1545 .help = "PSoC 5LP flash command group",
1547 .chain = psoc5lp_exec_command_handlers,
1549 COMMAND_REGISTRATION_DONE
1552 const struct flash_driver psoc5lp_flash = {
1554 .commands = psoc5lp_command_handlers,
1555 .flash_bank_command = psoc5lp_flash_bank_command,
1556 .info = psoc5lp_get_info_command,
1557 .probe = psoc5lp_probe,
1558 .auto_probe = psoc5lp_auto_probe,
1559 .protect_check = psoc5lp_protect_check,
1560 .read = default_flash_read,
1561 .erase = psoc5lp_erase,
1562 .erase_check = psoc5lp_erase_check,
1563 .write = psoc5lp_write,
1564 .free_driver_priv = default_flash_free_driver_priv,