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