]> git.sur5r.net Git - openocd/blob - src/flash/nor/psoc5lp.c
flash/nor/psoc5lp: fix bad commit 2d5f2ede55150235352773a976166c3ab68297bc
[openocd] / src / flash / nor / psoc5lp.c
1 /*
2  * PSoC 5LP flash driver
3  *
4  * Copyright (c) 2016 Andreas Färber
5  *
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.
10  *
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.
15  *
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/>.
18  */
19
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23
24 #include "imp.h"
25 #include <helper/time_support.h>
26 #include <target/armv7m.h>
27
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
47
48 #define PM_ACT_CFG12_EN_EE (1 << 4)
49
50 #define SPC_KEY1 0xB6
51 #define SPC_KEY2 0xD3
52
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
68
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
73
74 #define SPC_ROW_PROTECTION 0
75
76 #define SPC_OPCODE_LEN 3
77
78 #define SPC_SR_DATA_READY (1 << 0)
79 #define SPC_SR_IDLE       (1 << 1)
80
81 #define PM_ACT_CFG0_EN_CLK_SPC      (1 << 3)
82
83 #define PHUB_CHx_BASIC_CFG_EN       (1 << 0)
84 #define PHUB_CHx_BASIC_CFG_WORK_SEP (1 << 5)
85
86 #define PHUB_CHx_ACTION_CPU_REQ (1 << 0)
87
88 #define PHUB_CFGMEMx_CFG0 (1 << 7)
89
90 #define PHUB_TDMEMx_ORIG_TD0_NEXT_TD_PTR_LAST (0xff << 16)
91 #define PHUB_TDMEMx_ORIG_TD0_INC_SRC_ADDR     (1 << 24)
92
93 #define NVL_3_ECCEN  (1 << 3)
94
95 #define ROW_SIZE           256
96 #define ROW_ECC_SIZE       32
97 #define ROWS_PER_SECTOR    64
98 #define SECTOR_SIZE        (ROWS_PER_SECTOR * ROW_SIZE)
99 #define ROWS_PER_BLOCK     256
100 #define BLOCK_SIZE         (ROWS_PER_BLOCK * ROW_SIZE)
101 #define SECTORS_PER_BLOCK  (BLOCK_SIZE / SECTOR_SIZE)
102 #define EEPROM_ROW_SIZE    16
103 #define EEPROM_SECTOR_SIZE (ROWS_PER_SECTOR * EEPROM_ROW_SIZE)
104 #define EEPROM_BLOCK_SIZE  (ROWS_PER_BLOCK * EEPROM_ROW_SIZE)
105
106 #define PART_NUMBER_LEN (17 + 1)
107
108 struct psoc5lp_device {
109         uint32_t id;
110         unsigned fam;
111         unsigned speed_mhz;
112         unsigned flash_kb;
113         unsigned eeprom_kb;
114 };
115
116 /*
117  * Device information collected from datasheets.
118  * Different temperature ranges (C/I/Q/A) may share IDs, not differing otherwise.
119  */
120 static const struct psoc5lp_device psoc5lp_devices[] = {
121         /* CY8C58LP Family Datasheet */
122         { .id = 0x2E11F069, .fam = 8, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 },
123         { .id = 0x2E120069, .fam = 8, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 },
124         { .id = 0x2E123069, .fam = 8, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 },
125         { .id = 0x2E124069, .fam = 8, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 },
126         { .id = 0x2E126069, .fam = 8, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 },
127         { .id = 0x2E127069, .fam = 8, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 },
128         { .id = 0x2E117069, .fam = 8, .speed_mhz = 67, .flash_kb = 128, .eeprom_kb = 2 },
129         { .id = 0x2E118069, .fam = 8, .speed_mhz = 67, .flash_kb = 128, .eeprom_kb = 2 },
130         { .id = 0x2E119069, .fam = 8, .speed_mhz = 67, .flash_kb = 128, .eeprom_kb = 2 },
131         { .id = 0x2E11C069, .fam = 8, .speed_mhz = 67, .flash_kb = 128, .eeprom_kb = 2 },
132         { .id = 0x2E114069, .fam = 8, .speed_mhz = 67, .flash_kb =  64, .eeprom_kb = 2 },
133         { .id = 0x2E115069, .fam = 8, .speed_mhz = 67, .flash_kb =  64, .eeprom_kb = 2 },
134         { .id = 0x2E116069, .fam = 8, .speed_mhz = 67, .flash_kb =  64, .eeprom_kb = 2 },
135         { .id = 0x2E160069, .fam = 8, .speed_mhz = 80, .flash_kb = 256, .eeprom_kb = 2 },
136         /*           ''                                                               */
137         { .id = 0x2E161069, .fam = 8, .speed_mhz = 80, .flash_kb = 256, .eeprom_kb = 2 },
138         /*           ''                                                               */
139         { .id = 0x2E1D2069, .fam = 8, .speed_mhz = 80, .flash_kb = 256, .eeprom_kb = 2 },
140         { .id = 0x2E1D6069, .fam = 8, .speed_mhz = 80, .flash_kb = 256, .eeprom_kb = 2 },
141
142         /* CY8C56LP Family Datasheet */
143         { .id = 0x2E10A069, .fam = 6, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 },
144         { .id = 0x2E10D069, .fam = 6, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 },
145         { .id = 0x2E10E069, .fam = 6, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 },
146         { .id = 0x2E106069, .fam = 6, .speed_mhz = 67, .flash_kb = 128, .eeprom_kb = 2 },
147         { .id = 0x2E108069, .fam = 6, .speed_mhz = 67, .flash_kb = 128, .eeprom_kb = 2 },
148         { .id = 0x2E109069, .fam = 6, .speed_mhz = 67, .flash_kb = 128, .eeprom_kb = 2 },
149         { .id = 0x2E101069, .fam = 6, .speed_mhz = 67, .flash_kb =  64, .eeprom_kb = 2 },
150         { .id = 0x2E104069, .fam = 6, .speed_mhz = 67, .flash_kb =  64, .eeprom_kb = 2 },
151         /*           ''                                                               */
152         { .id = 0x2E105069, .fam = 6, .speed_mhz = 67, .flash_kb =  64, .eeprom_kb = 2 },
153         { .id = 0x2E128069, .fam = 6, .speed_mhz = 67, .flash_kb = 128, .eeprom_kb = 2 },
154         /*           ''                                                               */
155         { .id = 0x2E122069, .fam = 6, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 },
156         { .id = 0x2E129069, .fam = 6, .speed_mhz = 67, .flash_kb = 128, .eeprom_kb = 2 },
157         { .id = 0x2E163069, .fam = 6, .speed_mhz = 80, .flash_kb = 256, .eeprom_kb = 2 },
158         { .id = 0x2E156069, .fam = 6, .speed_mhz = 80, .flash_kb = 256, .eeprom_kb = 2 },
159         { .id = 0x2E1D3069, .fam = 6, .speed_mhz = 80, .flash_kb = 256, .eeprom_kb = 2 },
160
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 },
176
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 },
193 };
194
195 static void psoc5lp_get_part_number(const struct psoc5lp_device *dev, char *str)
196 {
197         strcpy(str, "CY8Cabcdefg-LPxxx");
198
199         str[4] = '5';
200         str[5] = '0' + dev->fam;
201
202         switch (dev->speed_mhz) {
203         case 67:
204                 str[6] = '6';
205                 break;
206         case 80:
207                 str[6] = '8';
208                 break;
209         default:
210                 str[6] = '?';
211         }
212
213         switch (dev->flash_kb) {
214         case 32:
215                 str[7] = '5';
216                 break;
217         case 64:
218                 str[7] = '6';
219                 break;
220         case 128:
221                 str[7] = '7';
222                 break;
223         case 256:
224                 str[7] = '8';
225                 break;
226         default:
227                 str[7] = '?';
228         }
229
230         /* Package does not matter. */
231         strncpy(str + 8, "xx", 2);
232
233         /* Temperate range cannot uniquely be identified. */
234         str[10] = 'x';
235 }
236
237 static int psoc5lp_get_device_id(struct target *target, uint32_t *id)
238 {
239         int retval;
240
241         retval = target_read_u32(target, PANTHER_DEVICE_ID, id); /* dummy read */
242         if (retval != ERROR_OK)
243                 return retval;
244         retval = target_read_u32(target, PANTHER_DEVICE_ID, id);
245         return retval;
246 }
247
248 static int psoc5lp_find_device(struct target *target,
249         const struct psoc5lp_device **device)
250 {
251         uint32_t device_id;
252         unsigned i;
253         int retval;
254
255         *device = NULL;
256
257         retval = psoc5lp_get_device_id(target, &device_id);
258         if (retval != ERROR_OK)
259                 return retval;
260         LOG_DEBUG("PANTHER_DEVICE_ID = 0x%08" PRIX32, device_id);
261
262         for (i = 0; i < ARRAY_SIZE(psoc5lp_devices); i++) {
263                 if (psoc5lp_devices[i].id == device_id) {
264                         *device = &psoc5lp_devices[i];
265                         return ERROR_OK;
266                 }
267         }
268
269         LOG_ERROR("Device 0x%08" PRIX32 " not supported", device_id);
270         return ERROR_FLASH_OPER_UNSUPPORTED;
271 }
272
273 static int psoc5lp_spc_enable_clock(struct target *target)
274 {
275         int retval;
276         uint8_t pm_act_cfg0;
277
278         retval = target_read_u8(target, PM_ACT_CFG0, &pm_act_cfg0);
279         if (retval != ERROR_OK) {
280                 LOG_ERROR("Cannot read PM_ACT_CFG0");
281                 return retval;
282         }
283
284         if (pm_act_cfg0 & PM_ACT_CFG0_EN_CLK_SPC)
285                 return ERROR_OK;        /* clock already enabled */
286
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");
290
291         return retval;
292 }
293
294 static int psoc5lp_spc_write_opcode(struct target *target, uint8_t opcode)
295 {
296         int retval;
297
298         retval = target_write_u8(target, SPC_CPU_DATA, SPC_KEY1);
299         if (retval != ERROR_OK)
300                 return retval;
301         retval = target_write_u8(target, SPC_CPU_DATA, SPC_KEY2 + opcode);
302         if (retval != ERROR_OK)
303                 return retval;
304         retval = target_write_u8(target, SPC_CPU_DATA, opcode);
305         return retval;
306 }
307
308 static void psoc5lp_spc_write_opcode_buffer(struct target *target,
309         uint8_t *buf, uint8_t opcode)
310 {
311         buf[0] = SPC_KEY1;
312         buf[1] = SPC_KEY2 + opcode;
313         buf[2] = opcode;
314 }
315
316 static int psoc5lp_spc_busy_wait_data(struct target *target)
317 {
318         int64_t endtime;
319         uint8_t sr;
320         int retval;
321
322         retval = target_read_u8(target, SPC_SR, &sr); /* dummy read */
323         if (retval != ERROR_OK)
324                 return retval;
325
326         endtime = timeval_ms() + 1000; /* 1 second timeout */
327         do {
328                 alive_sleep(1);
329                 retval = target_read_u8(target, SPC_SR, &sr);
330                 if (retval != ERROR_OK)
331                         return retval;
332                 if (sr == SPC_SR_DATA_READY)
333                         return ERROR_OK;
334         } while (timeval_ms() < endtime);
335
336         return ERROR_FLASH_OPERATION_FAILED;
337 }
338
339 static int psoc5lp_spc_busy_wait_idle(struct target *target)
340 {
341         int64_t endtime;
342         uint8_t sr;
343         int retval;
344
345         retval = target_read_u8(target, SPC_SR, &sr); /* dummy read */
346         if (retval != ERROR_OK)
347                 return retval;
348
349         endtime = timeval_ms() + 1000; /* 1 second timeout */
350         do {
351                 alive_sleep(1);
352                 retval = target_read_u8(target, SPC_SR, &sr);
353                 if (retval != ERROR_OK)
354                         return retval;
355                 if (sr == SPC_SR_IDLE)
356                         return ERROR_OK;
357         } while (timeval_ms() < endtime);
358
359         return ERROR_FLASH_OPERATION_FAILED;
360 }
361
362 static int psoc5lp_spc_load_row(struct target *target,
363         uint8_t array_id, const uint8_t *data, unsigned row_size)
364 {
365         unsigned i;
366         int retval;
367
368         retval = psoc5lp_spc_write_opcode(target, SPC_LOAD_ROW);
369         if (retval != ERROR_OK)
370                 return retval;
371         retval = target_write_u8(target, SPC_CPU_DATA, array_id);
372         if (retval != ERROR_OK)
373                 return retval;
374
375         for (i = 0; i < row_size; i++) {
376                 retval = target_write_u8(target, SPC_CPU_DATA, data[i]);
377                 if (retval != ERROR_OK)
378                         return retval;
379         }
380
381         retval = psoc5lp_spc_busy_wait_idle(target);
382         if (retval != ERROR_OK)
383                 return retval;
384
385         return ERROR_OK;
386 }
387
388 static int psoc5lp_spc_read_byte(struct target *target,
389         uint8_t array_id, uint8_t offset, uint8_t *data)
390 {
391         int retval;
392
393         retval = psoc5lp_spc_write_opcode(target, SPC_READ_BYTE);
394         if (retval != ERROR_OK)
395                 return retval;
396         retval = target_write_u8(target, SPC_CPU_DATA, array_id);
397         if (retval != ERROR_OK)
398                 return retval;
399         retval = target_write_u8(target, SPC_CPU_DATA, offset);
400         if (retval != ERROR_OK)
401                 return retval;
402
403         retval = psoc5lp_spc_busy_wait_data(target);
404         if (retval != ERROR_OK)
405                 return retval;
406
407         retval = target_read_u8(target, SPC_CPU_DATA, data);
408         if (retval != ERROR_OK)
409                 return retval;
410
411         retval = psoc5lp_spc_busy_wait_idle(target);
412         if (retval != ERROR_OK)
413                 return retval;
414
415         return ERROR_OK;
416 }
417
418 static int psoc5lp_spc_write_row(struct target *target,
419         uint8_t array_id, uint16_t row_id, const uint8_t *temp)
420 {
421         int retval;
422
423         retval = psoc5lp_spc_write_opcode(target, SPC_WRITE_ROW);
424         if (retval != ERROR_OK)
425                 return retval;
426         retval = target_write_u8(target, SPC_CPU_DATA, array_id);
427         if (retval != ERROR_OK)
428                 return retval;
429         retval = target_write_u8(target, SPC_CPU_DATA, row_id >> 8);
430         if (retval != ERROR_OK)
431                 return retval;
432         retval = target_write_u8(target, SPC_CPU_DATA, row_id & 0xff);
433         if (retval != ERROR_OK)
434                 return retval;
435         retval = target_write_u8(target, SPC_CPU_DATA, temp[0]);
436         if (retval != ERROR_OK)
437                 return retval;
438         retval = target_write_u8(target, SPC_CPU_DATA, temp[1]);
439         if (retval != ERROR_OK)
440                 return retval;
441
442         retval = psoc5lp_spc_busy_wait_idle(target);
443         if (retval != ERROR_OK)
444                 return retval;
445
446         return ERROR_OK;
447 }
448
449 static int psoc5lp_spc_erase_sector(struct target *target,
450         uint8_t array_id, uint8_t row_id)
451 {
452         int retval;
453
454         retval = psoc5lp_spc_write_opcode(target, SPC_ERASE_SECTOR);
455         if (retval != ERROR_OK)
456                 return retval;
457         retval = target_write_u8(target, SPC_CPU_DATA, array_id);
458         if (retval != ERROR_OK)
459                 return retval;
460         retval = target_write_u8(target, SPC_CPU_DATA, row_id);
461         if (retval != ERROR_OK)
462                 return retval;
463
464         retval = psoc5lp_spc_busy_wait_idle(target);
465         if (retval != ERROR_OK)
466                 return retval;
467
468         return ERROR_OK;
469 }
470
471 static int psoc5lp_spc_erase_all(struct target *target)
472 {
473         int retval;
474
475         retval = psoc5lp_spc_write_opcode(target, SPC_ERASE_ALL);
476         if (retval != ERROR_OK)
477                 return retval;
478
479         retval = psoc5lp_spc_busy_wait_idle(target);
480         if (retval != ERROR_OK)
481                 return retval;
482
483         return ERROR_OK;
484 }
485
486 static int psoc5lp_spc_read_hidden_row(struct target *target,
487         uint8_t array_id, uint8_t row_id, uint8_t *data)
488 {
489         int i, retval;
490
491         retval = psoc5lp_spc_write_opcode(target, SPC_READ_HIDDEN_ROW);
492         if (retval != ERROR_OK)
493                 return retval;
494         retval = target_write_u8(target, SPC_CPU_DATA, array_id);
495         if (retval != ERROR_OK)
496                 return retval;
497         retval = target_write_u8(target, SPC_CPU_DATA, row_id);
498         if (retval != ERROR_OK)
499                 return retval;
500
501         retval = psoc5lp_spc_busy_wait_data(target);
502         if (retval != ERROR_OK)
503                 return retval;
504
505         for (i = 0; i < ROW_SIZE; i++) {
506                 retval = target_read_u8(target, SPC_CPU_DATA, &data[i]);
507                 if (retval != ERROR_OK)
508                         return retval;
509         }
510
511         retval = psoc5lp_spc_busy_wait_idle(target);
512         if (retval != ERROR_OK)
513                 return retval;
514
515         return ERROR_OK;
516 }
517
518 static int psoc5lp_spc_get_temp(struct target *target, uint8_t samples,
519         uint8_t *data)
520 {
521         int retval;
522
523         retval = psoc5lp_spc_write_opcode(target, SPC_GET_TEMP);
524         if (retval != ERROR_OK)
525                 return retval;
526         retval = target_write_u8(target, SPC_CPU_DATA, samples);
527         if (retval != ERROR_OK)
528                 return retval;
529
530         retval = psoc5lp_spc_busy_wait_data(target);
531         if (retval != ERROR_OK)
532                 return retval;
533
534         retval = target_read_u8(target, SPC_CPU_DATA, &data[0]);
535         if (retval != ERROR_OK)
536                 return retval;
537         retval = target_read_u8(target, SPC_CPU_DATA, &data[1]);
538         if (retval != ERROR_OK)
539                 return retval;
540
541         retval = psoc5lp_spc_busy_wait_idle(target);
542         if (retval != ERROR_OK)
543                 return retval;
544
545         return ERROR_OK;
546 }
547
548 /*
549  * EEPROM
550  */
551
552 struct psoc5lp_eeprom_flash_bank {
553         bool probed;
554         const struct psoc5lp_device *device;
555 };
556
557 static int psoc5lp_eeprom_erase(struct flash_bank *bank, int first, int last)
558 {
559         int i, retval;
560
561         for (i = first; i <= last; i++) {
562                 retval = psoc5lp_spc_erase_sector(bank->target,
563                                 SPC_ARRAY_EEPROM, i);
564                 if (retval != ERROR_OK)
565                         return retval;
566         }
567
568         return ERROR_OK;
569 }
570
571 static int psoc5lp_eeprom_write(struct flash_bank *bank,
572         const uint8_t *buffer, uint32_t offset, uint32_t byte_count)
573 {
574         struct target *target = bank->target;
575         uint8_t temp[2];
576         unsigned row;
577         int retval;
578
579         if (offset % EEPROM_ROW_SIZE != 0) {
580                 LOG_ERROR("Writes must be row-aligned, got offset 0x%08" PRIx32,
581                         offset);
582                 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
583         }
584
585         retval = psoc5lp_spc_get_temp(target, 3, temp);
586         if (retval != ERROR_OK) {
587                 LOG_ERROR("Unable to read Die temperature");
588                 return retval;
589         }
590         LOG_DEBUG("Get_Temp: sign 0x%02" PRIx8 ", magnitude 0x%02" PRIx8,
591                 temp[0], temp[1]);
592
593         for (row = offset / EEPROM_ROW_SIZE; byte_count >= EEPROM_ROW_SIZE; row++) {
594                 retval = psoc5lp_spc_load_row(target, SPC_ARRAY_EEPROM,
595                                 buffer, EEPROM_ROW_SIZE);
596                 if (retval != ERROR_OK)
597                         return retval;
598
599                 retval = psoc5lp_spc_write_row(target, SPC_ARRAY_EEPROM,
600                                 row, temp);
601                 if (retval != ERROR_OK)
602                         return retval;
603
604                 buffer += EEPROM_ROW_SIZE;
605                 byte_count -= EEPROM_ROW_SIZE;
606                 offset += EEPROM_ROW_SIZE;
607         }
608         if (byte_count > 0) {
609                 uint8_t buf[EEPROM_ROW_SIZE];
610
611                 memcpy(buf, buffer, byte_count);
612                 memset(buf + byte_count, bank->default_padded_value,
613                                 EEPROM_ROW_SIZE - byte_count);
614
615                 LOG_DEBUG("Padding %d bytes", EEPROM_ROW_SIZE - byte_count);
616                 retval = psoc5lp_spc_load_row(target, SPC_ARRAY_EEPROM,
617                                 buf, EEPROM_ROW_SIZE);
618                 if (retval != ERROR_OK)
619                         return retval;
620
621                 retval = psoc5lp_spc_write_row(target, SPC_ARRAY_EEPROM,
622                                 row, temp);
623                 if (retval != ERROR_OK)
624                         return retval;
625         }
626
627         return ERROR_OK;
628 }
629
630 static int psoc5lp_eeprom_protect_check(struct flash_bank *bank)
631 {
632         int i;
633
634         for (i = 0; i < bank->num_sectors; i++)
635                 bank->sectors[i].is_protected = -1;
636
637         return ERROR_OK;
638 }
639
640 static int psoc5lp_eeprom_get_info_command(struct flash_bank *bank, char *buf, int buf_size)
641 {
642         struct psoc5lp_eeprom_flash_bank *psoc_eeprom_bank = bank->driver_priv;
643         char part_number[PART_NUMBER_LEN];
644
645         psoc5lp_get_part_number(psoc_eeprom_bank->device, part_number);
646
647         snprintf(buf, buf_size, "%s", part_number);
648
649         return ERROR_OK;
650 }
651
652 static int psoc5lp_eeprom_probe(struct flash_bank *bank)
653 {
654         struct psoc5lp_eeprom_flash_bank *psoc_eeprom_bank = bank->driver_priv;
655         uint32_t flash_addr = bank->base;
656         uint32_t val;
657         int i, retval;
658
659         if (psoc_eeprom_bank->probed)
660                 return ERROR_OK;
661
662         if (bank->target->state != TARGET_HALTED) {
663                 LOG_ERROR("Target not halted");
664                 return ERROR_TARGET_NOT_HALTED;
665         }
666
667         retval = psoc5lp_find_device(bank->target, &psoc_eeprom_bank->device);
668         if (retval != ERROR_OK)
669                 return retval;
670
671         retval = target_read_u32(bank->target, PM_ACT_CFG12, &val);
672         if (retval != ERROR_OK)
673                 return retval;
674         if (!(val & PM_ACT_CFG12_EN_EE)) {
675                 val |= PM_ACT_CFG12_EN_EE;
676                 retval = target_write_u32(bank->target, PM_ACT_CFG12, val);
677                 if (retval != ERROR_OK)
678                         return retval;
679         }
680
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;
690
691                 flash_addr += bank->sectors[i].size;
692         }
693
694         bank->default_padded_value = bank->erased_value = 0x00;
695
696         psoc_eeprom_bank->probed = true;
697
698         return ERROR_OK;
699 }
700
701 static int psoc5lp_eeprom_auto_probe(struct flash_bank *bank)
702 {
703         struct psoc5lp_eeprom_flash_bank *psoc_eeprom_bank = bank->driver_priv;
704
705         if (psoc_eeprom_bank->probed)
706                 return ERROR_OK;
707
708         return psoc5lp_eeprom_probe(bank);
709 }
710
711 FLASH_BANK_COMMAND_HANDLER(psoc5lp_eeprom_flash_bank_command)
712 {
713         struct psoc5lp_eeprom_flash_bank *psoc_eeprom_bank;
714
715         psoc_eeprom_bank = malloc(sizeof(struct psoc5lp_eeprom_flash_bank));
716         if (!psoc_eeprom_bank)
717                 return ERROR_FLASH_OPERATION_FAILED;
718
719         psoc_eeprom_bank->probed = false;
720         psoc_eeprom_bank->device = NULL;
721
722         bank->driver_priv = psoc_eeprom_bank;
723
724         return ERROR_OK;
725 }
726
727 static const struct command_registration psoc5lp_eeprom_exec_command_handlers[] = {
728         COMMAND_REGISTRATION_DONE
729 };
730
731 static const struct command_registration psoc5lp_eeprom_command_handlers[] = {
732         {
733                 .name = "psoc5lp_eeprom",
734                 .mode = COMMAND_ANY,
735                 .help = "PSoC 5LP EEPROM command group",
736                 .usage = "",
737                 .chain = psoc5lp_eeprom_exec_command_handlers,
738         },
739         COMMAND_REGISTRATION_DONE
740 };
741
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,
754 };
755
756 /*
757  * Program Flash
758  */
759
760 struct psoc5lp_flash_bank {
761         bool probed;
762         const struct psoc5lp_device *device;
763         bool ecc_enabled;
764 };
765
766 static int psoc5lp_erase(struct flash_bank *bank, int first, int last)
767 {
768         struct psoc5lp_flash_bank *psoc_bank = bank->driver_priv;
769         int i, retval;
770
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;
777                 }
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;
783                 }
784         }
785
786         for (i = first; i <= last; i++) {
787                 retval = psoc5lp_spc_erase_sector(bank->target,
788                                 i / SECTORS_PER_BLOCK, i % SECTORS_PER_BLOCK);
789                 if (retval != ERROR_OK)
790                         return retval;
791         }
792
793         return ERROR_OK;
794 }
795
796 /* Derived from core.c:default_flash_blank_check() */
797 static int psoc5lp_erase_check(struct flash_bank *bank)
798 {
799         struct psoc5lp_flash_bank *psoc_bank = bank->driver_priv;
800         struct target *target = bank->target;
801         int i, retval;
802
803         if (target->state != TARGET_HALTED) {
804                 LOG_ERROR("Target not halted");
805                 return ERROR_TARGET_NOT_HALTED;
806         }
807
808         struct target_memory_check_block *block_array;
809         block_array = malloc(bank->num_sectors * sizeof(struct target_memory_check_block));
810         if (block_array == NULL)
811                 return ERROR_FAIL;
812
813         for (i = 0; i < bank->num_sectors; i++) {
814                 block_array[i].address = bank->base + bank->sectors[i].offset;
815                 block_array[i].size = bank->sectors[i].size;
816                 block_array[i].result = UINT32_MAX; /* erase state unknown */
817         }
818
819         bool fast_check = true;
820         for (i = 0; i < bank->num_sectors; ) {
821                 retval = armv7m_blank_check_memory(target,
822                                         block_array + i, bank->num_sectors - i,
823                                         bank->erased_value);
824                 if (retval < 1) {
825                         /* Run slow fallback if the first run gives no result
826                          * otherwise use possibly incomplete results */
827                         if (i == 0)
828                                 fast_check = false;
829                         break;
830                 }
831                 i += retval; /* add number of blocks done this round */
832         }
833
834         if (fast_check) {
835                 if (!psoc_bank->ecc_enabled) {
836                         int half_sectors = bank->num_sectors / 2;
837                         for (i = 0; i < half_sectors / 2; i++)
838                                 bank->sectors[i].is_erased =
839                                         (block_array[i].result != 1)
840                                         ? block_array[i + half_sectors].result
841                                         : block_array[i].result;
842                 } else {
843                         for (i = 0; i < bank->num_sectors; i++)
844                                 bank->sectors[i].is_erased = block_array[i].result;
845                 }
846                 retval = ERROR_OK;
847         } else {
848                 LOG_ERROR("Can't run erase check - add working memory");
849                 retval = ERROR_FAIL;
850         }
851         free(block_array);
852
853         return retval;
854 }
855
856 static int psoc5lp_write(struct flash_bank *bank, const uint8_t *buffer,
857                 uint32_t offset, uint32_t byte_count)
858 {
859         struct psoc5lp_flash_bank *psoc_bank = bank->driver_priv;
860         struct target *target = bank->target;
861         struct working_area *code_area, *even_row_area, *odd_row_area;
862         uint32_t row_size;
863         uint8_t temp[2], buf[12], ecc_bytes[ROW_ECC_SIZE];
864         unsigned array_id, row;
865         int i, retval;
866
867         if (offset + byte_count > bank->size) {
868                 LOG_ERROR("Writing to ECC not supported");
869                 return ERROR_FLASH_DST_OUT_OF_BANK;
870         }
871
872         if (offset % ROW_SIZE != 0) {
873                 LOG_ERROR("Writes must be row-aligned, got offset 0x%08" PRIx32,
874                         offset);
875                 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
876         }
877
878         row_size = ROW_SIZE;
879         if (!psoc_bank->ecc_enabled) {
880                 row_size += ROW_ECC_SIZE;
881                 memset(ecc_bytes, bank->default_padded_value, ROW_ECC_SIZE);
882         }
883
884         retval = psoc5lp_spc_get_temp(target, 3, temp);
885         if (retval != ERROR_OK) {
886                 LOG_ERROR("Unable to read Die temperature");
887                 return retval;
888         }
889         LOG_DEBUG("Get_Temp: sign 0x%02" PRIx8 ", magnitude 0x%02" PRIx8,
890                 temp[0], temp[1]);
891
892         assert(target_get_working_area_avail(target) == target->working_area_size);
893         retval = target_alloc_working_area(target,
894                         target_get_working_area_avail(target) / 2, &code_area);
895         if (retval != ERROR_OK) {
896                 LOG_ERROR("Could not allocate working area for program SRAM");
897                 return retval;
898         }
899         assert(code_area->address < 0x20000000);
900
901         retval = target_alloc_working_area(target,
902                         SPC_OPCODE_LEN + 1 + row_size + 3 + SPC_OPCODE_LEN + 6,
903                         &even_row_area);
904         if (retval != ERROR_OK) {
905                 LOG_ERROR("Could not allocate working area for even row");
906                 goto err_alloc_even;
907         }
908         assert(even_row_area->address >= 0x20000000);
909
910         retval = target_alloc_working_area(target, even_row_area->size,
911                         &odd_row_area);
912         if (retval != ERROR_OK) {
913                 LOG_ERROR("Could not allocate working area for odd row");
914                 goto err_alloc_odd;
915         }
916         assert(odd_row_area->address >= 0x20000000);
917
918         for (array_id = offset / BLOCK_SIZE; byte_count > 0; array_id++) {
919                 for (row = (offset / ROW_SIZE) % ROWS_PER_BLOCK;
920                      row < ROWS_PER_BLOCK && byte_count > 0; row++) {
921                         bool even_row = (row % 2 == 0);
922                         struct working_area *data_area = even_row ? even_row_area : odd_row_area;
923                         unsigned len = MIN(ROW_SIZE, byte_count);
924
925                         LOG_DEBUG("Writing load command for array %u row %u at 0x%08" TARGET_PRIxADDR,
926                                 array_id, row, data_area->address);
927
928                         psoc5lp_spc_write_opcode_buffer(target, buf, SPC_LOAD_ROW);
929                         buf[SPC_OPCODE_LEN] = array_id;
930                         retval = target_write_buffer(target, data_area->address, 4, buf);
931                         if (retval != ERROR_OK)
932                                 goto err_write;
933
934                         retval = target_write_buffer(target,
935                                 data_area->address + SPC_OPCODE_LEN + 1,
936                                 len, buffer);
937                         if (retval != ERROR_OK)
938                                 goto err_write;
939                         buffer += len;
940                         byte_count -= len;
941                         offset += len;
942
943                         if (len < ROW_SIZE) {
944                                 uint8_t padding[ROW_SIZE];
945
946                                 memset(padding, bank->default_padded_value, ROW_SIZE);
947
948                                 LOG_DEBUG("Padding %d bytes", ROW_SIZE - len);
949                                 retval = target_write_buffer(target,
950                                         data_area->address + SPC_OPCODE_LEN + 1 + len,
951                                         ROW_SIZE - len, padding);
952                                 if (retval != ERROR_OK)
953                                         goto err_write;
954                         }
955
956                         if (!psoc_bank->ecc_enabled) {
957                                 retval = target_write_buffer(target,
958                                         data_area->address + SPC_OPCODE_LEN + 1 + ROW_SIZE,
959                                         sizeof(ecc_bytes), ecc_bytes);
960                                 if (retval != ERROR_OK)
961                                         goto err_write;
962                         }
963
964                         for (i = 0; i < 3; i++)
965                                 buf[i] = 0x00; /* 3 NOPs for short delay */
966                         psoc5lp_spc_write_opcode_buffer(target, buf + 3, SPC_PRG_ROW);
967                         buf[3 + SPC_OPCODE_LEN] = array_id;
968                         buf[3 + SPC_OPCODE_LEN + 1] = row >> 8;
969                         buf[3 + SPC_OPCODE_LEN + 2] = row & 0xff;
970                         memcpy(buf + 3 + SPC_OPCODE_LEN + 3, temp, 2);
971                         buf[3 + SPC_OPCODE_LEN + 5] = 0x00; /* padding */
972                         retval = target_write_buffer(target,
973                                 data_area->address + SPC_OPCODE_LEN + 1 + row_size,
974                                 12, buf);
975                         if (retval != ERROR_OK)
976                                 goto err_write;
977
978                         retval = target_write_u32(target,
979                                 even_row ? PHUB_CH0_BASIC_STATUS : PHUB_CH1_BASIC_STATUS,
980                                 (even_row ? 0 : 1) << 8);
981                         if (retval != ERROR_OK)
982                                 goto err_dma;
983
984                         retval = target_write_u32(target,
985                                 even_row ? PHUB_CH0_BASIC_CFG : PHUB_CH1_BASIC_CFG,
986                                 PHUB_CHx_BASIC_CFG_WORK_SEP | PHUB_CHx_BASIC_CFG_EN);
987                         if (retval != ERROR_OK)
988                                 goto err_dma;
989
990                         retval = target_write_u32(target,
991                                 even_row ? PHUB_CFGMEM0_CFG0 : PHUB_CFGMEM1_CFG0,
992                                 PHUB_CFGMEMx_CFG0);
993                         if (retval != ERROR_OK)
994                                 goto err_dma;
995
996                         retval = target_write_u32(target,
997                                 even_row ? PHUB_CFGMEM0_CFG1 : PHUB_CFGMEM1_CFG1,
998                                 ((SPC_CPU_DATA >> 16) << 16) | (data_area->address >> 16));
999                         if (retval != ERROR_OK)
1000                                 goto err_dma;
1001
1002                         retval = target_write_u32(target,
1003                                 even_row ? PHUB_TDMEM0_ORIG_TD0 : PHUB_TDMEM1_ORIG_TD0,
1004                                 PHUB_TDMEMx_ORIG_TD0_INC_SRC_ADDR |
1005                                 PHUB_TDMEMx_ORIG_TD0_NEXT_TD_PTR_LAST |
1006                                 ((SPC_OPCODE_LEN + 1 + row_size + 3 + SPC_OPCODE_LEN + 5) & 0xfff));
1007                         if (retval != ERROR_OK)
1008                                 goto err_dma;
1009
1010                         retval = target_write_u32(target,
1011                                 even_row ? PHUB_TDMEM0_ORIG_TD1 : PHUB_TDMEM1_ORIG_TD1,
1012                                 ((SPC_CPU_DATA & 0xffff) << 16) | (data_area->address & 0xffff));
1013                         if (retval != ERROR_OK)
1014                                 goto err_dma;
1015
1016                         retval = psoc5lp_spc_busy_wait_idle(target);
1017                         if (retval != ERROR_OK)
1018                                 goto err_idle;
1019
1020                         retval = target_write_u32(target,
1021                                 even_row ? PHUB_CH0_ACTION : PHUB_CH1_ACTION,
1022                                 PHUB_CHx_ACTION_CPU_REQ);
1023                         if (retval != ERROR_OK)
1024                                 goto err_dma_action;
1025                 }
1026         }
1027
1028         retval = psoc5lp_spc_busy_wait_idle(target);
1029
1030 err_dma_action:
1031 err_idle:
1032 err_dma:
1033 err_write:
1034         target_free_working_area(target, odd_row_area);
1035 err_alloc_odd:
1036         target_free_working_area(target, even_row_area);
1037 err_alloc_even:
1038         target_free_working_area(target, code_area);
1039
1040         return retval;
1041 }
1042
1043 static int psoc5lp_protect_check(struct flash_bank *bank)
1044 {
1045         struct psoc5lp_flash_bank *psoc_bank = bank->driver_priv;
1046         uint8_t row_data[ROW_SIZE];
1047         const unsigned protection_bytes_per_sector = ROWS_PER_SECTOR * 2 / 8;
1048         unsigned i, j, k, num_sectors;
1049         int retval;
1050
1051         if (bank->target->state != TARGET_HALTED) {
1052                 LOG_ERROR("Target not halted");
1053                 return ERROR_TARGET_NOT_HALTED;
1054         }
1055
1056         for (i = 0; i < DIV_ROUND_UP(bank->size, BLOCK_SIZE); i++) {
1057                 retval = psoc5lp_spc_read_hidden_row(bank->target, i,
1058                                 SPC_ROW_PROTECTION, row_data);
1059                 if (retval != ERROR_OK)
1060                         return retval;
1061
1062                 /* Last flash array may have less rows, but in practice full sectors. */
1063                 if (i == bank->size / BLOCK_SIZE)
1064                         num_sectors = (bank->size % BLOCK_SIZE) / SECTOR_SIZE;
1065                 else
1066                         num_sectors = SECTORS_PER_BLOCK;
1067
1068                 for (j = 0; j < num_sectors; j++) {
1069                         int sector_nr = i * SECTORS_PER_BLOCK + j;
1070                         struct flash_sector *sector = &bank->sectors[sector_nr];
1071                         struct flash_sector *ecc_sector;
1072
1073                         if (psoc_bank->ecc_enabled)
1074                                 ecc_sector = &bank->sectors[bank->num_sectors + sector_nr];
1075                         else
1076                                 ecc_sector = &bank->sectors[bank->num_sectors / 2 + sector_nr];
1077
1078                         sector->is_protected = ecc_sector->is_protected = 0;
1079                         for (k = protection_bytes_per_sector * j;
1080                              k < protection_bytes_per_sector * (j + 1); k++) {
1081                                 assert(k < protection_bytes_per_sector * SECTORS_PER_BLOCK);
1082                                 LOG_DEBUG("row[%u][%02u] = 0x%02" PRIx8, i, k, row_data[k]);
1083                                 if (row_data[k] != 0x00) {
1084                                         sector->is_protected = ecc_sector->is_protected = 1;
1085                                         break;
1086                                 }
1087                         }
1088                 }
1089         }
1090
1091         return ERROR_OK;
1092 }
1093
1094 static int psoc5lp_get_info_command(struct flash_bank *bank, char *buf, int buf_size)
1095 {
1096         struct psoc5lp_flash_bank *psoc_bank = bank->driver_priv;
1097         char part_number[PART_NUMBER_LEN];
1098         const char *ecc;
1099
1100         psoc5lp_get_part_number(psoc_bank->device, part_number);
1101         ecc = psoc_bank->ecc_enabled ? "ECC enabled" : "ECC disabled";
1102
1103         snprintf(buf, buf_size, "%s %s", part_number, ecc);
1104
1105         return ERROR_OK;
1106 }
1107
1108 static int psoc5lp_probe(struct flash_bank *bank)
1109 {
1110         struct target *target = bank->target;
1111         struct psoc5lp_flash_bank *psoc_bank = bank->driver_priv;
1112         uint32_t flash_addr = bank->base;
1113         uint8_t nvl[4], temp[2];
1114         int i, retval;
1115
1116         if (target->state != TARGET_HALTED) {
1117                 LOG_ERROR("Target not halted");
1118                 return ERROR_TARGET_NOT_HALTED;
1119         }
1120
1121         if (!psoc_bank->device) {
1122                 retval = psoc5lp_find_device(target, &psoc_bank->device);
1123                 if (retval != ERROR_OK)
1124                         return retval;
1125
1126                 bank->size = psoc_bank->device->flash_kb * 1024;
1127         }
1128
1129         bank->num_sectors = DIV_ROUND_UP(bank->size, SECTOR_SIZE);
1130
1131         if (!psoc_bank->probed) {
1132                 retval = psoc5lp_spc_enable_clock(target);
1133                 if (retval != ERROR_OK)
1134                         return retval;
1135
1136                 /* First values read are inaccurate, so do it once now. */
1137                 retval = psoc5lp_spc_get_temp(target, 3, temp);
1138                 if (retval != ERROR_OK) {
1139                         LOG_ERROR("Unable to read Die temperature");
1140                         return retval;
1141                 }
1142
1143                 bank->sectors = calloc(bank->num_sectors * 2,
1144                                        sizeof(struct flash_sector));
1145                 for (i = 0; i < bank->num_sectors; i++) {
1146                         bank->sectors[i].size = SECTOR_SIZE;
1147                         bank->sectors[i].offset = flash_addr - bank->base;
1148                         bank->sectors[i].is_erased = -1;
1149                         bank->sectors[i].is_protected = -1;
1150
1151                         flash_addr += bank->sectors[i].size;
1152                 }
1153                 flash_addr = 0x48000000;
1154                 for (i = bank->num_sectors; i < bank->num_sectors * 2; i++) {
1155                         bank->sectors[i].size = ROWS_PER_SECTOR * ROW_ECC_SIZE;
1156                         bank->sectors[i].offset = flash_addr - bank->base;
1157                         bank->sectors[i].is_erased = -1;
1158                         bank->sectors[i].is_protected = -1;
1159
1160                         flash_addr += bank->sectors[i].size;
1161                 }
1162
1163                 bank->default_padded_value = bank->erased_value = 0x00;
1164
1165                 psoc_bank->probed = true;
1166         }
1167
1168         retval = psoc5lp_spc_read_byte(target, SPC_ARRAY_NVL_USER, 3, &nvl[3]);
1169         if (retval != ERROR_OK)
1170                 return retval;
1171         LOG_DEBUG("NVL[%d] = 0x%02" PRIx8, 3, nvl[3]);
1172         psoc_bank->ecc_enabled = nvl[3] & NVL_3_ECCEN;
1173
1174         if (!psoc_bank->ecc_enabled)
1175                 bank->num_sectors *= 2;
1176
1177         return ERROR_OK;
1178 }
1179
1180 static int psoc5lp_auto_probe(struct flash_bank *bank)
1181 {
1182         return psoc5lp_probe(bank);
1183 }
1184
1185 COMMAND_HANDLER(psoc5lp_handle_mass_erase_command)
1186 {
1187         struct flash_bank *bank;
1188         int retval;
1189
1190         if (CMD_ARGC < 1)
1191                 return ERROR_COMMAND_SYNTAX_ERROR;
1192
1193         retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
1194         if (retval != ERROR_OK)
1195                 return retval;
1196
1197         retval = psoc5lp_spc_erase_all(bank->target);
1198         if (retval == ERROR_OK)
1199                 command_print(CMD_CTX, "PSoC 5LP erase succeeded");
1200         else
1201                 command_print(CMD_CTX, "PSoC 5LP erase failed");
1202
1203         return retval;
1204 }
1205
1206 FLASH_BANK_COMMAND_HANDLER(psoc5lp_flash_bank_command)
1207 {
1208         struct psoc5lp_flash_bank *psoc_bank;
1209
1210         psoc_bank = malloc(sizeof(struct psoc5lp_flash_bank));
1211         if (!psoc_bank)
1212                 return ERROR_FLASH_OPERATION_FAILED;
1213
1214         psoc_bank->probed = false;
1215         psoc_bank->device = NULL;
1216
1217         bank->driver_priv = psoc_bank;
1218
1219         return ERROR_OK;
1220 }
1221
1222 static const struct command_registration psoc5lp_exec_command_handlers[] = {
1223         {
1224                 .name = "mass_erase",
1225                 .handler = psoc5lp_handle_mass_erase_command,
1226                 .mode = COMMAND_EXEC,
1227                 .usage = "bank_id",
1228                 .help = "Erase all flash data and ECC/configuration bytes, "
1229                         "all flash protection rows, "
1230                         "and all row latches in all flash arrays on the device.",
1231         },
1232         COMMAND_REGISTRATION_DONE
1233 };
1234
1235 static const struct command_registration psoc5lp_command_handlers[] = {
1236         {
1237                 .name = "psoc5lp",
1238                 .mode = COMMAND_ANY,
1239                 .help = "PSoC 5LP flash command group",
1240                 .usage = "",
1241                 .chain = psoc5lp_exec_command_handlers,
1242         },
1243         COMMAND_REGISTRATION_DONE
1244 };
1245
1246 struct flash_driver psoc5lp_flash = {
1247         .name = "psoc5lp",
1248         .commands = psoc5lp_command_handlers,
1249         .flash_bank_command = psoc5lp_flash_bank_command,
1250         .info = psoc5lp_get_info_command,
1251         .probe = psoc5lp_probe,
1252         .auto_probe = psoc5lp_auto_probe,
1253         .protect_check = psoc5lp_protect_check,
1254         .read = default_flash_read,
1255         .erase = psoc5lp_erase,
1256         .erase_check = psoc5lp_erase_check,
1257         .write = psoc5lp_write,
1258 };