OpenOCD
sfdp.c
Go to the documentation of this file.
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 
3 /***************************************************************************
4  * Copyright (C) 2019 by Andreas Bolsch <andreas.bolsch@mni.thm.de *
5  ***************************************************************************/
6 
7 #ifdef HAVE_CONFIG_H
8 #include "config.h"
9 #endif
10 
11 #include "imp.h"
12 #include "spi.h"
13 #include "sfdp.h"
14 
15 #define SFDP_MAGIC 0x50444653
16 #define SFDP_ACCESS_PROT 0xFF
17 #define SFDP_BASIC_FLASH 0xFF00
18 #define SFDP_4BYTE_ADDR 0xFF84
19 
20 static const char *sfdp_name = "sfdp";
21 
22 struct sfdp_hdr {
23  uint32_t signature;
24  uint32_t revision;
25 };
26 
27 struct sfdp_phdr {
28  uint32_t revision;
29  uint32_t ptr;
30 };
31 
33  uint32_t fast_addr; /* 01: fast read and 3/4 address bytes */
34  uint32_t density; /* 02: memory density */
35  uint32_t fast_1x4; /* 03: 1-1-4 and 1-4-4 fast read */
36  uint32_t fast_1x2; /* 04: 1-2-2 and 1-1-2 fast read */
37  uint32_t fast_444; /* 05: 4-4-4 and 2-2-2 fast read */
38  uint32_t read_222; /* 06: 2-2-2 fast read instr and dummy */
39  uint32_t read_444; /* 07: 4-4-4 fast read instr and dummy */
40  uint32_t erase_t12; /* 08: erase types 1, 2 */
41  uint32_t erase_t34; /* 09: erase types 3, 4 */
42  uint32_t erase_time; /* 10: erase times for types 1 - 4 */
43  uint32_t chip_byte; /* 11: chip erase time, byte prog time, page prog */
44  uint32_t susp_time; /* 12: suspend and resume times */
45  uint32_t susp_instr; /* 13: suspend and resume instr */
46  uint32_t pwrd_instr; /* 14: powerdown instr */
47  uint32_t quad_req; /* 15: quad enable requirements */
48  uint32_t addr_reset; /* 16: 3-/4-byte addressing and reset */
49  uint32_t read_1x8; /* 17: 1-1-8 and 1-8-8 fast read instr and dummy */
50  uint32_t dtr_drive; /* 18: dtr modes and drive strength */
51  uint32_t octal_req; /* 19: octal enable requirements */
52  uint32_t speed_888; /* 20: speed in 8-8-8 modes */
53 };
54 
56  uint32_t flags; /* 01: various flags */
57  uint32_t erase_t1234; /* 02: erase commands */
58 };
59 
60 /* Try to get parameters from flash via SFDP */
61 int spi_sfdp(struct flash_bank *bank, struct flash_device *dev,
63 {
64  struct sfdp_hdr header;
65  struct sfdp_phdr *pheaders = NULL;
66  uint32_t *ptable = NULL;
67  unsigned int j, k, nph;
68  int retval, erase_type = 0;
69 
70  memset(dev, 0, sizeof(struct flash_device));
71 
72  /* retrieve SFDP header */
73  memset(&header, 0, sizeof(header));
74  retval = read_sfdp_block(bank, 0x0, sizeof(header) >> 2, (uint32_t *)&header);
75  if (retval != ERROR_OK)
76  return retval;
77  LOG_DEBUG("header 0x%08" PRIx32 " 0x%08" PRIx32, header.signature, header.revision);
78  if (header.signature != SFDP_MAGIC) {
79  LOG_INFO("no SDFP found");
81  }
82  if (((header.revision >> 24) & 0xFF) != SFDP_ACCESS_PROT) {
83  LOG_ERROR("access protocol 0x%02x not implemented",
84  (header.revision >> 24) & 0xFFU);
86  }
87 
88  /* retrieve table of parameter headers */
89  nph = ((header.revision >> 16) & 0xFF) + 1;
90  LOG_DEBUG("parameter headers: %d", nph);
91  pheaders = malloc(sizeof(struct sfdp_phdr) * nph);
92  if (!pheaders) {
93  LOG_ERROR("not enough memory");
94  return ERROR_FAIL;
95  }
96  memset(pheaders, 0, sizeof(struct sfdp_phdr) * nph);
97  retval = read_sfdp_block(bank, sizeof(header),
98  (sizeof(struct sfdp_phdr) >> 2) * nph, (uint32_t *)pheaders);
99  if (retval != ERROR_OK)
100  goto err;
101 
102  for (k = 0; k < nph; k++) {
103  uint8_t words = (pheaders[k].revision >> 24) & 0xFF;
104  uint16_t id = (((pheaders[k].ptr) >> 16) & 0xFF00) | (pheaders[k].revision & 0xFF);
105  uint32_t ptr = pheaders[k].ptr & 0xFFFFFF;
106 
107  LOG_DEBUG("pheader %d len=0x%02" PRIx8 " id=0x%04" PRIx16
108  " ptr=0x%06" PRIx32, k, words, id, ptr);
109 
110  /* retrieve parameter table */
111  ptable = malloc(words << 2);
112  if (!ptable) {
113  LOG_ERROR("not enough memory");
114  retval = ERROR_FAIL;
115  goto err;
116  }
117  retval = read_sfdp_block(bank, ptr, words, ptable);
118  if (retval != ERROR_OK)
119  goto err;
120 
121  for (j = 0; j < words; j++)
122  LOG_DEBUG("word %02d 0x%08X", j + 1, ptable[j]);
123 
124  if (id == SFDP_BASIC_FLASH) {
125  struct sfdp_basic_flash_param *table = (struct sfdp_basic_flash_param *)ptable;
126  uint16_t erase;
127 
128  if (words < 9) {
129  LOG_ERROR("id=0x%04" PRIx16 " invalid length %d", id, words);
131  goto err;
132  }
133 
134  LOG_DEBUG("basic flash parameter table");
135  /* dummy device name */
136  dev->name = sfdp_name;
137 
138  /* default instructions */
139  dev->read_cmd = SPIFLASH_READ;
142 
143  /* get device size */
144  if (table->density & (1UL << 31))
145  dev->size_in_bytes = 1UL << ((table->density & ~(1UL << 31)) - 3);
146  else
147  dev->size_in_bytes = (table->density + 1) >> 3;
148 
149  /* 2-2-2 read instruction, not used */
150  if (table->fast_444 & (1UL << 0))
151  dev->qread_cmd = (table->read_222 >> 24) & 0xFF;
152 
153  /* 4-4-4 read instruction */
154  if (table->fast_444 & (1UL << 4))
155  dev->qread_cmd = (table->read_444 >> 24) & 0xFF;
156 
157  /* find the largest erase block size and instruction */
158  erase = (table->erase_t12 >> 0) & 0xFFFF;
159  erase_type = 1;
160  if (((table->erase_t12 >> 16) & 0xFF) > (erase & 0xFF)) {
161  erase = (table->erase_t12 >> 16) & 0xFFFF;
162  erase_type = 2;
163  }
164  if (((table->erase_t34 >> 0) & 0xFF) > (erase & 0xFF)) {
165  erase = (table->erase_t34 >> 0) & 0xFFFF;
166  erase_type = 3;
167  }
168  if (((table->erase_t34 >> 16) & 0xFF) > (erase & 0xFF)) {
169  erase = (table->erase_t34 >> 16) & 0xFFFF;
170  erase_type = 4;
171  }
172  dev->erase_cmd = (erase >> 8) & 0xFF;
173  dev->sectorsize = 1UL << (erase & 0xFF);
174 
175  if ((offsetof(struct sfdp_basic_flash_param, chip_byte) >> 2) < words) {
176  /* get Program Page Size, if chip_byte present, that's optional */
177  dev->pagesize = 1UL << ((table->chip_byte >> 4) & 0x0F);
178  } else {
179  /* no explicit page size specified ... */
180  if (table->fast_addr & (1UL << 2)) {
181  /* Write Granularity = 1, use 64 bytes */
182  dev->pagesize = 1UL << 6;
183  } else {
184  /* Write Granularity = 0, use 16 bytes */
185  dev->pagesize = 1UL << 4;
186  }
187  }
188 
189  if (dev->size_in_bytes > (1UL << 24)) {
190  if (((table->fast_addr >> 17) & 0x3) == 0x0)
191  LOG_ERROR("device needs paging - not implemented");
192 
193  /* 4-byte addresses needed if more than 16 MBytes */
194  if (((offsetof(struct sfdp_basic_flash_param, addr_reset) >> 2) < words) &&
195  (table->addr_reset & (1UL << 29))) {
196  /* dedicated 4-byte-address instructions, hopefully these ...
197  * this entry is unfortunately optional as well
198  * a subsequent 4-byte address table may overwrite this */
199  dev->read_cmd = 0x13;
200  dev->pprog_cmd = 0x12;
201  dev->erase_cmd = 0xDC;
202  if (dev->qread_cmd != 0)
203  dev->qread_cmd = 0xEC;
204  } else if (((table->fast_addr >> 17) & 0x3) == 0x1)
205  LOG_INFO("device has to be switched to 4-byte addresses");
206  }
207  } else if (id == SFDP_4BYTE_ADDR) {
208  struct sfdp_4byte_addr_param *table = (struct sfdp_4byte_addr_param *)ptable;
209 
210  if (words >= (offsetof(struct sfdp_4byte_addr_param, erase_t1234)
211  + sizeof(table->erase_t1234)) >> 2) {
212  LOG_INFO("4-byte address parameter table");
213 
214  /* read and page program instructions */
215  if (table->flags & (1UL << 0))
216  dev->read_cmd = 0x13;
217  if (table->flags & (1UL << 5))
218  dev->qread_cmd = 0xEC;
219  if (table->flags & (1UL << 6))
220  dev->pprog_cmd = 0x12;
221 
222  /* erase instructions */
223  if ((erase_type == 1) && (table->flags & (1UL << 9)))
224  dev->erase_cmd = (table->erase_t1234 >> 0) & 0xFF;
225  else if ((erase_type == 2) && (table->flags & (1UL << 10)))
226  dev->erase_cmd = (table->erase_t1234 >> 8) & 0xFF;
227  else if ((erase_type == 3) && (table->flags & (1UL << 11)))
228  dev->erase_cmd = (table->erase_t1234 >> 16) & 0xFF;
229  else if ((erase_type == 4) && (table->flags & (1UL << 12)))
230  dev->erase_cmd = (table->erase_t1234 >> 24) & 0xFF;
231  } else
232  LOG_ERROR("parameter table id=0x%04" PRIx16 " invalid length %d", id, words);
233  } else
234  LOG_DEBUG("unimplemented parameter table id=0x%04" PRIx16, id);
235 
236  free(ptable);
237  ptable = NULL;
238  }
239 
240  if (erase_type != 0) {
241  LOG_INFO("valid SFDP detected");
242  retval = ERROR_OK;
243  } else {
244  LOG_ERROR("incomplete/invalid SFDP");
246  }
247 
248 err:
249  free(pheaders);
250  free(ptable);
251 
252  return retval;
253 }
uint8_t bank
Definition: esirisc.c:135
#define ERROR_FLASH_BANK_NOT_PROBED
Definition: flash/common.h:35
#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
int spi_sfdp(struct flash_bank *bank, struct flash_device *dev, read_sfdp_block_t read_sfdp_block)
Definition: sfdp.c:61
#define SFDP_ACCESS_PROT
Definition: sfdp.c:16
#define SFDP_BASIC_FLASH
Definition: sfdp.c:17
#define SFDP_MAGIC
Definition: sfdp.c:15
#define SFDP_4BYTE_ADDR
Definition: sfdp.c:18
static const char * sfdp_name
Definition: sfdp.c:20
int(* read_sfdp_block_t)(struct flash_bank *bank, uint32_t addr, uint32_t words, uint32_t *buffer)
Definition: sfdp.h:18
#define SPIFLASH_PAGE_PROGRAM
Definition: spi.h:76
#define SPIFLASH_READ
Definition: spi.h:78
#define SPIFLASH_MASS_ERASE
Definition: spi.h:79
static int read_sfdp_block(struct flash_bank *bank, uint32_t addr, uint32_t words, uint32_t *buffer)
Definition: stmqspi.c:1809
Provides details of a flash bank, available either on-chip or through a major interface.
Definition: nor/core.h:75
uint8_t read_cmd
Definition: spi.h:22
uint32_t sectorsize
Definition: spi.h:29
uint8_t chip_erase_cmd
Definition: spi.h:26
const char * name
Definition: spi.h:21
uint32_t pagesize
Definition: spi.h:28
uint32_t size_in_bytes
Definition: spi.h:30
uint8_t pprog_cmd
Definition: spi.h:24
uint8_t erase_cmd
Definition: spi.h:25
uint8_t qread_cmd
Definition: spi.h:23
uint32_t erase_t1234
Definition: sfdp.c:57
uint32_t flags
Definition: sfdp.c:56
uint32_t speed_888
Definition: sfdp.c:52
uint32_t fast_addr
Definition: sfdp.c:33
uint32_t read_1x8
Definition: sfdp.c:49
uint32_t chip_byte
Definition: sfdp.c:43
uint32_t erase_t12
Definition: sfdp.c:40
uint32_t read_222
Definition: sfdp.c:38
uint32_t read_444
Definition: sfdp.c:39
uint32_t density
Definition: sfdp.c:34
uint32_t pwrd_instr
Definition: sfdp.c:46
uint32_t addr_reset
Definition: sfdp.c:48
uint32_t dtr_drive
Definition: sfdp.c:50
uint32_t fast_444
Definition: sfdp.c:37
uint32_t quad_req
Definition: sfdp.c:47
uint32_t susp_time
Definition: sfdp.c:44
uint32_t erase_time
Definition: sfdp.c:42
uint32_t susp_instr
Definition: sfdp.c:45
uint32_t fast_1x2
Definition: sfdp.c:36
uint32_t erase_t34
Definition: sfdp.c:41
uint32_t fast_1x4
Definition: sfdp.c:35
uint32_t octal_req
Definition: sfdp.c:51
Definition: sfdp.c:22
uint32_t signature
Definition: sfdp.c:23
uint32_t revision
Definition: sfdp.c:24
Definition: sfdp.c:27
uint32_t revision
Definition: sfdp.c:28
uint32_t ptr
Definition: sfdp.c:29
#define NULL
Definition: usb.h:16