flash/nor: Add PSoC 5LP flash driver
[fw/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 SPC_CPU_DATA            0x40004720
30 #define SPC_SR                  0x40004722
31 #define PHUB_CH0_BASIC_CFG      0x40007010
32 #define PHUB_CH0_ACTION         0x40007014
33 #define PHUB_CH0_BASIC_STATUS   0x40007018
34 #define PHUB_CH1_BASIC_CFG      0x40007020
35 #define PHUB_CH1_ACTION         0x40007024
36 #define PHUB_CH1_BASIC_STATUS   0x40007028
37 #define PHUB_CFGMEM0_CFG0       0x40007600
38 #define PHUB_CFGMEM0_CFG1       0x40007604
39 #define PHUB_CFGMEM1_CFG0       0x40007608
40 #define PHUB_CFGMEM1_CFG1       0x4000760C
41 #define PHUB_TDMEM0_ORIG_TD0    0x40007800
42 #define PHUB_TDMEM0_ORIG_TD1    0x40007804
43 #define PHUB_TDMEM1_ORIG_TD0    0x40007808
44 #define PHUB_TDMEM1_ORIG_TD1    0x4000780C
45 #define PANTHER_DEVICE_ID       0x4008001C
46
47 #define SPC_KEY1 0xB6
48 #define SPC_KEY2 0xD3
49
50 #define SPC_LOAD_BYTE           0x00
51 #define SPC_LOAD_MULTI_BYTE     0x01
52 #define SPC_LOAD_ROW            0x02
53 #define SPC_READ_BYTE           0x03
54 #define SPC_READ_MULTI_BYTE     0x04
55 #define SPC_WRITE_ROW           0x05
56 #define SPC_WRITE_USER_NVL      0x06
57 #define SPC_PRG_ROW             0x07
58 #define SPC_ERASE_SECTOR        0x08
59 #define SPC_ERASE_ALL           0x09
60 #define SPC_READ_HIDDEN_ROW     0x0A
61 #define SPC_PROGRAM_PROTECT_ROW 0x0B
62 #define SPC_GET_CHECKSUM        0x0C
63 #define SPC_GET_TEMP            0x0E
64 #define SPC_READ_VOLATILE_BYTE  0x10
65
66 #define SPC_ARRAY_ALL      0x3F
67 #define SPC_ARRAY_EEPROM   0x40
68 #define SPC_ARRAY_NVL_USER 0x80
69 #define SPC_ARRAY_NVL_WO   0xF8
70
71 #define SPC_ROW_PROTECTION 0
72
73 #define SPC_OPCODE_LEN 3
74
75 #define SPC_SR_DATA_READY (1 << 0)
76 #define SPC_SR_IDLE       (1 << 1)
77
78 #define PM_ACT_CFG0_EN_CLK_SPC      (1 << 3)
79
80 #define PHUB_CHx_BASIC_CFG_EN       (1 << 0)
81 #define PHUB_CHx_BASIC_CFG_WORK_SEP (1 << 5)
82
83 #define PHUB_CHx_ACTION_CPU_REQ (1 << 0)
84
85 #define PHUB_CFGMEMx_CFG0 (1 << 7)
86
87 #define PHUB_TDMEMx_ORIG_TD0_NEXT_TD_PTR_LAST (0xff << 16)
88 #define PHUB_TDMEMx_ORIG_TD0_INC_SRC_ADDR     (1 << 24)
89
90 #define NVL_3_ECCEN  (1 << 3)
91
92 #define ROW_SIZE           256
93 #define ROW_ECC_SIZE       32
94 #define ROWS_PER_SECTOR    64
95 #define SECTOR_SIZE        (ROWS_PER_SECTOR * ROW_SIZE)
96 #define ROWS_PER_BLOCK     256
97 #define BLOCK_SIZE         (ROWS_PER_BLOCK * ROW_SIZE)
98 #define SECTORS_PER_BLOCK  (BLOCK_SIZE / SECTOR_SIZE)
99
100 #define PART_NUMBER_LEN (17 + 1)
101
102 struct psoc5lp_device {
103         uint32_t id;
104         unsigned fam;
105         unsigned speed_mhz;
106         unsigned flash_kb;
107         unsigned eeprom_kb;
108 };
109
110 /*
111  * Device information collected from datasheets.
112  * Different temperature ranges (C/I/Q/A) may share IDs, not differing otherwise.
113  */
114 static const struct psoc5lp_device psoc5lp_devices[] = {
115         /* CY8C58LP Family Datasheet */
116         { .id = 0x2E11F069, .fam = 8, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 },
117         { .id = 0x2E120069, .fam = 8, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 },
118         { .id = 0x2E123069, .fam = 8, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 },
119         { .id = 0x2E124069, .fam = 8, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 },
120         { .id = 0x2E126069, .fam = 8, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 },
121         { .id = 0x2E127069, .fam = 8, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 },
122         { .id = 0x2E117069, .fam = 8, .speed_mhz = 67, .flash_kb = 128, .eeprom_kb = 2 },
123         { .id = 0x2E118069, .fam = 8, .speed_mhz = 67, .flash_kb = 128, .eeprom_kb = 2 },
124         { .id = 0x2E119069, .fam = 8, .speed_mhz = 67, .flash_kb = 128, .eeprom_kb = 2 },
125         { .id = 0x2E11C069, .fam = 8, .speed_mhz = 67, .flash_kb = 128, .eeprom_kb = 2 },
126         { .id = 0x2E114069, .fam = 8, .speed_mhz = 67, .flash_kb =  64, .eeprom_kb = 2 },
127         { .id = 0x2E115069, .fam = 8, .speed_mhz = 67, .flash_kb =  64, .eeprom_kb = 2 },
128         { .id = 0x2E116069, .fam = 8, .speed_mhz = 67, .flash_kb =  64, .eeprom_kb = 2 },
129         { .id = 0x2E160069, .fam = 8, .speed_mhz = 80, .flash_kb = 256, .eeprom_kb = 2 },
130         /*           ''                                                               */
131         { .id = 0x2E161069, .fam = 8, .speed_mhz = 80, .flash_kb = 256, .eeprom_kb = 2 },
132         /*           ''                                                               */
133         { .id = 0x2E1D2069, .fam = 8, .speed_mhz = 80, .flash_kb = 256, .eeprom_kb = 2 },
134         { .id = 0x2E1D6069, .fam = 8, .speed_mhz = 80, .flash_kb = 256, .eeprom_kb = 2 },
135
136         /* CY8C56LP Family Datasheet */
137         { .id = 0x2E10A069, .fam = 6, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 },
138         { .id = 0x2E10D069, .fam = 6, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 },
139         { .id = 0x2E10E069, .fam = 6, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 },
140         { .id = 0x2E106069, .fam = 6, .speed_mhz = 67, .flash_kb = 128, .eeprom_kb = 2 },
141         { .id = 0x2E108069, .fam = 6, .speed_mhz = 67, .flash_kb = 128, .eeprom_kb = 2 },
142         { .id = 0x2E109069, .fam = 6, .speed_mhz = 67, .flash_kb = 128, .eeprom_kb = 2 },
143         { .id = 0x2E101069, .fam = 6, .speed_mhz = 67, .flash_kb =  64, .eeprom_kb = 2 },
144         { .id = 0x2E104069, .fam = 6, .speed_mhz = 67, .flash_kb =  64, .eeprom_kb = 2 },
145         /*           ''                                                               */
146         { .id = 0x2E105069, .fam = 6, .speed_mhz = 67, .flash_kb =  64, .eeprom_kb = 2 },
147         { .id = 0x2E128069, .fam = 6, .speed_mhz = 67, .flash_kb = 128, .eeprom_kb = 2 },
148         /*           ''                                                               */
149         { .id = 0x2E122069, .fam = 6, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 },
150         { .id = 0x2E129069, .fam = 6, .speed_mhz = 67, .flash_kb = 128, .eeprom_kb = 2 },
151         { .id = 0x2E163069, .fam = 6, .speed_mhz = 80, .flash_kb = 256, .eeprom_kb = 2 },
152         { .id = 0x2E156069, .fam = 6, .speed_mhz = 80, .flash_kb = 256, .eeprom_kb = 2 },
153         { .id = 0x2E1D3069, .fam = 6, .speed_mhz = 80, .flash_kb = 256, .eeprom_kb = 2 },
154
155         /* CY8C54LP Family Datasheet */
156         { .id = 0x2E11A069, .fam = 4, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 },
157         { .id = 0x2E16A069, .fam = 4, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 },
158         { .id = 0x2E12A069, .fam = 4, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 },
159         { .id = 0x2E103069, .fam = 4, .speed_mhz = 67, .flash_kb = 128, .eeprom_kb = 2 },
160         { .id = 0x2E16C069, .fam = 4, .speed_mhz = 67, .flash_kb = 128, .eeprom_kb = 2 },
161         { .id = 0x2E102069, .fam = 4, .speed_mhz = 67, .flash_kb =  64, .eeprom_kb = 2 },
162         { .id = 0x2E148069, .fam = 4, .speed_mhz = 67, .flash_kb =  64, .eeprom_kb = 2 },
163         { .id = 0x2E155069, .fam = 4, .speed_mhz = 67, .flash_kb =  64, .eeprom_kb = 2 },
164         { .id = 0x2E16B069, .fam = 4, .speed_mhz = 67, .flash_kb =  64, .eeprom_kb = 2 },
165         { .id = 0x2E12B069, .fam = 4, .speed_mhz = 67, .flash_kb =  32, .eeprom_kb = 2 },
166         { .id = 0x2E168069, .fam = 4, .speed_mhz = 67, .flash_kb =  32, .eeprom_kb = 2 },
167         { .id = 0x2E178069, .fam = 4, .speed_mhz = 80, .flash_kb = 256, .eeprom_kb = 2 },
168         { .id = 0x2E15D069, .fam = 4, .speed_mhz = 80, .flash_kb = 256, .eeprom_kb = 2 },
169         { .id = 0x2E1D4069, .fam = 4, .speed_mhz = 80, .flash_kb = 256, .eeprom_kb = 2 },
170
171         /* CY8C52LP Family Datasheet */
172         { .id = 0x2E11E069, .fam = 2, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 },
173         { .id = 0x2E12F069, .fam = 2, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 },
174         { .id = 0x2E133069, .fam = 2, .speed_mhz = 67, .flash_kb = 128, .eeprom_kb = 2 },
175         { .id = 0x2E159069, .fam = 2, .speed_mhz = 67, .flash_kb = 128, .eeprom_kb = 2 },
176         { .id = 0x2E11D069, .fam = 2, .speed_mhz = 67, .flash_kb =  64, .eeprom_kb = 2 },
177         { .id = 0x2E121069, .fam = 2, .speed_mhz = 67, .flash_kb =  64, .eeprom_kb = 2 },
178         { .id = 0x2E184069, .fam = 2, .speed_mhz = 67, .flash_kb =  64, .eeprom_kb = 2 },
179         { .id = 0x2E196069, .fam = 2, .speed_mhz = 67, .flash_kb =  64, .eeprom_kb = 2 },
180         { .id = 0x2E132069, .fam = 2, .speed_mhz = 67, .flash_kb =  32, .eeprom_kb = 2 },
181         { .id = 0x2E138069, .fam = 2, .speed_mhz = 67, .flash_kb =  32, .eeprom_kb = 2 },
182         { .id = 0x2E13A069, .fam = 2, .speed_mhz = 67, .flash_kb =  32, .eeprom_kb = 2 },
183         { .id = 0x2E152069, .fam = 2, .speed_mhz = 67, .flash_kb =  32, .eeprom_kb = 2 },
184         { .id = 0x2E15F069, .fam = 2, .speed_mhz = 80, .flash_kb = 256, .eeprom_kb = 2 },
185         { .id = 0x2E15A069, .fam = 2, .speed_mhz = 80, .flash_kb = 256, .eeprom_kb = 2 },
186         { .id = 0x2E1D5069, .fam = 2, .speed_mhz = 80, .flash_kb = 256, .eeprom_kb = 2 },
187 };
188
189 static void psoc5lp_get_part_number(const struct psoc5lp_device *dev, char *str)
190 {
191         strcpy(str, "CY8Cabcdefg-LPxxx");
192
193         str[4] = '5';
194         str[5] = '0' + dev->fam;
195
196         switch (dev->speed_mhz) {
197         case 67:
198                 str[6] = '6';
199                 break;
200         case 80:
201                 str[6] = '8';
202                 break;
203         default:
204                 str[6] = '?';
205         }
206
207         switch (dev->flash_kb) {
208         case 32:
209                 str[7] = '5';
210                 break;
211         case 64:
212                 str[7] = '6';
213                 break;
214         case 128:
215                 str[7] = '7';
216                 break;
217         case 256:
218                 str[7] = '8';
219                 break;
220         default:
221                 str[7] = '?';
222         }
223
224         /* Package does not matter. */
225         strncpy(str + 8, "xx", 2);
226
227         /* Temperate range cannot uniquely be identified. */
228         str[10] = 'x';
229 }
230
231 static int psoc5lp_get_device_id(struct target *target, uint32_t *id)
232 {
233         int retval;
234
235         retval = target_read_u32(target, PANTHER_DEVICE_ID, id); /* dummy read */
236         if (retval != ERROR_OK)
237                 return retval;
238         retval = target_read_u32(target, PANTHER_DEVICE_ID, id);
239         return retval;
240 }
241
242 static int psoc5lp_find_device(struct target *target,
243         const struct psoc5lp_device **device)
244 {
245         uint32_t device_id;
246         unsigned i;
247         int retval;
248
249         *device = NULL;
250
251         retval = psoc5lp_get_device_id(target, &device_id);
252         if (retval != ERROR_OK)
253                 return retval;
254         LOG_DEBUG("PANTHER_DEVICE_ID = 0x%08" PRIX32, device_id);
255
256         for (i = 0; i < ARRAY_SIZE(psoc5lp_devices); i++) {
257                 if (psoc5lp_devices[i].id == device_id) {
258                         *device = &psoc5lp_devices[i];
259                         return ERROR_OK;
260                 }
261         }
262
263         LOG_ERROR("Device 0x%08" PRIX32 " not supported", device_id);
264         return ERROR_FLASH_OPER_UNSUPPORTED;
265 }
266
267 static int psoc5lp_spc_enable_clock(struct target *target)
268 {
269         int retval;
270         uint8_t pm_act_cfg0;
271
272         retval = target_read_u8(target, PM_ACT_CFG0, &pm_act_cfg0);
273         if (retval != ERROR_OK) {
274                 LOG_ERROR("Cannot read PM_ACT_CFG0");
275                 return retval;
276         }
277
278         if (pm_act_cfg0 & PM_ACT_CFG0_EN_CLK_SPC)
279                 return ERROR_OK;        /* clock already enabled */
280
281         retval = target_write_u8(target, PM_ACT_CFG0, pm_act_cfg0 | PM_ACT_CFG0_EN_CLK_SPC);
282         if (retval != ERROR_OK)
283                 LOG_ERROR("Cannot enable SPC clock");
284
285         return retval;
286 }
287
288 static int psoc5lp_spc_write_opcode(struct target *target, uint8_t opcode)
289 {
290         int retval;
291
292         retval = target_write_u8(target, SPC_CPU_DATA, SPC_KEY1);
293         if (retval != ERROR_OK)
294                 return retval;
295         retval = target_write_u8(target, SPC_CPU_DATA, SPC_KEY2 + opcode);
296         if (retval != ERROR_OK)
297                 return retval;
298         retval = target_write_u8(target, SPC_CPU_DATA, opcode);
299         return retval;
300 }
301
302 static void psoc5lp_spc_write_opcode_buffer(struct target *target,
303         uint8_t *buf, uint8_t opcode)
304 {
305         buf[0] = SPC_KEY1;
306         buf[1] = SPC_KEY2 + opcode;
307         buf[2] = opcode;
308 }
309
310 static int psoc5lp_spc_busy_wait_data(struct target *target)
311 {
312         int64_t endtime;
313         uint8_t sr;
314         int retval;
315
316         retval = target_read_u8(target, SPC_SR, &sr); /* dummy read */
317         if (retval != ERROR_OK)
318                 return retval;
319
320         endtime = timeval_ms() + 1000; /* 1 second timeout */
321         do {
322                 alive_sleep(1);
323                 retval = target_read_u8(target, SPC_SR, &sr);
324                 if (retval != ERROR_OK)
325                         return retval;
326                 if (sr == SPC_SR_DATA_READY)
327                         return ERROR_OK;
328         } while (timeval_ms() < endtime);
329
330         return ERROR_FLASH_OPERATION_FAILED;
331 }
332
333 static int psoc5lp_spc_busy_wait_idle(struct target *target)
334 {
335         int64_t endtime;
336         uint8_t sr;
337         int retval;
338
339         retval = target_read_u8(target, SPC_SR, &sr); /* dummy read */
340         if (retval != ERROR_OK)
341                 return retval;
342
343         endtime = timeval_ms() + 1000; /* 1 second timeout */
344         do {
345                 alive_sleep(1);
346                 retval = target_read_u8(target, SPC_SR, &sr);
347                 if (retval != ERROR_OK)
348                         return retval;
349                 if (sr == SPC_SR_IDLE)
350                         return ERROR_OK;
351         } while (timeval_ms() < endtime);
352
353         return ERROR_FLASH_OPERATION_FAILED;
354 }
355
356 static int psoc5lp_spc_read_byte(struct target *target,
357         uint8_t array_id, uint8_t offset, uint8_t *data)
358 {
359         int retval;
360
361         retval = psoc5lp_spc_write_opcode(target, SPC_READ_BYTE);
362         if (retval != ERROR_OK)
363                 return retval;
364         retval = target_write_u8(target, SPC_CPU_DATA, array_id);
365         if (retval != ERROR_OK)
366                 return retval;
367         retval = target_write_u8(target, SPC_CPU_DATA, offset);
368         if (retval != ERROR_OK)
369                 return retval;
370
371         retval = psoc5lp_spc_busy_wait_data(target);
372         if (retval != ERROR_OK)
373                 return retval;
374
375         retval = target_read_u8(target, SPC_CPU_DATA, data);
376         if (retval != ERROR_OK)
377                 return retval;
378
379         retval = psoc5lp_spc_busy_wait_idle(target);
380         if (retval != ERROR_OK)
381                 return retval;
382
383         return ERROR_OK;
384 }
385
386 static int psoc5lp_spc_erase_sector(struct target *target,
387         uint8_t array_id, uint8_t row_id)
388 {
389         int retval;
390
391         retval = psoc5lp_spc_write_opcode(target, SPC_ERASE_SECTOR);
392         if (retval != ERROR_OK)
393                 return retval;
394         retval = target_write_u8(target, SPC_CPU_DATA, array_id);
395         if (retval != ERROR_OK)
396                 return retval;
397         retval = target_write_u8(target, SPC_CPU_DATA, row_id);
398         if (retval != ERROR_OK)
399                 return retval;
400
401         retval = psoc5lp_spc_busy_wait_idle(target);
402         if (retval != ERROR_OK)
403                 return retval;
404
405         return ERROR_OK;
406 }
407
408 static int psoc5lp_spc_erase_all(struct target *target)
409 {
410         int retval;
411
412         retval = psoc5lp_spc_write_opcode(target, SPC_ERASE_ALL);
413         if (retval != ERROR_OK)
414                 return retval;
415
416         retval = psoc5lp_spc_busy_wait_idle(target);
417         if (retval != ERROR_OK)
418                 return retval;
419
420         return ERROR_OK;
421 }
422
423 static int psoc5lp_spc_read_hidden_row(struct target *target,
424         uint8_t array_id, uint8_t row_id, uint8_t *data)
425 {
426         int i, retval;
427
428         retval = psoc5lp_spc_write_opcode(target, SPC_READ_HIDDEN_ROW);
429         if (retval != ERROR_OK)
430                 return retval;
431         retval = target_write_u8(target, SPC_CPU_DATA, array_id);
432         if (retval != ERROR_OK)
433                 return retval;
434         retval = target_write_u8(target, SPC_CPU_DATA, row_id);
435         if (retval != ERROR_OK)
436                 return retval;
437
438         retval = psoc5lp_spc_busy_wait_data(target);
439         if (retval != ERROR_OK)
440                 return retval;
441
442         for (i = 0; i < ROW_SIZE; i++) {
443                 retval = target_read_u8(target, SPC_CPU_DATA, &data[i]);
444                 if (retval != ERROR_OK)
445                         return retval;
446         }
447
448         retval = psoc5lp_spc_busy_wait_idle(target);
449         if (retval != ERROR_OK)
450                 return retval;
451
452         return ERROR_OK;
453 }
454
455 static int psoc5lp_spc_get_temp(struct target *target, uint8_t samples,
456         uint8_t *data)
457 {
458         int retval;
459
460         retval = psoc5lp_spc_write_opcode(target, SPC_GET_TEMP);
461         if (retval != ERROR_OK)
462                 return retval;
463         retval = target_write_u8(target, SPC_CPU_DATA, samples);
464         if (retval != ERROR_OK)
465                 return retval;
466
467         retval = psoc5lp_spc_busy_wait_data(target);
468         if (retval != ERROR_OK)
469                 return retval;
470
471         retval = target_read_u8(target, SPC_CPU_DATA, &data[0]);
472         if (retval != ERROR_OK)
473                 return retval;
474         retval = target_read_u8(target, SPC_CPU_DATA, &data[1]);
475         if (retval != ERROR_OK)
476                 return retval;
477
478         retval = psoc5lp_spc_busy_wait_idle(target);
479         if (retval != ERROR_OK)
480                 return retval;
481
482         return ERROR_OK;
483 }
484
485 /*
486  * Program Flash
487  */
488
489 struct psoc5lp_flash_bank {
490         bool probed;
491         const struct psoc5lp_device *device;
492         bool ecc_enabled;
493 };
494
495 static int psoc5lp_erase(struct flash_bank *bank, int first, int last)
496 {
497         struct psoc5lp_flash_bank *psoc_bank = bank->driver_priv;
498         int i, retval;
499
500         if (!psoc_bank->ecc_enabled) {
501                 /* Silently avoid erasing sectors twice */
502                 if (last >= first + bank->num_sectors / 2) {
503                         LOG_DEBUG("Skipping duplicate erase of sectors %d to %d",
504                                 first + bank->num_sectors / 2, last);
505                         last = first + (bank->num_sectors / 2) - 1;
506                 }
507                 /* Check for any remaining ECC sectors */
508                 if (last >= bank->num_sectors / 2) {
509                         LOG_WARNING("Skipping erase of ECC region sectors %d to %d",
510                                 bank->num_sectors / 2, last);
511                         last = (bank->num_sectors / 2) - 1;
512                 }
513         }
514
515         for (i = first; i <= last; i++) {
516                 retval = psoc5lp_spc_erase_sector(bank->target,
517                                 i / SECTORS_PER_BLOCK, i % SECTORS_PER_BLOCK);
518                 if (retval != ERROR_OK)
519                         return retval;
520         }
521
522         return ERROR_OK;
523 }
524
525 /* Derived from core.c:default_flash_blank_check() */
526 static int psoc5lp_erase_check(struct flash_bank *bank)
527 {
528         struct psoc5lp_flash_bank *psoc_bank = bank->driver_priv;
529         struct target *target = bank->target;
530         uint32_t blank;
531         int i, num_sectors, retval;
532
533         if (target->state != TARGET_HALTED) {
534                 LOG_ERROR("Target not halted");
535                 return ERROR_TARGET_NOT_HALTED;
536         }
537
538         num_sectors = bank->num_sectors;
539         if (!psoc_bank->ecc_enabled)
540                 num_sectors /= 2;
541
542         for (i = 0; i < num_sectors; i++) {
543                 uint32_t address = bank->base + bank->sectors[i].offset;
544                 uint32_t size = bank->sectors[i].size;
545
546                 retval = armv7m_blank_check_memory(target, address, size,
547                                 &blank, bank->erased_value);
548                 if (retval != ERROR_OK)
549                         return retval;
550
551                 if (blank == 0x00 && !psoc_bank->ecc_enabled) {
552                         address = bank->base + bank->sectors[num_sectors + i].offset;
553                         size = bank->sectors[num_sectors + i].size;
554
555                         retval = armv7m_blank_check_memory(target, address, size,
556                                         &blank, bank->erased_value);
557                         if (retval != ERROR_OK)
558                                 return retval;
559                 }
560
561                 if (blank == 0x00) {
562                         bank->sectors[i].is_erased = 1;
563                         bank->sectors[num_sectors + i].is_erased = 1;
564                 } else {
565                         bank->sectors[i].is_erased = 0;
566                         bank->sectors[num_sectors + i].is_erased = 0;
567                 }
568         }
569
570         return ERROR_OK;
571 }
572
573 static int psoc5lp_write(struct flash_bank *bank, const uint8_t *buffer,
574                 uint32_t offset, uint32_t byte_count)
575 {
576         struct psoc5lp_flash_bank *psoc_bank = bank->driver_priv;
577         struct target *target = bank->target;
578         struct working_area *code_area, *even_row_area, *odd_row_area;
579         uint32_t row_size;
580         uint8_t temp[2], buf[12], ecc_bytes[ROW_ECC_SIZE];
581         unsigned array_id, row;
582         int i, retval;
583
584         if (offset + byte_count > bank->size) {
585                 LOG_ERROR("Writing to ECC not supported");
586                 return ERROR_FLASH_DST_OUT_OF_BANK;
587         }
588
589         if (offset % ROW_SIZE != 0) {
590                 LOG_ERROR("Writes must be row-aligned, got offset 0x%08" PRIx32,
591                         offset);
592                 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
593         }
594
595         row_size = ROW_SIZE;
596         if (!psoc_bank->ecc_enabled) {
597                 row_size += ROW_ECC_SIZE;
598                 memset(ecc_bytes, bank->default_padded_value, ROW_ECC_SIZE);
599         }
600
601         retval = psoc5lp_spc_get_temp(target, 3, temp);
602         if (retval != ERROR_OK) {
603                 LOG_ERROR("Unable to read Die temperature");
604                 return retval;
605         }
606         LOG_DEBUG("Get_Temp: sign 0x%02" PRIx8 ", magnitude 0x%02" PRIx8,
607                 temp[0], temp[1]);
608
609         assert(target_get_working_area_avail(target) == target->working_area_size);
610         retval = target_alloc_working_area(target,
611                         target_get_working_area_avail(target) / 2, &code_area);
612         if (retval != ERROR_OK) {
613                 LOG_ERROR("Could not allocate working area for program SRAM");
614                 return retval;
615         }
616         assert(code_area->address < 0x20000000);
617
618         retval = target_alloc_working_area(target,
619                         SPC_OPCODE_LEN + 1 + row_size + 3 + SPC_OPCODE_LEN + 6,
620                         &even_row_area);
621         if (retval != ERROR_OK) {
622                 LOG_ERROR("Could not allocate working area for even row");
623                 goto err_alloc_even;
624         }
625         assert(even_row_area->address >= 0x20000000);
626
627         retval = target_alloc_working_area(target, even_row_area->size,
628                         &odd_row_area);
629         if (retval != ERROR_OK) {
630                 LOG_ERROR("Could not allocate working area for odd row");
631                 goto err_alloc_odd;
632         }
633         assert(odd_row_area->address >= 0x20000000);
634
635         for (array_id = offset / BLOCK_SIZE; byte_count > 0; array_id++) {
636                 for (row = (offset / ROW_SIZE) % ROWS_PER_BLOCK;
637                      row < ROWS_PER_BLOCK && byte_count > 0; row++) {
638                         bool even_row = (row % 2 == 0);
639                         struct working_area *data_area = even_row ? even_row_area : odd_row_area;
640                         unsigned len = MIN(ROW_SIZE, byte_count);
641
642                         LOG_DEBUG("Writing load command for array %u row %u at 0x%08" TARGET_PRIxADDR,
643                                 array_id, row, data_area->address);
644
645                         psoc5lp_spc_write_opcode_buffer(target, buf, SPC_LOAD_ROW);
646                         buf[SPC_OPCODE_LEN] = array_id;
647                         retval = target_write_buffer(target, data_area->address, 4, buf);
648                         if (retval != ERROR_OK)
649                                 goto err_write;
650
651                         retval = target_write_buffer(target,
652                                 data_area->address + SPC_OPCODE_LEN + 1,
653                                 len, buffer);
654                         if (retval != ERROR_OK)
655                                 goto err_write;
656                         buffer += len;
657                         byte_count -= len;
658                         offset += len;
659
660                         if (len < ROW_SIZE) {
661                                 uint8_t padding[ROW_SIZE];
662
663                                 memset(padding, bank->default_padded_value, ROW_SIZE);
664
665                                 LOG_DEBUG("Padding %d bytes", ROW_SIZE - len);
666                                 retval = target_write_buffer(target,
667                                         data_area->address + SPC_OPCODE_LEN + 1 + len,
668                                         ROW_SIZE - len, padding);
669                                 if (retval != ERROR_OK)
670                                         goto err_write;
671                         }
672
673                         if (!psoc_bank->ecc_enabled) {
674                                 retval = target_write_buffer(target,
675                                         data_area->address + SPC_OPCODE_LEN + 1 + ROW_SIZE,
676                                         sizeof(ecc_bytes), ecc_bytes);
677                                 if (retval != ERROR_OK)
678                                         goto err_write;
679                         }
680
681                         for (i = 0; i < 3; i++)
682                                 buf[i] = 0x00; /* 3 NOPs for short delay */
683                         psoc5lp_spc_write_opcode_buffer(target, buf + 3, SPC_PRG_ROW);
684                         buf[3 + SPC_OPCODE_LEN] = array_id;
685                         buf[3 + SPC_OPCODE_LEN + 1] = row >> 8;
686                         buf[3 + SPC_OPCODE_LEN + 2] = row & 0xff;
687                         memcpy(buf + 3 + SPC_OPCODE_LEN + 3, temp, 2);
688                         buf[3 + SPC_OPCODE_LEN + 5] = 0x00; /* padding */
689                         retval = target_write_buffer(target,
690                                 data_area->address + SPC_OPCODE_LEN + 1 + row_size,
691                                 12, buf);
692                         if (retval != ERROR_OK)
693                                 goto err_write;
694
695                         retval = target_write_u32(target,
696                                 even_row ? PHUB_CH0_BASIC_STATUS : PHUB_CH1_BASIC_STATUS,
697                                 (even_row ? 0 : 1) << 8);
698                         if (retval != ERROR_OK)
699                                 goto err_dma;
700
701                         retval = target_write_u32(target,
702                                 even_row ? PHUB_CH0_BASIC_CFG : PHUB_CH1_BASIC_CFG,
703                                 PHUB_CHx_BASIC_CFG_WORK_SEP | PHUB_CHx_BASIC_CFG_EN);
704                         if (retval != ERROR_OK)
705                                 goto err_dma;
706
707                         retval = target_write_u32(target,
708                                 even_row ? PHUB_CFGMEM0_CFG0 : PHUB_CFGMEM1_CFG0,
709                                 PHUB_CFGMEMx_CFG0);
710                         if (retval != ERROR_OK)
711                                 goto err_dma;
712
713                         retval = target_write_u32(target,
714                                 even_row ? PHUB_CFGMEM0_CFG1 : PHUB_CFGMEM1_CFG1,
715                                 ((SPC_CPU_DATA >> 16) << 16) | (data_area->address >> 16));
716                         if (retval != ERROR_OK)
717                                 goto err_dma;
718
719                         retval = target_write_u32(target,
720                                 even_row ? PHUB_TDMEM0_ORIG_TD0 : PHUB_TDMEM1_ORIG_TD0,
721                                 PHUB_TDMEMx_ORIG_TD0_INC_SRC_ADDR |
722                                 PHUB_TDMEMx_ORIG_TD0_NEXT_TD_PTR_LAST |
723                                 ((SPC_OPCODE_LEN + 1 + row_size + 3 + SPC_OPCODE_LEN + 5) & 0xfff));
724                         if (retval != ERROR_OK)
725                                 goto err_dma;
726
727                         retval = target_write_u32(target,
728                                 even_row ? PHUB_TDMEM0_ORIG_TD1 : PHUB_TDMEM1_ORIG_TD1,
729                                 ((SPC_CPU_DATA & 0xffff) << 16) | (data_area->address & 0xffff));
730                         if (retval != ERROR_OK)
731                                 goto err_dma;
732
733                         retval = psoc5lp_spc_busy_wait_idle(target);
734                         if (retval != ERROR_OK)
735                                 goto err_idle;
736
737                         retval = target_write_u32(target,
738                                 even_row ? PHUB_CH0_ACTION : PHUB_CH1_ACTION,
739                                 PHUB_CHx_ACTION_CPU_REQ);
740                         if (retval != ERROR_OK)
741                                 goto err_dma_action;
742                 }
743         }
744
745         retval = psoc5lp_spc_busy_wait_idle(target);
746
747 err_dma_action:
748 err_idle:
749 err_dma:
750 err_write:
751         target_free_working_area(target, odd_row_area);
752 err_alloc_odd:
753         target_free_working_area(target, even_row_area);
754 err_alloc_even:
755         target_free_working_area(target, code_area);
756
757         return retval;
758 }
759
760 static int psoc5lp_protect_check(struct flash_bank *bank)
761 {
762         struct psoc5lp_flash_bank *psoc_bank = bank->driver_priv;
763         uint8_t row_data[ROW_SIZE];
764         const unsigned protection_bytes_per_sector = ROWS_PER_SECTOR * 2 / 8;
765         unsigned i, j, k, num_sectors;
766         int retval;
767
768         if (bank->target->state != TARGET_HALTED) {
769                 LOG_ERROR("Target not halted");
770                 return ERROR_TARGET_NOT_HALTED;
771         }
772
773         for (i = 0; i < DIV_ROUND_UP(bank->size, BLOCK_SIZE); i++) {
774                 retval = psoc5lp_spc_read_hidden_row(bank->target, i,
775                                 SPC_ROW_PROTECTION, row_data);
776                 if (retval != ERROR_OK)
777                         return retval;
778
779                 /* Last flash array may have less rows, but in practice full sectors. */
780                 if (i == bank->size / BLOCK_SIZE)
781                         num_sectors = (bank->size % BLOCK_SIZE) / SECTOR_SIZE;
782                 else
783                         num_sectors = SECTORS_PER_BLOCK;
784
785                 for (j = 0; j < num_sectors; j++) {
786                         int sector_nr = i * SECTORS_PER_BLOCK + j;
787                         struct flash_sector *sector = &bank->sectors[sector_nr];
788                         struct flash_sector *ecc_sector;
789
790                         if (psoc_bank->ecc_enabled)
791                                 ecc_sector = &bank->sectors[bank->num_sectors + sector_nr];
792                         else
793                                 ecc_sector = &bank->sectors[bank->num_sectors / 2 + sector_nr];
794
795                         sector->is_protected = ecc_sector->is_protected = 0;
796                         for (k = protection_bytes_per_sector * j;
797                              k < protection_bytes_per_sector * (j + 1); k++) {
798                                 assert(k < protection_bytes_per_sector * SECTORS_PER_BLOCK);
799                                 LOG_DEBUG("row[%u][%02u] = 0x%02" PRIx8, i, k, row_data[k]);
800                                 if (row_data[k] != 0x00) {
801                                         sector->is_protected = ecc_sector->is_protected = 1;
802                                         break;
803                                 }
804                         }
805                 }
806         }
807
808         return ERROR_OK;
809 }
810
811 static int psoc5lp_get_info_command(struct flash_bank *bank, char *buf, int buf_size)
812 {
813         struct psoc5lp_flash_bank *psoc_bank = bank->driver_priv;
814         char part_number[PART_NUMBER_LEN];
815         const char *ecc;
816
817         psoc5lp_get_part_number(psoc_bank->device, part_number);
818         ecc = psoc_bank->ecc_enabled ? "ECC enabled" : "ECC disabled";
819
820         snprintf(buf, buf_size, "%s %s", part_number, ecc);
821
822         return ERROR_OK;
823 }
824
825 static int psoc5lp_probe(struct flash_bank *bank)
826 {
827         struct target *target = bank->target;
828         struct psoc5lp_flash_bank *psoc_bank = bank->driver_priv;
829         uint32_t flash_addr = bank->base;
830         uint8_t nvl[4], temp[2];
831         int i, retval;
832
833         if (target->state != TARGET_HALTED) {
834                 LOG_ERROR("Target not halted");
835                 return ERROR_TARGET_NOT_HALTED;
836         }
837
838         if (!psoc_bank->device) {
839                 retval = psoc5lp_find_device(target, &psoc_bank->device);
840                 if (retval != ERROR_OK)
841                         return retval;
842
843                 bank->size = psoc_bank->device->flash_kb * 1024;
844         }
845
846         bank->num_sectors = DIV_ROUND_UP(bank->size, SECTOR_SIZE);
847
848         if (!psoc_bank->probed) {
849                 retval = psoc5lp_spc_enable_clock(target);
850                 if (retval != ERROR_OK)
851                         return retval;
852
853                 /* First values read are inaccurate, so do it once now. */
854                 retval = psoc5lp_spc_get_temp(target, 3, temp);
855                 if (retval != ERROR_OK) {
856                         LOG_ERROR("Unable to read Die temperature");
857                         return retval;
858                 }
859
860                 bank->sectors = calloc(bank->num_sectors * 2,
861                                        sizeof(struct flash_sector));
862                 for (i = 0; i < bank->num_sectors; i++) {
863                         bank->sectors[i].size = SECTOR_SIZE;
864                         bank->sectors[i].offset = flash_addr - bank->base;
865                         bank->sectors[i].is_erased = -1;
866                         bank->sectors[i].is_protected = -1;
867
868                         flash_addr += bank->sectors[i].size;
869                 }
870                 flash_addr = 0x48000000;
871                 for (i = bank->num_sectors; i < bank->num_sectors * 2; i++) {
872                         bank->sectors[i].size = ROWS_PER_SECTOR * ROW_ECC_SIZE;
873                         bank->sectors[i].offset = flash_addr - bank->base;
874                         bank->sectors[i].is_erased = -1;
875                         bank->sectors[i].is_protected = -1;
876
877                         flash_addr += bank->sectors[i].size;
878                 }
879
880                 bank->default_padded_value = bank->erased_value = 0x00;
881
882                 psoc_bank->probed = true;
883         }
884
885         retval = psoc5lp_spc_read_byte(target, SPC_ARRAY_NVL_USER, 3, &nvl[3]);
886         if (retval != ERROR_OK)
887                 return retval;
888         LOG_DEBUG("NVL[%d] = 0x%02" PRIx8, 3, nvl[3]);
889         psoc_bank->ecc_enabled = nvl[3] & NVL_3_ECCEN;
890
891         if (!psoc_bank->ecc_enabled)
892                 bank->num_sectors *= 2;
893
894         return ERROR_OK;
895 }
896
897 static int psoc5lp_auto_probe(struct flash_bank *bank)
898 {
899         return psoc5lp_probe(bank);
900 }
901
902 COMMAND_HANDLER(psoc5lp_handle_mass_erase_command)
903 {
904         struct flash_bank *bank;
905         int retval;
906
907         if (CMD_ARGC < 1)
908                 return ERROR_COMMAND_SYNTAX_ERROR;
909
910         retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
911         if (retval != ERROR_OK)
912                 return retval;
913
914         retval = psoc5lp_spc_erase_all(bank->target);
915         if (retval == ERROR_OK)
916                 command_print(CMD_CTX, "PSoC 5LP erase succeeded");
917         else
918                 command_print(CMD_CTX, "PSoC 5LP erase failed");
919
920         return retval;
921 }
922
923 FLASH_BANK_COMMAND_HANDLER(psoc5lp_flash_bank_command)
924 {
925         struct psoc5lp_flash_bank *psoc_bank;
926
927         psoc_bank = malloc(sizeof(struct psoc5lp_flash_bank));
928         if (!psoc_bank)
929                 return ERROR_FLASH_OPERATION_FAILED;
930
931         psoc_bank->probed = false;
932         psoc_bank->device = NULL;
933
934         bank->driver_priv = psoc_bank;
935
936         return ERROR_OK;
937 }
938
939 static const struct command_registration psoc5lp_exec_command_handlers[] = {
940         {
941                 .name = "mass_erase",
942                 .handler = psoc5lp_handle_mass_erase_command,
943                 .mode = COMMAND_EXEC,
944                 .usage = "bank_id",
945                 .help = "Erase all flash data and ECC/configuration bytes, "
946                         "all flash protection rows, "
947                         "and all row latches in all flash arrays on the device.",
948         },
949         COMMAND_REGISTRATION_DONE
950 };
951
952 static const struct command_registration psoc5lp_command_handlers[] = {
953         {
954                 .name = "psoc5lp",
955                 .mode = COMMAND_ANY,
956                 .help = "PSoC 5LP flash command group",
957                 .usage = "",
958                 .chain = psoc5lp_exec_command_handlers,
959         },
960         COMMAND_REGISTRATION_DONE
961 };
962
963 struct flash_driver psoc5lp_flash = {
964         .name = "psoc5lp",
965         .commands = psoc5lp_command_handlers,
966         .flash_bank_command = psoc5lp_flash_bank_command,
967         .info = psoc5lp_get_info_command,
968         .probe = psoc5lp_probe,
969         .auto_probe = psoc5lp_auto_probe,
970         .protect_check = psoc5lp_protect_check,
971         .read = default_flash_read,
972         .erase = psoc5lp_erase,
973         .erase_check = psoc5lp_erase_check,
974         .write = psoc5lp_write,
975 };