Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
QSPIFBlockDevice.cpp
00001 00002 /* mbed Microcontroller Library 00003 * Copyright (c) 2016 ARM Limited 00004 * 00005 * Licensed under the Apache License, Version 2.0 (the "License"); 00006 * you may not use this file except in compliance with the License. 00007 * You may obtain a copy of the License at 00008 * 00009 * http://www.apache.org/licenses/LICENSE-2.0 00010 * 00011 * Unless required by applicable law or agreed to in writing, software 00012 * distributed under the License is distributed on an "AS IS" BASIS, 00013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00014 * See the License for the specific language governing permissions and 00015 * limitations under the License. 00016 */ 00017 00018 //#include "./mbed-os/drivers/qspi.h" 00019 00020 #define DEVICE_QSPI 1 00021 00022 #include "QSPIFBlockDevice.h" 00023 00024 /* Default QSPIF Parameters */ 00025 /****************************/ 00026 #define QSPIF_DEFAULT_READ_SIZE 1 00027 #define QSPIF_DEFAULT_PROG_SIZE 1 00028 #define QSPIF_DEFAULT_SE_SIZE 4096 00029 #define QSPI_MAX_STATUS_REGISTER_SIZE 2 00030 #define QSPI_STATUS_REGISTER_WRITE_TIMEOUT_MSEC 50 00031 #define QSPIF_DEFAULT_TIMEOUT_MSEC 1 00032 00033 00034 /* SFDP Header Parsing */ 00035 /***********************/ 00036 #define QSPIF_SFDP_HEADER_SIZE 8 00037 #define QSPIF_PARAM_HEADER_SIZE 8 00038 00039 /* Basic Parameters Table Parsing */ 00040 /**********************************/ 00041 #define SFDP_DEFAULT_BASIC_PARAMS_TABLE_SIZE_BYTES 64 /* 16 DWORDS */ 00042 //READ Instruction support according to BUS Configuration 00043 #define QSPIF_BASIC_PARAM_TABLE_FAST_READ_SUPPORT_BYTE 2 00044 #define QSPIF_BASIC_PARAM_TABLE_QPI_READ_SUPPOR_BYTE 16 00045 #define QSPIF_BASIC_PARAM_TABLE_444_READ_INST_BYTE 27 00046 #define QSPIF_BASIC_PARAM_TABLE_144_READ_INST_BYTE 9 00047 #define QSPIF_BASIC_PARAM_TABLE_114_READ_INST_BYTE 11 00048 #define QSPIF_BASIC_PARAM_TABLE_222_READ_INST_BYTE 23 00049 #define QSPIF_BASIC_PARAM_TABLE_122_READ_INST_BYTE 15 00050 #define QSPIF_BASIC_PARAM_TABLE_112_READ_INST_BYTE 13 00051 #define QSPIF_BASIC_PARAM_TABLE_PAGE_SIZE_BYTE 40 00052 // Quad Enable Params 00053 #define QSPIF_BASIC_PARAM_TABLE_QER_BYTE 58 00054 #define QSPIF_BASIC_PARAM_TABLE_444_MODE_EN_SEQ_BYTE 56 00055 // Erase Types Params 00056 #define QSPIF_BASIC_PARAM_ERASE_TYPE_1_BYTE 29 00057 #define QSPIF_BASIC_PARAM_ERASE_TYPE_2_BYTE 31 00058 #define QSPIF_BASIC_PARAM_ERASE_TYPE_3_BYTE 33 00059 #define QSPIF_BASIC_PARAM_ERASE_TYPE_4_BYTE 35 00060 #define QSPIF_BASIC_PARAM_ERASE_TYPE_1_SIZE_BYTE 28 00061 #define QSPIF_BASIC_PARAM_ERASE_TYPE_2_SIZE_BYTE 30 00062 #define QSPIF_BASIC_PARAM_ERASE_TYPE_3_SIZE_BYTE 32 00063 #define QSPIF_BASIC_PARAM_ERASE_TYPE_4_SIZE_BYTE 34 00064 #define QSPIF_BASIC_PARAM_4K_ERASE_TYPE_BYTE 1 00065 00066 // Debug Printouts 00067 #define QSPIF_DEBUG_ERROR 1 00068 #define QSPIF_DEBUG_WARNING 2 00069 #define QSPIF_DEBUG_INFO 3 00070 #define QSPIF_DEBUG_DEBUG 4 00071 #define QSPIF_DEBUG_TRACE 5 00072 // #define QSPIF_DEFAULT_DEBUG_LEVEL QSPIF_DEBUG_INFO 00073 // #define QSPIF_DEFAULT_DEBUG_LEVEL QSPIF_DEBUG_TRACE 00074 #define QSPIF_DEFAULT_DEBUG_LEVEL QSPIF_DEBUG_WARNING 00075 00076 00077 enum qspif_default_instructions { 00078 QSPIF_NOP = 0x00, // No operation 00079 QSPIF_PP = 0x02, // Page Program data 00080 QSPIF_READ = 0x03, // Read data 00081 QSPIF_SE = 0x20, // 4KB Sector Erase 00082 QSPIF_SFDP = 0x5a, // Read SFDP 00083 00084 QSPIF_WRSR = 0x01, // Write Status/Configuration Register 00085 QSPIF_WRDI = 0x04, // Write Disable 00086 QSPIF_RDSR = 0x05, // Read Status Register 00087 QSPIF_WREN = 0x06, // Write Enable 00088 00089 QSPIF_RSTEN = 0x66, // Reset Enable 00090 QSPIF_RST = 0x99, // Reset 00091 QSPIF_RDID = 0x9f, // Read Manufacturer and JDEC Device ID 00092 }; 00093 00094 #define __FILENAME__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__) 00095 00096 #define QSPIF_LOG(level,...) {\ 00097 if (level <= QSPIF_DEFAULT_DEBUG_LEVEL) {\ 00098 char str[256];\ 00099 sprintf(str, "\n[%s][%s:%d], ", __FILENAME__, __FUNCTION__, __LINE__);\ 00100 sprintf(str+strlen(str),__VA_ARGS__);\ 00101 printf(str);\ 00102 }\ 00103 } 00104 00105 // Mutex is used for some QSPI Driver commands that must be done sequentially with no other commands in between 00106 // e.g. (1)Set Write Enable, (2)Program, (3)Wait Memory Ready 00107 SingletonPtr<PlatformMutex> QSPIFBlockDevice::_mutex; 00108 00109 00110 /********* Public API Functions *********/ 00111 /****************************************/ 00112 00113 QSPIFBlockDevice::QSPIFBlockDevice(PinName io0, PinName io1, PinName io2, PinName io3, PinName sclk, PinName csel, 00114 int clock_mode, int freq) 00115 : _qspi(io0, io1, io2, io3, sclk, csel, clock_mode), _deviceSizeBytes(0) 00116 { 00117 //_cs = 1; 00118 is_initialized = false; 00119 _minCommonEraseSize = 0; 00120 _regions_count = 1; 00121 _region_erase_types[0] = 0; 00122 00123 //Default Bus Setup 1_1_1 with 0 dummy and mode cycles 00124 _inst_width = QSPI_CFG_BUS_SINGLE; 00125 _address_width = QSPI_CFG_BUS_SINGLE; 00126 _address_size = QSPI_CFG_ADDR_SIZE_24; 00127 _alt_width = QSPI_CFG_BUS_SINGLE; 00128 _alt_size = QSPI_CFG_ALT_SIZE_8; 00129 _data_width = QSPI_CFG_BUS_SINGLE; 00130 _dummy_and_mode_cycles = 0; 00131 00132 if (QSPI_STATUS_OK != _qspiSetFrequency(freq)) { 00133 QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: QSPI Set Frequency Failed"); 00134 } 00135 } 00136 00137 00138 int QSPIFBlockDevice::init() 00139 { 00140 00141 uint8_t vendor_device_ids[4]; 00142 size_t data_length = 3; 00143 00144 _mutex->lock(); 00145 if (is_initialized == true) { 00146 _mutex->unlock(); 00147 return 0; 00148 } 00149 00150 // Soft Reset 00151 if ( -1 == _resetFlashMem()) { 00152 QSPIF_LOG(QSPIF_DEBUG_INFO, "ERROR: init - Unable to initialize flash memory, tests failed\n"); 00153 return -1; 00154 } else { 00155 QSPIF_LOG(QSPIF_DEBUG_INFO, "INFO: Initialize flash memory OK\n"); 00156 } 00157 00158 00159 00160 /* Read Manufacturer ID (1byte), and Device ID (2bytes)*/ 00161 int status = _qspiSendReadCommand(QSPIF_RDID, (char *)vendor_device_ids, 0x0 /*address*/, data_length); 00162 if (status != QSPI_STATUS_OK) { 00163 QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: init - Read Vendor ID Failed"); 00164 return status; 00165 } 00166 00167 switch (vendor_device_ids[0]) { 00168 case 0xbf: 00169 // SST devices come preset with block protection 00170 // enabled for some regions, issue write disable instruction to clear 00171 _setWriteEnable(); 00172 //_cmdwrite(0x98, 0, 0, 0x0, NULL); 00173 _qspiSendGeneralCommand(QSPIF_WRDI, -1, NULL, 0, NULL, 0); 00174 00175 break; 00176 } 00177 00178 //Synchronize Device 00179 if ( false == _isMemReady()) { 00180 QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: init - _isMemReady Failed"); 00181 return BD_ERROR_DEVICE_ERROR; 00182 } 00183 00184 00185 /**************************** Parse SFDP Header ***********************************/ 00186 uint32_t basic_table_addr = NULL; 00187 size_t basic_table_size = 0; 00188 uint32_t sector_map_table_addr = NULL; 00189 size_t sector_map_table_size = 0; 00190 if ( 0 != _sfdpParseSFDPHeaders(basic_table_addr, basic_table_size, sector_map_table_addr, sector_map_table_size)) { 00191 QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: init - Parse SFDP Headers Failed"); 00192 return BD_ERROR_DEVICE_ERROR; 00193 } 00194 00195 00196 /**************************** Parse Basic Parameters Table ***********************************/ 00197 if ( 0 != _sfdpParseBasicParamTable(basic_table_addr, basic_table_size) ) { 00198 QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: init - Parse Basic Param Table Failed"); 00199 return BD_ERROR_DEVICE_ERROR; 00200 } 00201 00202 00203 /**************************** Parse Sector Map Table ***********************************/ 00204 _region_size_bytes[0] = 00205 _deviceSizeBytes; // If there's no region map, we have a single region sized the entire device size 00206 _region_high_boundary[0] = _deviceSizeBytes - 1; 00207 00208 if ( (sector_map_table_addr != NULL) && (0 != sector_map_table_size) ) { 00209 QSPIF_LOG(QSPIF_DEBUG_INFO, "INFO: init - Parsing Sector Map Table - addr: 0x%xh, Size: %d", sector_map_table_addr, 00210 sector_map_table_size); 00211 if ( 0 != _sfdpParseSectorMapTable(sector_map_table_addr, sector_map_table_size) ) { 00212 QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: init - Parse Sector Map Table Failed"); 00213 return BD_ERROR_DEVICE_ERROR; 00214 } 00215 } 00216 00217 00218 // Configure BUS Mode to 1_1_1 for all commands other than Read 00219 _qspiConfiureFormat( QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_SINGLE, QSPI_CFG_ADDR_SIZE_24, QSPI_CFG_BUS_SINGLE, 00220 QSPI_CFG_ALT_SIZE_8, QSPI_CFG_BUS_SINGLE, 0); 00221 /*// Soft Reset 00222 if( -1 == _resetFlashMem()) { 00223 QSPIF_LOG(QSPIF_DEBUG_INFO,"ERROR: init - Unable to initialize flash memory, tests failed\n"); 00224 return -1; 00225 } else { 00226 QSPIF_LOG(QSPIF_DEBUG_INFO,"INFO: Initialize flash memory OK\n"); 00227 }*/ 00228 00229 is_initialized = true; 00230 _mutex->unlock(); 00231 00232 return 0; 00233 } 00234 00235 int QSPIFBlockDevice::deinit() 00236 { 00237 _mutex->lock(); 00238 if (is_initialized == false) { 00239 _mutex->unlock(); 00240 return 0; 00241 } 00242 qspi_status_t status = _qspiSendGeneralCommand(QSPIF_WRDI, -1, NULL, 0, NULL, 0); 00243 int result = 0; 00244 00245 if (status != QSPI_STATUS_OK) { 00246 QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: Write Disable failed"); 00247 result = -1; 00248 } 00249 is_initialized = false; 00250 _mutex->unlock(); 00251 00252 return result; 00253 } 00254 00255 00256 int QSPIFBlockDevice::read(void *buffer, bd_addr_t addr, bd_size_t size) 00257 { 00258 00259 00260 int status = 0; 00261 00262 QSPIF_LOG(QSPIF_DEBUG_INFO, "INFO Inst: 0x%xh", _readInstruction); 00263 00264 _mutex->lock(); 00265 00266 _qspiConfiureFormat( 00267 _inst_width, //Bus width for Instruction phase 00268 _address_width, //Bus width for Address phase 00269 _address_size, 00270 _alt_width, //Bus width for Alt phase 00271 _alt_size, 00272 _data_width, //Bus width for Data phase 00273 _dummy_and_mode_cycles); 00274 //_qspiConfiureFormat( QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_SINGLE, QSPI_CFG_ADDR_SIZE_24, QSPI_CFG_BUS_SINGLE, QSPI_CFG_ALT_SIZE_8, QSPI_CFG_BUS_SINGLE, 8); 00275 00276 if (QSPI_STATUS_OK != _qspiSendReadCommand(_readInstruction, buffer, addr, size)) { 00277 status = -1; 00278 QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: Read failed\n"); 00279 } 00280 00281 // All commands other than Read use default 1-1-1 Bus mode (Program/Erase are constrained by flash memory performance less than that of the bus) 00282 _qspiConfiureFormat( QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_SINGLE, QSPI_CFG_ADDR_SIZE_24, QSPI_CFG_BUS_SINGLE, 00283 QSPI_CFG_ALT_SIZE_8, QSPI_CFG_BUS_SINGLE, 0); 00284 00285 _mutex->unlock(); 00286 return status; 00287 00288 } 00289 00290 00291 00292 00293 int QSPIFBlockDevice::program(const void *buffer, bd_addr_t addr, bd_size_t size) 00294 { 00295 qspi_status_t result = QSPI_STATUS_OK; 00296 bool program_failed = false; 00297 int status = 0; 00298 uint32_t offset = 0; 00299 uint32_t chunk = 0; 00300 bd_size_t writtenBytes = 0; 00301 00302 while (size > 0) { 00303 00304 // Write on _pageSizeBytes boundaries (Default 256 bytes a page) 00305 offset = addr % _pageSizeBytes; 00306 chunk = (offset + size < _pageSizeBytes) ? size : (_pageSizeBytes - offset); 00307 writtenBytes = chunk; 00308 00309 _mutex->lock(); 00310 00311 //Send WREN 00312 if (_setWriteEnable() != 0) { 00313 QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: Write Enabe failed\n"); 00314 program_failed = true; 00315 goto Exit_Point; 00316 } 00317 00318 if ( false == _isMemReady()) { 00319 QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: Device not ready, write failed\n"); 00320 program_failed = true; 00321 goto Exit_Point; 00322 } 00323 00324 result = _qspiSendProgramCommand(_progInstruction, buffer, addr, &writtenBytes); 00325 if ( (result != QSPI_STATUS_OK) || (chunk != writtenBytes) ) { 00326 QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: Write failed"); 00327 program_failed = true; 00328 goto Exit_Point; 00329 } 00330 00331 buffer = static_cast<const uint8_t *>(buffer) + chunk; 00332 addr += chunk; 00333 size -= chunk; 00334 00335 wait_ms(QSPIF_DEFAULT_TIMEOUT_MSEC); 00336 00337 if ( false == _isMemReady()) { 00338 QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: Device not ready after write, failed\n"); 00339 program_failed = true; 00340 goto Exit_Point; 00341 } 00342 _mutex->unlock(); 00343 00344 00345 } 00346 00347 Exit_Point: 00348 if (program_failed) { 00349 _mutex->unlock(); 00350 status = -1; 00351 } 00352 00353 return status; 00354 } 00355 00356 00357 int QSPIFBlockDevice::erase(bd_addr_t addr, bd_size_t inSize) 00358 { 00359 00360 int type = 0; 00361 uint32_t chunk = 4096; 00362 unsigned int curEraseInst = _eraseInstruction; 00363 int size = (int)inSize; 00364 bool erase_failed = false; 00365 int status = 0; 00366 // Find region of erased address 00367 int region = _utilsFindAddrRegion((int)addr); 00368 // Erase Types of selected region 00369 uint8_t bitfield = _region_erase_types[region]; 00370 00371 00372 while (size > 0) { 00373 00374 // iterate to find next Largest erase type (1) supported by region, 2) smaller than size) 00375 // find the matching instruction and erase size chunk for that type. 00376 type = _utilsIterateNextLargestEraseType(bitfield, (int)size, (int)addr, _region_high_boundary[region]); 00377 curEraseInst = _eraseTypeInstArr[type]; 00378 chunk = _eraseTypeSizeArr[type]; 00379 00380 QSPIF_LOG(QSPIF_DEBUG_DEBUG, " Debug: addr: 0x%xh, size:%d, Inst: 0x%xh, chunk: %d , ", 00381 (int)addr, (int)size, curEraseInst, chunk); 00382 00383 _mutex->lock(); 00384 00385 if (_setWriteEnable() != 0) { 00386 QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: QSPI Erase - Write Enable failed"); 00387 erase_failed = true; 00388 goto Exit_Point; 00389 } 00390 00391 if ( false == _isMemReady()) { 00392 QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: QSPI Erase Device not ready - failed"); 00393 erase_failed = true; 00394 goto Exit_Point; 00395 } 00396 00397 if (QSPI_STATUS_OK != _qspiSendEraseCommand(curEraseInst, addr, size) ) { 00398 QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: QSPI Erase command failed!"); 00399 erase_failed = true; 00400 goto Exit_Point; 00401 } 00402 00403 addr += chunk; 00404 size -= chunk; 00405 00406 if ( (size > 0) && (addr > _region_high_boundary[region]) ) { 00407 // erase crossed to next region 00408 region++; 00409 bitfield = _region_erase_types[region]; 00410 } 00411 wait_ms(QSPIF_DEFAULT_TIMEOUT_MSEC); 00412 if ( false == _isMemReady()) { 00413 QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: QSPI After Erase Device not ready - failed\n"); 00414 erase_failed = true; 00415 goto Exit_Point; 00416 } 00417 _mutex->unlock(); 00418 00419 } 00420 00421 00422 Exit_Point: 00423 if (erase_failed) { 00424 _mutex->unlock(); 00425 status = -1; 00426 } 00427 00428 return status; 00429 } 00430 00431 00432 00433 bd_size_t QSPIFBlockDevice::get_read_size() const 00434 { 00435 return QSPIF_DEFAULT_READ_SIZE; 00436 } 00437 00438 bd_size_t QSPIFBlockDevice::get_program_size() const 00439 { 00440 return QSPIF_DEFAULT_PROG_SIZE; 00441 } 00442 00443 bd_size_t QSPIFBlockDevice::get_erase_size() const 00444 { 00445 return _minCommonEraseSize; 00446 } 00447 00448 00449 // Find minimal erase size supported by address region 00450 bd_size_t QSPIFBlockDevice::get_erase_size(bd_addr_t addr) 00451 { 00452 // Find region of current address 00453 int region = _utilsFindAddrRegion((int)addr); 00454 00455 int minRegionEraseSize = _minCommonEraseSize; 00456 int8_t type_mask = 0x01; 00457 int i_ind = 0; 00458 00459 if (region != -1) { 00460 type_mask = 0x01; 00461 00462 for (i_ind = 0; i_ind < 4; i_ind++) { 00463 // loop through erase types supported by region 00464 if (_region_erase_types[region] & type_mask) { 00465 00466 minRegionEraseSize = _eraseTypeSizeArr[i_ind]; 00467 break; 00468 } 00469 type_mask = type_mask << 1; 00470 } 00471 00472 if (i_ind == 4) { 00473 QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: no erase type was found for region addr"); 00474 } 00475 } 00476 00477 return (bd_size_t)minRegionEraseSize; 00478 00479 } 00480 00481 bd_size_t QSPIFBlockDevice::size() const 00482 { 00483 return _deviceSizeBytes; 00484 } 00485 00486 00487 /*********************************************************/ 00488 /********** SFDP Parsing and Detection Functions *********/ 00489 /*********************************************************/ 00490 00491 int QSPIFBlockDevice::_sfdpParseSectorMapTable(uint32_t sector_map_table_addr, size_t sector_map_table_size) 00492 { 00493 uint8_t sector_map_table[SFDP_DEFAULT_BASIC_PARAMS_TABLE_SIZE_BYTES]; /* Up To 16 DWORDS = 64 Bytes */ 00494 uint32_t tmpRegionSize = 0; 00495 int i_ind = 0; 00496 int prevBoundary = 0; 00497 // Default set to all type bits 1-4 are common 00498 _minCommonEraseType = 0x0F; 00499 00500 qspi_status_t status = _qspiSendReadCommand(QSPIF_SFDP, (char *)sector_map_table, sector_map_table_addr /*address*/, 00501 sector_map_table_size); 00502 if (status != QSPI_STATUS_OK) { 00503 QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: init - Read SFDP First Table Failed"); 00504 return -1; 00505 } 00506 00507 //QSPIF_LOG(QSPIF_DEBUG_DEBUG,\nDEBUG: "Read table: %x %x %x %x %x %x %x %x %x[56] %x[57] %x[58] %x[59] %x[52]\n",sector_map_table[0], 00508 // sector_map_table[1], 00509 // sector_map_table[2], 00510 // sector_map_table[3], 00511 // sector_map_table[4], 00512 // sector_map_table[5], 00513 // sector_map_table[6], 00514 // sector_map_table[7], sector_map_table[56], sector_map_table[57], sector_map_table[58], sector_map_table[59], sector_map_table[52]); 00515 00516 // Currently we support only Single Map Descriptor 00517 if (! ( (sector_map_table[0] & 0x3) == 0x03 ) && (sector_map_table[1] == 0x0) ) { 00518 QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: Sector Map - Supporting Only Single! Map Descriptor (not map commands)"); 00519 return -1; 00520 } 00521 00522 _regions_count = sector_map_table[2] + 1; 00523 if (_regions_count > QSPIF_MAX_REGIONS) { 00524 QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: Supporting up to %d regions, current setup to %d regions - fail", 00525 QSPIF_MAX_REGIONS, _regions_count); 00526 return -1; 00527 } 00528 00529 // Loop through Regions and set for each one: size, supported erase types, high boundary offset 00530 // Calculate minimum Common Erase Type for all Regions 00531 for (i_ind = 0; i_ind < _regions_count; i_ind++) { 00532 tmpRegionSize = ((*((uint32_t *)§or_map_table[(i_ind + 1) * 4])) >> 8) & 0x00FFFFFF; // bits 9-32 00533 _region_size_bytes[i_ind] = (tmpRegionSize + 1) * 256; // Region size is 0 based multiple of 256 bytes; 00534 _region_erase_types[i_ind] = sector_map_table[(i_ind + 1) * 4] & 0x0F; // bits 1-4 00535 _minCommonEraseType &= _region_erase_types[i_ind]; 00536 _region_high_boundary[i_ind] = (_region_size_bytes[i_ind] - 1) + prevBoundary; 00537 prevBoundary = _region_high_boundary[i_ind] + 1; 00538 } 00539 00540 // Calc minimum Common Erase Size from _minCommonEraseType 00541 uint8_t type_mask = 0x01; 00542 for (i_ind = 0; i_ind < 4; i_ind++) { 00543 if (_minCommonEraseType & type_mask) { 00544 _minCommonEraseType = i_ind; 00545 _minCommonEraseSize = _eraseTypeSizeArr[i_ind]; 00546 break; 00547 } 00548 type_mask = type_mask << 1; 00549 } 00550 00551 if (i_ind == 4) { 00552 // No common erase type was found between regions 00553 _minCommonEraseType = 0; 00554 _minCommonEraseSize = -1; 00555 } 00556 00557 return 0; 00558 } 00559 00560 00561 int QSPIFBlockDevice::_sfdpParseBasicParamTable(uint32_t basic_table_addr, size_t basic_table_size) 00562 { 00563 uint8_t param_table[SFDP_DEFAULT_BASIC_PARAMS_TABLE_SIZE_BYTES]; /* Up To 16 DWORDS = 64 Bytes */ 00564 00565 qspi_status_t status = _qspiSendReadCommand(QSPIF_SFDP, (char *)param_table, basic_table_addr /*address*/, 00566 basic_table_size); 00567 if (status != QSPI_STATUS_OK) { 00568 QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: init - Read SFDP First Table Failed, Status %d",status); 00569 return -1; 00570 } 00571 00572 QSPIF_LOG(QSPIF_DEBUG_DEBUG, "DEBUG: Read table: %x %x %x %x %x %x %x %x %x[56] %x[57] %x[58] %x[59] %x[52]\n", 00573 param_table[0], 00574 param_table[1], 00575 param_table[2], 00576 param_table[3], 00577 param_table[4], 00578 param_table[5], 00579 param_table[6], 00580 param_table[7], param_table[56], param_table[57], param_table[58], param_table[59], param_table[52]); 00581 00582 00583 // Check address size, currently only supports 3byte addresses 00584 if ((param_table[2] & 0x4) != 0 || (param_table[7] & 0x80) != 0) { 00585 QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: init - verify 3byte addressing Failed"); 00586 return -1; 00587 } 00588 00589 // Get device density (stored in bits - 1) 00590 uint32_t density_bits = ( 00591 (param_table[7] << 24) | 00592 (param_table[6] << 16) | 00593 (param_table[5] << 8 ) | 00594 param_table[4] ); 00595 _deviceSizeBytes = (density_bits + 1) / 8; 00596 00597 // Set Default read/program/erase Instructions 00598 _readInstruction = QSPIF_READ; 00599 _progInstruction = QSPIF_PP; 00600 _eraseInstruction = QSPIF_SE; 00601 00602 // Set Page Size (QSPI write must be done on Page limits) 00603 _pageSizeBytes = _sfdpDetectPageSize(param_table); 00604 00605 // Detect and Set Erase Types 00606 bool shouldSetQuadEnable = false; 00607 bool isQPIMode = false; 00608 _sfdpDetectEraseTypesInstAndSize(param_table, _erase4KInst, _eraseTypeInstArr, _eraseTypeSizeArr); 00609 _eraseInstruction = _erase4KInst; 00610 00611 00612 // Detect and Set fastest Bus mode (default 1-1-1) 00613 _sfdpDetectBestBusReadMode(param_table, shouldSetQuadEnable, isQPIMode, _readInstruction); 00614 00615 if (true == shouldSetQuadEnable) { 00616 // Set Quad Enable and QPI Bus modes if Supported 00617 QSPIF_LOG(QSPIF_DEBUG_INFO, "INFO: init - Setting Quad Enable"); 00618 _sfdpSetQuadEnabled(param_table); 00619 if (true == isQPIMode) { 00620 QSPIF_LOG(QSPIF_DEBUG_INFO, "INFO: init - Setting QPI mode"); 00621 _sfdpSetQPIEnabled(param_table); 00622 } 00623 } 00624 return 0; 00625 } 00626 00627 int QSPIFBlockDevice::_sfdpParseSFDPHeaders(uint32_t& basic_table_addr, size_t& basic_table_size, 00628 uint32_t& sector_map_table_addr, size_t& sector_map_table_size) 00629 { 00630 uint8_t sfdp_header[QSPIF_SFDP_HEADER_SIZE]; 00631 uint8_t param_header[QSPIF_PARAM_HEADER_SIZE]; 00632 size_t data_length = QSPIF_SFDP_HEADER_SIZE; 00633 bd_addr_t addr = 0x0; 00634 00635 // Set 1-1-1 bus mode for SFDP header parsing 00636 _qspiConfiureFormat( QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_SINGLE, QSPI_CFG_ADDR_SIZE_24, QSPI_CFG_BUS_SINGLE, 00637 QSPI_CFG_ALT_SIZE_8, QSPI_CFG_BUS_SINGLE, 8); 00638 00639 qspi_status_t status = _qspiSendReadCommand(QSPIF_SFDP, (char *)sfdp_header, addr /*address*/, data_length); 00640 if (status != QSPI_STATUS_OK) { 00641 QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: init - Read SFDP Failed"); 00642 return -1; 00643 } 00644 00645 00646 QSPIF_LOG(QSPIF_DEBUG_DEBUG, "DEBUG11: Read SFDP Header: %x %x %x %x %x %x %x %x\n", sfdp_header[0], 00647 sfdp_header[1], 00648 sfdp_header[2], 00649 sfdp_header[3], 00650 sfdp_header[4], 00651 sfdp_header[5], 00652 sfdp_header[6], 00653 sfdp_header[7]); 00654 00655 00656 // Verify SFDP signature for sanity 00657 // Also check that major/minor version is acceptable 00658 if (!(memcmp(&sfdp_header[0], "SFDP", 4) == 0 && sfdp_header[5] == 1)) { 00659 QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: init - _verify SFDP signature and version Failed"); 00660 return -1; 00661 } else { 00662 QSPIF_LOG(QSPIF_DEBUG_INFO, "INFO: init - verified SFDP Signature and version Successfully"); 00663 } 00664 00665 // Discover Number of Parameter Headers 00666 int number_of_param_headers = (int)(sfdp_header[6]) + 1; 00667 QSPIF_LOG(QSPIF_DEBUG_DEBUG, "DEBUG: number of Param Headers: %d", number_of_param_headers); 00668 00669 00670 addr += QSPIF_SFDP_HEADER_SIZE; 00671 data_length = QSPIF_PARAM_HEADER_SIZE; 00672 00673 // Loop over Param Headers and parse them (currently supported Basic Param Table and Sector Region Map Table) 00674 for (int i_ind = 0; i_ind < number_of_param_headers; i_ind++) { 00675 00676 status = _qspiSendReadCommand(QSPIF_SFDP, (char *)param_header, addr, data_length); 00677 if (status != QSPI_STATUS_OK) { 00678 QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: init - Read Param Table %d Failed", i_ind + 1); 00679 return -1; 00680 } 00681 // The SFDP spec indicates the standard table is always at offset 0 00682 // in the parameter headers, we check just to be safe 00683 if (param_header[2] != 1) { 00684 QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: Param Table %d - Major Version should be 1!", i_ind + 1); 00685 return -1; 00686 } 00687 00688 if ((param_header[0] == 0) && (param_header[7] == 0xFF)) { 00689 // Found Basic Params Table: LSB=0x00, MSB=0xFF 00690 QSPIF_LOG(QSPIF_DEBUG_DEBUG, "DEBUG: Found Basic Param Table at Table: %d", i_ind + 1); 00691 basic_table_addr = ( (param_header[6] << 16) | (param_header[5] << 8) | (param_header[4]) ); 00692 // Supporting up to 64 Bytes Table (16 DWORDS) 00693 basic_table_size = ((param_header[3] * 4) < SFDP_DEFAULT_BASIC_PARAMS_TABLE_SIZE_BYTES) ? (param_header[11] * 4) : 64; 00694 00695 } else if ((param_header[0] == 81) && (param_header[7] == 0xFF)) { 00696 // Found Sector Map Table: LSB=0x81, MSB=0xFF 00697 QSPIF_LOG(QSPIF_DEBUG_DEBUG, "DEBUG: Found Sector Map Table at Table: %d", i_ind + 1); 00698 sector_map_table_addr = ( (param_header[6] << 16) | (param_header[5] << 8) | (param_header[4]) ); 00699 00700 sector_map_table_size = param_header[3] * 4; 00701 00702 } 00703 addr += QSPIF_PARAM_HEADER_SIZE; 00704 00705 } 00706 return 0; 00707 } 00708 00709 00710 00711 int QSPIFBlockDevice::_sfdpSetQPIEnabled(uint8_t *basicParamTablePtr) 00712 { 00713 uint8_t config_reg[1]; 00714 00715 // QPI 4-4-4 Enable Procedure is specified in 5 Bits 00716 uint8_t en_seq_444_value = ( ((basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_444_MODE_EN_SEQ_BYTE] & 0xF0) >> 4) | (( 00717 basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_444_MODE_EN_SEQ_BYTE + 1] & 0x01) << 4 )); 00718 00719 switch (en_seq_444_value) { 00720 case 1: 00721 case 2: 00722 QSPIF_LOG(QSPIF_DEBUG_DEBUG, "DEBUG: _setQPIEnabled - send command 38h"); 00723 /*if (_setWriteEnable() != 0) { 00724 printf("ERROR: Write Enabe failed\n"); 00725 return -1; 00726 } 00727 if( false == _isMemReady()) { 00728 printf("ERROR: Device not ready, write failed\n"); 00729 return -1; 00730 }*/ 00731 00732 _qspiSendGeneralCommand(0x38, -1, NULL, 0, NULL, 0); 00733 /*wait_ms(QSPI_STATUS_REGISTER_WRITE_TIMEOUT_MSEC); 00734 if( false == _isMemReady()) { 00735 printf("ERROR: Device not ready after write, failed\n"); 00736 return -1; 00737 }*/ 00738 00739 00740 break; 00741 00742 case 4: 00743 QSPIF_LOG(QSPIF_DEBUG_DEBUG, "DEBUG: _setQPIEnabled - send command 35h"); 00744 _qspiSendGeneralCommand(0x35, -1, NULL, 0, NULL, 0); 00745 break; 00746 00747 case 8: 00748 QSPIF_LOG(QSPIF_DEBUG_DEBUG, "DEBUG: _setQPIEnabled - set config bit 6 and send command 71h"); 00749 _qspiSendGeneralCommand(0x65, 0x800003, NULL, 0, (char *)config_reg, 1); 00750 config_reg[1] |= 0x40; //Set Bit 6 00751 _qspiSendGeneralCommand(0x71, 0x800003, NULL, 0, (char *)config_reg, 1); 00752 break; 00753 00754 case 16: 00755 QSPIF_LOG(QSPIF_DEBUG_DEBUG, "DEBUG: _setQPIEnabled - reset config bits 0-7 and send command 61h"); 00756 _qspiSendGeneralCommand(0x65, -1, NULL, 0, (char *)config_reg, 1); 00757 config_reg[1] &= 0x7F; //Reset Bit 7 of CR 00758 00759 00760 00761 00762 /* 00763 if (_setWriteEnable() != 0) { 00764 printf("ERROR: Write Enabe failed\n"); 00765 return -1; 00766 } 00767 if( false == _isMemReady()) { 00768 printf("ERROR: Device not ready, write failed\n"); 00769 return -1; 00770 }*/ 00771 00772 _qspiSendGeneralCommand(0x61, -1, NULL, 0, (char *)config_reg, 1); 00773 00774 00775 /* wait_ms(QSPI_STATUS_REGISTER_WRITE_TIMEOUT_MSEC); 00776 if( false == _isMemReady()) { 00777 printf("ERROR: Device not ready after write, failed\n"); 00778 return -1; 00779 } 00780 00781 00782 00783 _qspiSendGeneralCommand(0x65, -1, NULL, 0, (char *)config_reg, 1); 00784 00785 if (_setWriteEnable() != 0) { 00786 printf("ERROR: Write Enabe failed\n"); 00787 return -1; 00788 } 00789 if( false == _isMemReady()) { 00790 printf("ERROR: Device not ready, write failed\n"); 00791 return -1; 00792 } 00793 config_reg[1] = 0x00; //Reset Bits 0-7 00794 _qspiSendGeneralCommand(0x61, -1, NULL, 0, (char *)config_reg, 1); 00795 wait_ms(QSPI_STATUS_REGISTER_WRITE_TIMEOUT_MSEC);*/ 00796 /* if( false == _isMemReady()) { 00797 printf("ERROR: Device not ready after write, failed\n"); 00798 return -1; 00799 }*/ 00800 00801 break; 00802 00803 default: 00804 QSPIF_LOG(QSPIF_DEBUG_WARNING, "WARNING: _setQPIEnabled - Unsuported En Seq 444 configuration"); 00805 break; 00806 00807 00808 } 00809 00810 return 0; 00811 } 00812 00813 00814 00815 int QSPIFBlockDevice::_sfdpSetQuadEnabled(uint8_t *basicParamTablePtr) 00816 { 00817 00818 int sr_read_size = QSPI_MAX_STATUS_REGISTER_SIZE; 00819 int sr_write_size = QSPI_MAX_STATUS_REGISTER_SIZE; 00820 00821 int status_reg_setup[QSPI_MAX_STATUS_REGISTER_SIZE]; 00822 uint8_t status_reg[QSPI_MAX_STATUS_REGISTER_SIZE]; 00823 unsigned int writeRegisterInst = QSPIF_WRSR; 00824 unsigned int readRegisterInst = QSPIF_RDSR; 00825 00826 uint8_t qer_value = (basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_QER_BYTE] & 0x70) >> 4; 00827 00828 00829 00830 switch (qer_value) { 00831 case 0: 00832 QSPIF_LOG(QSPIF_DEBUG_DEBUG, "DEBUG: Device Does not Have a QE Bit, continue based on Read Inst"); 00833 return 0; 00834 00835 case 1: 00836 case 4: 00837 status_reg_setup[0] = 0; 00838 status_reg_setup[1] = 0x02; 00839 QSPIF_LOG(QSPIF_DEBUG_DEBUG, "DEBUG: Setting QE Bit, Bit 1 of Status Reg 2"); 00840 break; 00841 00842 case 2: 00843 status_reg_setup[0] = 0x40; 00844 status_reg_setup[1] = 0; 00845 sr_write_size = 1; 00846 sr_read_size = 1; 00847 QSPIF_LOG(QSPIF_DEBUG_DEBUG, "DEBUG: Setting QE Bit, Bit 6 of Status Reg 1"); 00848 break; 00849 00850 case 3: 00851 status_reg_setup[0] = 0x80; // Bit 7 of Status Reg 1 00852 status_reg_setup[1] = 0; 00853 sr_write_size = 1; 00854 sr_read_size = 1; 00855 writeRegisterInst = 0x3E; 00856 readRegisterInst = 0x3F; 00857 QSPIF_LOG(QSPIF_DEBUG_DEBUG, "DEBUG: Setting QE Bit, Bit 7 of Status Reg 1"); 00858 break; 00859 case 5: 00860 status_reg_setup[0] = 0; 00861 status_reg_setup[1] = 0x02; 00862 readRegisterInst = 0x35; 00863 sr_read_size = 1; 00864 QSPIF_LOG(QSPIF_DEBUG_DEBUG, "DEBUG: Setting QE Bit, Bit 1 of Status Reg 2 -special read command"); 00865 break; 00866 default: 00867 QSPIF_LOG(QSPIF_DEBUG_WARNING, "WARNING: _setQuadEnable - Unsuported QER configuration"); 00868 break; 00869 00870 00871 } 00872 00873 // Read Status Register 00874 if (QSPI_STATUS_OK == _qspiSendGeneralCommand(readRegisterInst, -1, NULL, 0, (char *)status_reg, 00875 sr_read_size) ) { // store received values in status_value 00876 QSPIF_LOG(QSPIF_DEBUG_DEBUG, "DEBUG: Reading Status Register Success: value = 0x%x\n", (int)status_reg[0]); 00877 } else { 00878 QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: Reading Status Register failed"); 00879 return -1; 00880 } 00881 00882 // Set Bits for Quad Enable 00883 status_reg[0] |= status_reg_setup[0]; 00884 status_reg[1] |= status_reg_setup[1]; 00885 00886 00887 // Write new Status Register Setup 00888 if (_setWriteEnable() != 0) { 00889 QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: Write Enabe failed\n"); 00890 return -1; 00891 } 00892 00893 if ( false == _isMemReady()) { 00894 QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: Device not ready, write failed"); 00895 return -1; 00896 } 00897 00898 if (QSPI_STATUS_OK == _qspiSendGeneralCommand(writeRegisterInst, -1, (char *)status_reg, sr_write_size, NULL, 00899 0) ) { // Write QE to status_register 00900 QSPIF_LOG(QSPIF_DEBUG_DEBUG, "DEBUG: _setQuadEnable - Writing Status Register Success: value = 0x%x", 00901 (int)status_reg[0]); 00902 } else { 00903 QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: _setQuadEnable - Writing Status Register failed"); 00904 return -1; 00905 } 00906 00907 wait_ms(QSPI_STATUS_REGISTER_WRITE_TIMEOUT_MSEC); 00908 00909 if ( false == _isMemReady()) { 00910 QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: Device not ready after write, failed"); 00911 return -1; 00912 } 00913 00914 00915 // For Debug 00916 memset(status_reg, 0, QSPI_MAX_STATUS_REGISTER_SIZE); 00917 if (QSPI_STATUS_OK == _qspiSendGeneralCommand(readRegisterInst, -1, NULL, 0, (char *)status_reg, 00918 sr_read_size) ) { // store received values in status_value 00919 QSPIF_LOG(QSPIF_DEBUG_DEBUG, "DEBUG: Reading Status Register Success: value = 0x%x\n", (int)status_reg[0]); 00920 } else { 00921 QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: Reading Status Register failed"); 00922 return -1; 00923 } 00924 00925 00926 return 0;//((status_reg[0] & QSPI_STATUS_BIT_QE) != 0 ? 0 : -1); 00927 } 00928 00929 00930 int QSPIFBlockDevice::_sfdpDetectPageSize(uint8_t *basicParamTablePtr) 00931 { 00932 int page2PowerSize = ( (int)basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_PAGE_SIZE_BYTE]) >> 4; 00933 int pageSize = _utilsMathPower(2, page2PowerSize); 00934 QSPIF_LOG(QSPIF_DEBUG_DEBUG, "DEBUG: _detectPageSize - Page Size: %d", pageSize); 00935 return pageSize; 00936 } 00937 00938 00939 00940 int QSPIFBlockDevice::_sfdpDetectEraseTypesInstAndSize(uint8_t *basicParamTablePtr, unsigned int& erase4KInst, 00941 unsigned int *eraseTypeInstArr, unsigned int *eraseTypeSizeArr) 00942 { 00943 erase4KInst = 0xff; 00944 bool found4KEraseType = false; 00945 uint8_t bitfield = 0x01; 00946 00947 // Erase 4K Inst is taken either from param table legacy 4K erase or superseded by erase Instruction for type of size 4K 00948 erase4KInst = basicParamTablePtr[QSPIF_BASIC_PARAM_4K_ERASE_TYPE_BYTE]; 00949 00950 // Loop Erase Types 1-4 00951 for (int i_ind = 0; i_ind < 4; i_ind++) { 00952 eraseTypeInstArr[i_ind] = 0xff; //0xFF default for unsupported type 00953 eraseTypeSizeArr[i_ind] = _utilsMathPower(2, basicParamTablePtr[QSPIF_BASIC_PARAM_ERASE_TYPE_1_SIZE_BYTE + 2 * i_ind]); 00954 if (eraseTypeSizeArr[i_ind] > 1) { 00955 // if size==1 type is not supported 00956 eraseTypeInstArr[i_ind] = basicParamTablePtr[QSPIF_BASIC_PARAM_ERASE_TYPE_1_BYTE + 2 * i_ind]; 00957 00958 if ((eraseTypeSizeArr[i_ind] < _minCommonEraseSize) || (_minCommonEraseSize == 0) ) { 00959 //Set default minimal common erase for singal region 00960 _minCommonEraseSize = eraseTypeSizeArr[i_ind]; 00961 } 00962 00963 if (eraseTypeSizeArr[i_ind] == 4096) { 00964 found4KEraseType = true; 00965 if (erase4KInst != eraseTypeInstArr[i_ind]) { 00966 //Verify 4KErase Type is identical to Legacy 4K erase type specified in Byte 1 of Param Table 00967 erase4KInst = eraseTypeInstArr[i_ind]; 00968 QSPIF_LOG(QSPIF_DEBUG_WARNING, 00969 "WARNING: _detectEraseTypesInstAndSize - Default 4K erase Inst is different than erase type Inst for 4K"); 00970 00971 } 00972 } 00973 _region_erase_types[0] |= bitfield; // If there's no region map, set region "0" types as defualt; 00974 } 00975 00976 QSPIF_LOG(QSPIF_DEBUG_DEBUG, "DEBUG: Erase Type %d - Inst: 0x%xh, Size: %d", (i_ind + 1), eraseTypeInstArr[i_ind], 00977 eraseTypeSizeArr[i_ind]); 00978 bitfield = bitfield << 1; 00979 } 00980 00981 if (false == found4KEraseType) { 00982 QSPIF_LOG(QSPIF_DEBUG_WARNING, "WARNING: Couldn't find Erase Type for 4KB size"); 00983 } 00984 return 0; 00985 } 00986 00987 00988 int QSPIFBlockDevice::_sfdpDetectBestBusReadMode(uint8_t *basicParamTablePtr, bool& setQuadEnable, bool& isQPIMode, 00989 unsigned int& readInst) 00990 { 00991 00992 bool isDone = false; 00993 00994 setQuadEnable = false; 00995 isQPIMode = false; 00996 int dummyCycles = 0; 00997 uint8_t examinedByte = basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_QPI_READ_SUPPOR_BYTE]; 00998 00999 do { // compound statement is the loop body 01000 01001 01002 01003 if (examinedByte & 0x10) { 01004 // QPI 4-4-4 Supported 01005 readInst = basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_444_READ_INST_BYTE]; 01006 setQuadEnable = true; 01007 isQPIMode = true; 01008 _dummy_and_mode_cycles = (basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_444_READ_INST_BYTE - 1] >> 5) 01009 + (basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_444_READ_INST_BYTE - 1] & 0x1F); 01010 QSPIF_LOG(QSPIF_DEBUG_DEBUG, "/nDEBUG: Read Bus Mode set to 4-4-4, Instruction: 0x%xh", _readInstruction); 01011 //_inst_width = QSPI_CFG_BUS_QUAD; 01012 _address_width = QSPI_CFG_BUS_QUAD; 01013 _data_width = QSPI_CFG_BUS_QUAD; 01014 01015 break; 01016 } 01017 01018 01019 examinedByte = basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_FAST_READ_SUPPORT_BYTE]; 01020 if (examinedByte & 0x40) { 01021 // Fast Read 1-4-4 Supported 01022 readInst = basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_144_READ_INST_BYTE]; 01023 setQuadEnable = true; 01024 // dummy cycles + mode cycles = Dummy Cycles 01025 _dummy_and_mode_cycles = (basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_144_READ_INST_BYTE - 1] >> 5) 01026 + (basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_144_READ_INST_BYTE - 1] & 0x1F); 01027 _address_width = QSPI_CFG_BUS_QUAD; 01028 _data_width = QSPI_CFG_BUS_QUAD; 01029 QSPIF_LOG(QSPIF_DEBUG_DEBUG, "/nDEBUG: Read Bus Mode set to 1-4-4, Instruction: 0x%xh", _readInstruction); 01030 break; 01031 } 01032 if (examinedByte & 0x80) { 01033 // Fast Read 1-1-4 Supported 01034 readInst = basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_114_READ_INST_BYTE]; 01035 setQuadEnable = true; 01036 _dummy_and_mode_cycles = (basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_114_READ_INST_BYTE - 1] >> 5) 01037 + (basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_114_READ_INST_BYTE - 1] & 0x1F); 01038 _data_width = QSPI_CFG_BUS_QUAD; 01039 QSPIF_LOG(QSPIF_DEBUG_DEBUG, "/nDEBUG: Read Bus Mode set to 1-1-4, Instruction: 0x%xh", _readInstruction); 01040 break; 01041 } 01042 examinedByte = basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_QPI_READ_SUPPOR_BYTE]; 01043 if (examinedByte & 0x01) { 01044 // Fast Read 2-2-2 Supported 01045 readInst = basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_222_READ_INST_BYTE]; 01046 _dummy_and_mode_cycles = (basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_222_READ_INST_BYTE - 1] >> 5) 01047 + (basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_222_READ_INST_BYTE - 1] & 0x1F); 01048 _address_width = QSPI_CFG_BUS_DUAL; 01049 _data_width = QSPI_CFG_BUS_DUAL; 01050 QSPIF_LOG(QSPIF_DEBUG_INFO, "/nINFO: Read Bus Mode set to 2-2-2, Instruction: 0x%xh", _readInstruction); 01051 break; 01052 } 01053 01054 examinedByte = basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_FAST_READ_SUPPORT_BYTE]; 01055 if (examinedByte & 0x20) { 01056 // Fast Read 1-2-2 Supported 01057 readInst = basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_122_READ_INST_BYTE]; 01058 _dummy_and_mode_cycles = (basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_122_READ_INST_BYTE - 1] >> 5) 01059 + (basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_122_READ_INST_BYTE - 1] & 0x1F); 01060 _address_width = QSPI_CFG_BUS_DUAL; 01061 _data_width = QSPI_CFG_BUS_DUAL; 01062 QSPIF_LOG(QSPIF_DEBUG_DEBUG, "/nDEBUG: Read Bus Mode set to 1-2-2, Instruction: 0x%xh", _readInstruction); 01063 break; 01064 } 01065 if (examinedByte & 0x01) { 01066 // Fast Read 1-1-2 Supported 01067 readInst = basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_112_READ_INST_BYTE]; 01068 _dummy_and_mode_cycles = (basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_112_READ_INST_BYTE - 1] >> 5) 01069 + (basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_112_READ_INST_BYTE - 1] & 0x1F); 01070 _data_width = QSPI_CFG_BUS_DUAL; 01071 QSPIF_LOG(QSPIF_DEBUG_DEBUG, "/nDEBUG: Read Bus Mode set to 1-1-2, Instruction: 0x%xh", _readInstruction); 01072 break; 01073 } 01074 QSPIF_LOG(QSPIF_DEBUG_DEBUG, "/nDEBUG: Read Bus Mode set to 1-1-1, Instruction: 0x%xh", _readInstruction); 01075 isDone = true; 01076 } while (isDone == false); 01077 01078 return 0; 01079 } 01080 01081 01082 int QSPIFBlockDevice::_resetFlashMem() 01083 { 01084 int status = 0; 01085 char status_value[2] = {0}; 01086 QSPIF_LOG(QSPIF_DEBUG_ERROR, "INFO: _resetFlashMem:\n"); 01087 //Read the Status Register from device 01088 if (QSPI_STATUS_OK == _qspiSendGeneralCommand(QSPIF_RDSR, -1, NULL, 0, status_value, 01089 1) ) { // store received values in status_value 01090 QSPIF_LOG(QSPIF_DEBUG_DEBUG, "DEBUG: Reading Status Register Success: value = 0x%x\n", (int)status_value[0]); 01091 } else { 01092 QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: Reading Status Register failed\n"); 01093 status = -1; 01094 } 01095 01096 if (0 == status) { 01097 //Send Reset Enable 01098 if (QSPI_STATUS_OK == _qspiSendGeneralCommand(QSPIF_RSTEN, -1, NULL, 0, NULL, 01099 0) ) { // store received values in status_value 01100 QSPIF_LOG(QSPIF_DEBUG_DEBUG, "DEBUG: Sending RSTEN Success\n"); 01101 } else { 01102 QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: Sending RSTEN failed\n"); 01103 status = -1; 01104 } 01105 01106 01107 if (0 == status) { 01108 //Send Reset 01109 if (QSPI_STATUS_OK == _qspiSendGeneralCommand(QSPIF_RST, -1, NULL, 0, NULL, 01110 0)) { // store received values in status_value 01111 QSPIF_LOG(QSPIF_DEBUG_DEBUG, "DEBUG: Sending RST Success\n"); 01112 } else { 01113 QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: Sending RST failed\n"); 01114 status = -1; 01115 } 01116 01117 _isMemReady(); 01118 } 01119 } 01120 01121 return status; 01122 } 01123 01124 01125 bool QSPIFBlockDevice::_isMemReady() 01126 { 01127 char status_value[2]; 01128 int retries = 0; 01129 bool memReady = true; 01130 01131 do { 01132 retries++; 01133 //Read the Status Register from device 01134 if (QSPI_STATUS_OK != _qspiSendGeneralCommand(QSPIF_RDSR, -1, NULL, 0, status_value, 01135 2)) { // store received values in status_value 01136 QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: Reading Status Register failed\n"); 01137 } 01138 } while ( (status_value[0] & 0x1) != 0 && retries < 10000 ); 01139 01140 if ((status_value[0] & 0x1) != 0) { 01141 QSPIF_LOG(QSPIF_DEBUG_DEBUG, "ERROR: _isMemReady FALSE\n"); 01142 memReady = false; 01143 } 01144 return memReady; 01145 } 01146 01147 01148 int QSPIFBlockDevice::_setWriteEnable() 01149 { 01150 int status = 0; 01151 if (QSPI_STATUS_OK != _qspiSendGeneralCommand(QSPIF_WREN, -1, NULL, 0, NULL, 0)) { 01152 QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR:Sending WREN command FAILED\n"); 01153 status = -1; 01154 } 01155 return status; 01156 } 01157 01158 01159 01160 /*********************************************/ 01161 /************* Utility Functions *************/ 01162 /*********************************************/ 01163 int QSPIFBlockDevice::_utilsMathPower(int base, int exp) 01164 { 01165 int result = 1; 01166 while (exp) { 01167 result *= base; 01168 exp--; 01169 } 01170 return result; 01171 } 01172 01173 01174 int QSPIFBlockDevice::_utilsFindAddrRegion(int offset) 01175 { 01176 if ((offset > (int)_deviceSizeBytes) || (_regions_count == 0)) { 01177 return -1; 01178 } 01179 01180 if (_regions_count == 1) { 01181 return 0; 01182 } 01183 01184 for (int i_ind = _regions_count - 2; i_ind >= 0; i_ind--) { 01185 01186 if (offset > _region_high_boundary[i_ind]) { 01187 return (i_ind + 1); 01188 } 01189 } 01190 return -1; 01191 01192 } 01193 01194 01195 int QSPIFBlockDevice::_utilsIterateNextLargestEraseType(uint8_t& bitfield, int size, int offset, int boundry) 01196 { 01197 uint8_t type_mask = 0x08; 01198 int i_ind = 0; 01199 int largestEraseType = 0; 01200 for (i_ind = 3; i_ind >= 0; i_ind--) { 01201 if (bitfield & type_mask) { 01202 largestEraseType = i_ind; 01203 if ( (size > _eraseTypeSizeArr[largestEraseType]) && 01204 ((boundry - offset) > _eraseTypeSizeArr[largestEraseType]) ) { 01205 break; 01206 } else { 01207 bitfield &= ~type_mask; 01208 } 01209 } 01210 type_mask = type_mask >> 1; 01211 } 01212 01213 if (i_ind == 4) { 01214 QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: no erase type was found for current region addr"); 01215 } 01216 return largestEraseType; 01217 01218 } 01219 01220 01221 /***************************************************/ 01222 /*********** QSPI Driver API Functions *************/ 01223 /***************************************************/ 01224 01225 qspi_status_t QSPIFBlockDevice::_qspiSetFrequency(int freq) 01226 { 01227 return _qspi.set_frequency(freq); 01228 } 01229 01230 01231 qspi_status_t QSPIFBlockDevice::_qspiSendReadCommand(unsigned int readInst, void *buffer, bd_addr_t addr, 01232 bd_size_t size) 01233 { 01234 // Check the address and size fit onto the chip. 01235 01236 /* OFR_DBG */ 01237 //MBED_ASSERT(is_valid_read(addr, size)); 01238 01239 size_t bufLen = size; 01240 01241 if (_qspi.read( readInst, -1, (unsigned int )addr, (char *)buffer, &bufLen) != QSPI_STATUS_OK ) { 01242 QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: Read failed"); 01243 return QSPI_STATUS_ERROR; 01244 } 01245 01246 return QSPI_STATUS_OK; 01247 01248 } 01249 01250 01251 qspi_status_t QSPIFBlockDevice::_qspiSendProgramCommand(unsigned int progInst, const void *buffer, bd_addr_t addr, 01252 bd_size_t *size) 01253 { 01254 // Check the address and size fit onto the chip. 01255 //MBED_ASSERT(is_valid_program(addr, (*size))); 01256 qspi_status_t result = QSPI_STATUS_OK; 01257 01258 result = _qspi.write( progInst, -1, addr/*(((unsigned int)addr) & 0x00FFFF00)*/, (char *)buffer, (size_t *)size); 01259 if (result != QSPI_STATUS_OK) { 01260 QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: QSPI Write failed"); 01261 } 01262 01263 return result; 01264 } 01265 01266 01267 qspi_status_t QSPIFBlockDevice::_qspiSendEraseCommand(unsigned int eraseInst, bd_addr_t addr, bd_size_t size) 01268 { 01269 // Check the address and size fit onto the chip. 01270 //MBED_ASSERT(is_valid_erase(addr, size)); 01271 01272 qspi_status_t result = QSPI_STATUS_OK; 01273 01274 result = _qspi.command_transfer(eraseInst, // command to send 01275 (((int)addr) & 0x00FFF000), // Align addr to 4096 01276 NULL, // do not transmit 01277 0, // do not transmit 01278 NULL, // just receive two bytes of data 01279 0); // store received values in status_value 01280 if (QSPI_STATUS_OK != result) { 01281 QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: QSPI Erase failed"); 01282 } 01283 01284 return result; 01285 01286 } 01287 01288 01289 qspi_status_t QSPIFBlockDevice::_qspiSendGeneralCommand(unsigned int instruction, bd_addr_t addr, const char *tx_buffer, 01290 size_t tx_length, const char *rx_buffer, size_t rx_length) 01291 { 01292 01293 01294 qspi_status_t status = _qspi.command_transfer(instruction, (int)addr, tx_buffer, tx_length, rx_buffer, rx_length); 01295 01296 if (QSPI_STATUS_OK != status) { 01297 QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR:Sending Generic command: %x", instruction); 01298 } 01299 01300 return status; 01301 } 01302 01303 01304 qspi_status_t QSPIFBlockDevice::_qspiConfiureFormat(qspi_bus_width_t inst_width, qspi_bus_width_t address_width, 01305 qspi_address_size_t address_size, qspi_bus_width_t alt_width, qspi_alt_size_t alt_size, qspi_bus_width_t data_width, 01306 int dummy_cycles) 01307 { 01308 _qspi.configure_format( inst_width, address_width, address_size, alt_width, alt_size, data_width, dummy_cycles); 01309 01310 return QSPI_STATUS_OK; 01311 } 01312 01313 01314 01315 01316
Generated on Tue Jul 12 2022 16:24:20 by
 1.7.2
 1.7.2