Skip to content

Commit 4a5fac3

Browse files
authored
Merge pull request #12528 from VeijoPesonen/sfdp_split_5
SFDP: consolidation of SFDP parsing [5/5]
2 parents c37b119 + b89e60b commit 4a5fac3

File tree

2 files changed

+118
-57
lines changed

2 files changed

+118
-57
lines changed

drivers/internal/SFDP.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ int sfdp_find_addr_region(bd_size_t offset, const sfdp_hdr_info &sfdp_info);
131131
* @param size Upper limit for region size
132132
* @param offset Offset value
133133
* @param region Region number
134-
* @param smptbl Information about different erase types
134+
* @param smptbl Information about different erase types
135135
*
136136
* @return Largest erase type
137137
*/

drivers/source/SFDP.cpp

Lines changed: 117 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,12 @@
1616
*/
1717

1818
#include <algorithm>
19-
#include <cstdint>
20-
#include <cstring>
19+
#include <memory>
20+
#include <stdint.h>
21+
#include <stdlib.h>
22+
#include <string.h>
23+
24+
#include "platform/mbed_error.h"
2125
#include "drivers/internal/SFDP.h"
2226

2327
#if (DEVICE_SPI || DEVICE_QSPI)
@@ -107,20 +111,69 @@ int sfdp_parse_single_param_header(sfdp_prm_hdr *phdr_ptr, sfdp_hdr_info &hdr_in
107111
return -1;
108112
}
109113

