takashi kadono / Mbed OS Nucleo_446

Dependencies:   ssd1331

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers SPIFBlockDevice.cpp Source File

SPIFBlockDevice.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 "SPIFBlockDevice.h"
00018 #include "mbed_critical.h"
00019 
00020 #include <string.h>
00021 #include "mbed_wait_api.h"
00022 
00023 #include "mbed_trace.h"
00024 #define TRACE_GROUP "SPIF"
00025 using namespace mbed;
00026 
00027 /* Default SPIF Parameters */
00028 /****************************/
00029 #define SPIF_DEFAULT_READ_SIZE  1
00030 #define SPIF_DEFAULT_PROG_SIZE  1
00031 #define SPIF_DEFAULT_PAGE_SIZE  256
00032 #define SPIF_DEFAULT_SE_SIZE    4096
00033 #define SPI_MAX_STATUS_REGISTER_SIZE 2
00034 #ifndef UINT64_MAX
00035 #define UINT64_MAX -1
00036 #endif
00037 #define SPI_NO_ADDRESS_COMMAND UINT64_MAX
00038 // Status Register Bits
00039 #define SPIF_STATUS_BIT_WIP 0x1 //Write In Progress
00040 #define SPIF_STATUS_BIT_WEL 0x2 // Write Enable Latch
00041 
00042 /* SFDP Header Parsing */
00043 /***********************/
00044 #define SPIF_SFDP_HEADER_SIZE 8
00045 #define SPIF_PARAM_HEADER_SIZE 8
00046 
00047 /* Basic Parameters Table Parsing */
00048 /**********************************/
00049 #define SFDP_DEFAULT_BASIC_PARAMS_TABLE_SIZE_BYTES 64 /* 16 DWORDS */
00050 //READ Instruction support according to BUS Configuration
00051 #define SPIF_BASIC_PARAM_TABLE_FAST_READ_SUPPORT_BYTE 2
00052 #define SPIF_BASIC_PARAM_TABLE_QPI_READ_SUPPORT_BYTE 16
00053 #define SPIF_BASIC_PARAM_TABLE_222_READ_INST_BYTE 23
00054 #define SPIF_BASIC_PARAM_TABLE_122_READ_INST_BYTE 15
00055 #define SPIF_BASIC_PARAM_TABLE_112_READ_INST_BYTE 13
00056 #define SPIF_BASIC_PARAM_TABLE_PAGE_SIZE_BYTE 40
00057 // Address Length
00058 #define SPIF_ADDR_SIZE_3_BYTES 3
00059 // Erase Types Params
00060 #define SPIF_BASIC_PARAM_ERASE_TYPE_1_BYTE 29
00061 #define SPIF_BASIC_PARAM_ERASE_TYPE_2_BYTE 31
00062 #define SPIF_BASIC_PARAM_ERASE_TYPE_3_BYTE 33
00063 #define SPIF_BASIC_PARAM_ERASE_TYPE_4_BYTE 35
00064 #define SPIF_BASIC_PARAM_ERASE_TYPE_1_SIZE_BYTE 28
00065 #define SPIF_BASIC_PARAM_ERASE_TYPE_2_SIZE_BYTE 30
00066 #define SPIF_BASIC_PARAM_ERASE_TYPE_3_SIZE_BYTE 32
00067 #define SPIF_BASIC_PARAM_ERASE_TYPE_4_SIZE_BYTE 34
00068 #define SPIF_BASIC_PARAM_4K_ERASE_TYPE_BYTE 1
00069 
00070 // Erase Types Per Region BitMask
00071 #define ERASE_BITMASK_TYPE4 0x08
00072 #define ERASE_BITMASK_TYPE1 0x01
00073 #define ERASE_BITMASK_NONE  0x00
00074 #define ERASE_BITMASK_ALL   0x0F
00075 
00076 #define IS_MEM_READY_MAX_RETRIES 10000
00077 
00078 enum spif_default_instructions {
00079     SPIF_NOP = 0x00, // No operation
00080     SPIF_PP = 0x02, // Page Program data
00081     SPIF_READ = 0x03, // Read data
00082     SPIF_SE   = 0x20, // 4KB Sector Erase
00083     SPIF_SFDP = 0x5a, // Read SFDP
00084     SPIF_WRSR = 0x01, // Write Status/Configuration Register
00085     SPIF_WRDI = 0x04, // Write Disable
00086     SPIF_RDSR = 0x05, // Read Status Register
00087     SPIF_WREN = 0x06, // Write Enable
00088     SPIF_RSTEN = 0x66, // Reset Enable
00089     SPIF_RST = 0x99, // Reset
00090     SPIF_RDID = 0x9f, // Read Manufacturer and JDEC Device ID
00091 };
00092 
00093 // Mutex is used for some SPI Driver commands that must be done sequentially with no other commands in between
00094 // e.g. (1)Set Write Enable, (2)Program, (3)Wait Memory Ready
00095 SingletonPtr<PlatformMutex>  SPIFBlockDevice::_mutex;
00096 
00097 // Local Function
00098 static unsigned int local_math_power(int base, int exp);
00099 
00100 //***********************
00101 // SPIF Block Device APIs
00102 //***********************
00103 SPIFBlockDevice::SPIFBlockDevice(
00104     PinName mosi, PinName miso, PinName sclk, PinName csel, int freq)
00105     : _spi(mosi, miso, sclk), _cs(csel), _device_size_bytes(0), _is_initialized(false), _init_ref_count(0)
00106 {
00107     _address_size = SPIF_ADDR_SIZE_3_BYTES;
00108     // Initial SFDP read tables are read with 8 dummy cycles
00109     // Default Bus Setup 1_1_1 with 0 dummy and mode cycles
00110     _read_dummy_and_mode_cycles = 8;
00111     _write_dummy_and_mode_cycles = 0;
00112     _dummy_and_mode_cycles = _read_dummy_and_mode_cycles;
00113 
00114     _min_common_erase_size = 0;
00115     _regions_count = 1;
00116     _region_erase_types_bitfield[0] = ERASE_BITMASK_NONE;
00117 
00118     if (SPIF_BD_ERROR_OK != _spi_set_frequency(freq)) {
00119         tr_error("ERROR: SPI Set Frequency Failed");
00120     }
00121 
00122     _cs = 1;
00123 }
00124 
00125 int SPIFBlockDevice::init()
00126 {
00127     uint8_t vendor_device_ids[4];
00128     size_t data_length = 3;
00129     int status = SPIF_BD_ERROR_OK;
00130     uint32_t basic_table_addr = 0;
00131     size_t basic_table_size = 0;
00132     uint32_t sector_map_table_addr = 0;
00133     size_t sector_map_table_size = 0;
00134     spif_bd_error spi_status = SPIF_BD_ERROR_OK;
00135 
00136     _mutex->lock();
00137 
00138     if (!_is_initialized) {
00139         _init_ref_count = 0;
00140     }
00141 
00142     _init_ref_count++;
00143 
00144     if (_init_ref_count != 1) {
00145         goto exit_point;
00146     }
00147 
00148     // Soft Reset
00149     if ( -1 == _reset_flash_mem()) {
00150         tr_error("ERROR: init - Unable to initialize flash memory, tests failed\n");
00151         status = SPIF_BD_ERROR_DEVICE_ERROR;
00152         goto exit_point;
00153     } else {
00154         tr_info("INFO: Initialize flash memory OK\n");
00155     }
00156 
00157 
00158     /* Read Manufacturer ID (1byte), and Device ID (2bytes)*/
00159     spi_status = _spi_send_general_command(SPIF_RDID, SPI_NO_ADDRESS_COMMAND, NULL, 0, (char *)vendor_device_ids,
00160                                            data_length);
00161     if (spi_status != SPIF_BD_ERROR_OK) {
00162         tr_error("ERROR: init - Read Vendor ID Failed");
00163         status = SPIF_BD_ERROR_DEVICE_ERROR;
00164         goto exit_point;
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             _set_write_enable();
00172             _spi_send_general_command(SPIF_WRDI, SPI_NO_ADDRESS_COMMAND, NULL, 0, NULL, 0);
00173             break;
00174     }
00175 
00176     //Synchronize Device
00177     if ( false == _is_mem_ready()) {
00178         tr_error("ERROR: init - _is_mem_ready Failed");
00179         status = SPIF_BD_ERROR_READY_FAILED;
00180         goto exit_point;
00181     }
00182 
00183     /**************************** Parse SFDP Header ***********************************/
00184     if ( 0 != _sfdp_parse_sfdp_headers(basic_table_addr, basic_table_size, sector_map_table_addr, sector_map_table_size)) {
00185         tr_error("ERROR: init - Parse SFDP Headers Failed");
00186         status = SPIF_BD_ERROR_PARSING_FAILED;
00187         goto exit_point;
00188     }
00189 
00190 
00191     /**************************** Parse Basic Parameters Table ***********************************/
00192     if ( 0 != _sfdp_parse_basic_param_table(basic_table_addr, basic_table_size) ) {
00193         tr_error("ERROR: init - Parse Basic Param Table Failed");
00194         status = SPIF_BD_ERROR_PARSING_FAILED;
00195         goto exit_point;
00196     }
00197 
00198     /**************************** Parse Sector Map Table ***********************************/
00199     _region_size_bytes[0] =
00200         _device_size_bytes; // If there's no region map, we have a single region sized the entire device size
00201     _region_high_boundary[0] = _device_size_bytes - 1;
00202 
00203     if ( (sector_map_table_addr != 0) && (0 != sector_map_table_size) ) {
00204         tr_info("INFO: init - Parsing Sector Map Table - addr: 0x%lxh, Size: %d", sector_map_table_addr,
00205                 sector_map_table_size);
00206         if (0 != _sfdp_parse_sector_map_table(sector_map_table_addr, sector_map_table_size) ) {
00207             tr_error("ERROR: init - Parse Sector Map Table Failed");
00208             status = SPIF_BD_ERROR_PARSING_FAILED;
00209             goto exit_point;
00210         }
00211     }
00212 
00213     // Configure  BUS Mode to 1_1_1 for all commands other than Read
00214     // Dummy And Mode Cycles Back default 0
00215     _dummy_and_mode_cycles = _write_dummy_and_mode_cycles;
00216     _is_initialized = true;
00217 
00218 exit_point:
00219     _mutex->unlock();
00220 
00221     return status;
00222 }
00223 
00224 
00225 int SPIFBlockDevice::deinit()
00226 {
00227     spif_bd_error status = SPIF_BD_ERROR_OK;
00228 
00229     _mutex->lock();
00230 
00231     if (!_is_initialized) {
00232         _init_ref_count = 0;
00233         goto exit_point;
00234     }
00235 
00236     _init_ref_count--;
00237 
00238     if (_init_ref_count) {
00239         goto exit_point;
00240     }
00241 
00242     // Disable Device for Writing
00243     status = _spi_send_general_command(SPIF_WRDI, SPI_NO_ADDRESS_COMMAND, NULL, 0, NULL, 0);
00244     if (status != SPIF_BD_ERROR_OK)  {
00245         tr_error("ERROR: Write Disable failed");
00246     }
00247     _is_initialized = false;
00248 
00249 exit_point:
00250     _mutex->unlock();
00251 
00252     return status;
00253 }
00254 
00255 int SPIFBlockDevice::read(void *buffer, bd_addr_t addr, bd_size_t size)
00256 {
00257     if (!_is_initialized) {
00258         return BD_ERROR_DEVICE_ERROR;
00259     }
00260 
00261     int status = SPIF_BD_ERROR_OK;
00262     tr_info("INFO Read - Inst: 0x%xh", _read_instruction);
00263     _mutex->lock();
00264 
00265     // Set Dummy Cycles for Specific Read Command Mode
00266     _dummy_and_mode_cycles = _read_dummy_and_mode_cycles;
00267 
00268     status = _spi_send_read_command(_read_instruction, static_cast<uint8_t *>(buffer), addr, size);
00269 
00270     // Set Dummy Cycles for all other command modes
00271     _dummy_and_mode_cycles = _write_dummy_and_mode_cycles;
00272 
00273     _mutex->unlock();
00274     return status;
00275 }
00276 
00277 int SPIFBlockDevice::program(const void *buffer, bd_addr_t addr, bd_size_t size)
00278 {
00279     if (!_is_initialized) {
00280         return BD_ERROR_DEVICE_ERROR;
00281     }
00282 
00283     bool program_failed = false;
00284     int status = SPIF_BD_ERROR_OK;
00285     uint32_t offset = 0;
00286     uint32_t chunk = 0;
00287 
00288     tr_debug("DEBUG: program - Buff: 0x%lxh, addr: %llu, size: %llu", (uint32_t)buffer, addr, size);
00289 
00290     while (size > 0) {
00291 
00292         // Write on _page_size_bytes boundaries (Default 256 bytes a page)
00293         offset = addr % _page_size_bytes;
00294         chunk = (offset + size < _page_size_bytes) ? size : (_page_size_bytes - offset);
00295 
00296         _mutex->lock();
00297 
00298         //Send WREN
00299         if (_set_write_enable() != 0) {
00300             tr_error("ERROR: Write Enabe failed\n");
00301             program_failed = true;
00302             status = SPIF_BD_ERROR_WREN_FAILED;
00303             goto exit_point;
00304         }
00305 
00306         _spi_send_program_command(_prog_instruction, buffer, addr, chunk);
00307 
00308         buffer = static_cast<const uint8_t *>(buffer) + chunk;
00309         addr += chunk;
00310         size -= chunk;
00311 
00312         if ( false == _is_mem_ready()) {
00313             tr_error("ERROR: Device not ready after write, failed\n");
00314             program_failed = true;
00315             status = SPIF_BD_ERROR_READY_FAILED;
00316             goto exit_point;
00317         }
00318         _mutex->unlock();
00319     }
00320 
00321 exit_point:
00322     if (program_failed) {
00323         _mutex->unlock();
00324     }
00325 
00326     return status;
00327 }
00328 
00329 int SPIFBlockDevice::erase(bd_addr_t addr, bd_size_t in_size)
00330 {
00331     if (!_is_initialized) {
00332         return BD_ERROR_DEVICE_ERROR;
00333     }
00334 
00335     int type = 0;
00336     uint32_t offset = 0;
00337     uint32_t chunk = 4096;
00338     int cur_erase_inst = _erase_instruction;
00339     int size = (int)in_size;
00340     bool erase_failed = false;
00341     int status = SPIF_BD_ERROR_OK;
00342     // Find region of erased address
00343     int region = _utils_find_addr_region(addr);
00344     // Erase Types of selected region
00345     uint8_t bitfield = _region_erase_types_bitfield[region];
00346 
00347     tr_info("DEBUG: erase - addr: %llu, in_size: %llu", addr, in_size);
00348 
00349     if ((addr + in_size) > _device_size_bytes) {
00350         tr_error("ERROR: erase exceeds flash device size");
00351         return SPIF_BD_ERROR_INVALID_ERASE_PARAMS;
00352     }
00353 
00354     if ( ((addr % get_erase_size(addr)) != 0 ) ||  (((addr + in_size) % get_erase_size(addr + in_size - 1)) != 0 ) ) {
00355         tr_error("ERROR: invalid erase - unaligned address and size");
00356         return SPIF_BD_ERROR_INVALID_ERASE_PARAMS;
00357     }
00358 
00359     // For each iteration erase the largest section supported by current region
00360     while (size > 0) {
00361 
00362         // iterate to find next Largest erase type ( a. supported by region, b. smaller than size)
00363         // find the matching instruction and erase size chunk for that type.
00364         type = _utils_iterate_next_largest_erase_type(bitfield, size, (unsigned int)addr, _region_high_boundary[region]);
00365         cur_erase_inst = _erase_type_inst_arr[type];
00366         offset = addr % _erase_type_size_arr[type];
00367         chunk = ( (offset + size) < _erase_type_size_arr[type]) ? size : (_erase_type_size_arr[type] - offset);
00368 
00369         tr_debug("DEBUG: erase - addr: %llu, size:%d, Inst: 0x%xh, chunk: %lu , ",
00370                  addr, size, cur_erase_inst, chunk);
00371         tr_debug("DEBUG: erase - Region: %d, Type:%d",
00372                  region, type);
00373 
00374         _mutex->lock();
00375 
00376         if (_set_write_enable() != 0) {
00377             tr_error("ERROR: SPI Erase Device not ready - failed");
00378             erase_failed = true;
00379             status = SPIF_BD_ERROR_READY_FAILED;
00380             goto exit_point;
00381         }
00382 
00383         _spi_send_erase_command(cur_erase_inst, addr, size);
00384 
00385         addr += chunk;
00386         size -= chunk;
00387 
00388         if ( (size > 0) && (addr > _region_high_boundary[region]) ) {
00389             // erase crossed to next region
00390             region++;
00391             bitfield = _region_erase_types_bitfield[region];
00392         }
00393 
00394         if ( false == _is_mem_ready()) {
00395             tr_error("ERROR: SPI After Erase Device not ready - failed\n");
00396             erase_failed = true;
00397             status = SPIF_BD_ERROR_READY_FAILED;
00398             goto exit_point;
00399         }
00400 
00401         _mutex->unlock();
00402     }
00403 
00404 exit_point:
00405     if (erase_failed) {
00406         _mutex->unlock();
00407     }
00408 
00409     return status;
00410 }
00411 
00412 bd_size_t SPIFBlockDevice::get_read_size() const
00413 {
00414     // Assuming all devices support 1byte read granularity
00415     return SPIF_DEFAULT_READ_SIZE;
00416 }
00417 
00418 bd_size_t SPIFBlockDevice::get_program_size() const
00419 {
00420     // Assuming all devices support 1byte program granularity
00421     return SPIF_DEFAULT_PROG_SIZE;
00422 }
00423 
00424 bd_size_t SPIFBlockDevice::get_erase_size() const
00425 {
00426     // return minimal erase size supported by all regions (0 if none exists)
00427     return _min_common_erase_size;
00428 }
00429 
00430 // Find minimal erase size supported by the region to which the address belongs to
00431 bd_size_t SPIFBlockDevice::get_erase_size(bd_addr_t addr)
00432 {
00433     // Find region of current address
00434     int region = _utils_find_addr_region(addr);
00435 
00436     unsigned int min_region_erase_size = _min_common_erase_size;
00437     int8_t type_mask = ERASE_BITMASK_TYPE1;
00438     int i_ind = 0;
00439 
00440     if (region != -1) {
00441         type_mask = 0x01;
00442 
00443         for (i_ind = 0; i_ind < 4; i_ind++) {
00444             // loop through erase types bitfield supported by region
00445             if (_region_erase_types_bitfield[region] & type_mask) {
00446 
00447                 min_region_erase_size = _erase_type_size_arr[i_ind];
00448                 break;
00449             }
00450             type_mask = type_mask << 1;
00451         }
00452 
00453         if (i_ind == 4) {
00454             tr_error("ERROR: no erase type was found for region addr");
00455         }
00456     }
00457 
00458     return (bd_size_t)min_region_erase_size;
00459 }
00460 
00461 bd_size_t SPIFBlockDevice::size() const
00462 {
00463     if (!_is_initialized) {
00464         return SPIF_BD_ERROR_DEVICE_ERROR;
00465     }
00466 
00467     return _device_size_bytes;
00468 }
00469 
00470 int SPIFBlockDevice::get_erase_value() const
00471 {
00472     return 0xFF;
00473 }
00474 
00475 /***************************************************/
00476 /*********** SPI Driver API Functions **************/
00477 /***************************************************/
00478 spif_bd_error SPIFBlockDevice::_spi_set_frequency(int freq)
00479 {
00480     _spi.frequency(freq);
00481     return SPIF_BD_ERROR_OK;
00482 }
00483 
00484 spif_bd_error SPIFBlockDevice::_spi_send_read_command(int read_inst, uint8_t *buffer, bd_addr_t addr, bd_size_t size)
00485 {
00486     uint32_t dummy_bytes = _dummy_and_mode_cycles / 8;
00487     int dummy_byte = 0;
00488 
00489     // csel must go low for the entire command (Inst, Address and Data)
00490     _cs = 0;
00491 
00492     // Write 1 byte Instruction
00493     _spi.write(read_inst);
00494 
00495     // Write Address (can be either 3 or 4 bytes long)
00496     for (int address_shift = ((_address_size - 1) * 8); address_shift >= 0; address_shift -= 8) {
00497         _spi.write((addr >> address_shift) & 0xFF);
00498     }
00499 
00500     // Write Dummy Cycles Bytes
00501     for (uint32_t i = 0; i < dummy_bytes; i++) {
00502         _spi.write(dummy_byte);
00503     }
00504 
00505     // Read Data
00506     for (bd_size_t i = 0; i < size; i++) {
00507         buffer[i] = _spi.write(0);
00508     }
00509 
00510     // csel back to high
00511     _cs = 1;
00512     return SPIF_BD_ERROR_OK;
00513 }
00514 
00515 spif_bd_error SPIFBlockDevice::_spi_send_program_command(int prog_inst, const void *buffer, bd_addr_t addr,
00516         bd_size_t size)
00517 {
00518     // Send Program (write) command to device driver
00519     uint32_t dummy_bytes = _dummy_and_mode_cycles / 8;
00520     int dummy_byte = 0;
00521     uint8_t *data = (uint8_t *)buffer;
00522 
00523     // csel must go low for the entire command (Inst, Address and Data)
00524     _cs = 0;
00525 
00526     // Write 1 byte Instruction
00527     _spi.write(prog_inst);
00528 
00529     // Write Address (can be either 3 or 4 bytes long)
00530     for (int address_shift = ((_address_size - 1) * 8); address_shift >= 0; address_shift -= 8) {
00531         _spi.write((addr >> address_shift) & 0xFF);
00532     }
00533 
00534     // Write Dummy Cycles Bytes
00535     for (uint32_t i = 0; i < dummy_bytes; i++) {
00536         _spi.write(dummy_byte);
00537     }
00538 
00539     // Write Data
00540     for (bd_size_t i = 0; i < size; i++) {
00541         _spi.write(data[i]);
00542     }
00543 
00544     // csel back to high
00545     _cs = 1;
00546 
00547     return SPIF_BD_ERROR_OK;
00548 }
00549 
00550 spif_bd_error SPIFBlockDevice::_spi_send_erase_command(int erase_inst, bd_addr_t addr, bd_size_t size)
00551 {
00552     tr_info("INFO: Erase Inst: 0x%xh, addr: %llu, size: %llu", erase_inst, addr, size);
00553     addr = (((int)addr) & 0x00FFF000);
00554     _spi_send_general_command(erase_inst, addr, NULL, 0, NULL, 0);
00555     return SPIF_BD_ERROR_OK;
00556 }
00557 
00558 spif_bd_error SPIFBlockDevice::_spi_send_general_command(int instruction, bd_addr_t addr, char *tx_buffer,
00559         size_t tx_length, char *rx_buffer, size_t rx_length)
00560 {
00561     // Send a general command Instruction to driver
00562     uint32_t dummy_bytes = _dummy_and_mode_cycles / 8;
00563     uint8_t dummy_byte = 0x00;
00564 
00565     // csel must go low for the entire command (Inst, Address and Data)
00566     _cs = 0;
00567 
00568     // Write 1 byte Instruction
00569     _spi.write(instruction);
00570 
00571     // Reading SPI Bus registers does not require Flash Address
00572     if (addr != SPI_NO_ADDRESS_COMMAND) {
00573         // Write Address (can be either 3 or 4 bytes long)
00574         for (int address_shift = ((_address_size - 1) * 8); address_shift >= 0; address_shift -= 8) {
00575             _spi.write((addr >> address_shift) & 0xFF);
00576         }
00577 
00578         // Write Dummy Cycles Bytes
00579         for (uint32_t i = 0; i < dummy_bytes; i++) {
00580             _spi.write(dummy_byte);
00581         }
00582     }
00583 
00584     // Read/Write Data
00585     _spi.write(tx_buffer, (int)tx_length, rx_buffer, (int)rx_length);
00586 
00587     // csel back to high
00588     _cs = 1;
00589 
00590     return SPIF_BD_ERROR_OK;
00591 }
00592 
00593 /*********************************************************/
00594 /********** SFDP Parsing and Detection Functions *********/
00595 /*********************************************************/
00596 int SPIFBlockDevice::_sfdp_parse_sector_map_table(uint32_t sector_map_table_addr, size_t sector_map_table_size)
00597 {
00598     uint8_t sector_map_table[SFDP_DEFAULT_BASIC_PARAMS_TABLE_SIZE_BYTES]; /* Up To 16 DWORDS = 64 Bytes */
00599     uint32_t tmp_region_size = 0;
00600     int i_ind = 0;
00601     int prev_boundary = 0;
00602     // Default set to all type bits 1-4 are common
00603     int min_common_erase_type_bits = ERASE_BITMASK_ALL;
00604 
00605 
00606     spif_bd_error status = _spi_send_read_command(SPIF_SFDP, sector_map_table, sector_map_table_addr /*address*/,
00607                            sector_map_table_size);
00608     if (status != SPIF_BD_ERROR_OK) {
00609         tr_error("ERROR: init - Read SFDP First Table Failed");
00610         return -1;
00611     }
00612 
00613     // Currently we support only Single Map Descriptor
00614     if (! ( (sector_map_table[0] & 0x3) == 0x03 ) && (sector_map_table[1]  == 0x0) ) {
00615         tr_error("ERROR: Sector Map - Supporting Only Single! Map Descriptor (not map commands)");
00616         return -1;
00617     }
00618 
00619     _regions_count = sector_map_table[2] + 1;
00620     if (_regions_count > SPIF_MAX_REGIONS) {
00621         tr_error("ERROR: Supporting up to %d regions, current setup to %d regions - fail",
00622                  SPIF_MAX_REGIONS, _regions_count);
00623         return -1;
00624     }
00625 
00626     // Loop through Regions and set for each one: size, supported erase types, high boundary offset
00627     // Calculate minimum Common Erase Type for all Regions
00628     for (i_ind = 0; i_ind < _regions_count; i_ind++) {
00629         tmp_region_size = ((*((uint32_t *)&sector_map_table[(i_ind + 1) * 4])) >> 8) & 0x00FFFFFF; // bits 9-32
00630         _region_size_bytes[i_ind] = (tmp_region_size + 1) * 256; // Region size is 0 based multiple of 256 bytes;
00631         _region_erase_types_bitfield[i_ind] = sector_map_table[(i_ind + 1) * 4] & 0x0F; // bits 1-4
00632         min_common_erase_type_bits &= _region_erase_types_bitfield[i_ind];
00633         _region_high_boundary[i_ind] = (_region_size_bytes[i_ind] - 1) + prev_boundary;
00634         prev_boundary = _region_high_boundary[i_ind] + 1;
00635     }
00636 
00637     // Calc minimum Common Erase Size from min_common_erase_type_bits
00638     uint8_t type_mask = ERASE_BITMASK_TYPE1;
00639     for (i_ind = 0; i_ind < 4; i_ind++) {
00640         if (min_common_erase_type_bits & type_mask) {
00641             _min_common_erase_size = _erase_type_size_arr[i_ind];
00642             break;
00643         }
00644         type_mask = type_mask << 1;
00645     }
00646 
00647     if (i_ind == 4) {
00648         // No common erase type was found between regions
00649         _min_common_erase_size = 0;
00650     }
00651 
00652     return 0;
00653 }
00654 
00655 int SPIFBlockDevice::_sfdp_parse_basic_param_table(uint32_t basic_table_addr, size_t basic_table_size)
00656 {
00657     uint8_t param_table[SFDP_DEFAULT_BASIC_PARAMS_TABLE_SIZE_BYTES]; /* Up To 16 DWORDS = 64 Bytes */
00658     //memset(param_table, 0, SFDP_DEFAULT_BASIC_PARAMS_TABLE_SIZE_BYTES);
00659 
00660     spif_bd_error status = _spi_send_read_command(SPIF_SFDP, param_table, basic_table_addr /*address*/,
00661                            basic_table_size);
00662     if (status != SPIF_BD_ERROR_OK) {
00663         tr_error("ERROR: init - Read SFDP First Table Failed");
00664         return -1;
00665     }
00666 
00667     // Check address size, currently only supports 3byte addresses
00668     if ((param_table[2] & 0x4) != 0 || (param_table[7] & 0x80) != 0) {
00669         tr_error("ERROR: init - verify 3byte addressing Failed");
00670         return -1;
00671     }
00672 
00673     // Get device density (stored in bits - 1)
00674     uint32_t density_bits = (
00675                                 (param_table[7] << 24) |
00676                                 (param_table[6] << 16) |
00677                                 (param_table[5] << 8 ) |
00678                                 param_table[4] );
00679     _device_size_bytes = (density_bits + 1) / 8;
00680 
00681     // Set Default read/program/erase Instructions
00682     _read_instruction = SPIF_READ;
00683     _prog_instruction = SPIF_PP;
00684     _erase_instruction = SPIF_SE;
00685 
00686     // Set Page Size (SPI write must be done on Page limits)
00687     _page_size_bytes = _sfdp_detect_page_size(param_table, basic_table_size);
00688 
00689     // Detect and Set Erase Types
00690     _sfdp_detect_erase_types_inst_and_size(param_table, basic_table_size, _erase4k_inst, _erase_type_inst_arr,
00691                                            _erase_type_size_arr);
00692     _erase_instruction = _erase4k_inst;
00693 
00694     // Detect and Set fastest Bus mode (default 1-1-1)
00695     _sfdp_detect_best_bus_read_mode(param_table, basic_table_size, _read_instruction);
00696 
00697     return 0;
00698 }
00699 
00700 int SPIFBlockDevice::_sfdp_parse_sfdp_headers(uint32_t& basic_table_addr, size_t& basic_table_size,
00701         uint32_t& sector_map_table_addr, size_t& sector_map_table_size)
00702 {
00703     uint8_t sfdp_header[16];
00704     uint8_t param_header[SPIF_SFDP_HEADER_SIZE];
00705     size_t data_length = SPIF_SFDP_HEADER_SIZE;
00706     bd_addr_t addr = 0x0;
00707 
00708     // Set 1-1-1 bus mode for SFDP header parsing
00709     // Initial SFDP read tables are read with 8 dummy cycles
00710     _read_dummy_and_mode_cycles = 8;
00711     _dummy_and_mode_cycles = 8;
00712 
00713     spif_bd_error status = _spi_send_read_command(SPIF_SFDP, sfdp_header, addr /*address*/, data_length);
00714     if (status != SPIF_BD_ERROR_OK) {
00715         tr_error("ERROR: init - Read SFDP Failed");
00716         return -1;
00717     }
00718 
00719     // Verify SFDP signature for sanity
00720     // Also check that major/minor version is acceptable
00721     if (!(memcmp(&sfdp_header[0], "SFDP", 4) == 0 && sfdp_header[5] == 1)) {
00722         tr_error("ERROR: init - _verify SFDP signature and version Failed");
00723         return -1;
00724     } else {
00725         tr_info("INFO: init - verified SFDP Signature and version Successfully");
00726     }
00727 
00728     // Discover Number of Parameter Headers
00729     int number_of_param_headers = (int)(sfdp_header[6]) + 1;
00730     tr_debug("DEBUG: number of Param Headers: %d", number_of_param_headers);
00731 
00732 
00733     addr += SPIF_SFDP_HEADER_SIZE;
00734     data_length = SPIF_PARAM_HEADER_SIZE;
00735 
00736     // Loop over Param Headers and parse them (currently supported Basic Param Table and Sector Region Map Table)
00737     for (int i_ind = 0; i_ind < number_of_param_headers; i_ind++) {
00738 
00739         status = _spi_send_read_command(SPIF_SFDP, param_header, addr, data_length);
00740         if (status != SPIF_BD_ERROR_OK) {
00741             tr_error("ERROR: init - Read Param Table %d Failed", i_ind + 1);
00742             return -1;
00743         }
00744 
00745         // The SFDP spec indicates the standard table is always at offset 0
00746         // in the parameter headers, we check just to be safe
00747         if (param_header[2] != 1) {
00748             tr_error("ERROR: Param Table %d - Major Version should be 1!", i_ind + 1);
00749             return -1;
00750         }
00751 
00752         if ((param_header[0] == 0) && (param_header[7] == 0xFF)) {
00753             // Found Basic Params Table: LSB=0x00, MSB=0xFF
00754             tr_debug("DEBUG: Found Basic Param Table at Table: %d", i_ind + 1);
00755             basic_table_addr = ( (param_header[6] << 16) | (param_header[5] << 8) | (param_header[4]) );
00756             // Supporting up to 64 Bytes Table (16 DWORDS)
00757             basic_table_size = ((param_header[3] * 4) < SFDP_DEFAULT_BASIC_PARAMS_TABLE_SIZE_BYTES) ? (param_header[3] * 4) : 64;
00758 
00759         } else if ((param_header[0] == 81) && (param_header[7] == 0xFF)) {
00760             // Found Sector Map Table: LSB=0x81, MSB=0xFF
00761             tr_debug("DEBUG: Found Sector Map Table at Table: %d", i_ind + 1);
00762             sector_map_table_addr = ( (param_header[6] << 16) | (param_header[5] << 8) | (param_header[4]) );
00763             sector_map_table_size = param_header[3] * 4;
00764 
00765         }
00766         addr += SPIF_PARAM_HEADER_SIZE;
00767 
00768     }
00769     return 0;
00770 }
00771 
00772 unsigned int SPIFBlockDevice::_sfdp_detect_page_size(uint8_t *basic_param_table_ptr, int basic_param_table_size)
00773 {
00774     unsigned int page_size = SPIF_DEFAULT_PAGE_SIZE;
00775 
00776     if (basic_param_table_size > SPIF_BASIC_PARAM_TABLE_PAGE_SIZE_BYTE) {
00777         // Page Size is specified by 4 Bits (N), calculated by 2^N
00778         int page_to_power_size = ( (int)basic_param_table_ptr[SPIF_BASIC_PARAM_TABLE_PAGE_SIZE_BYTE]) >> 4;
00779         page_size = local_math_power(2, page_to_power_size);
00780         tr_debug("DEBUG: Detected Page Size: %d", page_size);
00781     } else {
00782         tr_debug("DEBUG: Using Default Page Size: %d", page_size);
00783     }
00784     return page_size;
00785 }
00786 
00787 int SPIFBlockDevice::_sfdp_detect_erase_types_inst_and_size(uint8_t *basic_param_table_ptr, int basic_param_table_size,
00788         int& erase4k_inst,
00789         int *erase_type_inst_arr, unsigned int *erase_type_size_arr)
00790 {
00791     erase4k_inst = 0xff;
00792     bool found_4Kerase_type = false;
00793     uint8_t bitfield = 0x01;
00794 
00795     // Erase 4K Inst is taken either from param table legacy 4K erase or superseded by erase Instruction for type of size 4K
00796     erase4k_inst = basic_param_table_ptr[SPIF_BASIC_PARAM_4K_ERASE_TYPE_BYTE];
00797 
00798     if (basic_param_table_size > SPIF_BASIC_PARAM_ERASE_TYPE_1_SIZE_BYTE) {
00799         // Loop Erase Types 1-4
00800         for (int i_ind = 0; i_ind < 4; i_ind++) {
00801             erase_type_inst_arr[i_ind] = 0xff; //0xFF default for unsupported type
00802             erase_type_size_arr[i_ind] = local_math_power(2,
00803                                          basic_param_table_ptr[SPIF_BASIC_PARAM_ERASE_TYPE_1_SIZE_BYTE + 2 * i_ind]); // Size given as 2^N
00804             tr_info("DEBUG: Erase Type(A) %d - Inst: 0x%xh, Size: %d", (i_ind + 1), erase_type_inst_arr[i_ind],
00805                     erase_type_size_arr[i_ind]);
00806             if (erase_type_size_arr[i_ind] > 1) {
00807                 // if size==1 type is not supported
00808                 erase_type_inst_arr[i_ind] = basic_param_table_ptr[SPIF_BASIC_PARAM_ERASE_TYPE_1_BYTE + 2 * i_ind];
00809 
00810                 if ((erase_type_size_arr[i_ind] < _min_common_erase_size) || (_min_common_erase_size == 0) ) {
00811                     //Set default minimal common erase for singal region
00812                     _min_common_erase_size = erase_type_size_arr[i_ind];
00813                 }
00814 
00815                 // SFDP standard requires 4K Erase type to exist and its instruction to be identical to legacy field erase instruction
00816                 if (erase_type_size_arr[i_ind] == 4096) {
00817                     found_4Kerase_type = true;
00818                     if (erase4k_inst != erase_type_inst_arr[i_ind]) {
00819                         //Verify 4KErase Type is identical to Legacy 4K erase type specified in Byte 1 of Param Table
00820                         erase4k_inst = erase_type_inst_arr[i_ind];
00821                         tr_warning("WARNING: _detectEraseTypesInstAndSize - Default 4K erase Inst is different than erase type Inst for 4K");
00822 
00823                     }
00824                 }
00825                 _region_erase_types_bitfield[0] |= bitfield; // If there's no region map, set region "0" types bitfield as defualt;
00826             }
00827 
00828             tr_info("INFO: Erase Type %d - Inst: 0x%xh, Size: %d", (i_ind + 1), erase_type_inst_arr[i_ind],
00829                     erase_type_size_arr[i_ind]);
00830             bitfield = bitfield << 1;
00831         }
00832     }
00833 
00834     if (false == found_4Kerase_type) {
00835         tr_warning("WARNING: Couldn't find Erase Type for 4KB size");
00836     }
00837     return 0;
00838 }
00839 
00840 int SPIFBlockDevice::_sfdp_detect_best_bus_read_mode(uint8_t *basic_param_table_ptr, int basic_param_table_size,
00841         int& read_inst)
00842 {
00843     do {
00844 
00845         // TBD - SPIF Dual Read Modes Require SPI driver support
00846         /*
00847         uint8_t examined_byte;
00848 
00849         if (basic_param_table_size > SPIF_BASIC_PARAM_TABLE_QPI_READ_SUPPORT_BYTE) {
00850             examined_byte = basic_param_table_ptr[SPIF_BASIC_PARAM_TABLE_QPI_READ_SUPPORT_BYTE];
00851             if (examined_byte & 0x01) {
00852                 //  Fast Read 2-2-2 Supported
00853                 read_inst = basic_param_table_ptr[SPIF_BASIC_PARAM_TABLE_222_READ_INST_BYTE];
00854                 _read_dummy_and_mode_cycles = (basic_param_table_ptr[SPIF_BASIC_PARAM_TABLE_222_READ_INST_BYTE - 1] >> 5)
00855                                          + (basic_param_table_ptr[SPIF_BASIC_PARAM_TABLE_222_READ_INST_BYTE - 1] & 0x1F);
00856                 tr_info("\nDEBUG: Read Bus Mode set to 2-2-2, Instruction: 0x%xh", read_inst);
00857                 break;
00858             }
00859         }
00860         examined_byte = basic_param_table_ptr[SPIF_BASIC_PARAM_TABLE_FAST_READ_SUPPORT_BYTE];
00861         if (examined_byte & 0x20) {
00862             //  Fast Read 1-2-2 Supported
00863             read_inst = basic_param_table_ptr[SPIF_BASIC_PARAM_TABLE_122_READ_INST_BYTE];
00864             _read_dummy_and_mode_cycles = (basic_param_table_ptr[SPIF_BASIC_PARAM_TABLE_122_READ_INST_BYTE - 1] >> 5)
00865                                      + (basic_param_table_ptr[SPIF_BASIC_PARAM_TABLE_122_READ_INST_BYTE - 1] & 0x1F);
00866             tr_debug("\nDEBUG: Read Bus Mode set to 1-2-2, Instruction: 0x%xh", read_inst);
00867             break;
00868         }
00869         if (examined_byte & 0x01) {
00870             // Fast Read 1-1-2 Supported
00871             read_inst = basic_param_table_ptr[SPIF_BASIC_PARAM_TABLE_112_READ_INST_BYTE];
00872             _read_dummy_and_mode_cycles = (basic_param_table_ptr[SPIF_BASIC_PARAM_TABLE_112_READ_INST_BYTE - 1] >> 5)
00873                                      + (basic_param_table_ptr[SPIF_BASIC_PARAM_TABLE_112_READ_INST_BYTE - 1] & 0x1F);
00874              tr_debug("\nDEBUG: Read Bus Mode set to 1-1-2, Instruction: 0x%xh", _read_instruction);
00875             break;
00876         }
00877          */
00878         _read_dummy_and_mode_cycles = 0;
00879         tr_debug("\nDEBUG: Read Bus Mode set to 1-1-1, Instruction: 0x%xh", read_inst);
00880     } while (false);
00881 
00882     return 0;
00883 }
00884 
00885 int SPIFBlockDevice::_reset_flash_mem()
00886 {
00887     // Perform Soft Reset of the Device prior to initialization
00888     int status = 0;
00889     char status_value[2] = {0};
00890     tr_info("INFO: _reset_flash_mem:\n");
00891     //Read the Status Register from device
00892     if (SPIF_BD_ERROR_OK == _spi_send_general_command(SPIF_RDSR, SPI_NO_ADDRESS_COMMAND, NULL, 0, status_value, 1) ) {
00893         // store received values in status_value
00894         tr_debug("DEBUG: Reading Status Register Success: value = 0x%x\n", (int)status_value[0]);
00895     } else {
00896         tr_debug("ERROR: Reading Status Register failed\n");
00897         status = -1;
00898     }
00899 
00900     if (0 == status) {
00901         //Send Reset Enable
00902         if (SPIF_BD_ERROR_OK == _spi_send_general_command(SPIF_RSTEN, SPI_NO_ADDRESS_COMMAND, NULL, 0, NULL, 0) ) {
00903             // store received values in status_value
00904             tr_debug("DEBUG: Sending RSTEN Success\n");
00905         } else {
00906             tr_error("ERROR: Sending RSTEN failed\n");
00907             status = -1;
00908         }
00909 
00910         if (0 == status) {
00911             //Send Reset
00912             if (SPIF_BD_ERROR_OK == _spi_send_general_command(SPIF_RST, SPI_NO_ADDRESS_COMMAND, NULL, 0, NULL, 0)) {
00913                 // store received values in status_value
00914                 tr_debug("DEBUG: Sending RST Success\n");
00915             } else {
00916                 tr_error("ERROR: Sending RST failed\n");
00917                 status = -1;
00918             }
00919             _is_mem_ready();
00920         }
00921     }
00922 
00923     return status;
00924 }
00925 
00926 bool SPIFBlockDevice::_is_mem_ready()
00927 {
00928     // Check Status Register Busy Bit to Verify the Device isn't Busy
00929     char status_value[2];
00930     int retries = 0;
00931     bool mem_ready = true;
00932 
00933     do {
00934         wait_ms(1);
00935         retries++;
00936         //Read the Status Register from device
00937         if (SPIF_BD_ERROR_OK != _spi_send_general_command(SPIF_RDSR, SPI_NO_ADDRESS_COMMAND, NULL, 0, status_value,
00938                 1)) {   // store received values in status_value
00939             tr_error("ERROR: Reading Status Register failed\n");
00940         }
00941     } while ( (status_value[0] & SPIF_STATUS_BIT_WIP) != 0 && retries < IS_MEM_READY_MAX_RETRIES );
00942 
00943     if ((status_value[0] & SPIF_STATUS_BIT_WIP) != 0) {
00944         tr_error("ERROR: _is_mem_ready FALSE\n");
00945         mem_ready = false;
00946     }
00947     return mem_ready;
00948 }
00949 
00950 int SPIFBlockDevice::_set_write_enable()
00951 {
00952     // Check Status Register Busy Bit to Verify the Device isn't Busy
00953     char status_value[2];
00954     int status = -1;
00955 
00956     do {
00957         if (SPIF_BD_ERROR_OK !=  _spi_send_general_command(SPIF_WREN, SPI_NO_ADDRESS_COMMAND, NULL, 0, NULL, 0)) {
00958             tr_error("ERROR:Sending WREN command FAILED\n");
00959             break;
00960         }
00961 
00962         if ( false == _is_mem_ready()) {
00963             tr_error("ERROR: Device not ready, write failed");
00964             break;
00965         }
00966 
00967         memset(status_value, 0, 2);
00968         if (SPIF_BD_ERROR_OK != _spi_send_general_command(SPIF_RDSR, SPI_NO_ADDRESS_COMMAND, NULL, 0, status_value,
00969                 1)) {   // store received values in status_value
00970             tr_error("ERROR: Reading Status Register failed\n");
00971             break;
00972         }
00973 
00974         if ((status_value[0] & SPIF_STATUS_BIT_WEL) == 0) {
00975             tr_error("ERROR: _set_write_enable failed\n");
00976             break;
00977         }
00978         status = 0;
00979     } while (false);
00980     return status;
00981 }
00982 
00983 /*********************************************/
00984 /************* Utility Functions *************/
00985 /*********************************************/
00986 int SPIFBlockDevice::_utils_find_addr_region(bd_size_t offset)
00987 {
00988     //Find the region to which the given offset belong to
00989     if ((offset > _device_size_bytes) || (_regions_count == 0)) {
00990         return -1;
00991     }
00992 
00993     if (_regions_count == 1) {
00994         return 0;
00995     }
00996 
00997     for (int i_ind = _regions_count - 2; i_ind >= 0; i_ind--) {
00998 
00999         if (offset > _region_high_boundary[i_ind]) {
01000             return (i_ind + 1);
01001         }
01002     }
01003     return -1;
01004 
01005 }
01006 
01007 int SPIFBlockDevice::_utils_iterate_next_largest_erase_type(uint8_t& bitfield, int size, int offset, int boundry)
01008 {
01009     // Iterate on all supported Erase Types of the Region to which the offset belong to.
01010     // Iterates from highest type to lowest
01011     uint8_t type_mask = ERASE_BITMASK_TYPE4;
01012     int i_ind  = 0;
01013     int largest_erase_type = 0;
01014     for (i_ind = 3; i_ind >= 0; i_ind--) {
01015         if (bitfield & type_mask) {
01016             largest_erase_type = i_ind;
01017             if ( (size > (int)(_erase_type_size_arr[largest_erase_type])) &&
01018                     ((boundry - offset) > (int)(_erase_type_size_arr[largest_erase_type])) ) {
01019                 break;
01020             } else {
01021                 bitfield &= ~type_mask;
01022             }
01023         }
01024         type_mask = type_mask >> 1;
01025     }
01026 
01027     if (i_ind == 4) {
01028         tr_error("ERROR: no erase type was found for current region addr");
01029     }
01030     return largest_erase_type;
01031 
01032 }
01033 
01034 /*********************************************/
01035 /************** Local Functions **************/
01036 /*********************************************/
01037 static unsigned int local_math_power(int base, int exp)
01038 {
01039     // Integer X^Y function, used to calculate size fields given in 2^N format
01040     int result = 1;
01041     while (exp) {
01042         result *= base;
01043         exp--;
01044     }
01045     return result;
01046 }
01047 
01048