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 addess different from other banks in the device
51 * we use the address of NVL programming data in Cypress images */
52 #define NVL_META_BASE 0x90000000
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. */
237 strncpy(str
+ 8, "xx", 2);
239 /* Temperate range cannot uniquely be identified. */
243 static int psoc5lp_get_device_id(struct target
*target
, uint32_t *id
)
247 retval
= target_read_u32(target
, PANTHER_DEVICE_ID
, id
); /* dummy read */
248 if (retval
!= ERROR_OK
)
250 retval
= target_read_u32(target
, PANTHER_DEVICE_ID
, id
);
254 static int psoc5lp_find_device(struct target
*target
,
255 const struct psoc5lp_device
**device
)
263 retval
= psoc5lp_get_device_id(target
, &device_id
);
264 if (retval
!= ERROR_OK
)
266 LOG_DEBUG("PANTHER_DEVICE_ID = 0x%08" PRIX32
, device_id
);
268 for (i
= 0; i
< ARRAY_SIZE(psoc5lp_devices
); i
++) {
269 if (psoc5lp_devices
[i
].id
== device_id
) {
270 *device
= &psoc5lp_devices
[i
];
275 LOG_ERROR("Device 0x%08" PRIX32
" not supported", device_id
);
276 return ERROR_FLASH_OPER_UNSUPPORTED
;
279 static int psoc5lp_spc_enable_clock(struct target
*target
)
284 retval
= target_read_u8(target
, PM_ACT_CFG0
, &pm_act_cfg0
);
285 if (retval
!= ERROR_OK
) {
286 LOG_ERROR("Cannot read PM_ACT_CFG0");
290 if (pm_act_cfg0
& PM_ACT_CFG0_EN_CLK_SPC
)
291 return ERROR_OK
; /* clock already enabled */
293 retval
= target_write_u8(target
, PM_ACT_CFG0
, pm_act_cfg0
| PM_ACT_CFG0_EN_CLK_SPC
);
294 if (retval
!= ERROR_OK
)
295 LOG_ERROR("Cannot enable SPC clock");
300 static int psoc5lp_spc_write_opcode(struct target
*target
, uint8_t opcode
)
304 retval
= target_write_u8(target
, SPC_CPU_DATA
, SPC_KEY1
);
305 if (retval
!= ERROR_OK
)
307 retval
= target_write_u8(target
, SPC_CPU_DATA
, SPC_KEY2
+ opcode
);
308 if (retval
!= ERROR_OK
)
310 retval
= target_write_u8(target
, SPC_CPU_DATA
, opcode
);
314 static void psoc5lp_spc_write_opcode_buffer(struct target
*target
,
315 uint8_t *buf
, uint8_t opcode
)
318 buf
[1] = SPC_KEY2
+ opcode
;
322 static int psoc5lp_spc_busy_wait_data(struct target
*target
)
328 retval
= target_read_u8(target
, SPC_SR
, &sr
); /* dummy read */
329 if (retval
!= ERROR_OK
)
332 endtime
= timeval_ms() + 1000; /* 1 second timeout */
335 retval
= target_read_u8(target
, SPC_SR
, &sr
);
336 if (retval
!= ERROR_OK
)
338 if (sr
== SPC_SR_DATA_READY
)
340 } while (timeval_ms() < endtime
);
342 return ERROR_FLASH_OPERATION_FAILED
;
345 static int psoc5lp_spc_busy_wait_idle(struct target
*target
)
351 retval
= target_read_u8(target
, SPC_SR
, &sr
); /* dummy read */
352 if (retval
!= ERROR_OK
)
355 endtime
= timeval_ms() + 1000; /* 1 second timeout */
358 retval
= target_read_u8(target
, SPC_SR
, &sr
);
359 if (retval
!= ERROR_OK
)
361 if (sr
== SPC_SR_IDLE
)
363 } while (timeval_ms() < endtime
);
365 return ERROR_FLASH_OPERATION_FAILED
;
368 static int psoc5lp_spc_load_byte(struct target
*target
,
369 uint8_t array_id
, uint8_t offset
, uint8_t value
)
373 retval
= psoc5lp_spc_write_opcode(target
, SPC_LOAD_BYTE
);
374 if (retval
!= ERROR_OK
)
376 retval
= target_write_u8(target
, SPC_CPU_DATA
, array_id
);
377 if (retval
!= ERROR_OK
)
379 retval
= target_write_u8(target
, SPC_CPU_DATA
, offset
);
380 if (retval
!= ERROR_OK
)
382 retval
= target_write_u8(target
, SPC_CPU_DATA
, value
);
383 if (retval
!= ERROR_OK
)
386 retval
= psoc5lp_spc_busy_wait_idle(target
);
387 if (retval
!= ERROR_OK
)
393 static int psoc5lp_spc_load_row(struct target
*target
,
394 uint8_t array_id
, const uint8_t *data
, unsigned row_size
)
399 retval
= psoc5lp_spc_write_opcode(target
, SPC_LOAD_ROW
);
400 if (retval
!= ERROR_OK
)
402 retval
= target_write_u8(target
, SPC_CPU_DATA
, array_id
);
403 if (retval
!= ERROR_OK
)
406 for (i
= 0; i
< row_size
; i
++) {
407 retval
= target_write_u8(target
, SPC_CPU_DATA
, data
[i
]);
408 if (retval
!= ERROR_OK
)
412 retval
= psoc5lp_spc_busy_wait_idle(target
);
413 if (retval
!= ERROR_OK
)
419 static int psoc5lp_spc_read_byte(struct target
*target
,
420 uint8_t array_id
, uint8_t offset
, uint8_t *data
)
424 retval
= psoc5lp_spc_write_opcode(target
, SPC_READ_BYTE
);
425 if (retval
!= ERROR_OK
)
427 retval
= target_write_u8(target
, SPC_CPU_DATA
, array_id
);
428 if (retval
!= ERROR_OK
)
430 retval
= target_write_u8(target
, SPC_CPU_DATA
, offset
);
431 if (retval
!= ERROR_OK
)
434 retval
= psoc5lp_spc_busy_wait_data(target
);
435 if (retval
!= ERROR_OK
)
438 retval
= target_read_u8(target
, SPC_CPU_DATA
, data
);
439 if (retval
!= ERROR_OK
)
442 retval
= psoc5lp_spc_busy_wait_idle(target
);
443 if (retval
!= ERROR_OK
)
449 static int psoc5lp_spc_write_row(struct target
*target
,
450 uint8_t array_id
, uint16_t row_id
, const uint8_t *temp
)
454 retval
= psoc5lp_spc_write_opcode(target
, SPC_WRITE_ROW
);
455 if (retval
!= ERROR_OK
)
457 retval
= target_write_u8(target
, SPC_CPU_DATA
, array_id
);
458 if (retval
!= ERROR_OK
)
460 retval
= target_write_u8(target
, SPC_CPU_DATA
, row_id
>> 8);
461 if (retval
!= ERROR_OK
)
463 retval
= target_write_u8(target
, SPC_CPU_DATA
, row_id
& 0xff);
464 if (retval
!= ERROR_OK
)
466 retval
= target_write_u8(target
, SPC_CPU_DATA
, temp
[0]);
467 if (retval
!= ERROR_OK
)
469 retval
= target_write_u8(target
, SPC_CPU_DATA
, temp
[1]);
470 if (retval
!= ERROR_OK
)
473 retval
= psoc5lp_spc_busy_wait_idle(target
);
474 if (retval
!= ERROR_OK
)
480 static int psoc5lp_spc_write_user_nvl(struct target
*target
,
485 retval
= psoc5lp_spc_write_opcode(target
, SPC_WRITE_USER_NVL
);
486 if (retval
!= ERROR_OK
)
488 retval
= target_write_u8(target
, SPC_CPU_DATA
, array_id
);
489 if (retval
!= ERROR_OK
)
492 retval
= psoc5lp_spc_busy_wait_idle(target
);
493 if (retval
!= ERROR_OK
)
499 static int psoc5lp_spc_erase_sector(struct target
*target
,
500 uint8_t array_id
, uint8_t row_id
)
504 retval
= psoc5lp_spc_write_opcode(target
, SPC_ERASE_SECTOR
);
505 if (retval
!= ERROR_OK
)
507 retval
= target_write_u8(target
, SPC_CPU_DATA
, array_id
);
508 if (retval
!= ERROR_OK
)
510 retval
= target_write_u8(target
, SPC_CPU_DATA
, row_id
);
511 if (retval
!= ERROR_OK
)
514 retval
= psoc5lp_spc_busy_wait_idle(target
);
515 if (retval
!= ERROR_OK
)
521 static int psoc5lp_spc_erase_all(struct target
*target
)
525 retval
= psoc5lp_spc_write_opcode(target
, SPC_ERASE_ALL
);
526 if (retval
!= ERROR_OK
)
529 retval
= psoc5lp_spc_busy_wait_idle(target
);
530 if (retval
!= ERROR_OK
)
536 static int psoc5lp_spc_read_hidden_row(struct target
*target
,
537 uint8_t array_id
, uint8_t row_id
, uint8_t *data
)
541 retval
= psoc5lp_spc_write_opcode(target
, SPC_READ_HIDDEN_ROW
);
542 if (retval
!= ERROR_OK
)
544 retval
= target_write_u8(target
, SPC_CPU_DATA
, array_id
);
545 if (retval
!= ERROR_OK
)
547 retval
= target_write_u8(target
, SPC_CPU_DATA
, row_id
);
548 if (retval
!= ERROR_OK
)
551 retval
= psoc5lp_spc_busy_wait_data(target
);
552 if (retval
!= ERROR_OK
)
555 for (i
= 0; i
< ROW_SIZE
; i
++) {
556 retval
= target_read_u8(target
, SPC_CPU_DATA
, &data
[i
]);
557 if (retval
!= ERROR_OK
)
561 retval
= psoc5lp_spc_busy_wait_idle(target
);
562 if (retval
!= ERROR_OK
)
568 static int psoc5lp_spc_get_temp(struct target
*target
, uint8_t samples
,
573 retval
= psoc5lp_spc_write_opcode(target
, SPC_GET_TEMP
);
574 if (retval
!= ERROR_OK
)
576 retval
= target_write_u8(target
, SPC_CPU_DATA
, samples
);
577 if (retval
!= ERROR_OK
)
580 retval
= psoc5lp_spc_busy_wait_data(target
);
581 if (retval
!= ERROR_OK
)
584 retval
= target_read_u8(target
, SPC_CPU_DATA
, &data
[0]);
585 if (retval
!= ERROR_OK
)
587 retval
= target_read_u8(target
, SPC_CPU_DATA
, &data
[1]);
588 if (retval
!= ERROR_OK
)
591 retval
= psoc5lp_spc_busy_wait_idle(target
);
592 if (retval
!= ERROR_OK
)
598 static int psoc5lp_spc_read_volatile_byte(struct target
*target
,
599 uint8_t array_id
, uint8_t offset
, uint8_t *data
)
603 retval
= psoc5lp_spc_write_opcode(target
, SPC_READ_VOLATILE_BYTE
);
604 if (retval
!= ERROR_OK
)
606 retval
= target_write_u8(target
, SPC_CPU_DATA
, array_id
);
607 if (retval
!= ERROR_OK
)
609 retval
= target_write_u8(target
, SPC_CPU_DATA
, offset
);
610 if (retval
!= ERROR_OK
)
613 retval
= psoc5lp_spc_busy_wait_data(target
);
614 if (retval
!= ERROR_OK
)
617 retval
= target_read_u8(target
, SPC_CPU_DATA
, data
);
618 if (retval
!= ERROR_OK
)
621 retval
= psoc5lp_spc_busy_wait_idle(target
);
622 if (retval
!= ERROR_OK
)
632 struct psoc5lp_nvl_flash_bank
{
634 const struct psoc5lp_device
*device
;
637 static int psoc5lp_nvl_read(struct flash_bank
*bank
,
638 uint8_t *buffer
, uint32_t offset
, uint32_t count
)
642 retval
= psoc5lp_spc_enable_clock(bank
->target
);
643 if (retval
!= ERROR_OK
)
647 retval
= psoc5lp_spc_read_byte(bank
->target
,
648 SPC_ARRAY_NVL_USER
, offset
, buffer
);
649 if (retval
!= ERROR_OK
)
659 static int psoc5lp_nvl_erase(struct flash_bank
*bank
, int first
, int last
)
661 LOG_WARNING("There is no erase operation for NV Latches");
662 return ERROR_FLASH_OPER_UNSUPPORTED
;
665 static int psoc5lp_nvl_erase_check(struct flash_bank
*bank
)
669 for (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_protect_check(struct flash_bank
*bank
)
759 for (i
= 0; i
< bank
->num_sectors
; i
++)
760 bank
->sectors
[i
].is_protected
= -1;
765 static int psoc5lp_nvl_get_info_command(struct flash_bank
*bank
,
766 char *buf
, int buf_size
)
768 struct psoc5lp_nvl_flash_bank
*psoc_nvl_bank
= bank
->driver_priv
;
769 char part_number
[PART_NUMBER_LEN
];
771 psoc5lp_get_part_number(psoc_nvl_bank
->device
, part_number
);
773 snprintf(buf
, buf_size
, "%s", part_number
);
778 static int psoc5lp_nvl_probe(struct flash_bank
*bank
)
780 struct psoc5lp_nvl_flash_bank
*psoc_nvl_bank
= bank
->driver_priv
;
783 if (psoc_nvl_bank
->probed
)
786 if (bank
->target
->state
!= TARGET_HALTED
) {
787 LOG_ERROR("Target not halted");
788 return ERROR_TARGET_NOT_HALTED
;
791 retval
= psoc5lp_find_device(bank
->target
, &psoc_nvl_bank
->device
);
792 if (retval
!= ERROR_OK
)
795 bank
->base
= NVL_META_BASE
;
797 bank
->num_sectors
= 1;
798 bank
->sectors
= calloc(bank
->num_sectors
,
799 sizeof(struct flash_sector
));
800 bank
->sectors
[0].offset
= 0;
801 bank
->sectors
[0].size
= 4;
802 bank
->sectors
[0].is_erased
= -1;
803 bank
->sectors
[0].is_protected
= -1;
805 psoc_nvl_bank
->probed
= true;
810 static int psoc5lp_nvl_auto_probe(struct flash_bank
*bank
)
812 struct psoc5lp_nvl_flash_bank
*psoc_nvl_bank
= bank
->driver_priv
;
814 if (psoc_nvl_bank
->probed
)
817 return psoc5lp_nvl_probe(bank
);
820 FLASH_BANK_COMMAND_HANDLER(psoc5lp_nvl_flash_bank_command
)
822 struct psoc5lp_nvl_flash_bank
*psoc_nvl_bank
;
824 psoc_nvl_bank
= malloc(sizeof(struct psoc5lp_nvl_flash_bank
));
826 return ERROR_FLASH_OPERATION_FAILED
;
828 psoc_nvl_bank
->probed
= false;
830 bank
->driver_priv
= psoc_nvl_bank
;
835 static const struct command_registration psoc5lp_nvl_exec_command_handlers
[] = {
836 COMMAND_REGISTRATION_DONE
839 static const struct command_registration psoc5lp_nvl_command_handlers
[] = {
841 .name
= "psoc5lp_nvl",
843 .help
= "PSoC 5LP NV Latch command group",
845 .chain
= psoc5lp_nvl_exec_command_handlers
,
847 COMMAND_REGISTRATION_DONE
850 struct flash_driver psoc5lp_nvl_flash
= {
851 .name
= "psoc5lp_nvl",
852 .commands
= psoc5lp_nvl_command_handlers
,
853 .flash_bank_command
= psoc5lp_nvl_flash_bank_command
,
854 .info
= psoc5lp_nvl_get_info_command
,
855 .probe
= psoc5lp_nvl_probe
,
856 .auto_probe
= psoc5lp_nvl_auto_probe
,
857 .protect_check
= psoc5lp_nvl_protect_check
,
858 .read
= psoc5lp_nvl_read
,
859 .erase
= psoc5lp_nvl_erase
,
860 .erase_check
= psoc5lp_nvl_erase_check
,
861 .write
= psoc5lp_nvl_write
,
868 struct psoc5lp_eeprom_flash_bank
{
870 const struct psoc5lp_device
*device
;
873 static int psoc5lp_eeprom_erase(struct flash_bank
*bank
, int first
, int last
)
877 for (i
= first
; i
<= last
; i
++) {
878 retval
= psoc5lp_spc_erase_sector(bank
->target
,
879 SPC_ARRAY_EEPROM
, i
);
880 if (retval
!= ERROR_OK
)
887 static int psoc5lp_eeprom_write(struct flash_bank
*bank
,
888 const uint8_t *buffer
, uint32_t offset
, uint32_t byte_count
)
890 struct target
*target
= bank
->target
;
895 if (offset
% EEPROM_ROW_SIZE
!= 0) {
896 LOG_ERROR("Writes must be row-aligned, got offset 0x%08" PRIx32
,
898 return ERROR_FLASH_DST_BREAKS_ALIGNMENT
;
901 retval
= psoc5lp_spc_get_temp(target
, 3, temp
);
902 if (retval
!= ERROR_OK
) {
903 LOG_ERROR("Unable to read Die temperature");
906 LOG_DEBUG("Get_Temp: sign 0x%02" PRIx8
", magnitude 0x%02" PRIx8
,
909 for (row
= offset
/ EEPROM_ROW_SIZE
; byte_count
>= EEPROM_ROW_SIZE
; row
++) {
910 retval
= psoc5lp_spc_load_row(target
, SPC_ARRAY_EEPROM
,
911 buffer
, EEPROM_ROW_SIZE
);
912 if (retval
!= ERROR_OK
)
915 retval
= psoc5lp_spc_write_row(target
, SPC_ARRAY_EEPROM
,
917 if (retval
!= ERROR_OK
)
920 buffer
+= EEPROM_ROW_SIZE
;
921 byte_count
-= EEPROM_ROW_SIZE
;
922 offset
+= EEPROM_ROW_SIZE
;
924 if (byte_count
> 0) {
925 uint8_t buf
[EEPROM_ROW_SIZE
];
927 memcpy(buf
, buffer
, byte_count
);
928 memset(buf
+ byte_count
, bank
->default_padded_value
,
929 EEPROM_ROW_SIZE
- byte_count
);
931 LOG_DEBUG("Padding %d bytes", EEPROM_ROW_SIZE
- byte_count
);
932 retval
= psoc5lp_spc_load_row(target
, SPC_ARRAY_EEPROM
,
933 buf
, EEPROM_ROW_SIZE
);
934 if (retval
!= ERROR_OK
)
937 retval
= psoc5lp_spc_write_row(target
, SPC_ARRAY_EEPROM
,
939 if (retval
!= ERROR_OK
)
946 static int psoc5lp_eeprom_protect_check(struct flash_bank
*bank
)
950 for (i
= 0; i
< bank
->num_sectors
; i
++)
951 bank
->sectors
[i
].is_protected
= -1;
956 static int psoc5lp_eeprom_get_info_command(struct flash_bank
*bank
, char *buf
, int buf_size
)
958 struct psoc5lp_eeprom_flash_bank
*psoc_eeprom_bank
= bank
->driver_priv
;
959 char part_number
[PART_NUMBER_LEN
];
961 psoc5lp_get_part_number(psoc_eeprom_bank
->device
, part_number
);
963 snprintf(buf
, buf_size
, "%s", part_number
);
968 static int psoc5lp_eeprom_probe(struct flash_bank
*bank
)
970 struct psoc5lp_eeprom_flash_bank
*psoc_eeprom_bank
= bank
->driver_priv
;
971 uint32_t flash_addr
= bank
->base
;
975 if (psoc_eeprom_bank
->probed
)
978 if (bank
->target
->state
!= TARGET_HALTED
) {
979 LOG_ERROR("Target not halted");
980 return ERROR_TARGET_NOT_HALTED
;
983 retval
= psoc5lp_find_device(bank
->target
, &psoc_eeprom_bank
->device
);
984 if (retval
!= ERROR_OK
)
987 retval
= target_read_u32(bank
->target
, PM_ACT_CFG12
, &val
);
988 if (retval
!= ERROR_OK
)
990 if (!(val
& PM_ACT_CFG12_EN_EE
)) {
991 val
|= PM_ACT_CFG12_EN_EE
;
992 retval
= target_write_u32(bank
->target
, PM_ACT_CFG12
, val
);
993 if (retval
!= ERROR_OK
)
997 bank
->size
= psoc_eeprom_bank
->device
->eeprom_kb
* 1024;
998 bank
->num_sectors
= DIV_ROUND_UP(bank
->size
, EEPROM_SECTOR_SIZE
);
999 bank
->sectors
= calloc(bank
->num_sectors
,
1000 sizeof(struct flash_sector
));
1001 for (i
= 0; i
< bank
->num_sectors
; i
++) {
1002 bank
->sectors
[i
].size
= EEPROM_SECTOR_SIZE
;
1003 bank
->sectors
[i
].offset
= flash_addr
- bank
->base
;
1004 bank
->sectors
[i
].is_erased
= -1;
1005 bank
->sectors
[i
].is_protected
= -1;
1007 flash_addr
+= bank
->sectors
[i
].size
;
1010 bank
->default_padded_value
= bank
->erased_value
= 0x00;
1012 psoc_eeprom_bank
->probed
= true;
1017 static int psoc5lp_eeprom_auto_probe(struct flash_bank
*bank
)
1019 struct psoc5lp_eeprom_flash_bank
*psoc_eeprom_bank
= bank
->driver_priv
;
1021 if (psoc_eeprom_bank
->probed
)
1024 return psoc5lp_eeprom_probe(bank
);
1027 FLASH_BANK_COMMAND_HANDLER(psoc5lp_eeprom_flash_bank_command
)
1029 struct psoc5lp_eeprom_flash_bank
*psoc_eeprom_bank
;
1031 psoc_eeprom_bank
= malloc(sizeof(struct psoc5lp_eeprom_flash_bank
));
1032 if (!psoc_eeprom_bank
)
1033 return ERROR_FLASH_OPERATION_FAILED
;
1035 psoc_eeprom_bank
->probed
= false;
1036 psoc_eeprom_bank
->device
= NULL
;
1038 bank
->driver_priv
= psoc_eeprom_bank
;
1043 static const struct command_registration psoc5lp_eeprom_exec_command_handlers
[] = {
1044 COMMAND_REGISTRATION_DONE
1047 static const struct command_registration psoc5lp_eeprom_command_handlers
[] = {
1049 .name
= "psoc5lp_eeprom",
1050 .mode
= COMMAND_ANY
,
1051 .help
= "PSoC 5LP EEPROM command group",
1053 .chain
= psoc5lp_eeprom_exec_command_handlers
,
1055 COMMAND_REGISTRATION_DONE
1058 struct flash_driver psoc5lp_eeprom_flash
= {
1059 .name
= "psoc5lp_eeprom",
1060 .commands
= psoc5lp_eeprom_command_handlers
,
1061 .flash_bank_command
= psoc5lp_eeprom_flash_bank_command
,
1062 .info
= psoc5lp_eeprom_get_info_command
,
1063 .probe
= psoc5lp_eeprom_probe
,
1064 .auto_probe
= psoc5lp_eeprom_auto_probe
,
1065 .protect_check
= psoc5lp_eeprom_protect_check
,
1066 .read
= default_flash_read
,
1067 .erase
= psoc5lp_eeprom_erase
,
1068 .erase_check
= default_flash_blank_check
,
1069 .write
= psoc5lp_eeprom_write
,
1076 struct psoc5lp_flash_bank
{
1078 const struct psoc5lp_device
*device
;
1082 static int psoc5lp_erase(struct flash_bank
*bank
, int first
, int last
)
1084 struct psoc5lp_flash_bank
*psoc_bank
= bank
->driver_priv
;
1087 if (!psoc_bank
->ecc_enabled
) {
1088 /* Silently avoid erasing sectors twice */
1089 if (last
>= first
+ bank
->num_sectors
/ 2) {
1090 LOG_DEBUG("Skipping duplicate erase of sectors %d to %d",
1091 first
+ bank
->num_sectors
/ 2, last
);
1092 last
= first
+ (bank
->num_sectors
/ 2) - 1;
1094 /* Check for any remaining ECC sectors */
1095 if (last
>= bank
->num_sectors
/ 2) {
1096 LOG_WARNING("Skipping erase of ECC region sectors %d to %d",
1097 bank
->num_sectors
/ 2, last
);
1098 last
= (bank
->num_sectors
/ 2) - 1;
1102 for (i
= first
; i
<= last
; i
++) {
1103 retval
= psoc5lp_spc_erase_sector(bank
->target
,
1104 i
/ SECTORS_PER_BLOCK
, i
% SECTORS_PER_BLOCK
);
1105 if (retval
!= ERROR_OK
)
1112 /* Derived from core.c:default_flash_blank_check() */
1113 static int psoc5lp_erase_check(struct flash_bank
*bank
)
1115 struct psoc5lp_flash_bank
*psoc_bank
= bank
->driver_priv
;
1116 struct target
*target
= bank
->target
;
1119 if (target
->state
!= TARGET_HALTED
) {
1120 LOG_ERROR("Target not halted");
1121 return ERROR_TARGET_NOT_HALTED
;
1124 struct target_memory_check_block
*block_array
;
1125 block_array
= malloc(bank
->num_sectors
* sizeof(struct target_memory_check_block
));
1126 if (block_array
== NULL
)
1129 for (i
= 0; i
< bank
->num_sectors
; i
++) {
1130 block_array
[i
].address
= bank
->base
+ bank
->sectors
[i
].offset
;
1131 block_array
[i
].size
= bank
->sectors
[i
].size
;
1132 block_array
[i
].result
= UINT32_MAX
; /* erase state unknown */
1135 bool fast_check
= true;
1136 for (i
= 0; i
< bank
->num_sectors
; ) {
1137 retval
= armv7m_blank_check_memory(target
,
1138 block_array
+ i
, bank
->num_sectors
- i
,
1139 bank
->erased_value
);
1141 /* Run slow fallback if the first run gives no result
1142 * otherwise use possibly incomplete results */
1147 i
+= retval
; /* add number of blocks done this round */
1151 if (!psoc_bank
->ecc_enabled
) {
1152 int half_sectors
= bank
->num_sectors
/ 2;
1153 for (i
= 0; i
< half_sectors
/ 2; i
++)
1154 bank
->sectors
[i
].is_erased
=
1155 (block_array
[i
].result
!= 1)
1156 ? block_array
[i
+ half_sectors
].result
1157 : block_array
[i
].result
;
1159 for (i
= 0; i
< bank
->num_sectors
; i
++)
1160 bank
->sectors
[i
].is_erased
= block_array
[i
].result
;
1164 LOG_ERROR("Can't run erase check - add working memory");
1165 retval
= ERROR_FAIL
;
1172 static int psoc5lp_write(struct flash_bank
*bank
, const uint8_t *buffer
,
1173 uint32_t offset
, uint32_t byte_count
)
1175 struct psoc5lp_flash_bank
*psoc_bank
= bank
->driver_priv
;
1176 struct target
*target
= bank
->target
;
1177 struct working_area
*code_area
, *even_row_area
, *odd_row_area
;
1179 uint8_t temp
[2], buf
[12], ecc_bytes
[ROW_ECC_SIZE
];
1180 unsigned array_id
, row
;
1183 if (offset
+ byte_count
> bank
->size
) {
1184 LOG_ERROR("Writing to ECC not supported");
1185 return ERROR_FLASH_DST_OUT_OF_BANK
;
1188 if (offset
% ROW_SIZE
!= 0) {
1189 LOG_ERROR("Writes must be row-aligned, got offset 0x%08" PRIx32
,
1191 return ERROR_FLASH_DST_BREAKS_ALIGNMENT
;
1194 row_size
= ROW_SIZE
;
1195 if (!psoc_bank
->ecc_enabled
) {
1196 row_size
+= ROW_ECC_SIZE
;
1197 memset(ecc_bytes
, bank
->default_padded_value
, ROW_ECC_SIZE
);
1200 retval
= psoc5lp_spc_get_temp(target
, 3, temp
);
1201 if (retval
!= ERROR_OK
) {
1202 LOG_ERROR("Unable to read Die temperature");
1205 LOG_DEBUG("Get_Temp: sign 0x%02" PRIx8
", magnitude 0x%02" PRIx8
,
1208 assert(target_get_working_area_avail(target
) == target
->working_area_size
);
1209 retval
= target_alloc_working_area(target
,
1210 target_get_working_area_avail(target
) / 2, &code_area
);
1211 if (retval
!= ERROR_OK
) {
1212 LOG_ERROR("Could not allocate working area for program SRAM");
1215 assert(code_area
->address
< 0x20000000);
1217 retval
= target_alloc_working_area(target
,
1218 SPC_OPCODE_LEN
+ 1 + row_size
+ 3 + SPC_OPCODE_LEN
+ 6,
1220 if (retval
!= ERROR_OK
) {
1221 LOG_ERROR("Could not allocate working area for even row");
1222 goto err_alloc_even
;
1224 assert(even_row_area
->address
>= 0x20000000);
1226 retval
= target_alloc_working_area(target
, even_row_area
->size
,
1228 if (retval
!= ERROR_OK
) {
1229 LOG_ERROR("Could not allocate working area for odd row");
1232 assert(odd_row_area
->address
>= 0x20000000);
1234 for (array_id
= offset
/ BLOCK_SIZE
; byte_count
> 0; array_id
++) {
1235 for (row
= (offset
/ ROW_SIZE
) % ROWS_PER_BLOCK
;
1236 row
< ROWS_PER_BLOCK
&& byte_count
> 0; row
++) {
1237 bool even_row
= (row
% 2 == 0);
1238 struct working_area
*data_area
= even_row
? even_row_area
: odd_row_area
;
1239 unsigned len
= MIN(ROW_SIZE
, byte_count
);
1241 LOG_DEBUG("Writing load command for array %u row %u at 0x%08" TARGET_PRIxADDR
,
1242 array_id
, row
, data_area
->address
);
1244 psoc5lp_spc_write_opcode_buffer(target
, buf
, SPC_LOAD_ROW
);
1245 buf
[SPC_OPCODE_LEN
] = array_id
;
1246 retval
= target_write_buffer(target
, data_area
->address
, 4, buf
);
1247 if (retval
!= ERROR_OK
)
1250 retval
= target_write_buffer(target
,
1251 data_area
->address
+ SPC_OPCODE_LEN
+ 1,
1253 if (retval
!= ERROR_OK
)
1259 if (len
< ROW_SIZE
) {
1260 uint8_t padding
[ROW_SIZE
];
1262 memset(padding
, bank
->default_padded_value
, ROW_SIZE
);
1264 LOG_DEBUG("Padding %d bytes", ROW_SIZE
- len
);
1265 retval
= target_write_buffer(target
,
1266 data_area
->address
+ SPC_OPCODE_LEN
+ 1 + len
,
1267 ROW_SIZE
- len
, padding
);
1268 if (retval
!= ERROR_OK
)
1272 if (!psoc_bank
->ecc_enabled
) {
1273 retval
= target_write_buffer(target
,
1274 data_area
->address
+ SPC_OPCODE_LEN
+ 1 + ROW_SIZE
,
1275 sizeof(ecc_bytes
), ecc_bytes
);
1276 if (retval
!= ERROR_OK
)
1280 for (i
= 0; i
< 3; i
++)
1281 buf
[i
] = 0x00; /* 3 NOPs for short delay */
1282 psoc5lp_spc_write_opcode_buffer(target
, buf
+ 3, SPC_PRG_ROW
);
1283 buf
[3 + SPC_OPCODE_LEN
] = array_id
;
1284 buf
[3 + SPC_OPCODE_LEN
+ 1] = row
>> 8;
1285 buf
[3 + SPC_OPCODE_LEN
+ 2] = row
& 0xff;
1286 memcpy(buf
+ 3 + SPC_OPCODE_LEN
+ 3, temp
, 2);
1287 buf
[3 + SPC_OPCODE_LEN
+ 5] = 0x00; /* padding */
1288 retval
= target_write_buffer(target
,
1289 data_area
->address
+ SPC_OPCODE_LEN
+ 1 + row_size
,
1291 if (retval
!= ERROR_OK
)
1294 retval
= target_write_u32(target
,
1295 even_row
? PHUB_CH0_BASIC_STATUS
: PHUB_CH1_BASIC_STATUS
,
1296 (even_row
? 0 : 1) << 8);
1297 if (retval
!= ERROR_OK
)
1300 retval
= target_write_u32(target
,
1301 even_row
? PHUB_CH0_BASIC_CFG
: PHUB_CH1_BASIC_CFG
,
1302 PHUB_CHx_BASIC_CFG_WORK_SEP
| PHUB_CHx_BASIC_CFG_EN
);
1303 if (retval
!= ERROR_OK
)
1306 retval
= target_write_u32(target
,
1307 even_row
? PHUB_CFGMEM0_CFG0
: PHUB_CFGMEM1_CFG0
,
1309 if (retval
!= ERROR_OK
)
1312 retval
= target_write_u32(target
,
1313 even_row
? PHUB_CFGMEM0_CFG1
: PHUB_CFGMEM1_CFG1
,
1314 ((SPC_CPU_DATA
>> 16) << 16) | (data_area
->address
>> 16));
1315 if (retval
!= ERROR_OK
)
1318 retval
= target_write_u32(target
,
1319 even_row
? PHUB_TDMEM0_ORIG_TD0
: PHUB_TDMEM1_ORIG_TD0
,
1320 PHUB_TDMEMx_ORIG_TD0_INC_SRC_ADDR
|
1321 PHUB_TDMEMx_ORIG_TD0_NEXT_TD_PTR_LAST
|
1322 ((SPC_OPCODE_LEN
+ 1 + row_size
+ 3 + SPC_OPCODE_LEN
+ 5) & 0xfff));
1323 if (retval
!= ERROR_OK
)
1326 retval
= target_write_u32(target
,
1327 even_row
? PHUB_TDMEM0_ORIG_TD1
: PHUB_TDMEM1_ORIG_TD1
,
1328 ((SPC_CPU_DATA
& 0xffff) << 16) | (data_area
->address
& 0xffff));
1329 if (retval
!= ERROR_OK
)
1332 retval
= psoc5lp_spc_busy_wait_idle(target
);
1333 if (retval
!= ERROR_OK
)
1336 retval
= target_write_u32(target
,
1337 even_row
? PHUB_CH0_ACTION
: PHUB_CH1_ACTION
,
1338 PHUB_CHx_ACTION_CPU_REQ
);
1339 if (retval
!= ERROR_OK
)
1340 goto err_dma_action
;
1344 retval
= psoc5lp_spc_busy_wait_idle(target
);
1350 target_free_working_area(target
, odd_row_area
);
1352 target_free_working_area(target
, even_row_area
);
1354 target_free_working_area(target
, code_area
);
1359 static int psoc5lp_protect_check(struct flash_bank
*bank
)
1361 struct psoc5lp_flash_bank
*psoc_bank
= bank
->driver_priv
;
1362 uint8_t row_data
[ROW_SIZE
];
1363 const unsigned protection_bytes_per_sector
= ROWS_PER_SECTOR
* 2 / 8;
1364 unsigned i
, j
, k
, num_sectors
;
1367 if (bank
->target
->state
!= TARGET_HALTED
) {
1368 LOG_ERROR("Target not halted");
1369 return ERROR_TARGET_NOT_HALTED
;
1372 for (i
= 0; i
< DIV_ROUND_UP(bank
->size
, BLOCK_SIZE
); i
++) {
1373 retval
= psoc5lp_spc_read_hidden_row(bank
->target
, i
,
1374 SPC_ROW_PROTECTION
, row_data
);
1375 if (retval
!= ERROR_OK
)
1378 /* Last flash array may have less rows, but in practice full sectors. */
1379 if (i
== bank
->size
/ BLOCK_SIZE
)
1380 num_sectors
= (bank
->size
% BLOCK_SIZE
) / SECTOR_SIZE
;
1382 num_sectors
= SECTORS_PER_BLOCK
;
1384 for (j
= 0; j
< num_sectors
; j
++) {
1385 int sector_nr
= i
* SECTORS_PER_BLOCK
+ j
;
1386 struct flash_sector
*sector
= &bank
->sectors
[sector_nr
];
1387 struct flash_sector
*ecc_sector
;
1389 if (psoc_bank
->ecc_enabled
)
1390 ecc_sector
= &bank
->sectors
[bank
->num_sectors
+ sector_nr
];
1392 ecc_sector
= &bank
->sectors
[bank
->num_sectors
/ 2 + sector_nr
];
1394 sector
->is_protected
= ecc_sector
->is_protected
= 0;
1395 for (k
= protection_bytes_per_sector
* j
;
1396 k
< protection_bytes_per_sector
* (j
+ 1); k
++) {
1397 assert(k
< protection_bytes_per_sector
* SECTORS_PER_BLOCK
);
1398 LOG_DEBUG("row[%u][%02u] = 0x%02" PRIx8
, i
, k
, row_data
[k
]);
1399 if (row_data
[k
] != 0x00) {
1400 sector
->is_protected
= ecc_sector
->is_protected
= 1;
1410 static int psoc5lp_get_info_command(struct flash_bank
*bank
, char *buf
, int buf_size
)
1412 struct psoc5lp_flash_bank
*psoc_bank
= bank
->driver_priv
;
1413 char part_number
[PART_NUMBER_LEN
];
1416 psoc5lp_get_part_number(psoc_bank
->device
, part_number
);
1417 ecc
= psoc_bank
->ecc_enabled
? "ECC enabled" : "ECC disabled";
1419 snprintf(buf
, buf_size
, "%s %s", part_number
, ecc
);
1424 static int psoc5lp_probe(struct flash_bank
*bank
)
1426 struct target
*target
= bank
->target
;
1427 struct psoc5lp_flash_bank
*psoc_bank
= bank
->driver_priv
;
1428 uint32_t flash_addr
= bank
->base
;
1429 uint8_t nvl
[4], temp
[2];
1432 if (target
->state
!= TARGET_HALTED
) {
1433 LOG_ERROR("Target not halted");
1434 return ERROR_TARGET_NOT_HALTED
;
1437 if (!psoc_bank
->device
) {
1438 retval
= psoc5lp_find_device(target
, &psoc_bank
->device
);
1439 if (retval
!= ERROR_OK
)
1442 bank
->size
= psoc_bank
->device
->flash_kb
* 1024;
1445 bank
->num_sectors
= DIV_ROUND_UP(bank
->size
, SECTOR_SIZE
);
1447 if (!psoc_bank
->probed
) {
1448 retval
= psoc5lp_spc_enable_clock(target
);
1449 if (retval
!= ERROR_OK
)
1452 /* First values read are inaccurate, so do it once now. */
1453 retval
= psoc5lp_spc_get_temp(target
, 3, temp
);
1454 if (retval
!= ERROR_OK
) {
1455 LOG_ERROR("Unable to read Die temperature");
1459 bank
->sectors
= calloc(bank
->num_sectors
* 2,
1460 sizeof(struct flash_sector
));
1461 for (i
= 0; i
< bank
->num_sectors
; i
++) {
1462 bank
->sectors
[i
].size
= SECTOR_SIZE
;
1463 bank
->sectors
[i
].offset
= flash_addr
- bank
->base
;
1464 bank
->sectors
[i
].is_erased
= -1;
1465 bank
->sectors
[i
].is_protected
= -1;
1467 flash_addr
+= bank
->sectors
[i
].size
;
1469 flash_addr
= 0x48000000;
1470 for (i
= bank
->num_sectors
; i
< bank
->num_sectors
* 2; i
++) {
1471 bank
->sectors
[i
].size
= ROWS_PER_SECTOR
* ROW_ECC_SIZE
;
1472 bank
->sectors
[i
].offset
= flash_addr
- bank
->base
;
1473 bank
->sectors
[i
].is_erased
= -1;
1474 bank
->sectors
[i
].is_protected
= -1;
1476 flash_addr
+= bank
->sectors
[i
].size
;
1479 bank
->default_padded_value
= bank
->erased_value
= 0x00;
1481 psoc_bank
->probed
= true;
1484 retval
= psoc5lp_spc_read_byte(target
, SPC_ARRAY_NVL_USER
, 3, &nvl
[3]);
1485 if (retval
!= ERROR_OK
)
1487 LOG_DEBUG("NVL[%d] = 0x%02" PRIx8
, 3, nvl
[3]);
1488 psoc_bank
->ecc_enabled
= nvl
[3] & NVL_3_ECCEN
;
1490 if (!psoc_bank
->ecc_enabled
)
1491 bank
->num_sectors
*= 2;
1496 static int psoc5lp_auto_probe(struct flash_bank
*bank
)
1498 return psoc5lp_probe(bank
);
1501 COMMAND_HANDLER(psoc5lp_handle_mass_erase_command
)
1503 struct flash_bank
*bank
;
1507 return ERROR_COMMAND_SYNTAX_ERROR
;
1509 retval
= CALL_COMMAND_HANDLER(flash_command_get_bank
, 0, &bank
);
1510 if (retval
!= ERROR_OK
)
1513 retval
= psoc5lp_spc_erase_all(bank
->target
);
1514 if (retval
== ERROR_OK
)
1515 command_print(CMD_CTX
, "PSoC 5LP erase succeeded");
1517 command_print(CMD_CTX
, "PSoC 5LP erase failed");
1522 FLASH_BANK_COMMAND_HANDLER(psoc5lp_flash_bank_command
)
1524 struct psoc5lp_flash_bank
*psoc_bank
;
1526 psoc_bank
= malloc(sizeof(struct psoc5lp_flash_bank
));
1528 return ERROR_FLASH_OPERATION_FAILED
;
1530 psoc_bank
->probed
= false;
1531 psoc_bank
->device
= NULL
;
1533 bank
->driver_priv
= psoc_bank
;
1538 static const struct command_registration psoc5lp_exec_command_handlers
[] = {
1540 .name
= "mass_erase",
1541 .handler
= psoc5lp_handle_mass_erase_command
,
1542 .mode
= COMMAND_EXEC
,
1544 .help
= "Erase all flash data and ECC/configuration bytes, "
1545 "all flash protection rows, "
1546 "and all row latches in all flash arrays on the device.",
1548 COMMAND_REGISTRATION_DONE
1551 static const struct command_registration psoc5lp_command_handlers
[] = {
1554 .mode
= COMMAND_ANY
,
1555 .help
= "PSoC 5LP flash command group",
1557 .chain
= psoc5lp_exec_command_handlers
,
1559 COMMAND_REGISTRATION_DONE
1562 struct flash_driver psoc5lp_flash
= {
1564 .commands
= psoc5lp_command_handlers
,
1565 .flash_bank_command
= psoc5lp_flash_bank_command
,
1566 .info
= psoc5lp_get_info_command
,
1567 .probe
= psoc5lp_probe
,
1568 .auto_probe
= psoc5lp_auto_probe
,
1569 .protect_check
= psoc5lp_protect_check
,
1570 .read
= default_flash_read
,
1571 .erase
= psoc5lp_erase
,
1572 .erase_check
= psoc5lp_erase_check
,
1573 .write
= psoc5lp_write
,