Workshop example

Dependencies:   X_NUCLEO_COMMON ST_INTERFACES

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers QSPIFBlockDevice.cpp Source File

QSPIFBlockDevice.cpp

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