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