openocd: fix SPDX tag format for files .c
[fw/openocd] / src / flash / nor / sfdp.c
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
32 struct sfdp_basic_flash_param {
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
55 struct sfdp_4byte_addr_param {
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,
62         read_sfdp_block_t read_sfdp_block)
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");
80                 return ERROR_FLASH_BANK_NOT_PROBED;
81         }
82         if (((header.revision >> 24) & 0xFF) != SFDP_ACCESS_PROT) {
83                 LOG_ERROR("access protocol 0x%02x not implemented",
84                         (header.revision >> 24) & 0xFFU);
85                 return ERROR_FLASH_BANK_NOT_PROBED;
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);
130                                 retval = ERROR_FLASH_BANK_NOT_PROBED;
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;
140                         dev->pprog_cmd = SPIFLASH_PAGE_PROGRAM;
141                         dev->chip_erase_cmd = SPIFLASH_MASS_ERASE;
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");
245                 retval = ERROR_FLASH_BANK_NOT_PROBED;
246         }
247
248 err:
249         free(pheaders);
250         free(ptable);
251
252         return retval;
253 }