]> git.sur5r.net Git - openocd/blob - src/flash/nor/psoc5lp.c
ae8e3d3bc17a5370fed494fdd302cf8fb00a1570
[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 PRT1_PC2                0x4000500A
33 #define PHUB_CH0_BASIC_CFG      0x40007010
34 #define PHUB_CH0_ACTION         0x40007014
35 #define PHUB_CH0_BASIC_STATUS   0x40007018
36 #define PHUB_CH1_BASIC_CFG      0x40007020
37 #define PHUB_CH1_ACTION         0x40007024
38 #define PHUB_CH1_BASIC_STATUS   0x40007028
39 #define PHUB_CFGMEM0_CFG0       0x40007600
40 #define PHUB_CFGMEM0_CFG1       0x40007604
41 #define PHUB_CFGMEM1_CFG0       0x40007608
42 #define PHUB_CFGMEM1_CFG1       0x4000760C
43 #define PHUB_TDMEM0_ORIG_TD0    0x40007800
44 #define PHUB_TDMEM0_ORIG_TD1    0x40007804
45 #define PHUB_TDMEM1_ORIG_TD0    0x40007808
46 #define PHUB_TDMEM1_ORIG_TD1    0x4000780C
47 #define PANTHER_DEVICE_ID       0x4008001C
48
49 /* NVL is not actually mapped to the Cortex-M address space
50  * As we need a base addess different from other banks in the device
51  * we use the address of NVL programming data in Cypress images */
52 #define NVL_META_BASE                   0x90000000
53
54 #define PM_ACT_CFG12_EN_EE (1 << 4)
55
56 #define SPC_KEY1 0xB6
57 #define SPC_KEY2 0xD3
58
59 #define SPC_LOAD_BYTE           0x00
60 #define SPC_LOAD_MULTI_BYTE     0x01
61 #define SPC_LOAD_ROW            0x02
62 #define SPC_READ_BYTE           0x03
63 #define SPC_READ_MULTI_BYTE     0x04
64 #define SPC_WRITE_ROW           0x05
65 #define SPC_WRITE_USER_NVL      0x06
66 #define SPC_PRG_ROW             0x07
67 #define SPC_ERASE_SECTOR        0x08
68 #define SPC_ERASE_ALL           0x09
69 #define SPC_READ_HIDDEN_ROW     0x0A
70 #define SPC_PROGRAM_PROTECT_ROW 0x0B
71 #define SPC_GET_CHECKSUM        0x0C
72 #define SPC_GET_TEMP            0x0E
73 #define SPC_READ_VOLATILE_BYTE  0x10
74
75 #define SPC_ARRAY_ALL      0x3F
76 #define SPC_ARRAY_EEPROM   0x40
77 #define SPC_ARRAY_NVL_USER 0x80
78 #define SPC_ARRAY_NVL_WO   0xF8
79
80 #define SPC_ROW_PROTECTION 0
81
82 #define SPC_OPCODE_LEN 3
83
84 #define SPC_SR_DATA_READY (1 << 0)
85 #define SPC_SR_IDLE       (1 << 1)
86
87 #define PM_ACT_CFG0_EN_CLK_SPC      (1 << 3)
88
89 #define PHUB_CHx_BASIC_CFG_EN       (1 << 0)
90 #define PHUB_CHx_BASIC_CFG_WORK_SEP (1 << 5)
91
92 #define PHUB_CHx_ACTION_CPU_REQ (1 << 0)
93
94 #define PHUB_CFGMEMx_CFG0 (1 << 7)
95
96 #define PHUB_TDMEMx_ORIG_TD0_NEXT_TD_PTR_LAST (0xff << 16)
97 #define PHUB_TDMEMx_ORIG_TD0_INC_SRC_ADDR     (1 << 24)
98
99 #define NVL_3_ECCEN  (1 << 3)
100
101 #define ROW_SIZE           256
102 #define ROW_ECC_SIZE       32
103 #define ROWS_PER_SECTOR    64
104 #define SECTOR_SIZE        (ROWS_PER_SECTOR * ROW_SIZE)
105 #define ROWS_PER_BLOCK     256
106 #define BLOCK_SIZE         (ROWS_PER_BLOCK * ROW_SIZE)
107 #define SECTORS_PER_BLOCK  (BLOCK_SIZE / SECTOR_SIZE)
108 #define EEPROM_ROW_SIZE    16
109 #define EEPROM_SECTOR_SIZE (ROWS_PER_SECTOR * EEPROM_ROW_SIZE)
110 #define EEPROM_BLOCK_SIZE  (ROWS_PER_BLOCK * EEPROM_ROW_SIZE)
111
112 #define PART_NUMBER_LEN (17 + 1)
113
114 struct psoc5lp_device {
115         uint32_t id;
116         unsigned fam;
117         unsigned speed_mhz;
118         unsigned flash_kb;
119         unsigned eeprom_kb;
120 };
121
122 /*
123  * Device information collected from datasheets.
124  * Different temperature ranges (C/I/Q/A) may share IDs, not differing otherwise.
125  */
126 static const struct psoc5lp_device psoc5lp_devices[] = {
127         /* CY8C58LP Family Datasheet */
128         { .id = 0x2E11F069, .fam = 8, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 },
129         { .id = 0x2E120069, .fam = 8, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 },
130         { .id = 0x2E123069, .fam = 8, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 },
131         { .id = 0x2E124069, .fam = 8, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 },
132         { .id = 0x2E126069, .fam = 8, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 },
133         { .id = 0x2E127069, .fam = 8, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 },
134         { .id = 0x2E117069, .fam = 8, .speed_mhz = 67, .flash_kb = 128, .eeprom_kb = 2 },
135         { .id = 0x2E118069, .fam = 8, .speed_mhz = 67, .flash_kb = 128, .eeprom_kb = 2 },
136         { .id = 0x2E119069, .fam = 8, .speed_mhz = 67, .flash_kb = 128, .eeprom_kb = 2 },
137         { .id = 0x2E11C069, .fam = 8, .speed_mhz = 67, .flash_kb = 128, .eeprom_kb = 2 },
138         { .id = 0x2E114069, .fam = 8, .speed_mhz = 67, .flash_kb =  64, .eeprom_kb = 2 },
139         { .id = 0x2E115069, .fam = 8, .speed_mhz = 67, .flash_kb =  64, .eeprom_kb = 2 },
140         { .id = 0x2E116069, .fam = 8, .speed_mhz = 67, .flash_kb =  64, .eeprom_kb = 2 },
141         { .id = 0x2E160069, .fam = 8, .speed_mhz = 80, .flash_kb = 256, .eeprom_kb = 2 },
142         /*           ''                                                               */
143         { .id = 0x2E161069, .fam = 8, .speed_mhz = 80, .flash_kb = 256, .eeprom_kb = 2 },
144         /*           ''                                                               */
145         { .id = 0x2E1D2069, .fam = 8, .speed_mhz = 80, .flash_kb = 256, .eeprom_kb = 2 },
146         { .id = 0x2E1D6069, .fam = 8, .speed_mhz = 80, .flash_kb = 256, .eeprom_kb = 2 },
147
148         /* CY8C56LP Family Datasheet */
149         { .id = 0x2E10A069, .fam = 6, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 },
150         { .id = 0x2E10D069, .fam = 6, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 },
151         { .id = 0x2E10E069, .fam = 6, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 },
152         { .id = 0x2E106069, .fam = 6, .speed_mhz = 67, .flash_kb = 128, .eeprom_kb = 2 },
153         { .id = 0x2E108069, .fam = 6, .speed_mhz = 67, .flash_kb = 128, .eeprom_kb = 2 },
154         { .id = 0x2E109069, .fam = 6, .speed_mhz = 67, .flash_kb = 128, .eeprom_kb = 2 },
155         { .id = 0x2E101069, .fam = 6, .speed_mhz = 67, .flash_kb =  64, .eeprom_kb = 2 },
156         { .id = 0x2E104069, .fam = 6, .speed_mhz = 67, .flash_kb =  64, .eeprom_kb = 2 },
157         /*           ''                                                               */
158         { .id = 0x2E105069, .fam = 6, .speed_mhz = 67, .flash_kb =  64, .eeprom_kb = 2 },
159         { .id = 0x2E128069, .fam = 6, .speed_mhz = 67, .flash_kb = 128, .eeprom_kb = 2 },
160         /*           ''                                                               */
161         { .id = 0x2E122069, .fam = 6, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 },
162         { .id = 0x2E129069, .fam = 6, .speed_mhz = 67, .flash_kb = 128, .eeprom_kb = 2 },
163         { .id = 0x2E163069, .fam = 6, .speed_mhz = 80, .flash_kb = 256, .eeprom_kb = 2 },
164         { .id = 0x2E156069, .fam = 6, .speed_mhz = 80, .flash_kb = 256, .eeprom_kb = 2 },
165         { .id = 0x2E1D3069, .fam = 6, .speed_mhz = 80, .flash_kb = 256, .eeprom_kb = 2 },
166
167         /* CY8C54LP Family Datasheet */
168         { .id = 0x2E11A069, .fam = 4, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 },
169         { .id = 0x2E16A069, .fam = 4, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 },
170         { .id = 0x2E12A069, .fam = 4, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 },
171         { .id = 0x2E103069, .fam = 4, .speed_mhz = 67, .flash_kb = 128, .eeprom_kb = 2 },
172         { .id = 0x2E16C069, .fam = 4, .speed_mhz = 67, .flash_kb = 128, .eeprom_kb = 2 },
173         { .id = 0x2E102069, .fam = 4, .speed_mhz = 67, .flash_kb =  64, .eeprom_kb = 2 },
174         { .id = 0x2E148069, .fam = 4, .speed_mhz = 67, .flash_kb =  64, .eeprom_kb = 2 },
175         { .id = 0x2E155069, .fam = 4, .speed_mhz = 67, .flash_kb =  64, .eeprom_kb = 2 },
176         { .id = 0x2E16B069, .fam = 4, .speed_mhz = 67, .flash_kb =  64, .eeprom_kb = 2 },
177         { .id = 0x2E12B069, .fam = 4, .speed_mhz = 67, .flash_kb =  32, .eeprom_kb = 2 },
178         { .id = 0x2E168069, .fam = 4, .speed_mhz = 67, .flash_kb =  32, .eeprom_kb = 2 },
179         { .id = 0x2E178069, .fam = 4, .speed_mhz = 80, .flash_kb = 256, .eeprom_kb = 2 },
180         { .id = 0x2E15D069, .fam = 4, .speed_mhz = 80, .flash_kb = 256, .eeprom_kb = 2 },
181         { .id = 0x2E1D4069, .fam = 4, .speed_mhz = 80, .flash_kb = 256, .eeprom_kb = 2 },
182
183         /* CY8C52LP Family Datasheet */
184         { .id = 0x2E11E069, .fam = 2, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 },
185         { .id = 0x2E12F069, .fam = 2, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 },
186         { .id = 0x2E133069, .fam = 2, .speed_mhz = 67, .flash_kb = 128, .eeprom_kb = 2 },
187         { .id = 0x2E159069, .fam = 2, .speed_mhz = 67, .flash_kb = 128, .eeprom_kb = 2 },
188         { .id = 0x2E11D069, .fam = 2, .speed_mhz = 67, .flash_kb =  64, .eeprom_kb = 2 },
189         { .id = 0x2E121069, .fam = 2, .speed_mhz = 67, .flash_kb =  64, .eeprom_kb = 2 },
190         { .id = 0x2E184069, .fam = 2, .speed_mhz = 67, .flash_kb =  64, .eeprom_kb = 2 },
191         { .id = 0x2E196069, .fam = 2, .speed_mhz = 67, .flash_kb =  64, .eeprom_kb = 2 },
192         { .id = 0x2E132069, .fam = 2, .speed_mhz = 67, .flash_kb =  32, .eeprom_kb = 2 },
193         { .id = 0x2E138069, .fam = 2, .speed_mhz = 67, .flash_kb =  32, .eeprom_kb = 2 },
194         { .id = 0x2E13A069, .fam = 2, .speed_mhz = 67, .flash_kb =  32, .eeprom_kb = 2 },
195         { .id = 0x2E152069, .fam = 2, .speed_mhz = 67, .flash_kb =  32, .eeprom_kb = 2 },
196         { .id = 0x2E15F069, .fam = 2, .speed_mhz = 80, .flash_kb = 256, .eeprom_kb = 2 },
197         { .id = 0x2E15A069, .fam = 2, .speed_mhz = 80, .flash_kb = 256, .eeprom_kb = 2 },
198         { .id = 0x2E1D5069, .fam = 2, .speed_mhz = 80, .flash_kb = 256, .eeprom_kb = 2 },
199 };
200
201 static void psoc5lp_get_part_number(const struct psoc5lp_device *dev, char *str)
202 {
203         strcpy(str, "CY8Cabcdefg-LPxxx");
204
205         str[4] = '5';
206         str[5] = '0' + dev->fam;
207
208         switch (dev->speed_mhz) {
209         case 67:
210                 str[6] = '6';
211                 break;
212         case 80:
213                 str[6] = '8';
214                 break;
215         default:
216                 str[6] = '?';
217         }
218
219         switch (dev->flash_kb) {
220         case 32:
221                 str[7] = '5';
222                 break;
223         case 64:
224                 str[7] = '6';
225                 break;
226         case 128:
227                 str[7] = '7';
228                 break;
229         case 256:
230                 str[7] = '8';
231                 break;
232         default:
233                 str[7] = '?';
234         }
235
236         /* Package does not matter. */
237         strncpy(str + 8, "xx", 2);
238
239         /* Temperate range cannot uniquely be identified. */
240         str[10] = 'x';
241 }
242
243 static int psoc5lp_get_device_id(struct target *target, uint32_t *id)
244 {
245         int retval;
246
247         retval = target_read_u32(target, PANTHER_DEVICE_ID, id); /* dummy read */
248         if (retval != ERROR_OK)
249                 return retval;
250         retval = target_read_u32(target, PANTHER_DEVICE_ID, id);
251         return retval;
252 }
253
254 static int psoc5lp_find_device(struct target *target,
255         const struct psoc5lp_device **device)
256 {
257         uint32_t device_id;
258         unsigned i;
259         int retval;
260
261         *device = NULL;
262
263         retval = psoc5lp_get_device_id(target, &device_id);
264         if (retval != ERROR_OK)
265                 return retval;
266         LOG_DEBUG("PANTHER_DEVICE_ID = 0x%08" PRIX32, device_id);
267
268         for (i = 0; i < ARRAY_SIZE(psoc5lp_devices); i++) {
269                 if (psoc5lp_devices[i].id == device_id) {
270                         *device = &psoc5lp_devices[i];
271                         return ERROR_OK;
272                 }
273         }
274
275         LOG_ERROR("Device 0x%08" PRIX32 " not supported", device_id);
276         return ERROR_FLASH_OPER_UNSUPPORTED;
277 }
278
279 static int psoc5lp_spc_enable_clock(struct target *target)
280 {
281         int retval;
282         uint8_t pm_act_cfg0;
283
284         retval = target_read_u8(target, PM_ACT_CFG0, &pm_act_cfg0);
285         if (retval != ERROR_OK) {
286                 LOG_ERROR("Cannot read PM_ACT_CFG0");
287                 return retval;
288         }
289
290         if (pm_act_cfg0 & PM_ACT_CFG0_EN_CLK_SPC)
291                 return ERROR_OK;        /* clock already enabled */
292
293         retval = target_write_u8(target, PM_ACT_CFG0, pm_act_cfg0 | PM_ACT_CFG0_EN_CLK_SPC);
294         if (retval != ERROR_OK)
295                 LOG_ERROR("Cannot enable SPC clock");
296
297         return retval;
298 }
299
300 static int psoc5lp_spc_write_opcode(struct target *target, uint8_t opcode)
301 {
302         int retval;
303
304         retval = target_write_u8(target, SPC_CPU_DATA, SPC_KEY1);
305         if (retval != ERROR_OK)
306                 return retval;
307         retval = target_write_u8(target, SPC_CPU_DATA, SPC_KEY2 + opcode);
308         if (retval != ERROR_OK)
309                 return retval;
310         retval = target_write_u8(target, SPC_CPU_DATA, opcode);
311         return retval;
312 }
313
314 static void psoc5lp_spc_write_opcode_buffer(struct target *target,
315         uint8_t *buf, uint8_t opcode)
316 {
317         buf[0] = SPC_KEY1;
318         buf[1] = SPC_KEY2 + opcode;
319         buf[2] = opcode;
320 }
321
322 static int psoc5lp_spc_busy_wait_data(struct target *target)
323 {
324         int64_t endtime;
325         uint8_t sr;
326         int retval;
327
328         retval = target_read_u8(target, SPC_SR, &sr); /* dummy read */
329         if (retval != ERROR_OK)
330                 return retval;
331
332         endtime = timeval_ms() + 1000; /* 1 second timeout */
333         do {
334                 alive_sleep(1);
335                 retval = target_read_u8(target, SPC_SR, &sr);
336                 if (retval != ERROR_OK)
337                         return retval;
338                 if (sr == SPC_SR_DATA_READY)
339                         return ERROR_OK;
340         } while (timeval_ms() < endtime);
341
342         return ERROR_FLASH_OPERATION_FAILED;
343 }
344
345 static int psoc5lp_spc_busy_wait_idle(struct target *target)
346 {
347         int64_t endtime;
348         uint8_t sr;
349         int retval;
350
351         retval = target_read_u8(target, SPC_SR, &sr); /* dummy read */
352         if (retval != ERROR_OK)
353                 return retval;
354
355         endtime = timeval_ms() + 1000; /* 1 second timeout */
356         do {
357                 alive_sleep(1);
358                 retval = target_read_u8(target, SPC_SR, &sr);
359                 if (retval != ERROR_OK)
360                         return retval;
361                 if (sr == SPC_SR_IDLE)
362                         return ERROR_OK;
363         } while (timeval_ms() < endtime);
364
365         return ERROR_FLASH_OPERATION_FAILED;
366 }
367
368 static int psoc5lp_spc_load_byte(struct target *target,
369         uint8_t array_id, uint8_t offset, uint8_t value)
370 {
371         int retval;
372
373         retval = psoc5lp_spc_write_opcode(target, SPC_LOAD_BYTE);
374         if (retval != ERROR_OK)
375                 return retval;
376         retval = target_write_u8(target, SPC_CPU_DATA, array_id);
377         if (retval != ERROR_OK)
378                 return retval;
379         retval = target_write_u8(target, SPC_CPU_DATA, offset);
380         if (retval != ERROR_OK)
381                 return retval;
382         retval = target_write_u8(target, SPC_CPU_DATA, value);
383         if (retval != ERROR_OK)
384                 return retval;
385
386         retval = psoc5lp_spc_busy_wait_idle(target);
387         if (retval != ERROR_OK)
388                 return retval;
389
390         return ERROR_OK;
391 }
392
393 static int psoc5lp_spc_load_row(struct target *target,
394         uint8_t array_id, const uint8_t *data, unsigned row_size)
395 {
396         unsigned i;
397         int retval;
398
399         retval = psoc5lp_spc_write_opcode(target, SPC_LOAD_ROW);
400         if (retval != ERROR_OK)
401                 return retval;
402         retval = target_write_u8(target, SPC_CPU_DATA, array_id);
403         if (retval != ERROR_OK)
404                 return retval;
405
406         for (i = 0; i < row_size; i++) {
407                 retval = target_write_u8(target, SPC_CPU_DATA, data[i]);
408                 if (retval != ERROR_OK)
409                         return retval;
410         }
411
412         retval = psoc5lp_spc_busy_wait_idle(target);
413         if (retval != ERROR_OK)
414                 return retval;
415
416         return ERROR_OK;
417 }
418
419 static int psoc5lp_spc_read_byte(struct target *target,
420         uint8_t array_id, uint8_t offset, uint8_t *data)
421 {
422         int retval;
423
424         retval = psoc5lp_spc_write_opcode(target, SPC_READ_BYTE);
425         if (retval != ERROR_OK)
426                 return retval;
427         retval = target_write_u8(target, SPC_CPU_DATA, array_id);
428         if (retval != ERROR_OK)
429                 return retval;
430         retval = target_write_u8(target, SPC_CPU_DATA, offset);
431         if (retval != ERROR_OK)
432                 return retval;
433
434         retval = psoc5lp_spc_busy_wait_data(target);
435         if (retval != ERROR_OK)
436                 return retval;
437
438         retval = target_read_u8(target, SPC_CPU_DATA, data);
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_write_row(struct target *target,
450         uint8_t array_id, uint16_t row_id, const uint8_t *temp)
451 {
452         int retval;
453
454         retval = psoc5lp_spc_write_opcode(target, SPC_WRITE_ROW);
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 >> 8);
461         if (retval != ERROR_OK)
462                 return retval;
463         retval = target_write_u8(target, SPC_CPU_DATA, row_id & 0xff);
464         if (retval != ERROR_OK)
465                 return retval;
466         retval = target_write_u8(target, SPC_CPU_DATA, temp[0]);
467         if (retval != ERROR_OK)
468                 return retval;
469         retval = target_write_u8(target, SPC_CPU_DATA, temp[1]);
470         if (retval != ERROR_OK)
471                 return retval;
472
473         retval = psoc5lp_spc_busy_wait_idle(target);
474         if (retval != ERROR_OK)
475                 return retval;
476
477         return ERROR_OK;
478 }
479
480 static int psoc5lp_spc_write_user_nvl(struct target *target,
481         uint8_t array_id)
482 {
483         int retval;
484
485         retval = psoc5lp_spc_write_opcode(target, SPC_WRITE_USER_NVL);
486         if (retval != ERROR_OK)
487                 return retval;
488         retval = target_write_u8(target, SPC_CPU_DATA, array_id);
489         if (retval != ERROR_OK)
490                 return retval;
491
492         retval = psoc5lp_spc_busy_wait_idle(target);
493         if (retval != ERROR_OK)
494                 return retval;
495
496         return ERROR_OK;
497 }
498
499 static int psoc5lp_spc_erase_sector(struct target *target,
500         uint8_t array_id, uint8_t row_id)
501 {
502         int retval;
503
504         retval = psoc5lp_spc_write_opcode(target, SPC_ERASE_SECTOR);
505         if (retval != ERROR_OK)
506                 return retval;
507         retval = target_write_u8(target, SPC_CPU_DATA, array_id);
508         if (retval != ERROR_OK)
509                 return retval;
510         retval = target_write_u8(target, SPC_CPU_DATA, row_id);
511         if (retval != ERROR_OK)
512                 return retval;
513
514         retval = psoc5lp_spc_busy_wait_idle(target);
515         if (retval != ERROR_OK)
516                 return retval;
517
518         return ERROR_OK;
519 }
520
521 static int psoc5lp_spc_erase_all(struct target *target)
522 {
523         int retval;
524
525         retval = psoc5lp_spc_write_opcode(target, SPC_ERASE_ALL);
526         if (retval != ERROR_OK)
527                 return retval;
528
529         retval = psoc5lp_spc_busy_wait_idle(target);
530         if (retval != ERROR_OK)
531                 return retval;
532
533         return ERROR_OK;
534 }
535
536 static int psoc5lp_spc_read_hidden_row(struct target *target,
537         uint8_t array_id, uint8_t row_id, uint8_t *data)
538 {
539         int i, retval;
540
541         retval = psoc5lp_spc_write_opcode(target, SPC_READ_HIDDEN_ROW);
542         if (retval != ERROR_OK)
543                 return retval;
544         retval = target_write_u8(target, SPC_CPU_DATA, array_id);
545         if (retval != ERROR_OK)
546                 return retval;
547         retval = target_write_u8(target, SPC_CPU_DATA, row_id);
548         if (retval != ERROR_OK)
549                 return retval;
550
551         retval = psoc5lp_spc_busy_wait_data(target);
552         if (retval != ERROR_OK)
553                 return retval;
554
555         for (i = 0; i < ROW_SIZE; i++) {
556                 retval = target_read_u8(target, SPC_CPU_DATA, &data[i]);
557                 if (retval != ERROR_OK)
558                         return retval;
559         }
560
561         retval = psoc5lp_spc_busy_wait_idle(target);
562         if (retval != ERROR_OK)
563                 return retval;
564
565         return ERROR_OK;
566 }
567
568 static int psoc5lp_spc_get_temp(struct target *target, uint8_t samples,
569         uint8_t *data)
570 {
571         int retval;
572
573         retval = psoc5lp_spc_write_opcode(target, SPC_GET_TEMP);
574         if (retval != ERROR_OK)
575                 return retval;
576         retval = target_write_u8(target, SPC_CPU_DATA, samples);
577         if (retval != ERROR_OK)
578                 return retval;
579
580         retval = psoc5lp_spc_busy_wait_data(target);
581         if (retval != ERROR_OK)
582                 return retval;
583
584         retval = target_read_u8(target, SPC_CPU_DATA, &data[0]);
585         if (retval != ERROR_OK)
586                 return retval;
587         retval = target_read_u8(target, SPC_CPU_DATA, &data[1]);
588         if (retval != ERROR_OK)
589                 return retval;
590
591         retval = psoc5lp_spc_busy_wait_idle(target);
592         if (retval != ERROR_OK)
593                 return retval;
594
595         return ERROR_OK;
596 }
597
598 static int psoc5lp_spc_read_volatile_byte(struct target *target,
599         uint8_t array_id, uint8_t offset, uint8_t *data)
600 {
601         int retval;
602
603         retval = psoc5lp_spc_write_opcode(target, SPC_READ_VOLATILE_BYTE);
604         if (retval != ERROR_OK)
605                 return retval;
606         retval = target_write_u8(target, SPC_CPU_DATA, array_id);
607         if (retval != ERROR_OK)
608                 return retval;
609         retval = target_write_u8(target, SPC_CPU_DATA, offset);
610         if (retval != ERROR_OK)
611                 return retval;
612
613         retval = psoc5lp_spc_busy_wait_data(target);
614         if (retval != ERROR_OK)
615                 return retval;
616
617         retval = target_read_u8(target, SPC_CPU_DATA, data);
618         if (retval != ERROR_OK)
619                 return retval;
620
621         retval = psoc5lp_spc_busy_wait_idle(target);
622         if (retval != ERROR_OK)
623                 return retval;
624
625         return ERROR_OK;
626 }
627
628 /*
629  * NV Latch
630  */
631
632 struct psoc5lp_nvl_flash_bank {
633         bool probed;
634         const struct psoc5lp_device *device;
635 };
636
637 static int psoc5lp_nvl_read(struct flash_bank *bank,
638         uint8_t *buffer, uint32_t offset, uint32_t count)
639 {
640         int retval;
641
642         retval = psoc5lp_spc_enable_clock(bank->target);
643         if (retval != ERROR_OK)
644                 return retval;
645
646         while (count > 0) {
647                 retval = psoc5lp_spc_read_byte(bank->target,
648                                 SPC_ARRAY_NVL_USER, offset, buffer);
649                 if (retval != ERROR_OK)
650                         return retval;
651                 buffer++;
652                 offset++;
653                 count--;
654         }
655
656         return ERROR_OK;
657 }
658
659 static int psoc5lp_nvl_erase(struct flash_bank *bank, int first, int last)
660 {
661         LOG_WARNING("There is no erase operation for NV Latches");
662         return ERROR_FLASH_OPER_UNSUPPORTED;
663 }
664
665 static int psoc5lp_nvl_erase_check(struct flash_bank *bank)
666 {
667         int i;
668
669         for (i = 0; i < bank->num_sectors; i++)
670                 bank->sectors[i].is_erased = 0;
671
672         return ERROR_OK;
673 }
674
675 static int psoc5lp_nvl_write(struct flash_bank *bank,
676         const uint8_t *buffer, uint32_t offset, uint32_t byte_count)
677 {
678         struct target *target = bank->target;
679         uint8_t *current_data, val;
680         bool write_required = false, pullup_needed = false, ecc_changed = false;
681         uint32_t i;
682         int retval;
683
684         if (offset != 0 || byte_count != bank->size) {
685                 LOG_ERROR("NVL can only be written in whole");
686                 return ERROR_FLASH_OPER_UNSUPPORTED;
687         }
688
689         current_data = calloc(1, bank->size);
690         if (!current_data)
691                 return ERROR_FAIL;
692         retval = psoc5lp_nvl_read(bank, current_data, offset, byte_count);
693         if (retval != ERROR_OK) {
694                 free(current_data);
695                 return retval;
696         }
697         for (i = offset; i < byte_count; i++) {
698                 if (current_data[i] != buffer[i]) {
699                         write_required = true;
700                         break;
701                 }
702         }
703         if (((buffer[2] & 0x80) == 0x80) && ((current_data[0] & 0x0C) != 0x08))
704                 pullup_needed = true;
705         if (((buffer[3] ^ current_data[3]) & 0x08) == 0x08)
706                 ecc_changed = true;
707         free(current_data);
708
709         if (!write_required) {
710                 LOG_INFO("Unchanged, skipping NVL write");
711                 return ERROR_OK;
712         }
713         if (pullup_needed) {
714                 retval = target_read_u8(target, PRT1_PC2, &val);
715                 if (retval != ERROR_OK)
716                         return retval;
717                 val &= 0xF0;
718                 val |= 0x05;
719                 retval = target_write_u8(target, PRT1_PC2, val);
720                 if (retval != ERROR_OK)
721                         return retval;
722         }
723
724         for (i = offset; i < byte_count; i++) {
725                 retval = psoc5lp_spc_load_byte(target,
726                                 SPC_ARRAY_NVL_USER, i, buffer[i]);
727                 if (retval != ERROR_OK)
728                         return retval;
729
730                 retval = psoc5lp_spc_read_volatile_byte(target,
731                                 SPC_ARRAY_NVL_USER, i, &val);
732                 if (retval != ERROR_OK)
733                         return retval;
734                 if (val != buffer[i]) {
735                         LOG_ERROR("Failed to load NVL byte %" PRIu32 ": "
736                                 "expected 0x%02" PRIx8 ", read 0x%02" PRIx8,
737                                 i, buffer[i], val);
738                         return ERROR_FLASH_OPERATION_FAILED;
739                 }
740         }
741
742         retval = psoc5lp_spc_write_user_nvl(target, SPC_ARRAY_NVL_USER);
743         if (retval != ERROR_OK)
744                 return retval;
745
746         if (ecc_changed) {
747                 retval = target_call_reset_callbacks(target, RESET_INIT);
748                 if (retval != ERROR_OK)
749                         LOG_WARNING("Reset failed after enabling or disabling ECC");
750         }
751
752         return ERROR_OK;
753 }
754
755 static int psoc5lp_nvl_protect_check(struct flash_bank *bank)
756 {
757         int i;
758
759         for (i = 0; i < bank->num_sectors; i++)
760                 bank->sectors[i].is_protected = -1;
761
762         return ERROR_OK;
763 }
764
765 static int psoc5lp_nvl_get_info_command(struct flash_bank *bank,
766         char *buf, int buf_size)
767 {
768         struct psoc5lp_nvl_flash_bank *psoc_nvl_bank = bank->driver_priv;
769         char part_number[PART_NUMBER_LEN];
770
771         psoc5lp_get_part_number(psoc_nvl_bank->device, part_number);
772
773         snprintf(buf, buf_size, "%s", part_number);
774
775         return ERROR_OK;
776 }
777
778 static int psoc5lp_nvl_probe(struct flash_bank *bank)
779 {
780         struct psoc5lp_nvl_flash_bank *psoc_nvl_bank = bank->driver_priv;
781         int retval;
782
783         if (psoc_nvl_bank->probed)
784                 return ERROR_OK;
785
786         if (bank->target->state != TARGET_HALTED) {
787                 LOG_ERROR("Target not halted");
788                 return ERROR_TARGET_NOT_HALTED;
789         }
790
791         retval = psoc5lp_find_device(bank->target, &psoc_nvl_bank->device);
792         if (retval != ERROR_OK)
793                 return retval;
794
795         bank->base = NVL_META_BASE;
796         bank->size = 4;
797         bank->num_sectors = 1;
798         bank->sectors = calloc(bank->num_sectors,
799                                sizeof(struct flash_sector));
800         bank->sectors[0].offset = 0;
801         bank->sectors[0].size = 4;
802         bank->sectors[0].is_erased = -1;
803         bank->sectors[0].is_protected = -1;
804
805         psoc_nvl_bank->probed = true;
806
807         return ERROR_OK;
808 }
809
810 static int psoc5lp_nvl_auto_probe(struct flash_bank *bank)
811 {
812         struct psoc5lp_nvl_flash_bank *psoc_nvl_bank = bank->driver_priv;
813
814         if (psoc_nvl_bank->probed)
815                 return ERROR_OK;
816
817         return psoc5lp_nvl_probe(bank);
818 }
819
820 FLASH_BANK_COMMAND_HANDLER(psoc5lp_nvl_flash_bank_command)
821 {
822         struct psoc5lp_nvl_flash_bank *psoc_nvl_bank;
823
824         psoc_nvl_bank = malloc(sizeof(struct psoc5lp_nvl_flash_bank));
825         if (!psoc_nvl_bank)
826                 return ERROR_FLASH_OPERATION_FAILED;
827
828         psoc_nvl_bank->probed = false;
829
830         bank->driver_priv = psoc_nvl_bank;
831
832         return ERROR_OK;
833 }
834
835 static const struct command_registration psoc5lp_nvl_exec_command_handlers[] = {
836         COMMAND_REGISTRATION_DONE
837 };
838
839 static const struct command_registration psoc5lp_nvl_command_handlers[] = {
840         {
841                 .name = "psoc5lp_nvl",
842                 .mode = COMMAND_ANY,
843                 .help = "PSoC 5LP NV Latch command group",
844                 .usage = "",
845                 .chain = psoc5lp_nvl_exec_command_handlers,
846         },
847         COMMAND_REGISTRATION_DONE
848 };
849
850 struct flash_driver psoc5lp_nvl_flash = {
851         .name = "psoc5lp_nvl",
852         .commands = psoc5lp_nvl_command_handlers,
853         .flash_bank_command = psoc5lp_nvl_flash_bank_command,
854         .info = psoc5lp_nvl_get_info_command,
855         .probe = psoc5lp_nvl_probe,
856         .auto_probe = psoc5lp_nvl_auto_probe,
857         .protect_check = psoc5lp_nvl_protect_check,
858         .read = psoc5lp_nvl_read,
859         .erase = psoc5lp_nvl_erase,
860         .erase_check = psoc5lp_nvl_erase_check,
861         .write = psoc5lp_nvl_write,
862 };
863
864 /*
865  * EEPROM
866  */
867
868 struct psoc5lp_eeprom_flash_bank {
869         bool probed;
870         const struct psoc5lp_device *device;
871 };
872
873 static int psoc5lp_eeprom_erase(struct flash_bank *bank, int first, int last)
874 {
875         int i, retval;
876
877         for (i = first; i <= last; i++) {
878                 retval = psoc5lp_spc_erase_sector(bank->target,
879                                 SPC_ARRAY_EEPROM, i);
880                 if (retval != ERROR_OK)
881                         return retval;
882         }
883
884         return ERROR_OK;
885 }
886
887 static int psoc5lp_eeprom_write(struct flash_bank *bank,
888         const uint8_t *buffer, uint32_t offset, uint32_t byte_count)
889 {
890         struct target *target = bank->target;
891         uint8_t temp[2];
892         unsigned row;
893         int retval;
894
895         if (offset % EEPROM_ROW_SIZE != 0) {
896                 LOG_ERROR("Writes must be row-aligned, got offset 0x%08" PRIx32,
897                         offset);
898                 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
899         }
900
901         retval = psoc5lp_spc_get_temp(target, 3, temp);
902         if (retval != ERROR_OK) {
903                 LOG_ERROR("Unable to read Die temperature");
904                 return retval;
905         }
906         LOG_DEBUG("Get_Temp: sign 0x%02" PRIx8 ", magnitude 0x%02" PRIx8,
907                 temp[0], temp[1]);
908
909         for (row = offset / EEPROM_ROW_SIZE; byte_count >= EEPROM_ROW_SIZE; row++) {
910                 retval = psoc5lp_spc_load_row(target, SPC_ARRAY_EEPROM,
911                                 buffer, EEPROM_ROW_SIZE);
912                 if (retval != ERROR_OK)
913                         return retval;
914
915                 retval = psoc5lp_spc_write_row(target, SPC_ARRAY_EEPROM,
916                                 row, temp);
917                 if (retval != ERROR_OK)
918                         return retval;
919
920                 buffer += EEPROM_ROW_SIZE;
921                 byte_count -= EEPROM_ROW_SIZE;
922                 offset += EEPROM_ROW_SIZE;
923         }
924         if (byte_count > 0) {
925                 uint8_t buf[EEPROM_ROW_SIZE];
926
927                 memcpy(buf, buffer, byte_count);
928                 memset(buf + byte_count, bank->default_padded_value,
929                                 EEPROM_ROW_SIZE - byte_count);
930
931                 LOG_DEBUG("Padding %d bytes", EEPROM_ROW_SIZE - byte_count);
932                 retval = psoc5lp_spc_load_row(target, SPC_ARRAY_EEPROM,
933                                 buf, EEPROM_ROW_SIZE);
934                 if (retval != ERROR_OK)
935                         return retval;
936
937                 retval = psoc5lp_spc_write_row(target, SPC_ARRAY_EEPROM,
938                                 row, temp);
939                 if (retval != ERROR_OK)
940                         return retval;
941         }
942
943         return ERROR_OK;
944 }
945
946 static int psoc5lp_eeprom_protect_check(struct flash_bank *bank)
947 {
948         int i;
949
950         for (i = 0; i < bank->num_sectors; i++)
951                 bank->sectors[i].is_protected = -1;
952
953         return ERROR_OK;
954 }
955
956 static int psoc5lp_eeprom_get_info_command(struct flash_bank *bank, char *buf, int buf_size)
957 {
958         struct psoc5lp_eeprom_flash_bank *psoc_eeprom_bank = bank->driver_priv;
959         char part_number[PART_NUMBER_LEN];
960
961         psoc5lp_get_part_number(psoc_eeprom_bank->device, part_number);
962
963         snprintf(buf, buf_size, "%s", part_number);
964
965         return ERROR_OK;
966 }
967
968 static int psoc5lp_eeprom_probe(struct flash_bank *bank)
969 {
970         struct psoc5lp_eeprom_flash_bank *psoc_eeprom_bank = bank->driver_priv;
971         uint32_t flash_addr = bank->base;
972         uint32_t val;
973         int i, retval;
974
975         if (psoc_eeprom_bank->probed)
976                 return ERROR_OK;
977
978         if (bank->target->state != TARGET_HALTED) {
979                 LOG_ERROR("Target not halted");
980                 return ERROR_TARGET_NOT_HALTED;
981         }
982
983         retval = psoc5lp_find_device(bank->target, &psoc_eeprom_bank->device);
984         if (retval != ERROR_OK)
985                 return retval;
986
987         retval = target_read_u32(bank->target, PM_ACT_CFG12, &val);
988         if (retval != ERROR_OK)
989                 return retval;
990         if (!(val & PM_ACT_CFG12_EN_EE)) {
991                 val |= PM_ACT_CFG12_EN_EE;
992                 retval = target_write_u32(bank->target, PM_ACT_CFG12, val);
993                 if (retval != ERROR_OK)
994                         return retval;
995         }
996
997         bank->size = psoc_eeprom_bank->device->eeprom_kb * 1024;
998         bank->num_sectors = DIV_ROUND_UP(bank->size, EEPROM_SECTOR_SIZE);
999         bank->sectors = calloc(bank->num_sectors,
1000                                sizeof(struct flash_sector));
1001         for (i = 0; i < bank->num_sectors; i++) {
1002                 bank->sectors[i].size = EEPROM_SECTOR_SIZE;
1003                 bank->sectors[i].offset = flash_addr - bank->base;
1004                 bank->sectors[i].is_erased = -1;
1005                 bank->sectors[i].is_protected = -1;
1006
1007                 flash_addr += bank->sectors[i].size;
1008         }
1009
1010         bank->default_padded_value = bank->erased_value = 0x00;
1011
1012         psoc_eeprom_bank->probed = true;
1013
1014         return ERROR_OK;
1015 }
1016
1017 static int psoc5lp_eeprom_auto_probe(struct flash_bank *bank)
1018 {
1019         struct psoc5lp_eeprom_flash_bank *psoc_eeprom_bank = bank->driver_priv;
1020
1021         if (psoc_eeprom_bank->probed)
1022                 return ERROR_OK;
1023
1024         return psoc5lp_eeprom_probe(bank);
1025 }
1026
1027 FLASH_BANK_COMMAND_HANDLER(psoc5lp_eeprom_flash_bank_command)
1028 {
1029         struct psoc5lp_eeprom_flash_bank *psoc_eeprom_bank;
1030
1031         psoc_eeprom_bank = malloc(sizeof(struct psoc5lp_eeprom_flash_bank));
1032         if (!psoc_eeprom_bank)
1033                 return ERROR_FLASH_OPERATION_FAILED;
1034
1035         psoc_eeprom_bank->probed = false;
1036         psoc_eeprom_bank->device = NULL;
1037
1038         bank->driver_priv = psoc_eeprom_bank;
1039
1040         return ERROR_OK;
1041 }
1042
1043 static const struct command_registration psoc5lp_eeprom_exec_command_handlers[] = {
1044         COMMAND_REGISTRATION_DONE
1045 };
1046
1047 static const struct command_registration psoc5lp_eeprom_command_handlers[] = {
1048         {
1049                 .name = "psoc5lp_eeprom",
1050                 .mode = COMMAND_ANY,
1051                 .help = "PSoC 5LP EEPROM command group",
1052                 .usage = "",
1053                 .chain = psoc5lp_eeprom_exec_command_handlers,
1054         },
1055         COMMAND_REGISTRATION_DONE
1056 };
1057
1058 struct flash_driver psoc5lp_eeprom_flash = {
1059         .name = "psoc5lp_eeprom",
1060         .commands = psoc5lp_eeprom_command_handlers,
1061         .flash_bank_command = psoc5lp_eeprom_flash_bank_command,
1062         .info = psoc5lp_eeprom_get_info_command,
1063         .probe = psoc5lp_eeprom_probe,
1064         .auto_probe = psoc5lp_eeprom_auto_probe,
1065         .protect_check = psoc5lp_eeprom_protect_check,
1066         .read = default_flash_read,
1067         .erase = psoc5lp_eeprom_erase,
1068         .erase_check = default_flash_blank_check,
1069         .write = psoc5lp_eeprom_write,
1070 };
1071
1072 /*
1073  * Program Flash
1074  */
1075
1076 struct psoc5lp_flash_bank {
1077         bool probed;
1078         const struct psoc5lp_device *device;
1079         bool ecc_enabled;
1080 };
1081
1082 static int psoc5lp_erase(struct flash_bank *bank, int first, int last)
1083 {
1084         struct psoc5lp_flash_bank *psoc_bank = bank->driver_priv;
1085         int i, retval;
1086
1087         if (!psoc_bank->ecc_enabled) {
1088                 /* Silently avoid erasing sectors twice */
1089                 if (last >= first + bank->num_sectors / 2) {
1090                         LOG_DEBUG("Skipping duplicate erase of sectors %d to %d",
1091                                 first + bank->num_sectors / 2, last);
1092                         last = first + (bank->num_sectors / 2) - 1;
1093                 }
1094                 /* Check for any remaining ECC sectors */
1095                 if (last >= bank->num_sectors / 2) {
1096                         LOG_WARNING("Skipping erase of ECC region sectors %d to %d",
1097                                 bank->num_sectors / 2, last);
1098                         last = (bank->num_sectors / 2) - 1;
1099                 }
1100         }
1101
1102         for (i = first; i <= last; i++) {
1103                 retval = psoc5lp_spc_erase_sector(bank->target,
1104                                 i / SECTORS_PER_BLOCK, i % SECTORS_PER_BLOCK);
1105                 if (retval != ERROR_OK)
1106                         return retval;
1107         }
1108
1109         return ERROR_OK;
1110 }
1111
1112 /* Derived from core.c:default_flash_blank_check() */
1113 static int psoc5lp_erase_check(struct flash_bank *bank)
1114 {
1115         struct psoc5lp_flash_bank *psoc_bank = bank->driver_priv;
1116         struct target *target = bank->target;
1117         int i, retval;
1118
1119         if (target->state != TARGET_HALTED) {
1120                 LOG_ERROR("Target not halted");
1121                 return ERROR_TARGET_NOT_HALTED;
1122         }
1123
1124         struct target_memory_check_block *block_array;
1125         block_array = malloc(bank->num_sectors * sizeof(struct target_memory_check_block));
1126         if (block_array == NULL)
1127                 return ERROR_FAIL;
1128
1129         for (i = 0; i < bank->num_sectors; i++) {
1130                 block_array[i].address = bank->base + bank->sectors[i].offset;
1131                 block_array[i].size = bank->sectors[i].size;
1132                 block_array[i].result = UINT32_MAX; /* erase state unknown */
1133         }
1134
1135         bool fast_check = true;
1136         for (i = 0; i < bank->num_sectors; ) {
1137                 retval = armv7m_blank_check_memory(target,
1138                                         block_array + i, bank->num_sectors - i,
1139                                         bank->erased_value);
1140                 if (retval < 1) {
1141                         /* Run slow fallback if the first run gives no result
1142                          * otherwise use possibly incomplete results */
1143                         if (i == 0)
1144                                 fast_check = false;
1145                         break;
1146                 }
1147                 i += retval; /* add number of blocks done this round */
1148         }
1149
1150         if (fast_check) {
1151                 if (!psoc_bank->ecc_enabled) {
1152                         int half_sectors = bank->num_sectors / 2;
1153                         for (i = 0; i < half_sectors / 2; i++)
1154                                 bank->sectors[i].is_erased =
1155                                         (block_array[i].result != 1)
1156                                         ? block_array[i + half_sectors].result
1157                                         : block_array[i].result;
1158                 } else {
1159                         for (i = 0; i < bank->num_sectors; i++)
1160                                 bank->sectors[i].is_erased = block_array[i].result;
1161                 }
1162                 retval = ERROR_OK;
1163         } else {
1164                 LOG_ERROR("Can't run erase check - add working memory");
1165                 retval = ERROR_FAIL;
1166         }
1167         free(block_array);
1168
1169         return retval;
1170 }
1171
1172 static int psoc5lp_write(struct flash_bank *bank, const uint8_t *buffer,
1173                 uint32_t offset, uint32_t byte_count)
1174 {
1175         struct psoc5lp_flash_bank *psoc_bank = bank->driver_priv;
1176         struct target *target = bank->target;
1177         struct working_area *code_area, *even_row_area, *odd_row_area;
1178         uint32_t row_size;
1179         uint8_t temp[2], buf[12], ecc_bytes[ROW_ECC_SIZE];
1180         unsigned array_id, row;
1181         int i, retval;
1182
1183         if (offset + byte_count > bank->size) {
1184                 LOG_ERROR("Writing to ECC not supported");
1185                 return ERROR_FLASH_DST_OUT_OF_BANK;
1186         }
1187
1188         if (offset % ROW_SIZE != 0) {
1189                 LOG_ERROR("Writes must be row-aligned, got offset 0x%08" PRIx32,
1190                         offset);
1191                 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
1192         }
1193
1194         row_size = ROW_SIZE;
1195         if (!psoc_bank->ecc_enabled) {
1196                 row_size += ROW_ECC_SIZE;
1197                 memset(ecc_bytes, bank->default_padded_value, ROW_ECC_SIZE);
1198         }
1199
1200         retval = psoc5lp_spc_get_temp(target, 3, temp);
1201         if (retval != ERROR_OK) {
1202                 LOG_ERROR("Unable to read Die temperature");
1203                 return retval;
1204         }
1205         LOG_DEBUG("Get_Temp: sign 0x%02" PRIx8 ", magnitude 0x%02" PRIx8,
1206                 temp[0], temp[1]);
1207
1208         assert(target_get_working_area_avail(target) == target->working_area_size);
1209         retval = target_alloc_working_area(target,
1210                         target_get_working_area_avail(target) / 2, &code_area);
1211         if (retval != ERROR_OK) {
1212                 LOG_ERROR("Could not allocate working area for program SRAM");
1213                 return retval;
1214         }
1215         assert(code_area->address < 0x20000000);
1216
1217         retval = target_alloc_working_area(target,
1218                         SPC_OPCODE_LEN + 1 + row_size + 3 + SPC_OPCODE_LEN + 6,
1219                         &even_row_area);
1220         if (retval != ERROR_OK) {
1221                 LOG_ERROR("Could not allocate working area for even row");
1222                 goto err_alloc_even;
1223         }
1224         assert(even_row_area->address >= 0x20000000);
1225
1226         retval = target_alloc_working_area(target, even_row_area->size,
1227                         &odd_row_area);
1228         if (retval != ERROR_OK) {
1229                 LOG_ERROR("Could not allocate working area for odd row");
1230                 goto err_alloc_odd;
1231         }
1232         assert(odd_row_area->address >= 0x20000000);
1233
1234         for (array_id = offset / BLOCK_SIZE; byte_count > 0; array_id++) {
1235                 for (row = (offset / ROW_SIZE) % ROWS_PER_BLOCK;
1236                      row < ROWS_PER_BLOCK && byte_count > 0; row++) {
1237                         bool even_row = (row % 2 == 0);
1238                         struct working_area *data_area = even_row ? even_row_area : odd_row_area;
1239                         unsigned len = MIN(ROW_SIZE, byte_count);
1240
1241                         LOG_DEBUG("Writing load command for array %u row %u at 0x%08" TARGET_PRIxADDR,
1242                                 array_id, row, data_area->address);
1243
1244                         psoc5lp_spc_write_opcode_buffer(target, buf, SPC_LOAD_ROW);
1245                         buf[SPC_OPCODE_LEN] = array_id;
1246                         retval = target_write_buffer(target, data_area->address, 4, buf);
1247                         if (retval != ERROR_OK)
1248                                 goto err_write;
1249
1250                         retval = target_write_buffer(target,
1251                                 data_area->address + SPC_OPCODE_LEN + 1,
1252                                 len, buffer);
1253                         if (retval != ERROR_OK)
1254                                 goto err_write;
1255                         buffer += len;
1256                         byte_count -= len;
1257                         offset += len;
1258
1259                         if (len < ROW_SIZE) {
1260                                 uint8_t padding[ROW_SIZE];
1261
1262                                 memset(padding, bank->default_padded_value, ROW_SIZE);
1263
1264                                 LOG_DEBUG("Padding %d bytes", ROW_SIZE - len);
1265                                 retval = target_write_buffer(target,
1266                                         data_area->address + SPC_OPCODE_LEN + 1 + len,
1267                                         ROW_SIZE - len, padding);
1268                                 if (retval != ERROR_OK)
1269                                         goto err_write;
1270                         }
1271
1272                         if (!psoc_bank->ecc_enabled) {
1273                                 retval = target_write_buffer(target,
1274                                         data_area->address + SPC_OPCODE_LEN + 1 + ROW_SIZE,
1275                                         sizeof(ecc_bytes), ecc_bytes);
1276                                 if (retval != ERROR_OK)
1277                                         goto err_write;
1278                         }
1279
1280                         for (i = 0; i < 3; i++)
1281                                 buf[i] = 0x00; /* 3 NOPs for short delay */
1282                         psoc5lp_spc_write_opcode_buffer(target, buf + 3, SPC_PRG_ROW);
1283                         buf[3 + SPC_OPCODE_LEN] = array_id;
1284                         buf[3 + SPC_OPCODE_LEN + 1] = row >> 8;
1285                         buf[3 + SPC_OPCODE_LEN + 2] = row & 0xff;
1286                         memcpy(buf + 3 + SPC_OPCODE_LEN + 3, temp, 2);
1287                         buf[3 + SPC_OPCODE_LEN + 5] = 0x00; /* padding */
1288                         retval = target_write_buffer(target,
1289                                 data_area->address + SPC_OPCODE_LEN + 1 + row_size,
1290                                 12, buf);
1291                         if (retval != ERROR_OK)
1292                                 goto err_write;
1293
1294                         retval = target_write_u32(target,
1295                                 even_row ? PHUB_CH0_BASIC_STATUS : PHUB_CH1_BASIC_STATUS,
1296                                 (even_row ? 0 : 1) << 8);
1297                         if (retval != ERROR_OK)
1298                                 goto err_dma;
1299
1300                         retval = target_write_u32(target,
1301                                 even_row ? PHUB_CH0_BASIC_CFG : PHUB_CH1_BASIC_CFG,
1302                                 PHUB_CHx_BASIC_CFG_WORK_SEP | PHUB_CHx_BASIC_CFG_EN);
1303                         if (retval != ERROR_OK)
1304                                 goto err_dma;
1305
1306                         retval = target_write_u32(target,
1307                                 even_row ? PHUB_CFGMEM0_CFG0 : PHUB_CFGMEM1_CFG0,
1308                                 PHUB_CFGMEMx_CFG0);
1309                         if (retval != ERROR_OK)
1310                                 goto err_dma;
1311
1312                         retval = target_write_u32(target,
1313                                 even_row ? PHUB_CFGMEM0_CFG1 : PHUB_CFGMEM1_CFG1,
1314                                 ((SPC_CPU_DATA >> 16) << 16) | (data_area->address >> 16));
1315                         if (retval != ERROR_OK)
1316                                 goto err_dma;
1317
1318                         retval = target_write_u32(target,
1319                                 even_row ? PHUB_TDMEM0_ORIG_TD0 : PHUB_TDMEM1_ORIG_TD0,
1320                                 PHUB_TDMEMx_ORIG_TD0_INC_SRC_ADDR |
1321                                 PHUB_TDMEMx_ORIG_TD0_NEXT_TD_PTR_LAST |
1322                                 ((SPC_OPCODE_LEN + 1 + row_size + 3 + SPC_OPCODE_LEN + 5) & 0xfff));
1323                         if (retval != ERROR_OK)
1324                                 goto err_dma;
1325
1326                         retval = target_write_u32(target,
1327                                 even_row ? PHUB_TDMEM0_ORIG_TD1 : PHUB_TDMEM1_ORIG_TD1,
1328                                 ((SPC_CPU_DATA & 0xffff) << 16) | (data_area->address & 0xffff));
1329                         if (retval != ERROR_OK)
1330                                 goto err_dma;
1331
1332                         retval = psoc5lp_spc_busy_wait_idle(target);
1333                         if (retval != ERROR_OK)
1334                                 goto err_idle;
1335
1336                         retval = target_write_u32(target,
1337                                 even_row ? PHUB_CH0_ACTION : PHUB_CH1_ACTION,
1338                                 PHUB_CHx_ACTION_CPU_REQ);
1339                         if (retval != ERROR_OK)
1340                                 goto err_dma_action;
1341                 }
1342         }
1343
1344         retval = psoc5lp_spc_busy_wait_idle(target);
1345
1346 err_dma_action:
1347 err_idle:
1348 err_dma:
1349 err_write:
1350         target_free_working_area(target, odd_row_area);
1351 err_alloc_odd:
1352         target_free_working_area(target, even_row_area);
1353 err_alloc_even:
1354         target_free_working_area(target, code_area);
1355
1356         return retval;
1357 }
1358
1359 static int psoc5lp_protect_check(struct flash_bank *bank)
1360 {
1361         struct psoc5lp_flash_bank *psoc_bank = bank->driver_priv;
1362         uint8_t row_data[ROW_SIZE];
1363         const unsigned protection_bytes_per_sector = ROWS_PER_SECTOR * 2 / 8;
1364         unsigned i, j, k, num_sectors;
1365         int retval;
1366
1367         if (bank->target->state != TARGET_HALTED) {
1368                 LOG_ERROR("Target not halted");
1369                 return ERROR_TARGET_NOT_HALTED;
1370         }
1371
1372         for (i = 0; i < DIV_ROUND_UP(bank->size, BLOCK_SIZE); i++) {
1373                 retval = psoc5lp_spc_read_hidden_row(bank->target, i,
1374                                 SPC_ROW_PROTECTION, row_data);
1375                 if (retval != ERROR_OK)
1376                         return retval;
1377
1378                 /* Last flash array may have less rows, but in practice full sectors. */
1379                 if (i == bank->size / BLOCK_SIZE)
1380                         num_sectors = (bank->size % BLOCK_SIZE) / SECTOR_SIZE;
1381                 else
1382                         num_sectors = SECTORS_PER_BLOCK;
1383
1384                 for (j = 0; j < num_sectors; j++) {
1385                         int sector_nr = i * SECTORS_PER_BLOCK + j;
1386                         struct flash_sector *sector = &bank->sectors[sector_nr];
1387                         struct flash_sector *ecc_sector;
1388
1389                         if (psoc_bank->ecc_enabled)
1390                                 ecc_sector = &bank->sectors[bank->num_sectors + sector_nr];
1391                         else
1392                                 ecc_sector = &bank->sectors[bank->num_sectors / 2 + sector_nr];
1393
1394                         sector->is_protected = ecc_sector->is_protected = 0;
1395                         for (k = protection_bytes_per_sector * j;
1396                              k < protection_bytes_per_sector * (j + 1); k++) {
1397                                 assert(k < protection_bytes_per_sector * SECTORS_PER_BLOCK);
1398                                 LOG_DEBUG("row[%u][%02u] = 0x%02" PRIx8, i, k, row_data[k]);
1399                                 if (row_data[k] != 0x00) {
1400                                         sector->is_protected = ecc_sector->is_protected = 1;
1401                                         break;
1402                                 }
1403                         }
1404                 }
1405         }
1406
1407         return ERROR_OK;
1408 }
1409
1410 static int psoc5lp_get_info_command(struct flash_bank *bank, char *buf, int buf_size)
1411 {
1412         struct psoc5lp_flash_bank *psoc_bank = bank->driver_priv;
1413         char part_number[PART_NUMBER_LEN];
1414         const char *ecc;
1415
1416         psoc5lp_get_part_number(psoc_bank->device, part_number);
1417         ecc = psoc_bank->ecc_enabled ? "ECC enabled" : "ECC disabled";
1418
1419         snprintf(buf, buf_size, "%s %s", part_number, ecc);
1420
1421         return ERROR_OK;
1422 }
1423
1424 static int psoc5lp_probe(struct flash_bank *bank)
1425 {
1426         struct target *target = bank->target;
1427         struct psoc5lp_flash_bank *psoc_bank = bank->driver_priv;
1428         uint32_t flash_addr = bank->base;
1429         uint8_t nvl[4], temp[2];
1430         int i, retval;
1431
1432         if (target->state != TARGET_HALTED) {
1433                 LOG_ERROR("Target not halted");
1434                 return ERROR_TARGET_NOT_HALTED;
1435         }
1436
1437         if (!psoc_bank->device) {
1438                 retval = psoc5lp_find_device(target, &psoc_bank->device);
1439                 if (retval != ERROR_OK)
1440                         return retval;
1441
1442                 bank->size = psoc_bank->device->flash_kb * 1024;
1443         }
1444
1445         bank->num_sectors = DIV_ROUND_UP(bank->size, SECTOR_SIZE);
1446
1447         if (!psoc_bank->probed) {
1448                 retval = psoc5lp_spc_enable_clock(target);
1449                 if (retval != ERROR_OK)
1450                         return retval;
1451
1452                 /* First values read are inaccurate, so do it once now. */
1453                 retval = psoc5lp_spc_get_temp(target, 3, temp);
1454                 if (retval != ERROR_OK) {
1455                         LOG_ERROR("Unable to read Die temperature");
1456                         return retval;
1457                 }
1458
1459                 bank->sectors = calloc(bank->num_sectors * 2,
1460                                        sizeof(struct flash_sector));
1461                 for (i = 0; i < bank->num_sectors; i++) {
1462                         bank->sectors[i].size = SECTOR_SIZE;
1463                         bank->sectors[i].offset = flash_addr - bank->base;
1464                         bank->sectors[i].is_erased = -1;
1465                         bank->sectors[i].is_protected = -1;
1466
1467                         flash_addr += bank->sectors[i].size;
1468                 }
1469                 flash_addr = 0x48000000;
1470                 for (i = bank->num_sectors; i < bank->num_sectors * 2; i++) {
1471                         bank->sectors[i].size = ROWS_PER_SECTOR * ROW_ECC_SIZE;
1472                         bank->sectors[i].offset = flash_addr - bank->base;
1473                         bank->sectors[i].is_erased = -1;
1474                         bank->sectors[i].is_protected = -1;
1475
1476                         flash_addr += bank->sectors[i].size;
1477                 }
1478
1479                 bank->default_padded_value = bank->erased_value = 0x00;
1480
1481                 psoc_bank->probed = true;
1482         }
1483
1484         retval = psoc5lp_spc_read_byte(target, SPC_ARRAY_NVL_USER, 3, &nvl[3]);
1485         if (retval != ERROR_OK)
1486                 return retval;
1487         LOG_DEBUG("NVL[%d] = 0x%02" PRIx8, 3, nvl[3]);
1488         psoc_bank->ecc_enabled = nvl[3] & NVL_3_ECCEN;
1489
1490         if (!psoc_bank->ecc_enabled)
1491                 bank->num_sectors *= 2;
1492
1493         return ERROR_OK;
1494 }
1495
1496 static int psoc5lp_auto_probe(struct flash_bank *bank)
1497 {
1498         return psoc5lp_probe(bank);
1499 }
1500
1501 COMMAND_HANDLER(psoc5lp_handle_mass_erase_command)
1502 {
1503         struct flash_bank *bank;
1504         int retval;
1505
1506         if (CMD_ARGC < 1)
1507                 return ERROR_COMMAND_SYNTAX_ERROR;
1508
1509         retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
1510         if (retval != ERROR_OK)
1511                 return retval;
1512
1513         retval = psoc5lp_spc_erase_all(bank->target);
1514         if (retval == ERROR_OK)
1515                 command_print(CMD_CTX, "PSoC 5LP erase succeeded");
1516         else
1517                 command_print(CMD_CTX, "PSoC 5LP erase failed");
1518
1519         return retval;
1520 }
1521
1522 FLASH_BANK_COMMAND_HANDLER(psoc5lp_flash_bank_command)
1523 {
1524         struct psoc5lp_flash_bank *psoc_bank;
1525
1526         psoc_bank = malloc(sizeof(struct psoc5lp_flash_bank));
1527         if (!psoc_bank)
1528                 return ERROR_FLASH_OPERATION_FAILED;
1529
1530         psoc_bank->probed = false;
1531         psoc_bank->device = NULL;
1532
1533         bank->driver_priv = psoc_bank;
1534
1535         return ERROR_OK;
1536 }
1537
1538 static const struct command_registration psoc5lp_exec_command_handlers[] = {
1539         {
1540                 .name = "mass_erase",
1541                 .handler = psoc5lp_handle_mass_erase_command,
1542                 .mode = COMMAND_EXEC,
1543                 .usage = "bank_id",
1544                 .help = "Erase all flash data and ECC/configuration bytes, "
1545                         "all flash protection rows, "
1546                         "and all row latches in all flash arrays on the device.",
1547         },
1548         COMMAND_REGISTRATION_DONE
1549 };
1550
1551 static const struct command_registration psoc5lp_command_handlers[] = {
1552         {
1553                 .name = "psoc5lp",
1554                 .mode = COMMAND_ANY,
1555                 .help = "PSoC 5LP flash command group",
1556                 .usage = "",
1557                 .chain = psoc5lp_exec_command_handlers,
1558         },
1559         COMMAND_REGISTRATION_DONE
1560 };
1561
1562 struct flash_driver psoc5lp_flash = {
1563         .name = "psoc5lp",
1564         .commands = psoc5lp_command_handlers,
1565         .flash_bank_command = psoc5lp_flash_bank_command,
1566         .info = psoc5lp_get_info_command,
1567         .probe = psoc5lp_probe,
1568         .auto_probe = psoc5lp_auto_probe,
1569         .protect_check = psoc5lp_protect_check,
1570         .read = default_flash_read,
1571         .erase = psoc5lp_erase,
1572         .erase_check = psoc5lp_erase_check,
1573         .write = psoc5lp_write,
1574 };