110-
if ((phdr_ptr->PID_LSB == 0) && (sfdp_get_param_id_msb(phdr_ptr->DWORD2) == 0xFF)) {
111-
tr_debug("Parameter header: Basic Parameter Header");
112-
hdr_info.bptbl.addr = sfdp_get_param_tbl_ptr(phdr_ptr->DWORD2);
113-
hdr_info.bptbl.size = std::min((phdr_ptr->P_LEN * 4), SFDP_BASIC_PARAMS_TBL_SIZE);
114+
int param_id_msb = sfdp_get_param_id_msb(phdr_ptr->DWORD2);
114115

115-
} else if ((phdr_ptr->PID_LSB == 0x81) && (sfdp_get_param_id_msb(phdr_ptr->DWORD2) == 0xFF)) {
116-
tr_debug("Parameter header: Sector Map Parameter Header");
117-
hdr_info.smptbl.addr = sfdp_get_param_tbl_ptr(phdr_ptr->DWORD2);
118-
hdr_info.smptbl.size = phdr_ptr->P_LEN * 4;
116+
/* MSB JEDEC ID */
117+
if (param_id_msb == 0xFF) {
119118

120-
} else {
121-
tr_debug("Parameter header: header vendor specific or unknown. Parameter ID LSB: 0x%" PRIX8 "; MSB: 0x%" PRIX8 "",
119+
/* LSB JEDEC ID */
120+
switch (phdr_ptr->PID_LSB) {
121+
case 0x0:
122+
tr_debug("Parameter header: JEDEC Basic Flash - Revision %" PRIX8 ".%" PRIX8 "",
123+
phdr_ptr->P_MAJOR,
124+
phdr_ptr->P_MINOR);
125+
hdr_info.bptbl.addr = sfdp_get_param_tbl_ptr(phdr_ptr->DWORD2);
126+
hdr_info.bptbl.size = std::min((phdr_ptr->P_LEN * 4), SFDP_BASIC_PARAMS_TBL_SIZE);
127+
break;
128+
case 0x81:
129+
tr_info("Parameter header: Sector Map");
130+
hdr_info.smptbl.addr = sfdp_get_param_tbl_ptr(phdr_ptr->DWORD2);
131+
hdr_info.smptbl.size = phdr_ptr->P_LEN * 4;
132+
break;
133+
/* Unsupported */
134+
case 0x03:
135+
tr_info("UNSUPPORTED:Parameter header: Replay Protected Monotonic Counters");
136+
break;
137+
case 0x84:
138+
tr_info("UNSUPPORTED:Parameter header: 4-byte Address Instruction");
139+
break;
140+
case 0x05:
141+
tr_info("UNSUPPORTED:Parameter header: eXtended Serial Peripheral Interface (xSPI) Profile 1.0");
142+
break;
143+
case 0x06:
144+
tr_info("UNSUPPORTED:Parameter header: eXtended Serial Peripheral Interface (xSPI) Profile 2.0");
145+
break;
146+
case 0x87:
147+
tr_info("UNSUPPORTED:Parameter header: SCCR Map for SPI Memory Devices");
148+
break;
149+
case 0x88:
150+
tr_info("UNSUPPORTED:Parameter header: SCCR Map Offsets for Multi-Chip SPI Memory Devices");
151+
break;
152+
case 0x09:
153+
tr_info("UNSUPPORTED:Parameter header: SCCR Map for xSPI Profile 2.0 Memory Devices");
154+
break;
155+
case 0x0A:
156+
tr_info("UNSUPPORTED:Parameter header: Command Sequences to Change to Octal DDR (8D-8D-8D) mode");
157+
break;
158+
case 0x0C:
159+
tr_info("UNSUPPORTED:Parameter header: x4 Quad IO with DS");
160+
break;
161+
case 0x8D:
162+
tr_info("UNSUPPORTED:Parameter header: Command Sequences to Change to Quad DDR (4S-4D-4D) mode");
163+
break;
164+
default:
165+
tr_debug("Parameter header: unknown JEDEC header. Parameter ID LSB: 0x%" PRIX8 "; MSB: 0x%" PRIX8 "",
166+
phdr_ptr->PID_LSB,
167+
sfdp_get_param_id_msb(phdr_ptr->DWORD2));
168+
}
169+
} else if (param_id_msb >= 0x80) { // MSB JEDEC ID
170+
tr_debug("Parameter header: unknown JEDEC header. Parameter ID LSB: 0x%" PRIX8 "; MSB: 0x%" PRIX8 "",
122171
phdr_ptr->PID_LSB,
123172
sfdp_get_param_id_msb(phdr_ptr->DWORD2));
173+
} else { // MSB Vendor ID
174+
tr_info("Parameter header: vendor specific header. Parameter ID LSB: 0x%" PRIX8 "; MSB: 0x%" PRIX8 "",
175+
phdr_ptr->PID_LSB,
176+
sfdp_get_param_id_msb(phdr_ptr->DWORD2));
124177
}
125178

126179
return 0;
@@ -157,10 +210,10 @@ int sfdp_parse_headers(Callback<int(bd_addr_t, void *, bd_size_t)> sfdp_reader,
157210
int hdr_status;
158211

159212
// Loop over Param Headers and parse them (currently supports Basic Param Table and Sector Region Map Table)
160-
for (int i_ind = 0; i_ind < number_of_param_headers; i_ind++) {
213+
for (int idx = 0; idx < number_of_param_headers; idx++) {
161214
status = sfdp_reader(addr, param_header, data_length);
162215
if (status < 0) {
163-
tr_error("Retrieving a parameter header %d failed", i_ind + 1);
216+
tr_error("Retrieving a parameter header %d failed", idx + 1);
164217
return -1;
165218
}
166219

@@ -178,9 +231,8 @@ int sfdp_parse_headers(Callback<int(bd_addr_t, void *, bd_size_t)> sfdp_reader,
178231

179232
int sfdp_parse_sector_map_table(Callback<int(bd_addr_t, void *, bd_size_t)> sfdp_reader, sfdp_hdr_info &sfdp_info)
180233
{
181-
uint8_t sector_map_table[SFDP_BASIC_PARAMS_TBL_SIZE]; /* Up To 20 DWORDS = 80 Bytes */
182234
uint32_t tmp_region_size = 0;
183-
int i_ind = 0;
235+
uint8_t type_mask;
184236
int prev_boundary = 0;
185237
// Default set to all type bits 1-4 are common
186238
int min_common_erase_type_bits = SFDP_ERASE_BITMASK_ALL;
@@ -191,25 +243,36 @@ int sfdp_parse_sector_map_table(Callback<int(bd_addr_t, void *, bd_size_t)> sfdp
191243

192244
if (!sfdp_info.smptbl.addr || !sfdp_info.smptbl.size) {
193245
tr_debug("No Sector Map Table");
194-
return 0;
246+
return MBED_SUCCESS;
195247
}
196248

197-
tr_debug("Parsing Sector Map Table - addr: 0x%" PRIx32 ", Size: %d", sfdp_info.smptbl.addr, sfdp_info.smptbl.size);
249+
/* The number of
250+
* - sector map configuration detection commands
251+
* - configurations
252+
* - regions in each configuration
253+
* is variable -> the size of this table is variable
254+
*/
255+
auto smptbl_buff = std::make_unique<uint8_t[]>(sfdp_info.smptbl.size);
256+
if (!smptbl_buff) {
257+
tr_error("Failed to allocate memory");
258+
return -1;
259+
}
198260

261+
tr_debug("Parsing Sector Map Table - addr: 0x%" PRIx32 ", Size: %d", sfdp_info.smptbl.addr, sfdp_info.smptbl.size);
199262

200-
int status = sfdp_reader(sfdp_info.smptbl.addr, sector_map_table, sfdp_info.smptbl.size);
263+
int status = sfdp_reader(sfdp_info.smptbl.addr, smptbl_buff.get(), sfdp_info.smptbl.size);
201264
if (status < 0) {
202265
tr_error("Sector Map: Table retrieval failed");
203266
return -1;
204267
}
205268

206269
// Currently we support only Single Map Descriptor
207-
if (!((sector_map_table[0] & 0x3) == 0x03) && (sector_map_table[1] == 0x0)) {
270+
if (!((smptbl_buff[0] & 0x3) == 0x03) && (smptbl_buff[1] == 0x0)) {
208271
tr_error("Sector Map: Supporting Only Single Map Descriptor (not map commands)");
209272
return -1;
210273
}
211274

212-
sfdp_info.smptbl.region_cnt = sector_map_table[2] + 1;
275+
sfdp_info.smptbl.region_cnt = smptbl_buff[2] + 1;
213276
if (sfdp_info.smptbl.region_cnt > SFDP_SECTOR_MAP_MAX_REGIONS) {
214277
tr_error("Sector Map: Supporting up to %d regions, current setup to %d regions - fail",
215278
SFDP_SECTOR_MAP_MAX_REGIONS,
@@ -219,34 +282,31 @@ int sfdp_parse_sector_map_table(Callback<int(bd_addr_t, void *, bd_size_t)> sfdp
219282

220283
// Loop through Regions and set for each one: size, supported erase types, high boundary offset
221284
// Calculate minimum Common Erase Type for all Regions
222-
for (i_ind = 0; i_ind < sfdp_info.smptbl.region_cnt; i_ind++) {
223-
tmp_region_size = ((*((uint32_t *)&sector_map_table[(i_ind + 1) * 4])) >> 8) & 0x00FFFFFF; // bits 9-32
224-
sfdp_info.smptbl.region_size[i_ind] = (tmp_region_size + 1) * 256; // Region size is 0 based multiple of 256 bytes;
285+
for (auto idx = 0; idx < sfdp_info.smptbl.region_cnt; idx++) {
286+
tmp_region_size = ((*((uint32_t *)&smptbl_buff[(idx + 1) * 4])) >> 8) & 0x00FFFFFF; // bits 9-32
287+
sfdp_info.smptbl.region_size[idx] = (tmp_region_size + 1) * 256; // Region size is 0 based multiple of 256 bytes;
225288

226-
sfdp_info.smptbl.region_erase_types_bitfld[i_ind] = sector_map_table[(i_ind + 1) * 4] & 0x0F; // bits 1-4
289+
sfdp_info.smptbl.region_erase_types_bitfld[idx] = smptbl_buff[(idx + 1) * 4] & 0x0F; // bits 1-4
227290

228-
min_common_erase_type_bits &= sfdp_info.smptbl.region_erase_types_bitfld[i_ind];
291+
min_common_erase_type_bits &= sfdp_info.smptbl.region_erase_types_bitfld[idx];
229292

230-
sfdp_info.smptbl.region_high_boundary[i_ind] = (sfdp_info.smptbl.region_size[i_ind] - 1) + prev_boundary;
293+
sfdp_info.smptbl.region_high_boundary[idx] = (sfdp_info.smptbl.region_size[idx] - 1) + prev_boundary;
231294

232-
prev_boundary = sfdp_info.smptbl.region_high_boundary[i_ind] + 1;
295+
prev_boundary = sfdp_info.smptbl.region_high_boundary[idx] + 1;
233296
}
234297

235298
// Calc minimum Common Erase Size from min_common_erase_type_bits
236-
uint8_t type_mask = SFDP_ERASE_BITMASK_TYPE1;
237-
for (i_ind = 0; i_ind < 4; i_ind++) {
299+
type_mask = SFDP_ERASE_BITMASK_TYPE1;
300+
// If no common erase type is found between regions
301+
sfdp_info.smptbl.regions_min_common_erase_size = 0;
302+
for (auto idx = 0; idx < 4; idx++) {
238303
if (min_common_erase_type_bits & type_mask) {
239-
sfdp_info.smptbl.regions_min_common_erase_size = sfdp_info.smptbl.erase_type_size_arr[i_ind];
304+
sfdp_info.smptbl.regions_min_common_erase_size = sfdp_info.smptbl.erase_type_size_arr[idx];
240305
break;
241306
}
242307
type_mask = type_mask << 1;
243308
}
244309

245-
if (i_ind == 4) {
246-
// No common erase type was found between regions
247-
sfdp_info.smptbl.regions_min_common_erase_size = 0;
248-
}
249-
250310
return 0;
251311
}
252312

@@ -275,27 +335,27 @@ int sfdp_detect_erase_types_inst_and_size(uint8_t *bptbl_ptr, sfdp_hdr_info &sfd
275335
// Erase 4K Inst is taken either from param table legacy 4K erase or superseded by erase Instruction for type of size 4K
276336
if (sfdp_info.bptbl.size > SFDP_BASIC_PARAM_TABLE_ERASE_TYPE_1_SIZE_BYTE) {
277337
// Loop Erase Types 1-4
278-
for (int i_ind = 0; i_ind < 4; i_ind++) {
279-
sfdp_info.smptbl.erase_type_inst_arr[i_ind] = -1; // Default for unsupported type
280-
sfdp_info.smptbl.erase_type_size_arr[i_ind] = 1
281-
<< bptbl_ptr[SFDP_BASIC_PARAM_TABLE_ERASE_TYPE_1_SIZE_BYTE + 2 * i_ind]; // Size is 2^N where N is the table value
282-
tr_debug("Erase Type(A) %d - Inst: 0x%xh, Size: %d", (i_ind + 1), sfdp_info.smptbl.erase_type_inst_arr[i_ind],
283-
sfdp_info.smptbl.erase_type_size_arr[i_ind]);
284-
if (sfdp_info.smptbl.erase_type_size_arr[i_ind] > 1) {
338+
for (int idx = 0; idx < 4; idx++) {
339+
sfdp_info.smptbl.erase_type_inst_arr[idx] = -1; // Default for unsupported type
340+
sfdp_info.smptbl.erase_type_size_arr[idx] = 1
341+
<< bptbl_ptr[SFDP_BASIC_PARAM_TABLE_ERASE_TYPE_1_SIZE_BYTE + 2 * idx]; // Size is 2^N where N is the table value
342+
tr_debug("Erase Type(A) %d - Inst: 0x%xh, Size: %d", (idx + 1), sfdp_info.smptbl.erase_type_inst_arr[idx],
343+
sfdp_info.smptbl.erase_type_size_arr[idx]);
344+
if (sfdp_info.smptbl.erase_type_size_arr[idx] > 1) {
285345
// if size==1 type is not supported
286-
sfdp_info.smptbl.erase_type_inst_arr[i_ind] = bptbl_ptr[SFDP_BASIC_PARAM_TABLE_ERASE_TYPE_1_BYTE
287-
+ 2 * i_ind];
346+
sfdp_info.smptbl.erase_type_inst_arr[idx] = bptbl_ptr[SFDP_BASIC_PARAM_TABLE_ERASE_TYPE_1_BYTE
347+
+ 2 * idx];
288348

289-
if ((sfdp_info.smptbl.erase_type_size_arr[i_ind] < sfdp_info.smptbl.regions_min_common_erase_size)
349+
if ((sfdp_info.smptbl.erase_type_size_arr[idx] < sfdp_info.smptbl.regions_min_common_erase_size)
290350
|| (sfdp_info.smptbl.regions_min_common_erase_size == 0)) {
291351
//Set default minimal common erase for signal region
292-
sfdp_info.smptbl.regions_min_common_erase_size = sfdp_info.smptbl.erase_type_size_arr[i_ind];
352+
sfdp_info.smptbl.regions_min_common_erase_size = sfdp_info.smptbl.erase_type_size_arr[idx];
293353
}
294354
sfdp_info.smptbl.region_erase_types_bitfld[0] |= bitfield; // If there's no region map, set region "0" types bitfield as default
295355
}
296356

297-
tr_debug("Erase Type %d - Inst: 0x%xh, Size: %d", (i_ind + 1), sfdp_info.smptbl.erase_type_inst_arr[i_ind],
298-
sfdp_info.smptbl.erase_type_size_arr[i_ind]);
357+
tr_debug("Erase Type %d - Inst: 0x%xh, Size: %d", (idx + 1), sfdp_info.smptbl.erase_type_inst_arr[idx],
358+
sfdp_info.smptbl.erase_type_size_arr[idx]);
299359
bitfield = bitfield << 1;
300360
}
301361
} else {
@@ -321,10 +381,10 @@ int sfdp_find_addr_region(bd_size_t offset, const sfdp_hdr_info &sfdp_info)
321381
return 0;
322382
}
323383

324-
for (int i_ind = sfdp_info.smptbl.region_cnt - 2; i_ind >= 0; i_ind--) {
384+
for (int idx = sfdp_info.smptbl.region_cnt - 2; idx >= 0; idx--) {
325385

326-
if (offset > sfdp_info.smptbl.region_high_boundary[i_ind]) {
327-
return (i_ind + 1);
386+
if (offset > sfdp_info.smptbl.region_high_boundary[idx]) {
387+
return (idx + 1);
328388
}
329389
}
330390
return -1;
@@ -338,11 +398,12 @@ int sfdp_iterate_next_largest_erase_type(uint8_t &bitfield,
338398
const sfdp_smptbl_info &smptbl)
339399
{
340400
uint8_t type_mask = SFDP_ERASE_BITMASK_TYPE4;
341-
int i_ind = 0;
342401
int largest_erase_type = 0;
343-
for (i_ind = 3; i_ind >= 0; i_ind--) {
402+
403+
int idx;
404+
for (idx = 3; idx >= 0; idx--) {
344405
if (bitfield & type_mask) {
345-
largest_erase_type = i_ind;
406+
largest_erase_type = idx;
346407
if ((size > (int)(smptbl.erase_type_size_arr[largest_erase_type])) &&
347408
((smptbl.region_high_boundary[region] - offset)
348409
> (int)(smptbl.erase_type_size_arr[largest_erase_type]))) {
@@ -354,7 +415,7 @@ int sfdp_iterate_next_largest_erase_type(uint8_t &bitfield,
354415
type_mask = type_mask >> 1;
355416
}
356417

357-
if (i_ind == 4) {
418+
if (idx == -1) {
358419
tr_error("No erase type was found for current region addr");
359420
}
360421
return largest_erase_type;

0 commit comments

Comments
 (0)