1 // SPDX-License-Identifier: GPL-2.0-or-later
4 * PSoC 5LP flash driver
6 * Copyright (c) 2016 Andreas Färber
14 #include <helper/time_support.h>
15 #include <target/armv7m.h>
17 #define PM_ACT_CFG0 0x400043A0
18 #define PM_ACT_CFG12 0x400043AC
19 #define SPC_CPU_DATA 0x40004720
20 #define SPC_SR 0x40004722
21 #define PRT1_PC2 0x4000500A
22 #define PHUB_CH0_BASIC_CFG 0x40007010
23 #define PHUB_CH0_ACTION 0x40007014
24 #define PHUB_CH0_BASIC_STATUS 0x40007018
25 #define PHUB_CH1_BASIC_CFG 0x40007020
26 #define PHUB_CH1_ACTION 0x40007024
27 #define PHUB_CH1_BASIC_STATUS 0x40007028
28 #define PHUB_CFGMEM0_CFG0 0x40007600
29 #define PHUB_CFGMEM0_CFG1 0x40007604
30 #define PHUB_CFGMEM1_CFG0 0x40007608
31 #define PHUB_CFGMEM1_CFG1 0x4000760C
32 #define PHUB_TDMEM0_ORIG_TD0 0x40007800
33 #define PHUB_TDMEM0_ORIG_TD1 0x40007804
34 #define PHUB_TDMEM1_ORIG_TD0 0x40007808
35 #define PHUB_TDMEM1_ORIG_TD1 0x4000780C
36 #define PANTHER_DEVICE_ID 0x4008001C
38 /* NVL is not actually mapped to the Cortex-M address space
39 * As we need a base address different from other banks in the device
40 * we use the address of NVL programming data in Cypress images */
41 #define NVL_META_BASE 0x90000000
43 #define PM_ACT_CFG12_EN_EE (1 << 4)
48 #define SPC_LOAD_BYTE 0x00
49 #define SPC_LOAD_MULTI_BYTE 0x01
50 #define SPC_LOAD_ROW 0x02
51 #define SPC_READ_BYTE 0x03
52 #define SPC_READ_MULTI_BYTE 0x04
53 #define SPC_WRITE_ROW 0x05
54 #define SPC_WRITE_USER_NVL 0x06
55 #define SPC_PRG_ROW 0x07
56 #define SPC_ERASE_SECTOR 0x08
57 #define SPC_ERASE_ALL 0x09
58 #define SPC_READ_HIDDEN_ROW 0x0A
59 #define SPC_PROGRAM_PROTECT_ROW 0x0B
60 #define SPC_GET_CHECKSUM 0x0C
61 #define SPC_GET_TEMP 0x0E
62 #define SPC_READ_VOLATILE_BYTE 0x10
64 #define SPC_ARRAY_ALL 0x3F
65 #define SPC_ARRAY_EEPROM 0x40
66 #define SPC_ARRAY_NVL_USER 0x80
67 #define SPC_ARRAY_NVL_WO 0xF8
69 #define SPC_ROW_PROTECTION 0
71 #define SPC_OPCODE_LEN 3
73 #define SPC_SR_DATA_READY (1 << 0)
74 #define SPC_SR_IDLE (1 << 1)
76 #define PM_ACT_CFG0_EN_CLK_SPC (1 << 3)
78 #define PHUB_CHX_BASIC_CFG_EN (1 << 0)
79 #define PHUB_CHX_BASIC_CFG_WORK_SEP (1 << 5)
81 #define PHUB_CHX_ACTION_CPU_REQ (1 << 0)
83 #define PHUB_CFGMEMX_CFG0 (1 << 7)
85 #define PHUB_TDMEMX_ORIG_TD0_NEXT_TD_PTR_LAST (0xff << 16)
86 #define PHUB_TDMEMX_ORIG_TD0_INC_SRC_ADDR (1 << 24)
88 #define NVL_3_ECCEN (1 << 3)
91 #define ROW_ECC_SIZE 32
92 #define ROWS_PER_SECTOR 64
93 #define SECTOR_SIZE (ROWS_PER_SECTOR * ROW_SIZE)
94 #define ROWS_PER_BLOCK 256
95 #define BLOCK_SIZE (ROWS_PER_BLOCK * ROW_SIZE)
96 #define SECTORS_PER_BLOCK (BLOCK_SIZE / SECTOR_SIZE)
97 #define EEPROM_ROW_SIZE 16
98 #define EEPROM_SECTOR_SIZE (ROWS_PER_SECTOR * EEPROM_ROW_SIZE)
99 #define EEPROM_BLOCK_SIZE (ROWS_PER_BLOCK * EEPROM_ROW_SIZE)
101 #define PART_NUMBER_LEN (17 + 1)
103 struct psoc5lp_device
{
112 * Device information collected from datasheets.
113 * Different temperature ranges (C/I/Q/A) may share IDs, not differing otherwise.
115 static const struct psoc5lp_device psoc5lp_devices
[] = {
116 /* CY8C58LP Family Datasheet */
117 { .id
= 0x2E11F069, .fam
= 8, .speed_mhz
= 67, .flash_kb
= 256, .eeprom_kb
= 2 },
118 { .id
= 0x2E120069, .fam
= 8, .speed_mhz
= 67, .flash_kb
= 256, .eeprom_kb
= 2 },
119 { .id
= 0x2E123069, .fam
= 8, .speed_mhz
= 67, .flash_kb
= 256, .eeprom_kb
= 2 },
120 { .id
= 0x2E124069, .fam
= 8, .speed_mhz
= 67, .flash_kb
= 256, .eeprom_kb
= 2 },
121 { .id
= 0x2E126069, .fam
= 8, .speed_mhz
= 67, .flash_kb
= 256, .eeprom_kb
= 2 },
122 { .id
= 0x2E127069, .fam
= 8, .speed_mhz
= 67, .flash_kb
= 256, .eeprom_kb
= 2 },
123 { .id
= 0x2E117069, .fam
= 8, .speed_mhz
= 67, .flash_kb
= 128, .eeprom_kb
= 2 },
124 { .id
= 0x2E118069, .fam
= 8, .speed_mhz
= 67, .flash_kb
= 128, .eeprom_kb
= 2 },
125 { .id
= 0x2E119069, .fam
= 8, .speed_mhz
= 67, .flash_kb
= 128, .eeprom_kb
= 2 },
126 { .id
= 0x2E11C069, .fam
= 8, .speed_mhz
= 67, .flash_kb
= 128, .eeprom_kb
= 2 },
127 { .id
= 0x2E114069, .fam
= 8, .speed_mhz
= 67, .flash_kb
= 64, .eeprom_kb
= 2 },
128 { .id
= 0x2E115069, .fam
= 8, .speed_mhz
= 67, .flash_kb
= 64, .eeprom_kb
= 2 },
129 { .id
= 0x2E116069, .fam
= 8, .speed_mhz
= 67, .flash_kb
= 64, .eeprom_kb
= 2 },
130 { .id
= 0x2E160069, .fam
= 8, .speed_mhz
= 80, .flash_kb
= 256, .eeprom_kb
= 2 },
132 { .id
= 0x2E161069, .fam
= 8, .speed_mhz
= 80, .flash_kb
= 256, .eeprom_kb
= 2 },
134 { .id
= 0x2E1D2069, .fam
= 8, .speed_mhz
= 80, .flash_kb
= 256, .eeprom_kb
= 2 },
135 { .id
= 0x2E1D6069, .fam
= 8, .speed_mhz
= 80, .flash_kb
= 256, .eeprom_kb
= 2 },
137 /* CY8C56LP Family Datasheet */
138 { .id
= 0x2E10A069, .fam
= 6, .speed_mhz
= 67, .flash_kb
= 256, .eeprom_kb
= 2 },
139 { .id
= 0x2E10D069, .fam
= 6, .speed_mhz
= 67, .flash_kb
= 256, .eeprom_kb
= 2 },
140 { .id
= 0x2E10E069, .fam
= 6, .speed_mhz
= 67, .flash_kb
= 256, .eeprom_kb
= 2 },
141 { .id
= 0x2E106069, .fam
= 6, .speed_mhz
= 67, .flash_kb
= 128, .eeprom_kb
= 2 },
142 { .id
= 0x2E108069, .fam
= 6, .speed_mhz
= 67, .flash_kb
= 128, .eeprom_kb
= 2 },
143 { .id
= 0x2E109069, .fam
= 6, .speed_mhz
= 67, .flash_kb
= 128, .eeprom_kb
= 2 },
144 { .id
= 0x2E101069, .fam
= 6, .speed_mhz
= 67, .flash_kb
= 64, .eeprom_kb
= 2 },
145 { .id
= 0x2E104069, .fam
= 6, .speed_mhz
= 67, .flash_kb
= 64, .eeprom_kb
= 2 },
147 { .id
= 0x2E105069, .fam
= 6, .speed_mhz
= 67, .flash_kb
= 64, .eeprom_kb
= 2 },
148 { .id
= 0x2E128069, .fam
= 6, .speed_mhz
= 67, .flash_kb
= 128, .eeprom_kb
= 2 },
150 { .id
= 0x2E122069, .fam
= 6, .speed_mhz
= 67, .flash_kb
= 256, .eeprom_kb
= 2 },
151 { .id
= 0x2E129069, .fam
= 6, .speed_mhz
= 67, .flash_kb
= 128, .eeprom_kb
= 2 },
152 { .id
= 0x2E163069, .fam
= 6, .speed_mhz
= 80, .flash_kb
= 256, .eeprom_kb
= 2 },
153 { .id
= 0x2E156069, .fam
= 6, .speed_mhz
= 80, .flash_kb
= 256, .eeprom_kb
= 2 },
154 { .id
= 0x2E1D3069, .fam
= 6, .speed_mhz
= 80, .flash_kb
= 256, .eeprom_kb
= 2 },
156 /* CY8C54LP Family Datasheet */
157 { .id
= 0x2E11A069, .fam
= 4, .speed_mhz
= 67, .flash_kb
= 256, .eeprom_kb
= 2 },
158 { .id
= 0x2E16A069, .fam
= 4, .speed_mhz
= 67, .flash_kb
= 256, .eeprom_kb
= 2 },
159 { .id
= 0x2E12A069, .fam
= 4, .speed_mhz
= 67, .flash_kb
= 256, .eeprom_kb
= 2 },
160 { .id
= 0x2E103069, .fam
= 4, .speed_mhz
= 67, .flash_kb
= 128, .eeprom_kb
= 2 },
161 { .id
= 0x2E16C069, .fam
= 4, .speed_mhz
= 67, .flash_kb
= 128, .eeprom_kb
= 2 },
162 { .id
= 0x2E102069, .fam
= 4, .speed_mhz
= 67, .flash_kb
= 64, .eeprom_kb
= 2 },
163 { .id
= 0x2E148069, .fam
= 4, .speed_mhz
= 67, .flash_kb
= 64, .eeprom_kb
= 2 },
164 { .id
= 0x2E155069, .fam
= 4, .speed_mhz
= 67, .flash_kb
= 64, .eeprom_kb
= 2 },
165 { .id
= 0x2E16B069, .fam
= 4, .speed_mhz
= 67, .flash_kb
= 64, .eeprom_kb
= 2 },
166 { .id
= 0x2E12B069, .fam
= 4, .speed_mhz
= 67, .flash_kb
= 32, .eeprom_kb
= 2 },
167 { .id
= 0x2E168069, .fam
= 4, .speed_mhz
= 67, .flash_kb
= 32, .eeprom_kb
= 2 },
168 { .id
= 0x2E178069, .fam
= 4, .speed_mhz
= 80, .flash_kb
= 256, .eeprom_kb
= 2 },
169 { .id
= 0x2E15D069, .fam
= 4, .speed_mhz
= 80, .flash_kb
= 256, .eeprom_kb
= 2 },
170 { .id
= 0x2E1D4069, .fam
= 4, .speed_mhz
= 80, .flash_kb
= 256, .eeprom_kb
= 2 },
172 /* CY8C52LP Family Datasheet */
173 { .id
= 0x2E11E069, .fam
= 2, .speed_mhz
= 67, .flash_kb
= 256, .eeprom_kb
= 2 },
174 { .id
= 0x2E12F069, .fam
= 2, .speed_mhz
= 67, .flash_kb
= 256, .eeprom_kb
= 2 },
175 { .id
= 0x2E133069, .fam
= 2, .speed_mhz
= 67, .flash_kb
= 128, .eeprom_kb
= 2 },
176 { .id
= 0x2E159069, .fam
= 2, .speed_mhz
= 67, .flash_kb
= 128, .eeprom_kb
= 2 },
177 { .id
= 0x2E11D069, .fam
= 2, .speed_mhz
= 67, .flash_kb
= 64, .eeprom_kb
= 2 },
178 { .id
= 0x2E121069, .fam
= 2, .speed_mhz
= 67, .flash_kb
= 64, .eeprom_kb
= 2 },
179 { .id
= 0x2E184069, .fam
= 2, .speed_mhz
= 67, .flash_kb
= 64, .eeprom_kb
= 2 },
180 { .id
= 0x2E196069, .fam
= 2, .speed_mhz
= 67, .flash_kb
= 64, .eeprom_kb
= 2 },
181 { .id
= 0x2E132069, .fam
= 2, .speed_mhz
= 67, .flash_kb
= 32, .eeprom_kb
= 2 },
182 { .id
= 0x2E138069, .fam
= 2, .speed_mhz
= 67, .flash_kb
= 32, .eeprom_kb
= 2 },
183 { .id
= 0x2E13A069, .fam
= 2, .speed_mhz
= 67, .flash_kb
= 32, .eeprom_kb
= 2 },
184 { .id
= 0x2E152069, .fam
= 2, .speed_mhz
= 67, .flash_kb
= 32, .eeprom_kb
= 2 },
185 { .id
= 0x2E15F069, .fam
= 2, .speed_mhz
= 80, .flash_kb
= 256, .eeprom_kb
= 2 },
186 { .id
= 0x2E15A069, .fam
= 2, .speed_mhz
= 80, .flash_kb
= 256, .eeprom_kb
= 2 },
187 { .id
= 0x2E1D5069, .fam
= 2, .speed_mhz
= 80, .flash_kb
= 256, .eeprom_kb
= 2 },
190 static void psoc5lp_get_part_number(const struct psoc5lp_device
*dev
, char *str
)
192 strcpy(str
, "CY8Cabcdefg-LPxxx");
195 str
[5] = '0' + dev
->fam
;
197 switch (dev
->speed_mhz
) {
208 switch (dev
->flash_kb
) {
225 /* Package does not matter. */
229 /* Temperate range cannot uniquely be identified. */
233 static int psoc5lp_get_device_id(struct target
*target
, uint32_t *id
)
237 retval
= target_read_u32(target
, PANTHER_DEVICE_ID
, id
); /* dummy read */
238 if (retval
!= ERROR_OK
)
240 retval
= target_read_u32(target
, PANTHER_DEVICE_ID
, id
);
244 static int psoc5lp_find_device(struct target
*target
,
245 const struct psoc5lp_device
**device
)
253 retval
= psoc5lp_get_device_id(target
, &device_id
);
254 if (retval
!= ERROR_OK
)
256 LOG_DEBUG("PANTHER_DEVICE_ID = 0x%08" PRIX32
, device_id
);
258 for (i
= 0; i
< ARRAY_SIZE(psoc5lp_devices
); i
++) {
259 if (psoc5lp_devices
[i
].id
== device_id
) {
260 *device
= &psoc5lp_devices
[i
];
265 LOG_ERROR("Device 0x%08" PRIX32
" not supported", device_id
);
266 return ERROR_FLASH_OPER_UNSUPPORTED
;
269 static int psoc5lp_spc_enable_clock(struct target
*target
)
274 retval
= target_read_u8(target
, PM_ACT_CFG0
, &pm_act_cfg0
);
275 if (retval
!= ERROR_OK
) {
276 LOG_ERROR("Cannot read PM_ACT_CFG0");
280 if (pm_act_cfg0
& PM_ACT_CFG0_EN_CLK_SPC
)
281 return ERROR_OK
; /* clock already enabled */
283 retval
= target_write_u8(target
, PM_ACT_CFG0
, pm_act_cfg0
| PM_ACT_CFG0_EN_CLK_SPC
);
284 if (retval
!= ERROR_OK
)
285 LOG_ERROR("Cannot enable SPC clock");
290 static int psoc5lp_spc_write_opcode(struct target
*target
, uint8_t opcode
)
294 retval
= target_write_u8(target
, SPC_CPU_DATA
, SPC_KEY1
);
295 if (retval
!= ERROR_OK
)
297 retval
= target_write_u8(target
, SPC_CPU_DATA
, SPC_KEY2
+ opcode
);
298 if (retval
!= ERROR_OK
)
300 retval
= target_write_u8(target
, SPC_CPU_DATA
, opcode
);
304 static void psoc5lp_spc_write_opcode_buffer(struct target
*target
,
305 uint8_t *buf
, uint8_t opcode
)
308 buf
[1] = SPC_KEY2
+ opcode
;
312 static int psoc5lp_spc_busy_wait_data(struct target
*target
)
318 retval
= target_read_u8(target
, SPC_SR
, &sr
); /* dummy read */
319 if (retval
!= ERROR_OK
)
322 endtime
= timeval_ms() + 1000; /* 1 second timeout */
325 retval
= target_read_u8(target
, SPC_SR
, &sr
);
326 if (retval
!= ERROR_OK
)
328 if (sr
== SPC_SR_DATA_READY
)
330 } while (timeval_ms() < endtime
);
332 return ERROR_FLASH_OPERATION_FAILED
;
335 static int psoc5lp_spc_busy_wait_idle(struct target
*target
)
341 retval
= target_read_u8(target
, SPC_SR
, &sr
); /* dummy read */
342 if (retval
!= ERROR_OK
)
345 endtime
= timeval_ms() + 1000; /* 1 second timeout */
348 retval
= target_read_u8(target
, SPC_SR
, &sr
);
349 if (retval
!= ERROR_OK
)
351 if (sr
== SPC_SR_IDLE
)
353 } while (timeval_ms() < endtime
);
355 return ERROR_FLASH_OPERATION_FAILED
;
358 static int psoc5lp_spc_load_byte(struct target
*target
,
359 uint8_t array_id
, uint8_t offset
, uint8_t value
)
363 retval
= psoc5lp_spc_write_opcode(target
, SPC_LOAD_BYTE
);
364 if (retval
!= ERROR_OK
)
366 retval
= target_write_u8(target
, SPC_CPU_DATA
, array_id
);
367 if (retval
!= ERROR_OK
)
369 retval
= target_write_u8(target
, SPC_CPU_DATA
, offset
);
370 if (retval
!= ERROR_OK
)
372 retval
= target_write_u8(target
, SPC_CPU_DATA
, value
);
373 if (retval
!= ERROR_OK
)
376 retval
= psoc5lp_spc_busy_wait_idle(target
);
377 if (retval
!= ERROR_OK
)
383 static int psoc5lp_spc_load_row(struct target
*target
,
384 uint8_t array_id
, const uint8_t *data
, unsigned row_size
)
389 retval
= psoc5lp_spc_write_opcode(target
, SPC_LOAD_ROW
);
390 if (retval
!= ERROR_OK
)
392 retval
= target_write_u8(target
, SPC_CPU_DATA
, array_id
);
393 if (retval
!= ERROR_OK
)
396 for (i
= 0; i
< row_size
; i
++) {
397 retval
= target_write_u8(target
, SPC_CPU_DATA
, data
[i
]);
398 if (retval
!= ERROR_OK
)
402 retval
= psoc5lp_spc_busy_wait_idle(target
);
403 if (retval
!= ERROR_OK
)
409 static int psoc5lp_spc_read_byte(struct target
*target
,
410 uint8_t array_id
, uint8_t offset
, uint8_t *data
)
414 retval
= psoc5lp_spc_write_opcode(target
, SPC_READ_BYTE
);
415 if (retval
!= ERROR_OK
)
417 retval
= target_write_u8(target
, SPC_CPU_DATA
, array_id
);
418 if (retval
!= ERROR_OK
)
420 retval
= target_write_u8(target
, SPC_CPU_DATA
, offset
);
421 if (retval
!= ERROR_OK
)
424 retval
= psoc5lp_spc_busy_wait_data(target
);
425 if (retval
!= ERROR_OK
)
428 retval
= target_read_u8(target
, SPC_CPU_DATA
, data
);
429 if (retval
!= ERROR_OK
)
432 retval
= psoc5lp_spc_busy_wait_idle(target
);
433 if (retval
!= ERROR_OK
)
439 static int psoc5lp_spc_write_row(struct target
*target
,
440 uint8_t array_id
, uint16_t row_id
, const uint8_t *temp
)
444 retval
= psoc5lp_spc_write_opcode(target
, SPC_WRITE_ROW
);
445 if (retval
!= ERROR_OK
)
447 retval
= target_write_u8(target
, SPC_CPU_DATA
, array_id
);
448 if (retval
!= ERROR_OK
)
450 retval
= target_write_u8(target
, SPC_CPU_DATA
, row_id
>> 8);
451 if (retval
!= ERROR_OK
)
453 retval
= target_write_u8(target
, SPC_CPU_DATA
, row_id
& 0xff);
454 if (retval
!= ERROR_OK
)
456 retval
= target_write_u8(target
, SPC_CPU_DATA
, temp
[0]);
457 if (retval
!= ERROR_OK
)
459 retval
= target_write_u8(target
, SPC_CPU_DATA
, temp
[1]);
460 if (retval
!= ERROR_OK
)
463 retval
= psoc5lp_spc_busy_wait_idle(target
);
464 if (retval
!= ERROR_OK
)
470 static int psoc5lp_spc_write_user_nvl(struct target
*target
,
475 retval
= psoc5lp_spc_write_opcode(target
, SPC_WRITE_USER_NVL
);
476 if (retval
!= ERROR_OK
)
478 retval
= target_write_u8(target
, SPC_CPU_DATA
, array_id
);
479 if (retval
!= ERROR_OK
)
482 retval
= psoc5lp_spc_busy_wait_idle(target
);
483 if (retval
!= ERROR_OK
)
489 static int psoc5lp_spc_erase_sector(struct target
*target
,
490 uint8_t array_id
, uint8_t row_id
)
494 retval
= psoc5lp_spc_write_opcode(target
, SPC_ERASE_SECTOR
);
495 if (retval
!= ERROR_OK
)
497 retval
= target_write_u8(target
, SPC_CPU_DATA
, array_id
);
498 if (retval
!= ERROR_OK
)
500 retval
= target_write_u8(target
, SPC_CPU_DATA
, row_id
);
501 if (retval
!= ERROR_OK
)
504 retval
= psoc5lp_spc_busy_wait_idle(target
);
505 if (retval
!= ERROR_OK
)
511 static int psoc5lp_spc_erase_all(struct target
*target
)
515 retval
= psoc5lp_spc_write_opcode(target
, SPC_ERASE_ALL
);
516 if (retval
!= ERROR_OK
)
519 retval
= psoc5lp_spc_busy_wait_idle(target
);
520 if (retval
!= ERROR_OK
)
526 static int psoc5lp_spc_read_hidden_row(struct target
*target
,
527 uint8_t array_id
, uint8_t row_id
, uint8_t *data
)
531 retval
= psoc5lp_spc_write_opcode(target
, SPC_READ_HIDDEN_ROW
);
532 if (retval
!= ERROR_OK
)
534 retval
= target_write_u8(target
, SPC_CPU_DATA
, array_id
);
535 if (retval
!= ERROR_OK
)
537 retval
= target_write_u8(target
, SPC_CPU_DATA
, row_id
);
538 if (retval
!= ERROR_OK
)
541 retval
= psoc5lp_spc_busy_wait_data(target
);
542 if (retval
!= ERROR_OK
)
545 for (i
= 0; i
< ROW_SIZE
; i
++) {
546 retval
= target_read_u8(target
, SPC_CPU_DATA
, &data
[i
]);
547 if (retval
!= ERROR_OK
)
551 retval
= psoc5lp_spc_busy_wait_idle(target
);
552 if (retval
!= ERROR_OK
)
558 static int psoc5lp_spc_get_temp(struct target
*target
, uint8_t samples
,
563 retval
= psoc5lp_spc_write_opcode(target
, SPC_GET_TEMP
);
564 if (retval
!= ERROR_OK
)
566 retval
= target_write_u8(target
, SPC_CPU_DATA
, samples
);
567 if (retval
!= ERROR_OK
)
570 retval
= psoc5lp_spc_busy_wait_data(target
);
571 if (retval
!= ERROR_OK
)
574 retval
= target_read_u8(target
, SPC_CPU_DATA
, &data
[0]);
575 if (retval
!= ERROR_OK
)
577 retval
= target_read_u8(target
, SPC_CPU_DATA
, &data
[1]);
578 if (retval
!= ERROR_OK
)
581 retval
= psoc5lp_spc_busy_wait_idle(target
);
582 if (retval
!= ERROR_OK
)
588 static int psoc5lp_spc_read_volatile_byte(struct target
*target
,
589 uint8_t array_id
, uint8_t offset
, uint8_t *data
)
593 retval
= psoc5lp_spc_write_opcode(target
, SPC_READ_VOLATILE_BYTE
);
594 if (retval
!= ERROR_OK
)
596 retval
= target_write_u8(target
, SPC_CPU_DATA
, array_id
);
597 if (retval
!= ERROR_OK
)
599 retval
= target_write_u8(target
, SPC_CPU_DATA
, offset
);
600 if (retval
!= ERROR_OK
)
603 retval
= psoc5lp_spc_busy_wait_data(target
);
604 if (retval
!= ERROR_OK
)
607 retval
= target_read_u8(target
, SPC_CPU_DATA
, data
);
608 if (retval
!= ERROR_OK
)
611 retval
= psoc5lp_spc_busy_wait_idle(target
);
612 if (retval
!= ERROR_OK
)
622 struct psoc5lp_nvl_flash_bank
{
624 const struct psoc5lp_device
*device
;
627 static int psoc5lp_nvl_read(struct flash_bank
*bank
,
628 uint8_t *buffer
, uint32_t offset
, uint32_t count
)
632 retval
= psoc5lp_spc_enable_clock(bank
->target
);
633 if (retval
!= ERROR_OK
)
637 retval
= psoc5lp_spc_read_byte(bank
->target
,
638 SPC_ARRAY_NVL_USER
, offset
, buffer
);
639 if (retval
!= ERROR_OK
)
649 static int psoc5lp_nvl_erase(struct flash_bank
*bank
, unsigned int first
,
652 LOG_WARNING("There is no erase operation for NV Latches");
653 return ERROR_FLASH_OPER_UNSUPPORTED
;
656 static int psoc5lp_nvl_erase_check(struct flash_bank
*bank
)
658 for (unsigned int i
= 0; i
< bank
->num_sectors
; i
++)
659 bank
->sectors
[i
].is_erased
= 0;
664 static int psoc5lp_nvl_write(struct flash_bank
*bank
,
665 const uint8_t *buffer
, uint32_t offset
, uint32_t byte_count
)
667 struct target
*target
= bank
->target
;
668 uint8_t *current_data
, val
;
669 bool write_required
= false, pullup_needed
= false, ecc_changed
= false;
673 if (offset
!= 0 || byte_count
!= bank
->size
) {
674 LOG_ERROR("NVL can only be written in whole");
675 return ERROR_FLASH_OPER_UNSUPPORTED
;
678 current_data
= calloc(1, bank
->size
);
681 retval
= psoc5lp_nvl_read(bank
, current_data
, offset
, byte_count
);
682 if (retval
!= ERROR_OK
) {
686 for (i
= offset
; i
< byte_count
; i
++) {
687 if (current_data
[i
] != buffer
[i
]) {
688 write_required
= true;
692 if (((buffer
[2] & 0x80) == 0x80) && ((current_data
[0] & 0x0C) != 0x08))
693 pullup_needed
= true;
694 if (((buffer
[3] ^ current_data
[3]) & 0x08) == 0x08)
698 if (!write_required
) {
699 LOG_INFO("Unchanged, skipping NVL write");
703 retval
= target_read_u8(target
, PRT1_PC2
, &val
);
704 if (retval
!= ERROR_OK
)
708 retval
= target_write_u8(target
, PRT1_PC2
, val
);
709 if (retval
!= ERROR_OK
)
713 for (i
= offset
; i
< byte_count
; i
++) {
714 retval
= psoc5lp_spc_load_byte(target
,
715 SPC_ARRAY_NVL_USER
, i
, buffer
[i
]);
716 if (retval
!= ERROR_OK
)
719 retval
= psoc5lp_spc_read_volatile_byte(target
,
720 SPC_ARRAY_NVL_USER
, i
, &val
);
721 if (retval
!= ERROR_OK
)
723 if (val
!= buffer
[i
]) {
724 LOG_ERROR("Failed to load NVL byte %" PRIu32
": "
725 "expected 0x%02" PRIx8
", read 0x%02" PRIx8
,
727 return ERROR_FLASH_OPERATION_FAILED
;
731 retval
= psoc5lp_spc_write_user_nvl(target
, SPC_ARRAY_NVL_USER
);
732 if (retval
!= ERROR_OK
)
736 retval
= target_call_reset_callbacks(target
, RESET_INIT
);
737 if (retval
!= ERROR_OK
)
738 LOG_WARNING("Reset failed after enabling or disabling ECC");
744 static int psoc5lp_nvl_get_info_command(struct flash_bank
*bank
,
745 struct command_invocation
*cmd
)
747 struct psoc5lp_nvl_flash_bank
*psoc_nvl_bank
= bank
->driver_priv
;
748 char part_number
[PART_NUMBER_LEN
];
750 psoc5lp_get_part_number(psoc_nvl_bank
->device
, part_number
);
752 command_print_sameline(cmd
, "%s", part_number
);
757 static int psoc5lp_nvl_probe(struct flash_bank
*bank
)
759 struct psoc5lp_nvl_flash_bank
*psoc_nvl_bank
= bank
->driver_priv
;
762 if (psoc_nvl_bank
->probed
)
765 if (bank
->target
->state
!= TARGET_HALTED
) {
766 LOG_ERROR("Target not halted");
767 return ERROR_TARGET_NOT_HALTED
;
770 retval
= psoc5lp_find_device(bank
->target
, &psoc_nvl_bank
->device
);
771 if (retval
!= ERROR_OK
)
774 bank
->base
= NVL_META_BASE
;
776 bank
->num_sectors
= 1;
777 bank
->sectors
= calloc(bank
->num_sectors
,
778 sizeof(struct flash_sector
));
779 bank
->sectors
[0].offset
= 0;
780 bank
->sectors
[0].size
= 4;
781 bank
->sectors
[0].is_erased
= -1;
782 bank
->sectors
[0].is_protected
= -1;
784 psoc_nvl_bank
->probed
= true;
789 static int psoc5lp_nvl_auto_probe(struct flash_bank
*bank
)
791 struct psoc5lp_nvl_flash_bank
*psoc_nvl_bank
= bank
->driver_priv
;
793 if (psoc_nvl_bank
->probed
)
796 return psoc5lp_nvl_probe(bank
);
799 FLASH_BANK_COMMAND_HANDLER(psoc5lp_nvl_flash_bank_command
)
801 struct psoc5lp_nvl_flash_bank
*psoc_nvl_bank
;
803 psoc_nvl_bank
= malloc(sizeof(struct psoc5lp_nvl_flash_bank
));
805 return ERROR_FLASH_OPERATION_FAILED
;
807 psoc_nvl_bank
->probed
= false;
809 bank
->driver_priv
= psoc_nvl_bank
;
814 const struct flash_driver psoc5lp_nvl_flash
= {
815 .name
= "psoc5lp_nvl",
816 .flash_bank_command
= psoc5lp_nvl_flash_bank_command
,
817 .info
= psoc5lp_nvl_get_info_command
,
818 .probe
= psoc5lp_nvl_probe
,
819 .auto_probe
= psoc5lp_nvl_auto_probe
,
820 .read
= psoc5lp_nvl_read
,
821 .erase
= psoc5lp_nvl_erase
,
822 .erase_check
= psoc5lp_nvl_erase_check
,
823 .write
= psoc5lp_nvl_write
,
824 .free_driver_priv
= default_flash_free_driver_priv
,
831 struct psoc5lp_eeprom_flash_bank
{
833 const struct psoc5lp_device
*device
;
836 static int psoc5lp_eeprom_erase(struct flash_bank
*bank
, unsigned int first
,
841 for (unsigned int i
= first
; i
<= last
; i
++) {
842 retval
= psoc5lp_spc_erase_sector(bank
->target
,
843 SPC_ARRAY_EEPROM
, i
);
844 if (retval
!= ERROR_OK
)
851 static int psoc5lp_eeprom_write(struct flash_bank
*bank
,
852 const uint8_t *buffer
, uint32_t offset
, uint32_t byte_count
)
854 struct target
*target
= bank
->target
;
859 if (offset
% EEPROM_ROW_SIZE
!= 0) {
860 LOG_ERROR("Writes must be row-aligned, got offset 0x%08" PRIx32
,
862 return ERROR_FLASH_DST_BREAKS_ALIGNMENT
;
865 retval
= psoc5lp_spc_get_temp(target
, 3, temp
);
866 if (retval
!= ERROR_OK
) {
867 LOG_ERROR("Unable to read Die temperature");
870 LOG_DEBUG("Get_Temp: sign 0x%02" PRIx8
", magnitude 0x%02" PRIx8
,
873 for (row
= offset
/ EEPROM_ROW_SIZE
; byte_count
>= EEPROM_ROW_SIZE
; row
++) {
874 retval
= psoc5lp_spc_load_row(target
, SPC_ARRAY_EEPROM
,
875 buffer
, EEPROM_ROW_SIZE
);
876 if (retval
!= ERROR_OK
)
879 retval
= psoc5lp_spc_write_row(target
, SPC_ARRAY_EEPROM
,
881 if (retval
!= ERROR_OK
)
884 buffer
+= EEPROM_ROW_SIZE
;
885 byte_count
-= EEPROM_ROW_SIZE
;
886 offset
+= EEPROM_ROW_SIZE
;
888 if (byte_count
> 0) {
889 uint8_t buf
[EEPROM_ROW_SIZE
];
891 memcpy(buf
, buffer
, byte_count
);
892 memset(buf
+ byte_count
, bank
->default_padded_value
,
893 EEPROM_ROW_SIZE
- byte_count
);
895 LOG_DEBUG("Padding %" PRIu32
" bytes", EEPROM_ROW_SIZE
- byte_count
);
896 retval
= psoc5lp_spc_load_row(target
, SPC_ARRAY_EEPROM
,
897 buf
, EEPROM_ROW_SIZE
);
898 if (retval
!= ERROR_OK
)
901 retval
= psoc5lp_spc_write_row(target
, SPC_ARRAY_EEPROM
,
903 if (retval
!= ERROR_OK
)
910 static int psoc5lp_eeprom_get_info_command(struct flash_bank
*bank
, struct command_invocation
*cmd
)
912 struct psoc5lp_eeprom_flash_bank
*psoc_eeprom_bank
= bank
->driver_priv
;
913 char part_number
[PART_NUMBER_LEN
];
915 psoc5lp_get_part_number(psoc_eeprom_bank
->device
, part_number
);
917 command_print_sameline(cmd
, "%s", part_number
);
922 static int psoc5lp_eeprom_probe(struct flash_bank
*bank
)
924 struct psoc5lp_eeprom_flash_bank
*psoc_eeprom_bank
= bank
->driver_priv
;
925 uint32_t flash_addr
= bank
->base
;
929 if (psoc_eeprom_bank
->probed
)
932 if (bank
->target
->state
!= TARGET_HALTED
) {
933 LOG_ERROR("Target not halted");
934 return ERROR_TARGET_NOT_HALTED
;
937 retval
= psoc5lp_find_device(bank
->target
, &psoc_eeprom_bank
->device
);
938 if (retval
!= ERROR_OK
)
941 retval
= target_read_u32(bank
->target
, PM_ACT_CFG12
, &val
);
942 if (retval
!= ERROR_OK
)
944 if (!(val
& PM_ACT_CFG12_EN_EE
)) {
945 val
|= PM_ACT_CFG12_EN_EE
;
946 retval
= target_write_u32(bank
->target
, PM_ACT_CFG12
, val
);
947 if (retval
!= ERROR_OK
)
951 bank
->size
= psoc_eeprom_bank
->device
->eeprom_kb
* 1024;
952 bank
->num_sectors
= DIV_ROUND_UP(bank
->size
, EEPROM_SECTOR_SIZE
);
953 bank
->sectors
= calloc(bank
->num_sectors
,
954 sizeof(struct flash_sector
));
955 for (unsigned int i
= 0; i
< bank
->num_sectors
; i
++) {
956 bank
->sectors
[i
].size
= EEPROM_SECTOR_SIZE
;
957 bank
->sectors
[i
].offset
= flash_addr
- bank
->base
;
958 bank
->sectors
[i
].is_erased
= -1;
959 bank
->sectors
[i
].is_protected
= -1;
961 flash_addr
+= bank
->sectors
[i
].size
;
964 bank
->default_padded_value
= bank
->erased_value
= 0x00;
966 psoc_eeprom_bank
->probed
= true;
971 static int psoc5lp_eeprom_auto_probe(struct flash_bank
*bank
)
973 struct psoc5lp_eeprom_flash_bank
*psoc_eeprom_bank
= bank
->driver_priv
;
975 if (psoc_eeprom_bank
->probed
)
978 return psoc5lp_eeprom_probe(bank
);
981 FLASH_BANK_COMMAND_HANDLER(psoc5lp_eeprom_flash_bank_command
)
983 struct psoc5lp_eeprom_flash_bank
*psoc_eeprom_bank
;
985 psoc_eeprom_bank
= malloc(sizeof(struct psoc5lp_eeprom_flash_bank
));
986 if (!psoc_eeprom_bank
)
987 return ERROR_FLASH_OPERATION_FAILED
;
989 psoc_eeprom_bank
->probed
= false;
990 psoc_eeprom_bank
->device
= NULL
;
992 bank
->driver_priv
= psoc_eeprom_bank
;
997 const struct flash_driver psoc5lp_eeprom_flash
= {
998 .name
= "psoc5lp_eeprom",
999 .flash_bank_command
= psoc5lp_eeprom_flash_bank_command
,
1000 .info
= psoc5lp_eeprom_get_info_command
,
1001 .probe
= psoc5lp_eeprom_probe
,
1002 .auto_probe
= psoc5lp_eeprom_auto_probe
,
1003 .read
= default_flash_read
,
1004 .erase
= psoc5lp_eeprom_erase
,
1005 .erase_check
= default_flash_blank_check
,
1006 .write
= psoc5lp_eeprom_write
,
1007 .free_driver_priv
= default_flash_free_driver_priv
,
1014 struct psoc5lp_flash_bank
{
1016 const struct psoc5lp_device
*device
;
1018 /* If ecc is disabled, num_sectors counts both std and ecc sectors.
1019 * If ecc is enabled, num_sectors indicates just the number of std sectors.
1020 * However ecc sector descriptors bank->sector[num_sectors..2*num_sectors-1]
1021 * are used for driver private flash operations */
1024 static int psoc5lp_erase(struct flash_bank
*bank
, unsigned int first
,
1027 struct psoc5lp_flash_bank
*psoc_bank
= bank
->driver_priv
;
1030 if (!psoc_bank
->ecc_enabled
) {
1031 /* Silently avoid erasing sectors twice */
1032 if (last
>= first
+ bank
->num_sectors
/ 2) {
1033 LOG_DEBUG("Skipping duplicate erase of sectors %u to %u",
1034 first
+ bank
->num_sectors
/ 2, last
);
1035 last
= first
+ (bank
->num_sectors
/ 2) - 1;
1037 /* Check for any remaining ECC sectors */
1038 if (last
>= bank
->num_sectors
/ 2) {
1039 LOG_WARNING("Skipping erase of ECC region sectors %u to %u",
1040 bank
->num_sectors
/ 2, last
);
1041 last
= (bank
->num_sectors
/ 2) - 1;
1045 for (unsigned int i
= first
; i
<= last
; i
++) {
1046 retval
= psoc5lp_spc_erase_sector(bank
->target
,
1047 i
/ SECTORS_PER_BLOCK
, i
% SECTORS_PER_BLOCK
);
1048 if (retval
!= ERROR_OK
)
1055 /* Derived from core.c:default_flash_blank_check() */
1056 static int psoc5lp_erase_check(struct flash_bank
*bank
)
1058 struct psoc5lp_flash_bank
*psoc_bank
= bank
->driver_priv
;
1059 struct target
*target
= bank
->target
;
1062 if (target
->state
!= TARGET_HALTED
) {
1063 LOG_ERROR("Target not halted");
1064 return ERROR_TARGET_NOT_HALTED
;
1067 unsigned int num_sectors
= bank
->num_sectors
;
1068 if (psoc_bank
->ecc_enabled
)
1069 num_sectors
*= 2; /* count both std and ecc sector always */
1071 struct target_memory_check_block
*block_array
;
1072 block_array
= malloc(num_sectors
* sizeof(struct target_memory_check_block
));
1076 for (unsigned int i
= 0; i
< num_sectors
; i
++) {
1077 block_array
[i
].address
= bank
->base
+ bank
->sectors
[i
].offset
;
1078 block_array
[i
].size
= bank
->sectors
[i
].size
;
1079 block_array
[i
].result
= UINT32_MAX
; /* erase state unknown */
1082 bool fast_check
= true;
1083 for (unsigned int i
= 0; i
< num_sectors
; ) {
1084 retval
= armv7m_blank_check_memory(target
,
1085 block_array
+ i
, num_sectors
- i
,
1086 bank
->erased_value
);
1088 /* Run slow fallback if the first run gives no result
1089 * otherwise use possibly incomplete results */
1094 i
+= retval
; /* add number of blocks done this round */
1098 if (psoc_bank
->ecc_enabled
) {
1099 for (unsigned int i
= 0; i
< bank
->num_sectors
; i
++)
1100 bank
->sectors
[i
].is_erased
=
1101 (block_array
[i
].result
!= 1)
1102 ? block_array
[i
].result
1103 : block_array
[i
+ bank
->num_sectors
].result
;
1104 /* if std sector is erased, use status of ecc sector */
1106 for (unsigned int i
= 0; i
< num_sectors
; i
++)
1107 bank
->sectors
[i
].is_erased
= block_array
[i
].result
;
1111 LOG_ERROR("Can't run erase check - add working memory");
1112 retval
= ERROR_FAIL
;
1119 static int psoc5lp_write(struct flash_bank
*bank
, const uint8_t *buffer
,
1120 uint32_t offset
, uint32_t byte_count
)
1122 struct psoc5lp_flash_bank
*psoc_bank
= bank
->driver_priv
;
1123 struct target
*target
= bank
->target
;
1124 struct working_area
*code_area
, *even_row_area
, *odd_row_area
;
1126 uint8_t temp
[2], buf
[12], ecc_bytes
[ROW_ECC_SIZE
];
1127 unsigned array_id
, row
;
1130 if (offset
+ byte_count
> bank
->size
) {
1131 LOG_ERROR("Writing to ECC not supported");
1132 return ERROR_FLASH_DST_OUT_OF_BANK
;
1135 if (offset
% ROW_SIZE
!= 0) {
1136 LOG_ERROR("Writes must be row-aligned, got offset 0x%08" PRIx32
,
1138 return ERROR_FLASH_DST_BREAKS_ALIGNMENT
;
1141 row_size
= ROW_SIZE
;
1142 if (!psoc_bank
->ecc_enabled
) {
1143 row_size
+= ROW_ECC_SIZE
;
1144 memset(ecc_bytes
, bank
->default_padded_value
, ROW_ECC_SIZE
);
1147 retval
= psoc5lp_spc_get_temp(target
, 3, temp
);
1148 if (retval
!= ERROR_OK
) {
1149 LOG_ERROR("Unable to read Die temperature");
1152 LOG_DEBUG("Get_Temp: sign 0x%02" PRIx8
", magnitude 0x%02" PRIx8
,
1155 assert(target_get_working_area_avail(target
) == target
->working_area_size
);
1156 retval
= target_alloc_working_area(target
,
1157 target_get_working_area_avail(target
) / 2, &code_area
);
1158 if (retval
!= ERROR_OK
) {
1159 LOG_ERROR("Could not allocate working area for program SRAM");
1162 assert(code_area
->address
< 0x20000000);
1164 retval
= target_alloc_working_area(target
,
1165 SPC_OPCODE_LEN
+ 1 + row_size
+ 3 + SPC_OPCODE_LEN
+ 6,
1167 if (retval
!= ERROR_OK
) {
1168 LOG_ERROR("Could not allocate working area for even row");
1169 goto err_alloc_even
;
1171 assert(even_row_area
->address
>= 0x20000000);
1173 retval
= target_alloc_working_area(target
, even_row_area
->size
,
1175 if (retval
!= ERROR_OK
) {
1176 LOG_ERROR("Could not allocate working area for odd row");
1179 assert(odd_row_area
->address
>= 0x20000000);
1181 for (array_id
= offset
/ BLOCK_SIZE
; byte_count
> 0; array_id
++) {
1182 for (row
= (offset
/ ROW_SIZE
) % ROWS_PER_BLOCK
;
1183 row
< ROWS_PER_BLOCK
&& byte_count
> 0; row
++) {
1184 bool even_row
= (row
% 2 == 0);
1185 struct working_area
*data_area
= even_row
? even_row_area
: odd_row_area
;
1186 unsigned len
= MIN(ROW_SIZE
, byte_count
);
1188 LOG_DEBUG("Writing load command for array %u row %u at " TARGET_ADDR_FMT
,
1189 array_id
, row
, data_area
->address
);
1191 psoc5lp_spc_write_opcode_buffer(target
, buf
, SPC_LOAD_ROW
);
1192 buf
[SPC_OPCODE_LEN
] = array_id
;
1193 retval
= target_write_buffer(target
, data_area
->address
, 4, buf
);
1194 if (retval
!= ERROR_OK
)
1197 retval
= target_write_buffer(target
,
1198 data_area
->address
+ SPC_OPCODE_LEN
+ 1,
1200 if (retval
!= ERROR_OK
)
1206 if (len
< ROW_SIZE
) {
1207 uint8_t padding
[ROW_SIZE
];
1209 memset(padding
, bank
->default_padded_value
, ROW_SIZE
);
1211 LOG_DEBUG("Padding %d bytes", ROW_SIZE
- len
);
1212 retval
= target_write_buffer(target
,
1213 data_area
->address
+ SPC_OPCODE_LEN
+ 1 + len
,
1214 ROW_SIZE
- len
, padding
);
1215 if (retval
!= ERROR_OK
)
1219 if (!psoc_bank
->ecc_enabled
) {
1220 retval
= target_write_buffer(target
,
1221 data_area
->address
+ SPC_OPCODE_LEN
+ 1 + ROW_SIZE
,
1222 sizeof(ecc_bytes
), ecc_bytes
);
1223 if (retval
!= ERROR_OK
)
1227 for (i
= 0; i
< 3; i
++)
1228 buf
[i
] = 0x00; /* 3 NOPs for short delay */
1229 psoc5lp_spc_write_opcode_buffer(target
, buf
+ 3, SPC_PRG_ROW
);
1230 buf
[3 + SPC_OPCODE_LEN
] = array_id
;
1231 buf
[3 + SPC_OPCODE_LEN
+ 1] = row
>> 8;
1232 buf
[3 + SPC_OPCODE_LEN
+ 2] = row
& 0xff;
1233 memcpy(buf
+ 3 + SPC_OPCODE_LEN
+ 3, temp
, 2);
1234 buf
[3 + SPC_OPCODE_LEN
+ 5] = 0x00; /* padding */
1235 retval
= target_write_buffer(target
,
1236 data_area
->address
+ SPC_OPCODE_LEN
+ 1 + row_size
,
1238 if (retval
!= ERROR_OK
)
1241 retval
= target_write_u32(target
,
1242 even_row
? PHUB_CH0_BASIC_STATUS
: PHUB_CH1_BASIC_STATUS
,
1243 (even_row
? 0 : 1) << 8);
1244 if (retval
!= ERROR_OK
)
1247 retval
= target_write_u32(target
,
1248 even_row
? PHUB_CH0_BASIC_CFG
: PHUB_CH1_BASIC_CFG
,
1249 PHUB_CHX_BASIC_CFG_WORK_SEP
| PHUB_CHX_BASIC_CFG_EN
);
1250 if (retval
!= ERROR_OK
)
1253 retval
= target_write_u32(target
,
1254 even_row
? PHUB_CFGMEM0_CFG0
: PHUB_CFGMEM1_CFG0
,
1256 if (retval
!= ERROR_OK
)
1259 retval
= target_write_u32(target
,
1260 even_row
? PHUB_CFGMEM0_CFG1
: PHUB_CFGMEM1_CFG1
,
1261 ((SPC_CPU_DATA
>> 16) << 16) | (data_area
->address
>> 16));
1262 if (retval
!= ERROR_OK
)
1265 retval
= target_write_u32(target
,
1266 even_row
? PHUB_TDMEM0_ORIG_TD0
: PHUB_TDMEM1_ORIG_TD0
,
1267 PHUB_TDMEMX_ORIG_TD0_INC_SRC_ADDR
|
1268 PHUB_TDMEMX_ORIG_TD0_NEXT_TD_PTR_LAST
|
1269 ((SPC_OPCODE_LEN
+ 1 + row_size
+ 3 + SPC_OPCODE_LEN
+ 5) & 0xfff));
1270 if (retval
!= ERROR_OK
)
1273 retval
= target_write_u32(target
,
1274 even_row
? PHUB_TDMEM0_ORIG_TD1
: PHUB_TDMEM1_ORIG_TD1
,
1275 ((SPC_CPU_DATA
& 0xffff) << 16) | (data_area
->address
& 0xffff));
1276 if (retval
!= ERROR_OK
)
1279 retval
= psoc5lp_spc_busy_wait_idle(target
);
1280 if (retval
!= ERROR_OK
)
1283 retval
= target_write_u32(target
,
1284 even_row
? PHUB_CH0_ACTION
: PHUB_CH1_ACTION
,
1285 PHUB_CHX_ACTION_CPU_REQ
);
1286 if (retval
!= ERROR_OK
)
1287 goto err_dma_action
;
1291 retval
= psoc5lp_spc_busy_wait_idle(target
);
1297 target_free_working_area(target
, odd_row_area
);
1299 target_free_working_area(target
, even_row_area
);
1301 target_free_working_area(target
, code_area
);
1306 static int psoc5lp_protect_check(struct flash_bank
*bank
)
1308 struct psoc5lp_flash_bank
*psoc_bank
= bank
->driver_priv
;
1309 uint8_t row_data
[ROW_SIZE
];
1310 const unsigned protection_bytes_per_sector
= ROWS_PER_SECTOR
* 2 / 8;
1311 unsigned i
, k
, num_sectors
;
1314 if (bank
->target
->state
!= TARGET_HALTED
) {
1315 LOG_ERROR("Target not halted");
1316 return ERROR_TARGET_NOT_HALTED
;
1319 for (i
= 0; i
< DIV_ROUND_UP(bank
->size
, BLOCK_SIZE
); i
++) {
1320 retval
= psoc5lp_spc_read_hidden_row(bank
->target
, i
,
1321 SPC_ROW_PROTECTION
, row_data
);
1322 if (retval
!= ERROR_OK
)
1325 /* Last flash array may have less rows, but in practice full sectors. */
1326 if (i
== bank
->size
/ BLOCK_SIZE
)
1327 num_sectors
= (bank
->size
% BLOCK_SIZE
) / SECTOR_SIZE
;
1329 num_sectors
= SECTORS_PER_BLOCK
;
1331 for (unsigned int j
= 0; j
< num_sectors
; j
++) {
1332 int sector_nr
= i
* SECTORS_PER_BLOCK
+ j
;
1333 struct flash_sector
*sector
= &bank
->sectors
[sector_nr
];
1334 struct flash_sector
*ecc_sector
;
1336 if (psoc_bank
->ecc_enabled
)
1337 ecc_sector
= &bank
->sectors
[bank
->num_sectors
+ sector_nr
];
1339 ecc_sector
= &bank
->sectors
[bank
->num_sectors
/ 2 + sector_nr
];
1341 sector
->is_protected
= ecc_sector
->is_protected
= 0;
1342 for (k
= protection_bytes_per_sector
* j
;
1343 k
< protection_bytes_per_sector
* (j
+ 1); k
++) {
1344 assert(k
< protection_bytes_per_sector
* SECTORS_PER_BLOCK
);
1345 LOG_DEBUG("row[%u][%02u] = 0x%02" PRIx8
, i
, k
, row_data
[k
]);
1346 if (row_data
[k
] != 0x00) {
1347 sector
->is_protected
= ecc_sector
->is_protected
= 1;
1357 static int psoc5lp_get_info_command(struct flash_bank
*bank
, struct command_invocation
*cmd
)
1359 struct psoc5lp_flash_bank
*psoc_bank
= bank
->driver_priv
;
1360 char part_number
[PART_NUMBER_LEN
];
1363 psoc5lp_get_part_number(psoc_bank
->device
, part_number
);
1364 ecc
= psoc_bank
->ecc_enabled
? "ECC enabled" : "ECC disabled";
1366 command_print_sameline(cmd
, "%s %s", part_number
, ecc
);
1371 static int psoc5lp_probe(struct flash_bank
*bank
)
1373 struct target
*target
= bank
->target
;
1374 struct psoc5lp_flash_bank
*psoc_bank
= bank
->driver_priv
;
1375 uint32_t flash_addr
= bank
->base
;
1376 uint8_t nvl
[4], temp
[2];
1379 if (target
->state
!= TARGET_HALTED
) {
1380 LOG_ERROR("Target not halted");
1381 return ERROR_TARGET_NOT_HALTED
;
1384 if (!psoc_bank
->device
) {
1385 retval
= psoc5lp_find_device(target
, &psoc_bank
->device
);
1386 if (retval
!= ERROR_OK
)
1389 bank
->size
= psoc_bank
->device
->flash_kb
* 1024;
1392 bank
->num_sectors
= DIV_ROUND_UP(bank
->size
, SECTOR_SIZE
);
1394 if (!psoc_bank
->probed
) {
1395 retval
= psoc5lp_spc_enable_clock(target
);
1396 if (retval
!= ERROR_OK
)
1399 /* First values read are inaccurate, so do it once now. */
1400 retval
= psoc5lp_spc_get_temp(target
, 3, temp
);
1401 if (retval
!= ERROR_OK
) {
1402 LOG_ERROR("Unable to read Die temperature");
1406 bank
->sectors
= calloc(bank
->num_sectors
* 2,
1407 sizeof(struct flash_sector
));
1408 for (unsigned int i
= 0; i
< bank
->num_sectors
; i
++) {
1409 bank
->sectors
[i
].size
= SECTOR_SIZE
;
1410 bank
->sectors
[i
].offset
= flash_addr
- bank
->base
;
1411 bank
->sectors
[i
].is_erased
= -1;
1412 bank
->sectors
[i
].is_protected
= -1;
1414 flash_addr
+= bank
->sectors
[i
].size
;
1416 flash_addr
= 0x48000000;
1417 for (unsigned int i
= bank
->num_sectors
; i
< bank
->num_sectors
* 2; i
++) {
1418 bank
->sectors
[i
].size
= ROWS_PER_SECTOR
* ROW_ECC_SIZE
;
1419 bank
->sectors
[i
].offset
= flash_addr
- bank
->base
;
1420 bank
->sectors
[i
].is_erased
= -1;
1421 bank
->sectors
[i
].is_protected
= -1;
1423 flash_addr
+= bank
->sectors
[i
].size
;
1426 bank
->default_padded_value
= bank
->erased_value
= 0x00;
1428 psoc_bank
->probed
= true;
1431 retval
= psoc5lp_spc_read_byte(target
, SPC_ARRAY_NVL_USER
, 3, &nvl
[3]);
1432 if (retval
!= ERROR_OK
)
1434 LOG_DEBUG("NVL[%d] = 0x%02" PRIx8
, 3, nvl
[3]);
1435 psoc_bank
->ecc_enabled
= nvl
[3] & NVL_3_ECCEN
;
1437 if (!psoc_bank
->ecc_enabled
)
1438 bank
->num_sectors
*= 2;
1443 static int psoc5lp_auto_probe(struct flash_bank
*bank
)
1445 return psoc5lp_probe(bank
);
1448 COMMAND_HANDLER(psoc5lp_handle_mass_erase_command
)
1450 struct flash_bank
*bank
;
1454 return ERROR_COMMAND_SYNTAX_ERROR
;
1456 retval
= CALL_COMMAND_HANDLER(flash_command_get_bank
, 0, &bank
);
1457 if (retval
!= ERROR_OK
)
1460 retval
= psoc5lp_spc_erase_all(bank
->target
);
1461 if (retval
== ERROR_OK
)
1462 command_print(CMD
, "PSoC 5LP erase succeeded");
1464 command_print(CMD
, "PSoC 5LP erase failed");
1469 FLASH_BANK_COMMAND_HANDLER(psoc5lp_flash_bank_command
)
1471 struct psoc5lp_flash_bank
*psoc_bank
;
1473 psoc_bank
= malloc(sizeof(struct psoc5lp_flash_bank
));
1475 return ERROR_FLASH_OPERATION_FAILED
;
1477 psoc_bank
->probed
= false;
1478 psoc_bank
->device
= NULL
;
1480 bank
->driver_priv
= psoc_bank
;
1485 static const struct command_registration psoc5lp_exec_command_handlers
[] = {
1487 .name
= "mass_erase",
1488 .handler
= psoc5lp_handle_mass_erase_command
,
1489 .mode
= COMMAND_EXEC
,
1491 .help
= "Erase all flash data and ECC/configuration bytes, "
1492 "all flash protection rows, "
1493 "and all row latches in all flash arrays on the device.",
1495 COMMAND_REGISTRATION_DONE
1498 static const struct command_registration psoc5lp_command_handlers
[] = {
1501 .mode
= COMMAND_ANY
,
1502 .help
= "PSoC 5LP flash command group",
1504 .chain
= psoc5lp_exec_command_handlers
,
1506 COMMAND_REGISTRATION_DONE
1509 const struct flash_driver psoc5lp_flash
= {
1511 .commands
= psoc5lp_command_handlers
,
1512 .flash_bank_command
= psoc5lp_flash_bank_command
,
1513 .info
= psoc5lp_get_info_command
,
1514 .probe
= psoc5lp_probe
,
1515 .auto_probe
= psoc5lp_auto_probe
,
1516 .protect_check
= psoc5lp_protect_check
,
1517 .read
= default_flash_read
,
1518 .erase
= psoc5lp_erase
,
1519 .erase_check
= psoc5lp_erase_check
,
1520 .write
= psoc5lp_write
,
1521 .free_driver_priv
= default_flash_free_driver_priv
,
Linking to existing account procedure
If you already have an account and want to add another login method
you
MUST first sign in with your existing account and
then change URL to read
https://review.openocd.org/login/?link
to get to this page again but this time it'll work for linking. Thank you.
SSH host keys fingerprints
1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=.. |
|+o.. . |
|*.o . . |
|+B . . . |
|Bo. = o S |
|Oo.+ + = |
|oB=.* = . o |
| =+=.+ + E |
|. .=o . o |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)