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