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