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