]> git.sur5r.net Git - openocd/blob - src/flash/nor/psoc5lp.c
psoc5lp: Add EEPROM flash driver
[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         uint32_t blank;
802         int i, num_sectors, retval;
803
804         if (target->state != TARGET_HALTED) {
805                 LOG_ERROR("Target not halted");
806                 return ERROR_TARGET_NOT_HALTED;
807         }
808
809         num_sectors = bank->num_sectors;
810         if (!psoc_bank->ecc_enabled)
811                 num_sectors /= 2;
812
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;
816
817                 retval = armv7m_blank_check_memory(target, address, size,
818                                 &blank, bank->erased_value);
819                 if (retval != ERROR_OK)
820                         return retval;
821
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;
825
826                         retval = armv7m_blank_check_memory(target, address, size,
827                                         &blank, bank->erased_value);
828                         if (retval != ERROR_OK)
829                                 return retval;
830                 }
831
832                 if (blank == 0x00) {
833                         bank->sectors[i].is_erased = 1;
834                         bank->sectors[num_sectors + i].is_erased = 1;
835                 } else {
836                         bank->sectors[i].is_erased = 0;
837                         bank->sectors[num_sectors + i].is_erased = 0;
838                 }
839         }
840
841         return ERROR_OK;
842 }
843
844 static int psoc5lp_write(struct flash_bank *bank, const uint8_t *buffer,
845                 uint32_t offset, uint32_t byte_count)
846 {
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;
850         uint32_t row_size;
851         uint8_t temp[2], buf[12], ecc_bytes[ROW_ECC_SIZE];
852         unsigned array_id, row;
853         int i, retval;
854
855         if (offset + byte_count > bank->size) {
856                 LOG_ERROR("Writing to ECC not supported");
857                 return ERROR_FLASH_DST_OUT_OF_BANK;
858         }
859
860         if (offset % ROW_SIZE != 0) {
861                 LOG_ERROR("Writes must be row-aligned, got offset 0x%08" PRIx32,
862                         offset);
863                 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
864         }
865
866         row_size = ROW_SIZE;
867         if (!psoc_bank->ecc_enabled) {
868                 row_size += ROW_ECC_SIZE;
869                 memset(ecc_bytes, bank->default_padded_value, ROW_ECC_SIZE);
870         }
871
872         retval = psoc5lp_spc_get_temp(target, 3, temp);
873         if (retval != ERROR_OK) {
874                 LOG_ERROR("Unable to read Die temperature");
875                 return retval;
876         }
877         LOG_DEBUG("Get_Temp: sign 0x%02" PRIx8 ", magnitude 0x%02" PRIx8,
878                 temp[0], temp[1]);
879
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");
885                 return retval;
886         }
887         assert(code_area->address < 0x20000000);
888
889         retval = target_alloc_working_area(target,
890                         SPC_OPCODE_LEN + 1 + row_size + 3 + SPC_OPCODE_LEN + 6,
891                         &even_row_area);
892         if (retval != ERROR_OK) {
893                 LOG_ERROR("Could not allocate working area for even row");
894                 goto err_alloc_even;
895         }
896         assert(even_row_area->address >= 0x20000000);
897
898         retval = target_alloc_working_area(target, even_row_area->size,
899                         &odd_row_area);
900         if (retval != ERROR_OK) {
901                 LOG_ERROR("Could not allocate working area for odd row");
902                 goto err_alloc_odd;
903         }
904         assert(odd_row_area->address >= 0x20000000);
905
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);
912
913                         LOG_DEBUG("Writing load command for array %u row %u at 0x%08" TARGET_PRIxADDR,
914                                 array_id, row, data_area->address);
915
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)
920                                 goto err_write;
921
922                         retval = target_write_buffer(target,
923                                 data_area->address + SPC_OPCODE_LEN + 1,
924                                 len, buffer);
925                         if (retval != ERROR_OK)
926                                 goto err_write;
927                         buffer += len;
928                         byte_count -= len;
929                         offset += len;
930
931                         if (len < ROW_SIZE) {
932                                 uint8_t padding[ROW_SIZE];
933
934                                 memset(padding, bank->default_padded_value, ROW_SIZE);
935
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)
941                                         goto err_write;
942                         }
943
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)
949                                         goto err_write;
950                         }
951
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,
962                                 12, buf);
963                         if (retval != ERROR_OK)
964                                 goto err_write;
965
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)
970                                 goto err_dma;
971
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)
976                                 goto err_dma;
977
978                         retval = target_write_u32(target,
979                                 even_row ? PHUB_CFGMEM0_CFG0 : PHUB_CFGMEM1_CFG0,
980                                 PHUB_CFGMEMx_CFG0);
981                         if (retval != ERROR_OK)
982                                 goto err_dma;
983
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)
988                                 goto err_dma;
989
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)
996                                 goto err_dma;
997
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)
1002                                 goto err_dma;
1003
1004                         retval = psoc5lp_spc_busy_wait_idle(target);
1005                         if (retval != ERROR_OK)
1006                                 goto err_idle;
1007
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;
1013                 }
1014         }
1015
1016         retval = psoc5lp_spc_busy_wait_idle(target);
1017
1018 err_dma_action:
1019 err_idle:
1020 err_dma:
1021 err_write:
1022         target_free_working_area(target, odd_row_area);
1023 err_alloc_odd:
1024         target_free_working_area(target, even_row_area);
1025 err_alloc_even:
1026         target_free_working_area(target, code_area);
1027
1028         return retval;
1029 }
1030
1031 static int psoc5lp_protect_check(struct flash_bank *bank)
1032 {
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;
1037         int retval;
1038
1039         if (bank->target->state != TARGET_HALTED) {
1040                 LOG_ERROR("Target not halted");
1041                 return ERROR_TARGET_NOT_HALTED;
1042         }
1043
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)
1048                         return retval;
1049
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;
1053                 else
1054                         num_sectors = SECTORS_PER_BLOCK;
1055
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;
1060
1061                         if (psoc_bank->ecc_enabled)
1062                                 ecc_sector = &bank->sectors[bank->num_sectors + sector_nr];
1063                         else
1064                                 ecc_sector = &bank->sectors[bank->num_sectors / 2 + sector_nr];
1065
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;
1073                                         break;
1074                                 }
1075                         }
1076                 }
1077         }
1078
1079         return ERROR_OK;
1080 }
1081
1082 static int psoc5lp_get_info_command(struct flash_bank *bank, char *buf, int buf_size)
1083 {
1084         struct psoc5lp_flash_bank *psoc_bank = bank->driver_priv;
1085         char part_number[PART_NUMBER_LEN];
1086         const char *ecc;
1087
1088         psoc5lp_get_part_number(psoc_bank->device, part_number);
1089         ecc = psoc_bank->ecc_enabled ? "ECC enabled" : "ECC disabled";
1090
1091         snprintf(buf, buf_size, "%s %s", part_number, ecc);
1092
1093         return ERROR_OK;
1094 }
1095
1096 static int psoc5lp_probe(struct flash_bank *bank)
1097 {
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];
1102         int i, retval;
1103
1104         if (target->state != TARGET_HALTED) {
1105                 LOG_ERROR("Target not halted");
1106                 return ERROR_TARGET_NOT_HALTED;
1107         }
1108
1109         if (!psoc_bank->device) {
1110                 retval = psoc5lp_find_device(target, &psoc_bank->device);
1111                 if (retval != ERROR_OK)
1112                         return retval;
1113
1114                 bank->size = psoc_bank->device->flash_kb * 1024;
1115         }
1116
1117         bank->num_sectors = DIV_ROUND_UP(bank->size, SECTOR_SIZE);
1118
1119         if (!psoc_bank->probed) {
1120                 retval = psoc5lp_spc_enable_clock(target);
1121                 if (retval != ERROR_OK)
1122                         return retval;
1123
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");
1128                         return retval;
1129                 }
1130
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;
1138
1139                         flash_addr += bank->sectors[i].size;
1140                 }
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;
1147
1148                         flash_addr += bank->sectors[i].size;
1149                 }
1150
1151                 bank->default_padded_value = bank->erased_value = 0x00;
1152
1153                 psoc_bank->probed = true;
1154         }
1155
1156         retval = psoc5lp_spc_read_byte(target, SPC_ARRAY_NVL_USER, 3, &nvl[3]);
1157         if (retval != ERROR_OK)
1158                 return retval;
1159         LOG_DEBUG("NVL[%d] = 0x%02" PRIx8, 3, nvl[3]);
1160         psoc_bank->ecc_enabled = nvl[3] & NVL_3_ECCEN;
1161
1162         if (!psoc_bank->ecc_enabled)
1163                 bank->num_sectors *= 2;
1164
1165         return ERROR_OK;
1166 }
1167
1168 static int psoc5lp_auto_probe(struct flash_bank *bank)
1169 {
1170         return psoc5lp_probe(bank);
1171 }
1172
1173 COMMAND_HANDLER(psoc5lp_handle_mass_erase_command)
1174 {
1175         struct flash_bank *bank;
1176         int retval;
1177
1178         if (CMD_ARGC < 1)
1179                 return ERROR_COMMAND_SYNTAX_ERROR;
1180
1181         retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
1182         if (retval != ERROR_OK)
1183                 return retval;
1184
1185         retval = psoc5lp_spc_erase_all(bank->target);
1186         if (retval == ERROR_OK)
1187                 command_print(CMD_CTX, "PSoC 5LP erase succeeded");
1188         else
1189                 command_print(CMD_CTX, "PSoC 5LP erase failed");
1190
1191         return retval;
1192 }
1193
1194 FLASH_BANK_COMMAND_HANDLER(psoc5lp_flash_bank_command)
1195 {
1196         struct psoc5lp_flash_bank *psoc_bank;
1197
1198         psoc_bank = malloc(sizeof(struct psoc5lp_flash_bank));
1199         if (!psoc_bank)
1200                 return ERROR_FLASH_OPERATION_FAILED;
1201
1202         psoc_bank->probed = false;
1203         psoc_bank->device = NULL;
1204
1205         bank->driver_priv = psoc_bank;
1206
1207         return ERROR_OK;
1208 }
1209
1210 static const struct command_registration psoc5lp_exec_command_handlers[] = {
1211         {
1212                 .name = "mass_erase",
1213                 .handler = psoc5lp_handle_mass_erase_command,
1214                 .mode = COMMAND_EXEC,
1215                 .usage = "bank_id",
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.",
1219         },
1220         COMMAND_REGISTRATION_DONE
1221 };
1222
1223 static const struct command_registration psoc5lp_command_handlers[] = {
1224         {
1225                 .name = "psoc5lp",
1226                 .mode = COMMAND_ANY,
1227                 .help = "PSoC 5LP flash command group",
1228                 .usage = "",
1229                 .chain = psoc5lp_exec_command_handlers,
1230         },
1231         COMMAND_REGISTRATION_DONE
1232 };
1233
1234 struct flash_driver psoc5lp_flash = {
1235         .name = "psoc5lp",
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,
1246 };