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