bug fix

Dependencies:   HTS221

Committer:
JimCarver
Date:
Fri Oct 12 21:22:49 2018 +0000
Revision:
0:6b753f761943
Initial commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
JimCarver 0:6b753f761943 1
JimCarver 0:6b753f761943 2 /* mbed Microcontroller Library
JimCarver 0:6b753f761943 3 * Copyright (c) 2016 ARM Limited
JimCarver 0:6b753f761943 4 *
JimCarver 0:6b753f761943 5 * Licensed under the Apache License, Version 2.0 (the "License");
JimCarver 0:6b753f761943 6 * you may not use this file except in compliance with the License.
JimCarver 0:6b753f761943 7 * You may obtain a copy of the License at
JimCarver 0:6b753f761943 8 *
JimCarver 0:6b753f761943 9 * http://www.apache.org/licenses/LICENSE-2.0
JimCarver 0:6b753f761943 10 *
JimCarver 0:6b753f761943 11 * Unless required by applicable law or agreed to in writing, software
JimCarver 0:6b753f761943 12 * distributed under the License is distributed on an "AS IS" BASIS,
JimCarver 0:6b753f761943 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
JimCarver 0:6b753f761943 14 * See the License for the specific language governing permissions and
JimCarver 0:6b753f761943 15 * limitations under the License.
JimCarver 0:6b753f761943 16 */
JimCarver 0:6b753f761943 17
JimCarver 0:6b753f761943 18 //#include "./mbed-os/drivers/qspi.h"
JimCarver 0:6b753f761943 19
JimCarver 0:6b753f761943 20 #define DEVICE_QSPI 1
JimCarver 0:6b753f761943 21
JimCarver 0:6b753f761943 22 #include "QSPIFBlockDevice.h"
JimCarver 0:6b753f761943 23
JimCarver 0:6b753f761943 24 /* Default QSPIF Parameters */
JimCarver 0:6b753f761943 25 /****************************/
JimCarver 0:6b753f761943 26 #define QSPIF_DEFAULT_READ_SIZE 1
JimCarver 0:6b753f761943 27 #define QSPIF_DEFAULT_PROG_SIZE 1
JimCarver 0:6b753f761943 28 #define QSPIF_DEFAULT_SE_SIZE 4096
JimCarver 0:6b753f761943 29 #define QSPI_MAX_STATUS_REGISTER_SIZE 2
JimCarver 0:6b753f761943 30 #define QSPI_STATUS_REGISTER_WRITE_TIMEOUT_MSEC 50
JimCarver 0:6b753f761943 31 #define QSPIF_DEFAULT_TIMEOUT_MSEC 1
JimCarver 0:6b753f761943 32
JimCarver 0:6b753f761943 33
JimCarver 0:6b753f761943 34 /* SFDP Header Parsing */
JimCarver 0:6b753f761943 35 /***********************/
JimCarver 0:6b753f761943 36 #define QSPIF_SFDP_HEADER_SIZE 8
JimCarver 0:6b753f761943 37 #define QSPIF_PARAM_HEADER_SIZE 8
JimCarver 0:6b753f761943 38
JimCarver 0:6b753f761943 39 /* Basic Parameters Table Parsing */
JimCarver 0:6b753f761943 40 /**********************************/
JimCarver 0:6b753f761943 41 #define SFDP_DEFAULT_BASIC_PARAMS_TABLE_SIZE_BYTES 64 /* 16 DWORDS */
JimCarver 0:6b753f761943 42 //READ Instruction support according to BUS Configuration
JimCarver 0:6b753f761943 43 #define QSPIF_BASIC_PARAM_TABLE_FAST_READ_SUPPORT_BYTE 2
JimCarver 0:6b753f761943 44 #define QSPIF_BASIC_PARAM_TABLE_QPI_READ_SUPPOR_BYTE 16
JimCarver 0:6b753f761943 45 #define QSPIF_BASIC_PARAM_TABLE_444_READ_INST_BYTE 27
JimCarver 0:6b753f761943 46 #define QSPIF_BASIC_PARAM_TABLE_144_READ_INST_BYTE 9
JimCarver 0:6b753f761943 47 #define QSPIF_BASIC_PARAM_TABLE_114_READ_INST_BYTE 11
JimCarver 0:6b753f761943 48 #define QSPIF_BASIC_PARAM_TABLE_222_READ_INST_BYTE 23
JimCarver 0:6b753f761943 49 #define QSPIF_BASIC_PARAM_TABLE_122_READ_INST_BYTE 15
JimCarver 0:6b753f761943 50 #define QSPIF_BASIC_PARAM_TABLE_112_READ_INST_BYTE 13
JimCarver 0:6b753f761943 51 #define QSPIF_BASIC_PARAM_TABLE_PAGE_SIZE_BYTE 40
JimCarver 0:6b753f761943 52 // Quad Enable Params
JimCarver 0:6b753f761943 53 #define QSPIF_BASIC_PARAM_TABLE_QER_BYTE 58
JimCarver 0:6b753f761943 54 #define QSPIF_BASIC_PARAM_TABLE_444_MODE_EN_SEQ_BYTE 56
JimCarver 0:6b753f761943 55 // Erase Types Params
JimCarver 0:6b753f761943 56 #define QSPIF_BASIC_PARAM_ERASE_TYPE_1_BYTE 29
JimCarver 0:6b753f761943 57 #define QSPIF_BASIC_PARAM_ERASE_TYPE_2_BYTE 31
JimCarver 0:6b753f761943 58 #define QSPIF_BASIC_PARAM_ERASE_TYPE_3_BYTE 33
JimCarver 0:6b753f761943 59 #define QSPIF_BASIC_PARAM_ERASE_TYPE_4_BYTE 35
JimCarver 0:6b753f761943 60 #define QSPIF_BASIC_PARAM_ERASE_TYPE_1_SIZE_BYTE 28
JimCarver 0:6b753f761943 61 #define QSPIF_BASIC_PARAM_ERASE_TYPE_2_SIZE_BYTE 30
JimCarver 0:6b753f761943 62 #define QSPIF_BASIC_PARAM_ERASE_TYPE_3_SIZE_BYTE 32
JimCarver 0:6b753f761943 63 #define QSPIF_BASIC_PARAM_ERASE_TYPE_4_SIZE_BYTE 34
JimCarver 0:6b753f761943 64 #define QSPIF_BASIC_PARAM_4K_ERASE_TYPE_BYTE 1
JimCarver 0:6b753f761943 65
JimCarver 0:6b753f761943 66 // Debug Printouts
JimCarver 0:6b753f761943 67 #define QSPIF_DEBUG_ERROR 1
JimCarver 0:6b753f761943 68 #define QSPIF_DEBUG_WARNING 2
JimCarver 0:6b753f761943 69 #define QSPIF_DEBUG_INFO 3
JimCarver 0:6b753f761943 70 #define QSPIF_DEBUG_DEBUG 4
JimCarver 0:6b753f761943 71 #define QSPIF_DEBUG_TRACE 5
JimCarver 0:6b753f761943 72 // #define QSPIF_DEFAULT_DEBUG_LEVEL QSPIF_DEBUG_INFO
JimCarver 0:6b753f761943 73 // #define QSPIF_DEFAULT_DEBUG_LEVEL QSPIF_DEBUG_TRACE
JimCarver 0:6b753f761943 74 #define QSPIF_DEFAULT_DEBUG_LEVEL QSPIF_DEBUG_WARNING
JimCarver 0:6b753f761943 75
JimCarver 0:6b753f761943 76
JimCarver 0:6b753f761943 77 enum qspif_default_instructions {
JimCarver 0:6b753f761943 78 QSPIF_NOP = 0x00, // No operation
JimCarver 0:6b753f761943 79 QSPIF_PP = 0x02, // Page Program data
JimCarver 0:6b753f761943 80 QSPIF_READ = 0x03, // Read data
JimCarver 0:6b753f761943 81 QSPIF_SE = 0x20, // 4KB Sector Erase
JimCarver 0:6b753f761943 82 QSPIF_SFDP = 0x5a, // Read SFDP
JimCarver 0:6b753f761943 83
JimCarver 0:6b753f761943 84 QSPIF_WRSR = 0x01, // Write Status/Configuration Register
JimCarver 0:6b753f761943 85 QSPIF_WRDI = 0x04, // Write Disable
JimCarver 0:6b753f761943 86 QSPIF_RDSR = 0x05, // Read Status Register
JimCarver 0:6b753f761943 87 QSPIF_WREN = 0x06, // Write Enable
JimCarver 0:6b753f761943 88
JimCarver 0:6b753f761943 89 QSPIF_RSTEN = 0x66, // Reset Enable
JimCarver 0:6b753f761943 90 QSPIF_RST = 0x99, // Reset
JimCarver 0:6b753f761943 91 QSPIF_RDID = 0x9f, // Read Manufacturer and JDEC Device ID
JimCarver 0:6b753f761943 92 };
JimCarver 0:6b753f761943 93
JimCarver 0:6b753f761943 94 #define __FILENAME__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__)
JimCarver 0:6b753f761943 95
JimCarver 0:6b753f761943 96 #define QSPIF_LOG(level,...) {\
JimCarver 0:6b753f761943 97 if (level <= QSPIF_DEFAULT_DEBUG_LEVEL) {\
JimCarver 0:6b753f761943 98 char str[256];\
JimCarver 0:6b753f761943 99 sprintf(str, "\n[%s][%s:%d], ", __FILENAME__, __FUNCTION__, __LINE__);\
JimCarver 0:6b753f761943 100 sprintf(str+strlen(str),__VA_ARGS__);\
JimCarver 0:6b753f761943 101 printf(str);\
JimCarver 0:6b753f761943 102 }\
JimCarver 0:6b753f761943 103 }
JimCarver 0:6b753f761943 104
JimCarver 0:6b753f761943 105 // Mutex is used for some QSPI Driver commands that must be done sequentially with no other commands in between
JimCarver 0:6b753f761943 106 // e.g. (1)Set Write Enable, (2)Program, (3)Wait Memory Ready
JimCarver 0:6b753f761943 107 SingletonPtr<PlatformMutex> QSPIFBlockDevice::_mutex;
JimCarver 0:6b753f761943 108
JimCarver 0:6b753f761943 109
JimCarver 0:6b753f761943 110 /********* Public API Functions *********/
JimCarver 0:6b753f761943 111 /****************************************/
JimCarver 0:6b753f761943 112
JimCarver 0:6b753f761943 113 QSPIFBlockDevice::QSPIFBlockDevice(PinName io0, PinName io1, PinName io2, PinName io3, PinName sclk, PinName csel,
JimCarver 0:6b753f761943 114 int clock_mode, int freq)
JimCarver 0:6b753f761943 115 : _qspi(io0, io1, io2, io3, sclk, csel, clock_mode), _deviceSizeBytes(0)
JimCarver 0:6b753f761943 116 {
JimCarver 0:6b753f761943 117 //_cs = 1;
JimCarver 0:6b753f761943 118 is_initialized = false;
JimCarver 0:6b753f761943 119 _minCommonEraseSize = 0;
JimCarver 0:6b753f761943 120 _regions_count = 1;
JimCarver 0:6b753f761943 121 _region_erase_types[0] = 0;
JimCarver 0:6b753f761943 122
JimCarver 0:6b753f761943 123 //Default Bus Setup 1_1_1 with 0 dummy and mode cycles
JimCarver 0:6b753f761943 124 _inst_width = QSPI_CFG_BUS_SINGLE;
JimCarver 0:6b753f761943 125 _address_width = QSPI_CFG_BUS_SINGLE;
JimCarver 0:6b753f761943 126 _address_size = QSPI_CFG_ADDR_SIZE_24;
JimCarver 0:6b753f761943 127 _alt_width = QSPI_CFG_BUS_SINGLE;
JimCarver 0:6b753f761943 128 _alt_size = QSPI_CFG_ALT_SIZE_8;
JimCarver 0:6b753f761943 129 _data_width = QSPI_CFG_BUS_SINGLE;
JimCarver 0:6b753f761943 130 _dummy_and_mode_cycles = 0;
JimCarver 0:6b753f761943 131
JimCarver 0:6b753f761943 132 if (QSPI_STATUS_OK != _qspiSetFrequency(freq)) {
JimCarver 0:6b753f761943 133 QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: QSPI Set Frequency Failed");
JimCarver 0:6b753f761943 134 }
JimCarver 0:6b753f761943 135 }
JimCarver 0:6b753f761943 136
JimCarver 0:6b753f761943 137
JimCarver 0:6b753f761943 138 int QSPIFBlockDevice::init()
JimCarver 0:6b753f761943 139 {
JimCarver 0:6b753f761943 140
JimCarver 0:6b753f761943 141 uint8_t vendor_device_ids[4];
JimCarver 0:6b753f761943 142 size_t data_length = 3;
JimCarver 0:6b753f761943 143
JimCarver 0:6b753f761943 144 _mutex->lock();
JimCarver 0:6b753f761943 145 if (is_initialized == true) {
JimCarver 0:6b753f761943 146 _mutex->unlock();
JimCarver 0:6b753f761943 147 return 0;
JimCarver 0:6b753f761943 148 }
JimCarver 0:6b753f761943 149
JimCarver 0:6b753f761943 150 // Soft Reset
JimCarver 0:6b753f761943 151 if ( -1 == _resetFlashMem()) {
JimCarver 0:6b753f761943 152 QSPIF_LOG(QSPIF_DEBUG_INFO, "ERROR: init - Unable to initialize flash memory, tests failed\n");
JimCarver 0:6b753f761943 153 return -1;
JimCarver 0:6b753f761943 154 } else {
JimCarver 0:6b753f761943 155 QSPIF_LOG(QSPIF_DEBUG_INFO, "INFO: Initialize flash memory OK\n");
JimCarver 0:6b753f761943 156 }
JimCarver 0:6b753f761943 157
JimCarver 0:6b753f761943 158
JimCarver 0:6b753f761943 159
JimCarver 0:6b753f761943 160 /* Read Manufacturer ID (1byte), and Device ID (2bytes)*/
JimCarver 0:6b753f761943 161 int status = _qspiSendReadCommand(QSPIF_RDID, (char *)vendor_device_ids, 0x0 /*address*/, data_length);
JimCarver 0:6b753f761943 162 if (status != QSPI_STATUS_OK) {
JimCarver 0:6b753f761943 163 QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: init - Read Vendor ID Failed");
JimCarver 0:6b753f761943 164 return status;
JimCarver 0:6b753f761943 165 }
JimCarver 0:6b753f761943 166
JimCarver 0:6b753f761943 167 switch (vendor_device_ids[0]) {
JimCarver 0:6b753f761943 168 case 0xbf:
JimCarver 0:6b753f761943 169 // SST devices come preset with block protection
JimCarver 0:6b753f761943 170 // enabled for some regions, issue write disable instruction to clear
JimCarver 0:6b753f761943 171 _setWriteEnable();
JimCarver 0:6b753f761943 172 //_cmdwrite(0x98, 0, 0, 0x0, NULL);
JimCarver 0:6b753f761943 173 _qspiSendGeneralCommand(QSPIF_WRDI, -1, NULL, 0, NULL, 0);
JimCarver 0:6b753f761943 174
JimCarver 0:6b753f761943 175 break;
JimCarver 0:6b753f761943 176 }
JimCarver 0:6b753f761943 177
JimCarver 0:6b753f761943 178 //Synchronize Device
JimCarver 0:6b753f761943 179 if ( false == _isMemReady()) {
JimCarver 0:6b753f761943 180 QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: init - _isMemReady Failed");
JimCarver 0:6b753f761943 181 return BD_ERROR_DEVICE_ERROR;
JimCarver 0:6b753f761943 182 }
JimCarver 0:6b753f761943 183
JimCarver 0:6b753f761943 184
JimCarver 0:6b753f761943 185 /**************************** Parse SFDP Header ***********************************/
JimCarver 0:6b753f761943 186 uint32_t basic_table_addr = NULL;
JimCarver 0:6b753f761943 187 size_t basic_table_size = 0;
JimCarver 0:6b753f761943 188 uint32_t sector_map_table_addr = NULL;
JimCarver 0:6b753f761943 189 size_t sector_map_table_size = 0;
JimCarver 0:6b753f761943 190 if ( 0 != _sfdpParseSFDPHeaders(basic_table_addr, basic_table_size, sector_map_table_addr, sector_map_table_size)) {
JimCarver 0:6b753f761943 191 QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: init - Parse SFDP Headers Failed");
JimCarver 0:6b753f761943 192 return BD_ERROR_DEVICE_ERROR;
JimCarver 0:6b753f761943 193 }
JimCarver 0:6b753f761943 194
JimCarver 0:6b753f761943 195
JimCarver 0:6b753f761943 196 /**************************** Parse Basic Parameters Table ***********************************/
JimCarver 0:6b753f761943 197 if ( 0 != _sfdpParseBasicParamTable(basic_table_addr, basic_table_size) ) {
JimCarver 0:6b753f761943 198 QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: init - Parse Basic Param Table Failed");
JimCarver 0:6b753f761943 199 return BD_ERROR_DEVICE_ERROR;
JimCarver 0:6b753f761943 200 }
JimCarver 0:6b753f761943 201
JimCarver 0:6b753f761943 202
JimCarver 0:6b753f761943 203 /**************************** Parse Sector Map Table ***********************************/
JimCarver 0:6b753f761943 204 _region_size_bytes[0] =
JimCarver 0:6b753f761943 205 _deviceSizeBytes; // If there's no region map, we have a single region sized the entire device size
JimCarver 0:6b753f761943 206 _region_high_boundary[0] = _deviceSizeBytes - 1;
JimCarver 0:6b753f761943 207
JimCarver 0:6b753f761943 208 if ( (sector_map_table_addr != NULL) && (0 != sector_map_table_size) ) {
JimCarver 0:6b753f761943 209 QSPIF_LOG(QSPIF_DEBUG_INFO, "INFO: init - Parsing Sector Map Table - addr: 0x%xh, Size: %d", sector_map_table_addr,
JimCarver 0:6b753f761943 210 sector_map_table_size);
JimCarver 0:6b753f761943 211 if ( 0 != _sfdpParseSectorMapTable(sector_map_table_addr, sector_map_table_size) ) {
JimCarver 0:6b753f761943 212 QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: init - Parse Sector Map Table Failed");
JimCarver 0:6b753f761943 213 return BD_ERROR_DEVICE_ERROR;
JimCarver 0:6b753f761943 214 }
JimCarver 0:6b753f761943 215 }
JimCarver 0:6b753f761943 216
JimCarver 0:6b753f761943 217
JimCarver 0:6b753f761943 218 // Configure BUS Mode to 1_1_1 for all commands other than Read
JimCarver 0:6b753f761943 219 _qspiConfiureFormat( QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_SINGLE, QSPI_CFG_ADDR_SIZE_24, QSPI_CFG_BUS_SINGLE,
JimCarver 0:6b753f761943 220 QSPI_CFG_ALT_SIZE_8, QSPI_CFG_BUS_SINGLE, 0);
JimCarver 0:6b753f761943 221 /*// Soft Reset
JimCarver 0:6b753f761943 222 if( -1 == _resetFlashMem()) {
JimCarver 0:6b753f761943 223 QSPIF_LOG(QSPIF_DEBUG_INFO,"ERROR: init - Unable to initialize flash memory, tests failed\n");
JimCarver 0:6b753f761943 224 return -1;
JimCarver 0:6b753f761943 225 } else {
JimCarver 0:6b753f761943 226 QSPIF_LOG(QSPIF_DEBUG_INFO,"INFO: Initialize flash memory OK\n");
JimCarver 0:6b753f761943 227 }*/
JimCarver 0:6b753f761943 228
JimCarver 0:6b753f761943 229 is_initialized = true;
JimCarver 0:6b753f761943 230 _mutex->unlock();
JimCarver 0:6b753f761943 231
JimCarver 0:6b753f761943 232 return 0;
JimCarver 0:6b753f761943 233 }
JimCarver 0:6b753f761943 234
JimCarver 0:6b753f761943 235 int QSPIFBlockDevice::deinit()
JimCarver 0:6b753f761943 236 {
JimCarver 0:6b753f761943 237 _mutex->lock();
JimCarver 0:6b753f761943 238 if (is_initialized == false) {
JimCarver 0:6b753f761943 239 _mutex->unlock();
JimCarver 0:6b753f761943 240 return 0;
JimCarver 0:6b753f761943 241 }
JimCarver 0:6b753f761943 242 qspi_status_t status = _qspiSendGeneralCommand(QSPIF_WRDI, -1, NULL, 0, NULL, 0);
JimCarver 0:6b753f761943 243 int result = 0;
JimCarver 0:6b753f761943 244
JimCarver 0:6b753f761943 245 if (status != QSPI_STATUS_OK) {
JimCarver 0:6b753f761943 246 QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: Write Disable failed");
JimCarver 0:6b753f761943 247 result = -1;
JimCarver 0:6b753f761943 248 }
JimCarver 0:6b753f761943 249 is_initialized = false;
JimCarver 0:6b753f761943 250 _mutex->unlock();
JimCarver 0:6b753f761943 251
JimCarver 0:6b753f761943 252 return result;
JimCarver 0:6b753f761943 253 }
JimCarver 0:6b753f761943 254
JimCarver 0:6b753f761943 255
JimCarver 0:6b753f761943 256 int QSPIFBlockDevice::read(void *buffer, bd_addr_t addr, bd_size_t size)
JimCarver 0:6b753f761943 257 {
JimCarver 0:6b753f761943 258
JimCarver 0:6b753f761943 259
JimCarver 0:6b753f761943 260 int status = 0;
JimCarver 0:6b753f761943 261
JimCarver 0:6b753f761943 262 QSPIF_LOG(QSPIF_DEBUG_INFO, "INFO Inst: 0x%xh", _readInstruction);
JimCarver 0:6b753f761943 263
JimCarver 0:6b753f761943 264 _mutex->lock();
JimCarver 0:6b753f761943 265
JimCarver 0:6b753f761943 266 _qspiConfiureFormat(
JimCarver 0:6b753f761943 267 _inst_width, //Bus width for Instruction phase
JimCarver 0:6b753f761943 268 _address_width, //Bus width for Address phase
JimCarver 0:6b753f761943 269 _address_size,
JimCarver 0:6b753f761943 270 _alt_width, //Bus width for Alt phase
JimCarver 0:6b753f761943 271 _alt_size,
JimCarver 0:6b753f761943 272 _data_width, //Bus width for Data phase
JimCarver 0:6b753f761943 273 _dummy_and_mode_cycles);
JimCarver 0:6b753f761943 274 //_qspiConfiureFormat( QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_SINGLE, QSPI_CFG_ADDR_SIZE_24, QSPI_CFG_BUS_SINGLE, QSPI_CFG_ALT_SIZE_8, QSPI_CFG_BUS_SINGLE, 8);
JimCarver 0:6b753f761943 275
JimCarver 0:6b753f761943 276 if (QSPI_STATUS_OK != _qspiSendReadCommand(_readInstruction, buffer, addr, size)) {
JimCarver 0:6b753f761943 277 status = -1;
JimCarver 0:6b753f761943 278 QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: Read failed\n");
JimCarver 0:6b753f761943 279 }
JimCarver 0:6b753f761943 280
JimCarver 0:6b753f761943 281 // 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)
JimCarver 0:6b753f761943 282 _qspiConfiureFormat( QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_SINGLE, QSPI_CFG_ADDR_SIZE_24, QSPI_CFG_BUS_SINGLE,
JimCarver 0:6b753f761943 283 QSPI_CFG_ALT_SIZE_8, QSPI_CFG_BUS_SINGLE, 0);
JimCarver 0:6b753f761943 284
JimCarver 0:6b753f761943 285 _mutex->unlock();
JimCarver 0:6b753f761943 286 return status;
JimCarver 0:6b753f761943 287
JimCarver 0:6b753f761943 288 }
JimCarver 0:6b753f761943 289
JimCarver 0:6b753f761943 290
JimCarver 0:6b753f761943 291
JimCarver 0:6b753f761943 292
JimCarver 0:6b753f761943 293 int QSPIFBlockDevice::program(const void *buffer, bd_addr_t addr, bd_size_t size)
JimCarver 0:6b753f761943 294 {
JimCarver 0:6b753f761943 295 qspi_status_t result = QSPI_STATUS_OK;
JimCarver 0:6b753f761943 296 bool program_failed = false;
JimCarver 0:6b753f761943 297 int status = 0;
JimCarver 0:6b753f761943 298 uint32_t offset = 0;
JimCarver 0:6b753f761943 299 uint32_t chunk = 0;
JimCarver 0:6b753f761943 300 bd_size_t writtenBytes = 0;
JimCarver 0:6b753f761943 301
JimCarver 0:6b753f761943 302 while (size > 0) {
JimCarver 0:6b753f761943 303
JimCarver 0:6b753f761943 304 // Write on _pageSizeBytes boundaries (Default 256 bytes a page)
JimCarver 0:6b753f761943 305 offset = addr % _pageSizeBytes;
JimCarver 0:6b753f761943 306 chunk = (offset + size < _pageSizeBytes) ? size : (_pageSizeBytes - offset);
JimCarver 0:6b753f761943 307 writtenBytes = chunk;
JimCarver 0:6b753f761943 308
JimCarver 0:6b753f761943 309 _mutex->lock();
JimCarver 0:6b753f761943 310
JimCarver 0:6b753f761943 311 //Send WREN
JimCarver 0:6b753f761943 312 if (_setWriteEnable() != 0) {
JimCarver 0:6b753f761943 313 QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: Write Enabe failed\n");
JimCarver 0:6b753f761943 314 program_failed = true;
JimCarver 0:6b753f761943 315 goto Exit_Point;
JimCarver 0:6b753f761943 316 }
JimCarver 0:6b753f761943 317
JimCarver 0:6b753f761943 318 if ( false == _isMemReady()) {
JimCarver 0:6b753f761943 319 QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: Device not ready, write failed\n");
JimCarver 0:6b753f761943 320 program_failed = true;
JimCarver 0:6b753f761943 321 goto Exit_Point;
JimCarver 0:6b753f761943 322 }
JimCarver 0:6b753f761943 323
JimCarver 0:6b753f761943 324 result = _qspiSendProgramCommand(_progInstruction, buffer, addr, &writtenBytes);
JimCarver 0:6b753f761943 325 if ( (result != QSPI_STATUS_OK) || (chunk != writtenBytes) ) {
JimCarver 0:6b753f761943 326 QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: Write failed");
JimCarver 0:6b753f761943 327 program_failed = true;
JimCarver 0:6b753f761943 328 goto Exit_Point;
JimCarver 0:6b753f761943 329 }
JimCarver 0:6b753f761943 330
JimCarver 0:6b753f761943 331 buffer = static_cast<const uint8_t *>(buffer) + chunk;
JimCarver 0:6b753f761943 332 addr += chunk;
JimCarver 0:6b753f761943 333 size -= chunk;
JimCarver 0:6b753f761943 334
JimCarver 0:6b753f761943 335 wait_ms(QSPIF_DEFAULT_TIMEOUT_MSEC);
JimCarver 0:6b753f761943 336
JimCarver 0:6b753f761943 337 if ( false == _isMemReady()) {
JimCarver 0:6b753f761943 338 QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: Device not ready after write, failed\n");
JimCarver 0:6b753f761943 339 program_failed = true;
JimCarver 0:6b753f761943 340 goto Exit_Point;
JimCarver 0:6b753f761943 341 }
JimCarver 0:6b753f761943 342 _mutex->unlock();
JimCarver 0:6b753f761943 343
JimCarver 0:6b753f761943 344
JimCarver 0:6b753f761943 345 }
JimCarver 0:6b753f761943 346
JimCarver 0:6b753f761943 347 Exit_Point:
JimCarver 0:6b753f761943 348 if (program_failed) {
JimCarver 0:6b753f761943 349 _mutex->unlock();
JimCarver 0:6b753f761943 350 status = -1;
JimCarver 0:6b753f761943 351 }
JimCarver 0:6b753f761943 352
JimCarver 0:6b753f761943 353 return status;
JimCarver 0:6b753f761943 354 }
JimCarver 0:6b753f761943 355
JimCarver 0:6b753f761943 356
JimCarver 0:6b753f761943 357 int QSPIFBlockDevice::erase(bd_addr_t addr, bd_size_t inSize)
JimCarver 0:6b753f761943 358 {
JimCarver 0:6b753f761943 359
JimCarver 0:6b753f761943 360 int type = 0;
JimCarver 0:6b753f761943 361 uint32_t chunk = 4096;
JimCarver 0:6b753f761943 362 unsigned int curEraseInst = _eraseInstruction;
JimCarver 0:6b753f761943 363 int size = (int)inSize;
JimCarver 0:6b753f761943 364 bool erase_failed = false;
JimCarver 0:6b753f761943 365 int status = 0;
JimCarver 0:6b753f761943 366 // Find region of erased address
JimCarver 0:6b753f761943 367 int region = _utilsFindAddrRegion((int)addr);
JimCarver 0:6b753f761943 368 // Erase Types of selected region
JimCarver 0:6b753f761943 369 uint8_t bitfield = _region_erase_types[region];
JimCarver 0:6b753f761943 370
JimCarver 0:6b753f761943 371
JimCarver 0:6b753f761943 372 while (size > 0) {
JimCarver 0:6b753f761943 373
JimCarver 0:6b753f761943 374 // iterate to find next Largest erase type (1) supported by region, 2) smaller than size)
JimCarver 0:6b753f761943 375 // find the matching instruction and erase size chunk for that type.
JimCarver 0:6b753f761943 376 type = _utilsIterateNextLargestEraseType(bitfield, (int)size, (int)addr, _region_high_boundary[region]);
JimCarver 0:6b753f761943 377 curEraseInst = _eraseTypeInstArr[type];
JimCarver 0:6b753f761943 378 chunk = _eraseTypeSizeArr[type];
JimCarver 0:6b753f761943 379
JimCarver 0:6b753f761943 380 QSPIF_LOG(QSPIF_DEBUG_DEBUG, " Debug: addr: 0x%xh, size:%d, Inst: 0x%xh, chunk: %d , ",
JimCarver 0:6b753f761943 381 (int)addr, (int)size, curEraseInst, chunk);
JimCarver 0:6b753f761943 382
JimCarver 0:6b753f761943 383 _mutex->lock();
JimCarver 0:6b753f761943 384
JimCarver 0:6b753f761943 385 if (_setWriteEnable() != 0) {
JimCarver 0:6b753f761943 386 QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: QSPI Erase - Write Enable failed");
JimCarver 0:6b753f761943 387 erase_failed = true;
JimCarver 0:6b753f761943 388 goto Exit_Point;
JimCarver 0:6b753f761943 389 }
JimCarver 0:6b753f761943 390
JimCarver 0:6b753f761943 391 if ( false == _isMemReady()) {
JimCarver 0:6b753f761943 392 QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: QSPI Erase Device not ready - failed");
JimCarver 0:6b753f761943 393 erase_failed = true;
JimCarver 0:6b753f761943 394 goto Exit_Point;
JimCarver 0:6b753f761943 395 }
JimCarver 0:6b753f761943 396
JimCarver 0:6b753f761943 397 if (QSPI_STATUS_OK != _qspiSendEraseCommand(curEraseInst, addr, size) ) {
JimCarver 0:6b753f761943 398 QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: QSPI Erase command failed!");
JimCarver 0:6b753f761943 399 erase_failed = true;
JimCarver 0:6b753f761943 400 goto Exit_Point;
JimCarver 0:6b753f761943 401 }
JimCarver 0:6b753f761943 402
JimCarver 0:6b753f761943 403 addr += chunk;
JimCarver 0:6b753f761943 404 size -= chunk;
JimCarver 0:6b753f761943 405
JimCarver 0:6b753f761943 406 if ( (size > 0) && (addr > _region_high_boundary[region]) ) {
JimCarver 0:6b753f761943 407 // erase crossed to next region
JimCarver 0:6b753f761943 408 region++;
JimCarver 0:6b753f761943 409 bitfield = _region_erase_types[region];
JimCarver 0:6b753f761943 410 }
JimCarver 0:6b753f761943 411 wait_ms(QSPIF_DEFAULT_TIMEOUT_MSEC);
JimCarver 0:6b753f761943 412 if ( false == _isMemReady()) {
JimCarver 0:6b753f761943 413 QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: QSPI After Erase Device not ready - failed\n");
JimCarver 0:6b753f761943 414 erase_failed = true;
JimCarver 0:6b753f761943 415 goto Exit_Point;
JimCarver 0:6b753f761943 416 }
JimCarver 0:6b753f761943 417 _mutex->unlock();
JimCarver 0:6b753f761943 418
JimCarver 0:6b753f761943 419 }
JimCarver 0:6b753f761943 420
JimCarver 0:6b753f761943 421
JimCarver 0:6b753f761943 422 Exit_Point:
JimCarver 0:6b753f761943 423 if (erase_failed) {
JimCarver 0:6b753f761943 424 _mutex->unlock();
JimCarver 0:6b753f761943 425 status = -1;
JimCarver 0:6b753f761943 426 }
JimCarver 0:6b753f761943 427
JimCarver 0:6b753f761943 428 return status;
JimCarver 0:6b753f761943 429 }
JimCarver 0:6b753f761943 430
JimCarver 0:6b753f761943 431
JimCarver 0:6b753f761943 432
JimCarver 0:6b753f761943 433 bd_size_t QSPIFBlockDevice::get_read_size() const
JimCarver 0:6b753f761943 434 {
JimCarver 0:6b753f761943 435 return QSPIF_DEFAULT_READ_SIZE;
JimCarver 0:6b753f761943 436 }
JimCarver 0:6b753f761943 437
JimCarver 0:6b753f761943 438 bd_size_t QSPIFBlockDevice::get_program_size() const
JimCarver 0:6b753f761943 439 {
JimCarver 0:6b753f761943 440 return QSPIF_DEFAULT_PROG_SIZE;
JimCarver 0:6b753f761943 441 }
JimCarver 0:6b753f761943 442
JimCarver 0:6b753f761943 443 bd_size_t QSPIFBlockDevice::get_erase_size() const
JimCarver 0:6b753f761943 444 {
JimCarver 0:6b753f761943 445 return _minCommonEraseSize;
JimCarver 0:6b753f761943 446 }
JimCarver 0:6b753f761943 447
JimCarver 0:6b753f761943 448
JimCarver 0:6b753f761943 449 // Find minimal erase size supported by address region
JimCarver 0:6b753f761943 450 bd_size_t QSPIFBlockDevice::get_erase_size(bd_addr_t addr)
JimCarver 0:6b753f761943 451 {
JimCarver 0:6b753f761943 452 // Find region of current address
JimCarver 0:6b753f761943 453 int region = _utilsFindAddrRegion((int)addr);
JimCarver 0:6b753f761943 454
JimCarver 0:6b753f761943 455 int minRegionEraseSize = _minCommonEraseSize;
JimCarver 0:6b753f761943 456 int8_t type_mask = 0x01;
JimCarver 0:6b753f761943 457 int i_ind = 0;
JimCarver 0:6b753f761943 458
JimCarver 0:6b753f761943 459 if (region != -1) {
JimCarver 0:6b753f761943 460 type_mask = 0x01;
JimCarver 0:6b753f761943 461
JimCarver 0:6b753f761943 462 for (i_ind = 0; i_ind < 4; i_ind++) {
JimCarver 0:6b753f761943 463 // loop through erase types supported by region
JimCarver 0:6b753f761943 464 if (_region_erase_types[region] & type_mask) {
JimCarver 0:6b753f761943 465
JimCarver 0:6b753f761943 466 minRegionEraseSize = _eraseTypeSizeArr[i_ind];
JimCarver 0:6b753f761943 467 break;
JimCarver 0:6b753f761943 468 }
JimCarver 0:6b753f761943 469 type_mask = type_mask << 1;
JimCarver 0:6b753f761943 470 }
JimCarver 0:6b753f761943 471
JimCarver 0:6b753f761943 472 if (i_ind == 4) {
JimCarver 0:6b753f761943 473 QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: no erase type was found for region addr");
JimCarver 0:6b753f761943 474 }
JimCarver 0:6b753f761943 475 }
JimCarver 0:6b753f761943 476
JimCarver 0:6b753f761943 477 return (bd_size_t)minRegionEraseSize;
JimCarver 0:6b753f761943 478
JimCarver 0:6b753f761943 479 }
JimCarver 0:6b753f761943 480
JimCarver 0:6b753f761943 481 bd_size_t QSPIFBlockDevice::size() const
JimCarver 0:6b753f761943 482 {
JimCarver 0:6b753f761943 483 return _deviceSizeBytes;
JimCarver 0:6b753f761943 484 }
JimCarver 0:6b753f761943 485
JimCarver 0:6b753f761943 486
JimCarver 0:6b753f761943 487 /*********************************************************/
JimCarver 0:6b753f761943 488 /********** SFDP Parsing and Detection Functions *********/
JimCarver 0:6b753f761943 489 /*********************************************************/
JimCarver 0:6b753f761943 490
JimCarver 0:6b753f761943 491 int QSPIFBlockDevice::_sfdpParseSectorMapTable(uint32_t sector_map_table_addr, size_t sector_map_table_size)
JimCarver 0:6b753f761943 492 {
JimCarver 0:6b753f761943 493 uint8_t sector_map_table[SFDP_DEFAULT_BASIC_PARAMS_TABLE_SIZE_BYTES]; /* Up To 16 DWORDS = 64 Bytes */
JimCarver 0:6b753f761943 494 uint32_t tmpRegionSize = 0;
JimCarver 0:6b753f761943 495 int i_ind = 0;
JimCarver 0:6b753f761943 496 int prevBoundary = 0;
JimCarver 0:6b753f761943 497 // Default set to all type bits 1-4 are common
JimCarver 0:6b753f761943 498 _minCommonEraseType = 0x0F;
JimCarver 0:6b753f761943 499
JimCarver 0:6b753f761943 500 qspi_status_t status = _qspiSendReadCommand(QSPIF_SFDP, (char *)sector_map_table, sector_map_table_addr /*address*/,
JimCarver 0:6b753f761943 501 sector_map_table_size);
JimCarver 0:6b753f761943 502 if (status != QSPI_STATUS_OK) {
JimCarver 0:6b753f761943 503 QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: init - Read SFDP First Table Failed");
JimCarver 0:6b753f761943 504 return -1;
JimCarver 0:6b753f761943 505 }
JimCarver 0:6b753f761943 506
JimCarver 0:6b753f761943 507 //QSPIF_LOG(QSPIF_DEBUG_DEBUG,\nDEBUG: "Read table: %x %x %x %x %x %x %x %x %x[56] %x[57] %x[58] %x[59] %x[52]\n",sector_map_table[0],
JimCarver 0:6b753f761943 508 // sector_map_table[1],
JimCarver 0:6b753f761943 509 // sector_map_table[2],
JimCarver 0:6b753f761943 510 // sector_map_table[3],
JimCarver 0:6b753f761943 511 // sector_map_table[4],
JimCarver 0:6b753f761943 512 // sector_map_table[5],
JimCarver 0:6b753f761943 513 // sector_map_table[6],
JimCarver 0:6b753f761943 514 // sector_map_table[7], sector_map_table[56], sector_map_table[57], sector_map_table[58], sector_map_table[59], sector_map_table[52]);
JimCarver 0:6b753f761943 515
JimCarver 0:6b753f761943 516 // Currently we support only Single Map Descriptor
JimCarver 0:6b753f761943 517 if (! ( (sector_map_table[0] & 0x3) == 0x03 ) && (sector_map_table[1] == 0x0) ) {
JimCarver 0:6b753f761943 518 QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: Sector Map - Supporting Only Single! Map Descriptor (not map commands)");
JimCarver 0:6b753f761943 519 return -1;
JimCarver 0:6b753f761943 520 }
JimCarver 0:6b753f761943 521
JimCarver 0:6b753f761943 522 _regions_count = sector_map_table[2] + 1;
JimCarver 0:6b753f761943 523 if (_regions_count > QSPIF_MAX_REGIONS) {
JimCarver 0:6b753f761943 524 QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: Supporting up to %d regions, current setup to %d regions - fail",
JimCarver 0:6b753f761943 525 QSPIF_MAX_REGIONS, _regions_count);
JimCarver 0:6b753f761943 526 return -1;
JimCarver 0:6b753f761943 527 }
JimCarver 0:6b753f761943 528
JimCarver 0:6b753f761943 529 // Loop through Regions and set for each one: size, supported erase types, high boundary offset
JimCarver 0:6b753f761943 530 // Calculate minimum Common Erase Type for all Regions
JimCarver 0:6b753f761943 531 for (i_ind = 0; i_ind < _regions_count; i_ind++) {
JimCarver 0:6b753f761943 532 tmpRegionSize = ((*((uint32_t *)&sector_map_table[(i_ind + 1) * 4])) >> 8) & 0x00FFFFFF; // bits 9-32
JimCarver 0:6b753f761943 533 _region_size_bytes[i_ind] = (tmpRegionSize + 1) * 256; // Region size is 0 based multiple of 256 bytes;
JimCarver 0:6b753f761943 534 _region_erase_types[i_ind] = sector_map_table[(i_ind + 1) * 4] & 0x0F; // bits 1-4
JimCarver 0:6b753f761943 535 _minCommonEraseType &= _region_erase_types[i_ind];
JimCarver 0:6b753f761943 536 _region_high_boundary[i_ind] = (_region_size_bytes[i_ind] - 1) + prevBoundary;
JimCarver 0:6b753f761943 537 prevBoundary = _region_high_boundary[i_ind] + 1;
JimCarver 0:6b753f761943 538 }
JimCarver 0:6b753f761943 539
JimCarver 0:6b753f761943 540 // Calc minimum Common Erase Size from _minCommonEraseType
JimCarver 0:6b753f761943 541 uint8_t type_mask = 0x01;
JimCarver 0:6b753f761943 542 for (i_ind = 0; i_ind < 4; i_ind++) {
JimCarver 0:6b753f761943 543 if (_minCommonEraseType & type_mask) {
JimCarver 0:6b753f761943 544 _minCommonEraseType = i_ind;
JimCarver 0:6b753f761943 545 _minCommonEraseSize = _eraseTypeSizeArr[i_ind];
JimCarver 0:6b753f761943 546 break;
JimCarver 0:6b753f761943 547 }
JimCarver 0:6b753f761943 548 type_mask = type_mask << 1;
JimCarver 0:6b753f761943 549 }
JimCarver 0:6b753f761943 550
JimCarver 0:6b753f761943 551 if (i_ind == 4) {
JimCarver 0:6b753f761943 552 // No common erase type was found between regions
JimCarver 0:6b753f761943 553 _minCommonEraseType = 0;
JimCarver 0:6b753f761943 554 _minCommonEraseSize = -1;
JimCarver 0:6b753f761943 555 }
JimCarver 0:6b753f761943 556
JimCarver 0:6b753f761943 557 return 0;
JimCarver 0:6b753f761943 558 }
JimCarver 0:6b753f761943 559
JimCarver 0:6b753f761943 560
JimCarver 0:6b753f761943 561 int QSPIFBlockDevice::_sfdpParseBasicParamTable(uint32_t basic_table_addr, size_t basic_table_size)
JimCarver 0:6b753f761943 562 {
JimCarver 0:6b753f761943 563 uint8_t param_table[SFDP_DEFAULT_BASIC_PARAMS_TABLE_SIZE_BYTES]; /* Up To 16 DWORDS = 64 Bytes */
JimCarver 0:6b753f761943 564
JimCarver 0:6b753f761943 565 qspi_status_t status = _qspiSendReadCommand(QSPIF_SFDP, (char *)param_table, basic_table_addr /*address*/,
JimCarver 0:6b753f761943 566 basic_table_size);
JimCarver 0:6b753f761943 567 if (status != QSPI_STATUS_OK) {
JimCarver 0:6b753f761943 568 QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: init - Read SFDP First Table Failed, Status %d",status);
JimCarver 0:6b753f761943 569 return -1;
JimCarver 0:6b753f761943 570 }
JimCarver 0:6b753f761943 571
JimCarver 0:6b753f761943 572 QSPIF_LOG(QSPIF_DEBUG_DEBUG, "DEBUG: Read table: %x %x %x %x %x %x %x %x %x[56] %x[57] %x[58] %x[59] %x[52]\n",
JimCarver 0:6b753f761943 573 param_table[0],
JimCarver 0:6b753f761943 574 param_table[1],
JimCarver 0:6b753f761943 575 param_table[2],
JimCarver 0:6b753f761943 576 param_table[3],
JimCarver 0:6b753f761943 577 param_table[4],
JimCarver 0:6b753f761943 578 param_table[5],
JimCarver 0:6b753f761943 579 param_table[6],
JimCarver 0:6b753f761943 580 param_table[7], param_table[56], param_table[57], param_table[58], param_table[59], param_table[52]);
JimCarver 0:6b753f761943 581
JimCarver 0:6b753f761943 582
JimCarver 0:6b753f761943 583 // Check address size, currently only supports 3byte addresses
JimCarver 0:6b753f761943 584 if ((param_table[2] & 0x4) != 0 || (param_table[7] & 0x80) != 0) {
JimCarver 0:6b753f761943 585 QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: init - verify 3byte addressing Failed");
JimCarver 0:6b753f761943 586 return -1;
JimCarver 0:6b753f761943 587 }
JimCarver 0:6b753f761943 588
JimCarver 0:6b753f761943 589 // Get device density (stored in bits - 1)
JimCarver 0:6b753f761943 590 uint32_t density_bits = (
JimCarver 0:6b753f761943 591 (param_table[7] << 24) |
JimCarver 0:6b753f761943 592 (param_table[6] << 16) |
JimCarver 0:6b753f761943 593 (param_table[5] << 8 ) |
JimCarver 0:6b753f761943 594 param_table[4] );
JimCarver 0:6b753f761943 595 _deviceSizeBytes = (density_bits + 1) / 8;
JimCarver 0:6b753f761943 596
JimCarver 0:6b753f761943 597 // Set Default read/program/erase Instructions
JimCarver 0:6b753f761943 598 _readInstruction = QSPIF_READ;
JimCarver 0:6b753f761943 599 _progInstruction = QSPIF_PP;
JimCarver 0:6b753f761943 600 _eraseInstruction = QSPIF_SE;
JimCarver 0:6b753f761943 601
JimCarver 0:6b753f761943 602 // Set Page Size (QSPI write must be done on Page limits)
JimCarver 0:6b753f761943 603 _pageSizeBytes = _sfdpDetectPageSize(param_table);
JimCarver 0:6b753f761943 604
JimCarver 0:6b753f761943 605 // Detect and Set Erase Types
JimCarver 0:6b753f761943 606 bool shouldSetQuadEnable = false;
JimCarver 0:6b753f761943 607 bool isQPIMode = false;
JimCarver 0:6b753f761943 608 _sfdpDetectEraseTypesInstAndSize(param_table, _erase4KInst, _eraseTypeInstArr, _eraseTypeSizeArr);
JimCarver 0:6b753f761943 609 _eraseInstruction = _erase4KInst;
JimCarver 0:6b753f761943 610
JimCarver 0:6b753f761943 611
JimCarver 0:6b753f761943 612 // Detect and Set fastest Bus mode (default 1-1-1)
JimCarver 0:6b753f761943 613 _sfdpDetectBestBusReadMode(param_table, shouldSetQuadEnable, isQPIMode, _readInstruction);
JimCarver 0:6b753f761943 614
JimCarver 0:6b753f761943 615 if (true == shouldSetQuadEnable) {
JimCarver 0:6b753f761943 616 // Set Quad Enable and QPI Bus modes if Supported
JimCarver 0:6b753f761943 617 QSPIF_LOG(QSPIF_DEBUG_INFO, "INFO: init - Setting Quad Enable");
JimCarver 0:6b753f761943 618 _sfdpSetQuadEnabled(param_table);
JimCarver 0:6b753f761943 619 if (true == isQPIMode) {
JimCarver 0:6b753f761943 620 QSPIF_LOG(QSPIF_DEBUG_INFO, "INFO: init - Setting QPI mode");
JimCarver 0:6b753f761943 621 _sfdpSetQPIEnabled(param_table);
JimCarver 0:6b753f761943 622 }
JimCarver 0:6b753f761943 623 }
JimCarver 0:6b753f761943 624 return 0;
JimCarver 0:6b753f761943 625 }
JimCarver 0:6b753f761943 626
JimCarver 0:6b753f761943 627 int QSPIFBlockDevice::_sfdpParseSFDPHeaders(uint32_t& basic_table_addr, size_t& basic_table_size,
JimCarver 0:6b753f761943 628 uint32_t& sector_map_table_addr, size_t& sector_map_table_size)
JimCarver 0:6b753f761943 629 {
JimCarver 0:6b753f761943 630 uint8_t sfdp_header[QSPIF_SFDP_HEADER_SIZE];
JimCarver 0:6b753f761943 631 uint8_t param_header[QSPIF_PARAM_HEADER_SIZE];
JimCarver 0:6b753f761943 632 size_t data_length = QSPIF_SFDP_HEADER_SIZE;
JimCarver 0:6b753f761943 633 bd_addr_t addr = 0x0;
JimCarver 0:6b753f761943 634
JimCarver 0:6b753f761943 635 // Set 1-1-1 bus mode for SFDP header parsing
JimCarver 0:6b753f761943 636 _qspiConfiureFormat( QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_SINGLE, QSPI_CFG_ADDR_SIZE_24, QSPI_CFG_BUS_SINGLE,
JimCarver 0:6b753f761943 637 QSPI_CFG_ALT_SIZE_8, QSPI_CFG_BUS_SINGLE, 8);
JimCarver 0:6b753f761943 638
JimCarver 0:6b753f761943 639 qspi_status_t status = _qspiSendReadCommand(QSPIF_SFDP, (char *)sfdp_header, addr /*address*/, data_length);
JimCarver 0:6b753f761943 640 if (status != QSPI_STATUS_OK) {
JimCarver 0:6b753f761943 641 QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: init - Read SFDP Failed");
JimCarver 0:6b753f761943 642 return -1;
JimCarver 0:6b753f761943 643 }
JimCarver 0:6b753f761943 644
JimCarver 0:6b753f761943 645
JimCarver 0:6b753f761943 646 QSPIF_LOG(QSPIF_DEBUG_DEBUG, "DEBUG11: Read SFDP Header: %x %x %x %x %x %x %x %x\n", sfdp_header[0],
JimCarver 0:6b753f761943 647 sfdp_header[1],
JimCarver 0:6b753f761943 648 sfdp_header[2],
JimCarver 0:6b753f761943 649 sfdp_header[3],
JimCarver 0:6b753f761943 650 sfdp_header[4],
JimCarver 0:6b753f761943 651 sfdp_header[5],
JimCarver 0:6b753f761943 652 sfdp_header[6],
JimCarver 0:6b753f761943 653 sfdp_header[7]);
JimCarver 0:6b753f761943 654
JimCarver 0:6b753f761943 655
JimCarver 0:6b753f761943 656 // Verify SFDP signature for sanity
JimCarver 0:6b753f761943 657 // Also check that major/minor version is acceptable
JimCarver 0:6b753f761943 658 if (!(memcmp(&sfdp_header[0], "SFDP", 4) == 0 && sfdp_header[5] == 1)) {
JimCarver 0:6b753f761943 659 QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: init - _verify SFDP signature and version Failed");
JimCarver 0:6b753f761943 660 return -1;
JimCarver 0:6b753f761943 661 } else {
JimCarver 0:6b753f761943 662 QSPIF_LOG(QSPIF_DEBUG_INFO, "INFO: init - verified SFDP Signature and version Successfully");
JimCarver 0:6b753f761943 663 }
JimCarver 0:6b753f761943 664
JimCarver 0:6b753f761943 665 // Discover Number of Parameter Headers
JimCarver 0:6b753f761943 666 int number_of_param_headers = (int)(sfdp_header[6]) + 1;
JimCarver 0:6b753f761943 667 QSPIF_LOG(QSPIF_DEBUG_DEBUG, "DEBUG: number of Param Headers: %d", number_of_param_headers);
JimCarver 0:6b753f761943 668
JimCarver 0:6b753f761943 669
JimCarver 0:6b753f761943 670 addr += QSPIF_SFDP_HEADER_SIZE;
JimCarver 0:6b753f761943 671 data_length = QSPIF_PARAM_HEADER_SIZE;
JimCarver 0:6b753f761943 672
JimCarver 0:6b753f761943 673 // Loop over Param Headers and parse them (currently supported Basic Param Table and Sector Region Map Table)
JimCarver 0:6b753f761943 674 for (int i_ind = 0; i_ind < number_of_param_headers; i_ind++) {
JimCarver 0:6b753f761943 675
JimCarver 0:6b753f761943 676 status = _qspiSendReadCommand(QSPIF_SFDP, (char *)param_header, addr, data_length);
JimCarver 0:6b753f761943 677 if (status != QSPI_STATUS_OK) {
JimCarver 0:6b753f761943 678 QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: init - Read Param Table %d Failed", i_ind + 1);
JimCarver 0:6b753f761943 679 return -1;
JimCarver 0:6b753f761943 680 }
JimCarver 0:6b753f761943 681 // The SFDP spec indicates the standard table is always at offset 0
JimCarver 0:6b753f761943 682 // in the parameter headers, we check just to be safe
JimCarver 0:6b753f761943 683 if (param_header[2] != 1) {
JimCarver 0:6b753f761943 684 QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: Param Table %d - Major Version should be 1!", i_ind + 1);
JimCarver 0:6b753f761943 685 return -1;
JimCarver 0:6b753f761943 686 }
JimCarver 0:6b753f761943 687
JimCarver 0:6b753f761943 688 if ((param_header[0] == 0) && (param_header[7] == 0xFF)) {
JimCarver 0:6b753f761943 689 // Found Basic Params Table: LSB=0x00, MSB=0xFF
JimCarver 0:6b753f761943 690 QSPIF_LOG(QSPIF_DEBUG_DEBUG, "DEBUG: Found Basic Param Table at Table: %d", i_ind + 1);
JimCarver 0:6b753f761943 691 basic_table_addr = ( (param_header[6] << 16) | (param_header[5] << 8) | (param_header[4]) );
JimCarver 0:6b753f761943 692 // Supporting up to 64 Bytes Table (16 DWORDS)
JimCarver 0:6b753f761943 693 basic_table_size = ((param_header[3] * 4) < SFDP_DEFAULT_BASIC_PARAMS_TABLE_SIZE_BYTES) ? (param_header[11] * 4) : 64;
JimCarver 0:6b753f761943 694
JimCarver 0:6b753f761943 695 } else if ((param_header[0] == 81) && (param_header[7] == 0xFF)) {
JimCarver 0:6b753f761943 696 // Found Sector Map Table: LSB=0x81, MSB=0xFF
JimCarver 0:6b753f761943 697 QSPIF_LOG(QSPIF_DEBUG_DEBUG, "DEBUG: Found Sector Map Table at Table: %d", i_ind + 1);
JimCarver 0:6b753f761943 698 sector_map_table_addr = ( (param_header[6] << 16) | (param_header[5] << 8) | (param_header[4]) );
JimCarver 0:6b753f761943 699
JimCarver 0:6b753f761943 700 sector_map_table_size = param_header[3] * 4;
JimCarver 0:6b753f761943 701
JimCarver 0:6b753f761943 702 }
JimCarver 0:6b753f761943 703 addr += QSPIF_PARAM_HEADER_SIZE;
JimCarver 0:6b753f761943 704
JimCarver 0:6b753f761943 705 }
JimCarver 0:6b753f761943 706 return 0;
JimCarver 0:6b753f761943 707 }
JimCarver 0:6b753f761943 708
JimCarver 0:6b753f761943 709
JimCarver 0:6b753f761943 710
JimCarver 0:6b753f761943 711 int QSPIFBlockDevice::_sfdpSetQPIEnabled(uint8_t *basicParamTablePtr)
JimCarver 0:6b753f761943 712 {
JimCarver 0:6b753f761943 713 uint8_t config_reg[1];
JimCarver 0:6b753f761943 714
JimCarver 0:6b753f761943 715 // QPI 4-4-4 Enable Procedure is specified in 5 Bits
JimCarver 0:6b753f761943 716 uint8_t en_seq_444_value = ( ((basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_444_MODE_EN_SEQ_BYTE] & 0xF0) >> 4) | ((
JimCarver 0:6b753f761943 717 basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_444_MODE_EN_SEQ_BYTE + 1] & 0x01) << 4 ));
JimCarver 0:6b753f761943 718
JimCarver 0:6b753f761943 719 switch (en_seq_444_value) {
JimCarver 0:6b753f761943 720 case 1:
JimCarver 0:6b753f761943 721 case 2:
JimCarver 0:6b753f761943 722 QSPIF_LOG(QSPIF_DEBUG_DEBUG, "DEBUG: _setQPIEnabled - send command 38h");
JimCarver 0:6b753f761943 723 /*if (_setWriteEnable() != 0) {
JimCarver 0:6b753f761943 724 printf("ERROR: Write Enabe failed\n");
JimCarver 0:6b753f761943 725 return -1;
JimCarver 0:6b753f761943 726 }
JimCarver 0:6b753f761943 727 if( false == _isMemReady()) {
JimCarver 0:6b753f761943 728 printf("ERROR: Device not ready, write failed\n");
JimCarver 0:6b753f761943 729 return -1;
JimCarver 0:6b753f761943 730 }*/
JimCarver 0:6b753f761943 731
JimCarver 0:6b753f761943 732 _qspiSendGeneralCommand(0x38, -1, NULL, 0, NULL, 0);
JimCarver 0:6b753f761943 733 /*wait_ms(QSPI_STATUS_REGISTER_WRITE_TIMEOUT_MSEC);
JimCarver 0:6b753f761943 734 if( false == _isMemReady()) {
JimCarver 0:6b753f761943 735 printf("ERROR: Device not ready after write, failed\n");
JimCarver 0:6b753f761943 736 return -1;
JimCarver 0:6b753f761943 737 }*/
JimCarver 0:6b753f761943 738
JimCarver 0:6b753f761943 739
JimCarver 0:6b753f761943 740 break;
JimCarver 0:6b753f761943 741
JimCarver 0:6b753f761943 742 case 4:
JimCarver 0:6b753f761943 743 QSPIF_LOG(QSPIF_DEBUG_DEBUG, "DEBUG: _setQPIEnabled - send command 35h");
JimCarver 0:6b753f761943 744 _qspiSendGeneralCommand(0x35, -1, NULL, 0, NULL, 0);
JimCarver 0:6b753f761943 745 break;
JimCarver 0:6b753f761943 746
JimCarver 0:6b753f761943 747 case 8:
JimCarver 0:6b753f761943 748 QSPIF_LOG(QSPIF_DEBUG_DEBUG, "DEBUG: _setQPIEnabled - set config bit 6 and send command 71h");
JimCarver 0:6b753f761943 749 _qspiSendGeneralCommand(0x65, 0x800003, NULL, 0, (char *)config_reg, 1);
JimCarver 0:6b753f761943 750 config_reg[1] |= 0x40; //Set Bit 6
JimCarver 0:6b753f761943 751 _qspiSendGeneralCommand(0x71, 0x800003, NULL, 0, (char *)config_reg, 1);
JimCarver 0:6b753f761943 752 break;
JimCarver 0:6b753f761943 753
JimCarver 0:6b753f761943 754 case 16:
JimCarver 0:6b753f761943 755 QSPIF_LOG(QSPIF_DEBUG_DEBUG, "DEBUG: _setQPIEnabled - reset config bits 0-7 and send command 61h");
JimCarver 0:6b753f761943 756 _qspiSendGeneralCommand(0x65, -1, NULL, 0, (char *)config_reg, 1);
JimCarver 0:6b753f761943 757 config_reg[1] &= 0x7F; //Reset Bit 7 of CR
JimCarver 0:6b753f761943 758
JimCarver 0:6b753f761943 759
JimCarver 0:6b753f761943 760
JimCarver 0:6b753f761943 761
JimCarver 0:6b753f761943 762 /*
JimCarver 0:6b753f761943 763 if (_setWriteEnable() != 0) {
JimCarver 0:6b753f761943 764 printf("ERROR: Write Enabe failed\n");
JimCarver 0:6b753f761943 765 return -1;
JimCarver 0:6b753f761943 766 }
JimCarver 0:6b753f761943 767 if( false == _isMemReady()) {
JimCarver 0:6b753f761943 768 printf("ERROR: Device not ready, write failed\n");
JimCarver 0:6b753f761943 769 return -1;
JimCarver 0:6b753f761943 770 }*/
JimCarver 0:6b753f761943 771
JimCarver 0:6b753f761943 772 _qspiSendGeneralCommand(0x61, -1, NULL, 0, (char *)config_reg, 1);
JimCarver 0:6b753f761943 773
JimCarver 0:6b753f761943 774
JimCarver 0:6b753f761943 775 /* wait_ms(QSPI_STATUS_REGISTER_WRITE_TIMEOUT_MSEC);
JimCarver 0:6b753f761943 776 if( false == _isMemReady()) {
JimCarver 0:6b753f761943 777 printf("ERROR: Device not ready after write, failed\n");
JimCarver 0:6b753f761943 778 return -1;
JimCarver 0:6b753f761943 779 }
JimCarver 0:6b753f761943 780
JimCarver 0:6b753f761943 781
JimCarver 0:6b753f761943 782
JimCarver 0:6b753f761943 783 _qspiSendGeneralCommand(0x65, -1, NULL, 0, (char *)config_reg, 1);
JimCarver 0:6b753f761943 784
JimCarver 0:6b753f761943 785 if (_setWriteEnable() != 0) {
JimCarver 0:6b753f761943 786 printf("ERROR: Write Enabe failed\n");
JimCarver 0:6b753f761943 787 return -1;
JimCarver 0:6b753f761943 788 }
JimCarver 0:6b753f761943 789 if( false == _isMemReady()) {
JimCarver 0:6b753f761943 790 printf("ERROR: Device not ready, write failed\n");
JimCarver 0:6b753f761943 791 return -1;
JimCarver 0:6b753f761943 792 }
JimCarver 0:6b753f761943 793 config_reg[1] = 0x00; //Reset Bits 0-7
JimCarver 0:6b753f761943 794 _qspiSendGeneralCommand(0x61, -1, NULL, 0, (char *)config_reg, 1);
JimCarver 0:6b753f761943 795 wait_ms(QSPI_STATUS_REGISTER_WRITE_TIMEOUT_MSEC);*/
JimCarver 0:6b753f761943 796 /* if( false == _isMemReady()) {
JimCarver 0:6b753f761943 797 printf("ERROR: Device not ready after write, failed\n");
JimCarver 0:6b753f761943 798 return -1;
JimCarver 0:6b753f761943 799 }*/
JimCarver 0:6b753f761943 800
JimCarver 0:6b753f761943 801 break;
JimCarver 0:6b753f761943 802
JimCarver 0:6b753f761943 803 default:
JimCarver 0:6b753f761943 804 QSPIF_LOG(QSPIF_DEBUG_WARNING, "WARNING: _setQPIEnabled - Unsuported En Seq 444 configuration");
JimCarver 0:6b753f761943 805 break;
JimCarver 0:6b753f761943 806
JimCarver 0:6b753f761943 807
JimCarver 0:6b753f761943 808 }
JimCarver 0:6b753f761943 809
JimCarver 0:6b753f761943 810 return 0;
JimCarver 0:6b753f761943 811 }
JimCarver 0:6b753f761943 812
JimCarver 0:6b753f761943 813
JimCarver 0:6b753f761943 814
JimCarver 0:6b753f761943 815 int QSPIFBlockDevice::_sfdpSetQuadEnabled(uint8_t *basicParamTablePtr)
JimCarver 0:6b753f761943 816 {
JimCarver 0:6b753f761943 817
JimCarver 0:6b753f761943 818 int sr_read_size = QSPI_MAX_STATUS_REGISTER_SIZE;
JimCarver 0:6b753f761943 819 int sr_write_size = QSPI_MAX_STATUS_REGISTER_SIZE;
JimCarver 0:6b753f761943 820
JimCarver 0:6b753f761943 821 int status_reg_setup[QSPI_MAX_STATUS_REGISTER_SIZE];
JimCarver 0:6b753f761943 822 uint8_t status_reg[QSPI_MAX_STATUS_REGISTER_SIZE];
JimCarver 0:6b753f761943 823 unsigned int writeRegisterInst = QSPIF_WRSR;
JimCarver 0:6b753f761943 824 unsigned int readRegisterInst = QSPIF_RDSR;
JimCarver 0:6b753f761943 825
JimCarver 0:6b753f761943 826 uint8_t qer_value = (basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_QER_BYTE] & 0x70) >> 4;
JimCarver 0:6b753f761943 827
JimCarver 0:6b753f761943 828
JimCarver 0:6b753f761943 829
JimCarver 0:6b753f761943 830 switch (qer_value) {
JimCarver 0:6b753f761943 831 case 0:
JimCarver 0:6b753f761943 832 QSPIF_LOG(QSPIF_DEBUG_DEBUG, "DEBUG: Device Does not Have a QE Bit, continue based on Read Inst");
JimCarver 0:6b753f761943 833 return 0;
JimCarver 0:6b753f761943 834
JimCarver 0:6b753f761943 835 case 1:
JimCarver 0:6b753f761943 836 case 4:
JimCarver 0:6b753f761943 837 status_reg_setup[0] = 0;
JimCarver 0:6b753f761943 838 status_reg_setup[1] = 0x02;
JimCarver 0:6b753f761943 839 QSPIF_LOG(QSPIF_DEBUG_DEBUG, "DEBUG: Setting QE Bit, Bit 1 of Status Reg 2");
JimCarver 0:6b753f761943 840 break;
JimCarver 0:6b753f761943 841
JimCarver 0:6b753f761943 842 case 2:
JimCarver 0:6b753f761943 843 status_reg_setup[0] = 0x40;
JimCarver 0:6b753f761943 844 status_reg_setup[1] = 0;
JimCarver 0:6b753f761943 845 sr_write_size = 1;
JimCarver 0:6b753f761943 846 sr_read_size = 1;
JimCarver 0:6b753f761943 847 QSPIF_LOG(QSPIF_DEBUG_DEBUG, "DEBUG: Setting QE Bit, Bit 6 of Status Reg 1");
JimCarver 0:6b753f761943 848 break;
JimCarver 0:6b753f761943 849
JimCarver 0:6b753f761943 850 case 3:
JimCarver 0:6b753f761943 851 status_reg_setup[0] = 0x80; // Bit 7 of Status Reg 1
JimCarver 0:6b753f761943 852 status_reg_setup[1] = 0;
JimCarver 0:6b753f761943 853 sr_write_size = 1;
JimCarver 0:6b753f761943 854 sr_read_size = 1;
JimCarver 0:6b753f761943 855 writeRegisterInst = 0x3E;
JimCarver 0:6b753f761943 856 readRegisterInst = 0x3F;
JimCarver 0:6b753f761943 857 QSPIF_LOG(QSPIF_DEBUG_DEBUG, "DEBUG: Setting QE Bit, Bit 7 of Status Reg 1");
JimCarver 0:6b753f761943 858 break;
JimCarver 0:6b753f761943 859 case 5:
JimCarver 0:6b753f761943 860 status_reg_setup[0] = 0;
JimCarver 0:6b753f761943 861 status_reg_setup[1] = 0x02;
JimCarver 0:6b753f761943 862 readRegisterInst = 0x35;
JimCarver 0:6b753f761943 863 sr_read_size = 1;
JimCarver 0:6b753f761943 864 QSPIF_LOG(QSPIF_DEBUG_DEBUG, "DEBUG: Setting QE Bit, Bit 1 of Status Reg 2 -special read command");
JimCarver 0:6b753f761943 865 break;
JimCarver 0:6b753f761943 866 default:
JimCarver 0:6b753f761943 867 QSPIF_LOG(QSPIF_DEBUG_WARNING, "WARNING: _setQuadEnable - Unsuported QER configuration");
JimCarver 0:6b753f761943 868 break;
JimCarver 0:6b753f761943 869
JimCarver 0:6b753f761943 870
JimCarver 0:6b753f761943 871 }
JimCarver 0:6b753f761943 872
JimCarver 0:6b753f761943 873 // Read Status Register
JimCarver 0:6b753f761943 874 if (QSPI_STATUS_OK == _qspiSendGeneralCommand(readRegisterInst, -1, NULL, 0, (char *)status_reg,
JimCarver 0:6b753f761943 875 sr_read_size) ) { // store received values in status_value
JimCarver 0:6b753f761943 876 QSPIF_LOG(QSPIF_DEBUG_DEBUG, "DEBUG: Reading Status Register Success: value = 0x%x\n", (int)status_reg[0]);
JimCarver 0:6b753f761943 877 } else {
JimCarver 0:6b753f761943 878 QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: Reading Status Register failed");
JimCarver 0:6b753f761943 879 return -1;
JimCarver 0:6b753f761943 880 }
JimCarver 0:6b753f761943 881
JimCarver 0:6b753f761943 882 // Set Bits for Quad Enable
JimCarver 0:6b753f761943 883 status_reg[0] |= status_reg_setup[0];
JimCarver 0:6b753f761943 884 status_reg[1] |= status_reg_setup[1];
JimCarver 0:6b753f761943 885
JimCarver 0:6b753f761943 886
JimCarver 0:6b753f761943 887 // Write new Status Register Setup
JimCarver 0:6b753f761943 888 if (_setWriteEnable() != 0) {
JimCarver 0:6b753f761943 889 QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: Write Enabe failed\n");
JimCarver 0:6b753f761943 890 return -1;
JimCarver 0:6b753f761943 891 }
JimCarver 0:6b753f761943 892
JimCarver 0:6b753f761943 893 if ( false == _isMemReady()) {
JimCarver 0:6b753f761943 894 QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: Device not ready, write failed");
JimCarver 0:6b753f761943 895 return -1;
JimCarver 0:6b753f761943 896 }
JimCarver 0:6b753f761943 897
JimCarver 0:6b753f761943 898 if (QSPI_STATUS_OK == _qspiSendGeneralCommand(writeRegisterInst, -1, (char *)status_reg, sr_write_size, NULL,
JimCarver 0:6b753f761943 899 0) ) { // Write QE to status_register
JimCarver 0:6b753f761943 900 QSPIF_LOG(QSPIF_DEBUG_DEBUG, "DEBUG: _setQuadEnable - Writing Status Register Success: value = 0x%x",
JimCarver 0:6b753f761943 901 (int)status_reg[0]);
JimCarver 0:6b753f761943 902 } else {
JimCarver 0:6b753f761943 903 QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: _setQuadEnable - Writing Status Register failed");
JimCarver 0:6b753f761943 904 return -1;
JimCarver 0:6b753f761943 905 }
JimCarver 0:6b753f761943 906
JimCarver 0:6b753f761943 907 wait_ms(QSPI_STATUS_REGISTER_WRITE_TIMEOUT_MSEC);
JimCarver 0:6b753f761943 908
JimCarver 0:6b753f761943 909 if ( false == _isMemReady()) {
JimCarver 0:6b753f761943 910 QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: Device not ready after write, failed");
JimCarver 0:6b753f761943 911 return -1;
JimCarver 0:6b753f761943 912 }
JimCarver 0:6b753f761943 913
JimCarver 0:6b753f761943 914
JimCarver 0:6b753f761943 915 // For Debug
JimCarver 0:6b753f761943 916 memset(status_reg, 0, QSPI_MAX_STATUS_REGISTER_SIZE);
JimCarver 0:6b753f761943 917 if (QSPI_STATUS_OK == _qspiSendGeneralCommand(readRegisterInst, -1, NULL, 0, (char *)status_reg,
JimCarver 0:6b753f761943 918 sr_read_size) ) { // store received values in status_value
JimCarver 0:6b753f761943 919 QSPIF_LOG(QSPIF_DEBUG_DEBUG, "DEBUG: Reading Status Register Success: value = 0x%x\n", (int)status_reg[0]);
JimCarver 0:6b753f761943 920 } else {
JimCarver 0:6b753f761943 921 QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: Reading Status Register failed");
JimCarver 0:6b753f761943 922 return -1;
JimCarver 0:6b753f761943 923 }
JimCarver 0:6b753f761943 924
JimCarver 0:6b753f761943 925
JimCarver 0:6b753f761943 926 return 0;//((status_reg[0] & QSPI_STATUS_BIT_QE) != 0 ? 0 : -1);
JimCarver 0:6b753f761943 927 }
JimCarver 0:6b753f761943 928
JimCarver 0:6b753f761943 929
JimCarver 0:6b753f761943 930 int QSPIFBlockDevice::_sfdpDetectPageSize(uint8_t *basicParamTablePtr)
JimCarver 0:6b753f761943 931 {
JimCarver 0:6b753f761943 932 int page2PowerSize = ( (int)basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_PAGE_SIZE_BYTE]) >> 4;
JimCarver 0:6b753f761943 933 int pageSize = _utilsMathPower(2, page2PowerSize);
JimCarver 0:6b753f761943 934 QSPIF_LOG(QSPIF_DEBUG_DEBUG, "DEBUG: _detectPageSize - Page Size: %d", pageSize);
JimCarver 0:6b753f761943 935 return pageSize;
JimCarver 0:6b753f761943 936 }
JimCarver 0:6b753f761943 937
JimCarver 0:6b753f761943 938
JimCarver 0:6b753f761943 939
JimCarver 0:6b753f761943 940 int QSPIFBlockDevice::_sfdpDetectEraseTypesInstAndSize(uint8_t *basicParamTablePtr, unsigned int& erase4KInst,
JimCarver 0:6b753f761943 941 unsigned int *eraseTypeInstArr, unsigned int *eraseTypeSizeArr)
JimCarver 0:6b753f761943 942 {
JimCarver 0:6b753f761943 943 erase4KInst = 0xff;
JimCarver 0:6b753f761943 944 bool found4KEraseType = false;
JimCarver 0:6b753f761943 945 uint8_t bitfield = 0x01;
JimCarver 0:6b753f761943 946
JimCarver 0:6b753f761943 947 // Erase 4K Inst is taken either from param table legacy 4K erase or superseded by erase Instruction for type of size 4K
JimCarver 0:6b753f761943 948 erase4KInst = basicParamTablePtr[QSPIF_BASIC_PARAM_4K_ERASE_TYPE_BYTE];
JimCarver 0:6b753f761943 949
JimCarver 0:6b753f761943 950 // Loop Erase Types 1-4
JimCarver 0:6b753f761943 951 for (int i_ind = 0; i_ind < 4; i_ind++) {
JimCarver 0:6b753f761943 952 eraseTypeInstArr[i_ind] = 0xff; //0xFF default for unsupported type
JimCarver 0:6b753f761943 953 eraseTypeSizeArr[i_ind] = _utilsMathPower(2, basicParamTablePtr[QSPIF_BASIC_PARAM_ERASE_TYPE_1_SIZE_BYTE + 2 * i_ind]);
JimCarver 0:6b753f761943 954 if (eraseTypeSizeArr[i_ind] > 1) {
JimCarver 0:6b753f761943 955 // if size==1 type is not supported
JimCarver 0:6b753f761943 956 eraseTypeInstArr[i_ind] = basicParamTablePtr[QSPIF_BASIC_PARAM_ERASE_TYPE_1_BYTE + 2 * i_ind];
JimCarver 0:6b753f761943 957
JimCarver 0:6b753f761943 958 if ((eraseTypeSizeArr[i_ind] < _minCommonEraseSize) || (_minCommonEraseSize == 0) ) {
JimCarver 0:6b753f761943 959 //Set default minimal common erase for singal region
JimCarver 0:6b753f761943 960 _minCommonEraseSize = eraseTypeSizeArr[i_ind];
JimCarver 0:6b753f761943 961 }
JimCarver 0:6b753f761943 962
JimCarver 0:6b753f761943 963 if (eraseTypeSizeArr[i_ind] == 4096) {
JimCarver 0:6b753f761943 964 found4KEraseType = true;
JimCarver 0:6b753f761943 965 if (erase4KInst != eraseTypeInstArr[i_ind]) {
JimCarver 0:6b753f761943 966 //Verify 4KErase Type is identical to Legacy 4K erase type specified in Byte 1 of Param Table
JimCarver 0:6b753f761943 967 erase4KInst = eraseTypeInstArr[i_ind];
JimCarver 0:6b753f761943 968 QSPIF_LOG(QSPIF_DEBUG_WARNING,
JimCarver 0:6b753f761943 969 "WARNING: _detectEraseTypesInstAndSize - Default 4K erase Inst is different than erase type Inst for 4K");
JimCarver 0:6b753f761943 970
JimCarver 0:6b753f761943 971 }
JimCarver 0:6b753f761943 972 }
JimCarver 0:6b753f761943 973 _region_erase_types[0] |= bitfield; // If there's no region map, set region "0" types as defualt;
JimCarver 0:6b753f761943 974 }
JimCarver 0:6b753f761943 975
JimCarver 0:6b753f761943 976 QSPIF_LOG(QSPIF_DEBUG_DEBUG, "DEBUG: Erase Type %d - Inst: 0x%xh, Size: %d", (i_ind + 1), eraseTypeInstArr[i_ind],
JimCarver 0:6b753f761943 977 eraseTypeSizeArr[i_ind]);
JimCarver 0:6b753f761943 978 bitfield = bitfield << 1;
JimCarver 0:6b753f761943 979 }
JimCarver 0:6b753f761943 980
JimCarver 0:6b753f761943 981 if (false == found4KEraseType) {
JimCarver 0:6b753f761943 982 QSPIF_LOG(QSPIF_DEBUG_WARNING, "WARNING: Couldn't find Erase Type for 4KB size");
JimCarver 0:6b753f761943 983 }
JimCarver 0:6b753f761943 984 return 0;
JimCarver 0:6b753f761943 985 }
JimCarver 0:6b753f761943 986
JimCarver 0:6b753f761943 987
JimCarver 0:6b753f761943 988 int QSPIFBlockDevice::_sfdpDetectBestBusReadMode(uint8_t *basicParamTablePtr, bool& setQuadEnable, bool& isQPIMode,
JimCarver 0:6b753f761943 989 unsigned int& readInst)
JimCarver 0:6b753f761943 990 {
JimCarver 0:6b753f761943 991
JimCarver 0:6b753f761943 992 bool isDone = false;
JimCarver 0:6b753f761943 993
JimCarver 0:6b753f761943 994 setQuadEnable = false;
JimCarver 0:6b753f761943 995 isQPIMode = false;
JimCarver 0:6b753f761943 996 int dummyCycles = 0;
JimCarver 0:6b753f761943 997 uint8_t examinedByte = basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_QPI_READ_SUPPOR_BYTE];
JimCarver 0:6b753f761943 998
JimCarver 0:6b753f761943 999 do { // compound statement is the loop body
JimCarver 0:6b753f761943 1000
JimCarver 0:6b753f761943 1001
JimCarver 0:6b753f761943 1002
JimCarver 0:6b753f761943 1003 if (examinedByte & 0x10) {
JimCarver 0:6b753f761943 1004 // QPI 4-4-4 Supported
JimCarver 0:6b753f761943 1005 readInst = basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_444_READ_INST_BYTE];
JimCarver 0:6b753f761943 1006 setQuadEnable = true;
JimCarver 0:6b753f761943 1007 isQPIMode = true;
JimCarver 0:6b753f761943 1008 _dummy_and_mode_cycles = (basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_444_READ_INST_BYTE - 1] >> 5)
JimCarver 0:6b753f761943 1009 + (basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_444_READ_INST_BYTE - 1] & 0x1F);
JimCarver 0:6b753f761943 1010 QSPIF_LOG(QSPIF_DEBUG_DEBUG, "/nDEBUG: Read Bus Mode set to 4-4-4, Instruction: 0x%xh", _readInstruction);
JimCarver 0:6b753f761943 1011 //_inst_width = QSPI_CFG_BUS_QUAD;
JimCarver 0:6b753f761943 1012 _address_width = QSPI_CFG_BUS_QUAD;
JimCarver 0:6b753f761943 1013 _data_width = QSPI_CFG_BUS_QUAD;
JimCarver 0:6b753f761943 1014
JimCarver 0:6b753f761943 1015 break;
JimCarver 0:6b753f761943 1016 }
JimCarver 0:6b753f761943 1017
JimCarver 0:6b753f761943 1018
JimCarver 0:6b753f761943 1019 examinedByte = basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_FAST_READ_SUPPORT_BYTE];
JimCarver 0:6b753f761943 1020 if (examinedByte & 0x40) {
JimCarver 0:6b753f761943 1021 // Fast Read 1-4-4 Supported
JimCarver 0:6b753f761943 1022 readInst = basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_144_READ_INST_BYTE];
JimCarver 0:6b753f761943 1023 setQuadEnable = true;
JimCarver 0:6b753f761943 1024 // dummy cycles + mode cycles = Dummy Cycles
JimCarver 0:6b753f761943 1025 _dummy_and_mode_cycles = (basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_144_READ_INST_BYTE - 1] >> 5)
JimCarver 0:6b753f761943 1026 + (basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_144_READ_INST_BYTE - 1] & 0x1F);
JimCarver 0:6b753f761943 1027 _address_width = QSPI_CFG_BUS_QUAD;
JimCarver 0:6b753f761943 1028 _data_width = QSPI_CFG_BUS_QUAD;
JimCarver 0:6b753f761943 1029 QSPIF_LOG(QSPIF_DEBUG_DEBUG, "/nDEBUG: Read Bus Mode set to 1-4-4, Instruction: 0x%xh", _readInstruction);
JimCarver 0:6b753f761943 1030 break;
JimCarver 0:6b753f761943 1031 }
JimCarver 0:6b753f761943 1032 if (examinedByte & 0x80) {
JimCarver 0:6b753f761943 1033 // Fast Read 1-1-4 Supported
JimCarver 0:6b753f761943 1034 readInst = basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_114_READ_INST_BYTE];
JimCarver 0:6b753f761943 1035 setQuadEnable = true;
JimCarver 0:6b753f761943 1036 _dummy_and_mode_cycles = (basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_114_READ_INST_BYTE - 1] >> 5)
JimCarver 0:6b753f761943 1037 + (basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_114_READ_INST_BYTE - 1] & 0x1F);
JimCarver 0:6b753f761943 1038 _data_width = QSPI_CFG_BUS_QUAD;
JimCarver 0:6b753f761943 1039 QSPIF_LOG(QSPIF_DEBUG_DEBUG, "/nDEBUG: Read Bus Mode set to 1-1-4, Instruction: 0x%xh", _readInstruction);
JimCarver 0:6b753f761943 1040 break;
JimCarver 0:6b753f761943 1041 }
JimCarver 0:6b753f761943 1042 examinedByte = basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_QPI_READ_SUPPOR_BYTE];
JimCarver 0:6b753f761943 1043 if (examinedByte & 0x01) {
JimCarver 0:6b753f761943 1044 // Fast Read 2-2-2 Supported
JimCarver 0:6b753f761943 1045 readInst = basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_222_READ_INST_BYTE];
JimCarver 0:6b753f761943 1046 _dummy_and_mode_cycles = (basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_222_READ_INST_BYTE - 1] >> 5)
JimCarver 0:6b753f761943 1047 + (basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_222_READ_INST_BYTE - 1] & 0x1F);
JimCarver 0:6b753f761943 1048 _address_width = QSPI_CFG_BUS_DUAL;
JimCarver 0:6b753f761943 1049 _data_width = QSPI_CFG_BUS_DUAL;
JimCarver 0:6b753f761943 1050 QSPIF_LOG(QSPIF_DEBUG_INFO, "/nINFO: Read Bus Mode set to 2-2-2, Instruction: 0x%xh", _readInstruction);
JimCarver 0:6b753f761943 1051 break;
JimCarver 0:6b753f761943 1052 }
JimCarver 0:6b753f761943 1053
JimCarver 0:6b753f761943 1054 examinedByte = basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_FAST_READ_SUPPORT_BYTE];
JimCarver 0:6b753f761943 1055 if (examinedByte & 0x20) {
JimCarver 0:6b753f761943 1056 // Fast Read 1-2-2 Supported
JimCarver 0:6b753f761943 1057 readInst = basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_122_READ_INST_BYTE];
JimCarver 0:6b753f761943 1058 _dummy_and_mode_cycles = (basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_122_READ_INST_BYTE - 1] >> 5)
JimCarver 0:6b753f761943 1059 + (basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_122_READ_INST_BYTE - 1] & 0x1F);
JimCarver 0:6b753f761943 1060 _address_width = QSPI_CFG_BUS_DUAL;
JimCarver 0:6b753f761943 1061 _data_width = QSPI_CFG_BUS_DUAL;
JimCarver 0:6b753f761943 1062 QSPIF_LOG(QSPIF_DEBUG_DEBUG, "/nDEBUG: Read Bus Mode set to 1-2-2, Instruction: 0x%xh", _readInstruction);
JimCarver 0:6b753f761943 1063 break;
JimCarver 0:6b753f761943 1064 }
JimCarver 0:6b753f761943 1065 if (examinedByte & 0x01) {
JimCarver 0:6b753f761943 1066 // Fast Read 1-1-2 Supported
JimCarver 0:6b753f761943 1067 readInst = basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_112_READ_INST_BYTE];
JimCarver 0:6b753f761943 1068 _dummy_and_mode_cycles = (basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_112_READ_INST_BYTE - 1] >> 5)
JimCarver 0:6b753f761943 1069 + (basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_112_READ_INST_BYTE - 1] & 0x1F);
JimCarver 0:6b753f761943 1070 _data_width = QSPI_CFG_BUS_DUAL;
JimCarver 0:6b753f761943 1071 QSPIF_LOG(QSPIF_DEBUG_DEBUG, "/nDEBUG: Read Bus Mode set to 1-1-2, Instruction: 0x%xh", _readInstruction);
JimCarver 0:6b753f761943 1072 break;
JimCarver 0:6b753f761943 1073 }
JimCarver 0:6b753f761943 1074 QSPIF_LOG(QSPIF_DEBUG_DEBUG, "/nDEBUG: Read Bus Mode set to 1-1-1, Instruction: 0x%xh", _readInstruction);
JimCarver 0:6b753f761943 1075 isDone = true;
JimCarver 0:6b753f761943 1076 } while (isDone == false);
JimCarver 0:6b753f761943 1077
JimCarver 0:6b753f761943 1078 return 0;
JimCarver 0:6b753f761943 1079 }
JimCarver 0:6b753f761943 1080
JimCarver 0:6b753f761943 1081
JimCarver 0:6b753f761943 1082 int QSPIFBlockDevice::_resetFlashMem()
JimCarver 0:6b753f761943 1083 {
JimCarver 0:6b753f761943 1084 int status = 0;
JimCarver 0:6b753f761943 1085 char status_value[2] = {0};
JimCarver 0:6b753f761943 1086 QSPIF_LOG(QSPIF_DEBUG_ERROR, "INFO: _resetFlashMem:\n");
JimCarver 0:6b753f761943 1087 //Read the Status Register from device
JimCarver 0:6b753f761943 1088 if (QSPI_STATUS_OK == _qspiSendGeneralCommand(QSPIF_RDSR, -1, NULL, 0, status_value,
JimCarver 0:6b753f761943 1089 1) ) { // store received values in status_value
JimCarver 0:6b753f761943 1090 QSPIF_LOG(QSPIF_DEBUG_DEBUG, "DEBUG: Reading Status Register Success: value = 0x%x\n", (int)status_value[0]);
JimCarver 0:6b753f761943 1091 } else {
JimCarver 0:6b753f761943 1092 QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: Reading Status Register failed\n");
JimCarver 0:6b753f761943 1093 status = -1;
JimCarver 0:6b753f761943 1094 }
JimCarver 0:6b753f761943 1095
JimCarver 0:6b753f761943 1096 if (0 == status) {
JimCarver 0:6b753f761943 1097 //Send Reset Enable
JimCarver 0:6b753f761943 1098 if (QSPI_STATUS_OK == _qspiSendGeneralCommand(QSPIF_RSTEN, -1, NULL, 0, NULL,
JimCarver 0:6b753f761943 1099 0) ) { // store received values in status_value
JimCarver 0:6b753f761943 1100 QSPIF_LOG(QSPIF_DEBUG_DEBUG, "DEBUG: Sending RSTEN Success\n");
JimCarver 0:6b753f761943 1101 } else {
JimCarver 0:6b753f761943 1102 QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: Sending RSTEN failed\n");
JimCarver 0:6b753f761943 1103 status = -1;
JimCarver 0:6b753f761943 1104 }
JimCarver 0:6b753f761943 1105
JimCarver 0:6b753f761943 1106
JimCarver 0:6b753f761943 1107 if (0 == status) {
JimCarver 0:6b753f761943 1108 //Send Reset
JimCarver 0:6b753f761943 1109 if (QSPI_STATUS_OK == _qspiSendGeneralCommand(QSPIF_RST, -1, NULL, 0, NULL,
JimCarver 0:6b753f761943 1110 0)) { // store received values in status_value
JimCarver 0:6b753f761943 1111 QSPIF_LOG(QSPIF_DEBUG_DEBUG, "DEBUG: Sending RST Success\n");
JimCarver 0:6b753f761943 1112 } else {
JimCarver 0:6b753f761943 1113 QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: Sending RST failed\n");
JimCarver 0:6b753f761943 1114 status = -1;
JimCarver 0:6b753f761943 1115 }
JimCarver 0:6b753f761943 1116
JimCarver 0:6b753f761943 1117 _isMemReady();
JimCarver 0:6b753f761943 1118 }
JimCarver 0:6b753f761943 1119 }
JimCarver 0:6b753f761943 1120
JimCarver 0:6b753f761943 1121 return status;
JimCarver 0:6b753f761943 1122 }
JimCarver 0:6b753f761943 1123
JimCarver 0:6b753f761943 1124
JimCarver 0:6b753f761943 1125 bool QSPIFBlockDevice::_isMemReady()
JimCarver 0:6b753f761943 1126 {
JimCarver 0:6b753f761943 1127 char status_value[2];
JimCarver 0:6b753f761943 1128 int retries = 0;
JimCarver 0:6b753f761943 1129 bool memReady = true;
JimCarver 0:6b753f761943 1130
JimCarver 0:6b753f761943 1131 do {
JimCarver 0:6b753f761943 1132 retries++;
JimCarver 0:6b753f761943 1133 //Read the Status Register from device
JimCarver 0:6b753f761943 1134 if (QSPI_STATUS_OK != _qspiSendGeneralCommand(QSPIF_RDSR, -1, NULL, 0, status_value,
JimCarver 0:6b753f761943 1135 2)) { // store received values in status_value
JimCarver 0:6b753f761943 1136 QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: Reading Status Register failed\n");
JimCarver 0:6b753f761943 1137 }
JimCarver 0:6b753f761943 1138 } while ( (status_value[0] & 0x1) != 0 && retries < 10000 );
JimCarver 0:6b753f761943 1139
JimCarver 0:6b753f761943 1140 if ((status_value[0] & 0x1) != 0) {
JimCarver 0:6b753f761943 1141 QSPIF_LOG(QSPIF_DEBUG_DEBUG, "ERROR: _isMemReady FALSE\n");
JimCarver 0:6b753f761943 1142 memReady = false;
JimCarver 0:6b753f761943 1143 }
JimCarver 0:6b753f761943 1144 return memReady;
JimCarver 0:6b753f761943 1145 }
JimCarver 0:6b753f761943 1146
JimCarver 0:6b753f761943 1147
JimCarver 0:6b753f761943 1148 int QSPIFBlockDevice::_setWriteEnable()
JimCarver 0:6b753f761943 1149 {
JimCarver 0:6b753f761943 1150 int status = 0;
JimCarver 0:6b753f761943 1151 if (QSPI_STATUS_OK != _qspiSendGeneralCommand(QSPIF_WREN, -1, NULL, 0, NULL, 0)) {
JimCarver 0:6b753f761943 1152 QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR:Sending WREN command FAILED\n");
JimCarver 0:6b753f761943 1153 status = -1;
JimCarver 0:6b753f761943 1154 }
JimCarver 0:6b753f761943 1155 return status;
JimCarver 0:6b753f761943 1156 }
JimCarver 0:6b753f761943 1157
JimCarver 0:6b753f761943 1158
JimCarver 0:6b753f761943 1159
JimCarver 0:6b753f761943 1160 /*********************************************/
JimCarver 0:6b753f761943 1161 /************* Utility Functions *************/
JimCarver 0:6b753f761943 1162 /*********************************************/
JimCarver 0:6b753f761943 1163 int QSPIFBlockDevice::_utilsMathPower(int base, int exp)
JimCarver 0:6b753f761943 1164 {
JimCarver 0:6b753f761943 1165 int result = 1;
JimCarver 0:6b753f761943 1166 while (exp) {
JimCarver 0:6b753f761943 1167 result *= base;
JimCarver 0:6b753f761943 1168 exp--;
JimCarver 0:6b753f761943 1169 }
JimCarver 0:6b753f761943 1170 return result;
JimCarver 0:6b753f761943 1171 }
JimCarver 0:6b753f761943 1172
JimCarver 0:6b753f761943 1173
JimCarver 0:6b753f761943 1174 int QSPIFBlockDevice::_utilsFindAddrRegion(int offset)
JimCarver 0:6b753f761943 1175 {
JimCarver 0:6b753f761943 1176 if ((offset > (int)_deviceSizeBytes) || (_regions_count == 0)) {
JimCarver 0:6b753f761943 1177 return -1;
JimCarver 0:6b753f761943 1178 }
JimCarver 0:6b753f761943 1179
JimCarver 0:6b753f761943 1180 if (_regions_count == 1) {
JimCarver 0:6b753f761943 1181 return 0;
JimCarver 0:6b753f761943 1182 }
JimCarver 0:6b753f761943 1183
JimCarver 0:6b753f761943 1184 for (int i_ind = _regions_count - 2; i_ind >= 0; i_ind--) {
JimCarver 0:6b753f761943 1185
JimCarver 0:6b753f761943 1186 if (offset > _region_high_boundary[i_ind]) {
JimCarver 0:6b753f761943 1187 return (i_ind + 1);
JimCarver 0:6b753f761943 1188 }
JimCarver 0:6b753f761943 1189 }
JimCarver 0:6b753f761943 1190 return -1;
JimCarver 0:6b753f761943 1191
JimCarver 0:6b753f761943 1192 }
JimCarver 0:6b753f761943 1193
JimCarver 0:6b753f761943 1194
JimCarver 0:6b753f761943 1195 int QSPIFBlockDevice::_utilsIterateNextLargestEraseType(uint8_t& bitfield, int size, int offset, int boundry)
JimCarver 0:6b753f761943 1196 {
JimCarver 0:6b753f761943 1197 uint8_t type_mask = 0x08;
JimCarver 0:6b753f761943 1198 int i_ind = 0;
JimCarver 0:6b753f761943 1199 int largestEraseType = 0;
JimCarver 0:6b753f761943 1200 for (i_ind = 3; i_ind >= 0; i_ind--) {
JimCarver 0:6b753f761943 1201 if (bitfield & type_mask) {
JimCarver 0:6b753f761943 1202 largestEraseType = i_ind;
JimCarver 0:6b753f761943 1203 if ( (size > _eraseTypeSizeArr[largestEraseType]) &&
JimCarver 0:6b753f761943 1204 ((boundry - offset) > _eraseTypeSizeArr[largestEraseType]) ) {
JimCarver 0:6b753f761943 1205 break;
JimCarver 0:6b753f761943 1206 } else {
JimCarver 0:6b753f761943 1207 bitfield &= ~type_mask;
JimCarver 0:6b753f761943 1208 }
JimCarver 0:6b753f761943 1209 }
JimCarver 0:6b753f761943 1210 type_mask = type_mask >> 1;
JimCarver 0:6b753f761943 1211 }
JimCarver 0:6b753f761943 1212
JimCarver 0:6b753f761943 1213 if (i_ind == 4) {
JimCarver 0:6b753f761943 1214 QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: no erase type was found for current region addr");
JimCarver 0:6b753f761943 1215 }
JimCarver 0:6b753f761943 1216 return largestEraseType;
JimCarver 0:6b753f761943 1217
JimCarver 0:6b753f761943 1218 }
JimCarver 0:6b753f761943 1219
JimCarver 0:6b753f761943 1220
JimCarver 0:6b753f761943 1221 /***************************************************/
JimCarver 0:6b753f761943 1222 /*********** QSPI Driver API Functions *************/
JimCarver 0:6b753f761943 1223 /***************************************************/
JimCarver 0:6b753f761943 1224
JimCarver 0:6b753f761943 1225 qspi_status_t QSPIFBlockDevice::_qspiSetFrequency(int freq)
JimCarver 0:6b753f761943 1226 {
JimCarver 0:6b753f761943 1227 return _qspi.set_frequency(freq);
JimCarver 0:6b753f761943 1228 }
JimCarver 0:6b753f761943 1229
JimCarver 0:6b753f761943 1230
JimCarver 0:6b753f761943 1231 qspi_status_t QSPIFBlockDevice::_qspiSendReadCommand(unsigned int readInst, void *buffer, bd_addr_t addr,
JimCarver 0:6b753f761943 1232 bd_size_t size)
JimCarver 0:6b753f761943 1233 {
JimCarver 0:6b753f761943 1234 // Check the address and size fit onto the chip.
JimCarver 0:6b753f761943 1235
JimCarver 0:6b753f761943 1236 /* OFR_DBG */
JimCarver 0:6b753f761943 1237 //MBED_ASSERT(is_valid_read(addr, size));
JimCarver 0:6b753f761943 1238
JimCarver 0:6b753f761943 1239 size_t bufLen = size;
JimCarver 0:6b753f761943 1240
JimCarver 0:6b753f761943 1241 if (_qspi.read( readInst, -1, (unsigned int )addr, (char *)buffer, &bufLen) != QSPI_STATUS_OK ) {
JimCarver 0:6b753f761943 1242 QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: Read failed");
JimCarver 0:6b753f761943 1243 return QSPI_STATUS_ERROR;
JimCarver 0:6b753f761943 1244 }
JimCarver 0:6b753f761943 1245
JimCarver 0:6b753f761943 1246 return QSPI_STATUS_OK;
JimCarver 0:6b753f761943 1247
JimCarver 0:6b753f761943 1248 }
JimCarver 0:6b753f761943 1249
JimCarver 0:6b753f761943 1250
JimCarver 0:6b753f761943 1251 qspi_status_t QSPIFBlockDevice::_qspiSendProgramCommand(unsigned int progInst, const void *buffer, bd_addr_t addr,
JimCarver 0:6b753f761943 1252 bd_size_t *size)
JimCarver 0:6b753f761943 1253 {
JimCarver 0:6b753f761943 1254 // Check the address and size fit onto the chip.
JimCarver 0:6b753f761943 1255 //MBED_ASSERT(is_valid_program(addr, (*size)));
JimCarver 0:6b753f761943 1256 qspi_status_t result = QSPI_STATUS_OK;
JimCarver 0:6b753f761943 1257
JimCarver 0:6b753f761943 1258 result = _qspi.write( progInst, -1, addr/*(((unsigned int)addr) & 0x00FFFF00)*/, (char *)buffer, (size_t *)size);
JimCarver 0:6b753f761943 1259 if (result != QSPI_STATUS_OK) {
JimCarver 0:6b753f761943 1260 QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: QSPI Write failed");
JimCarver 0:6b753f761943 1261 }
JimCarver 0:6b753f761943 1262
JimCarver 0:6b753f761943 1263 return result;
JimCarver 0:6b753f761943 1264 }
JimCarver 0:6b753f761943 1265
JimCarver 0:6b753f761943 1266
JimCarver 0:6b753f761943 1267 qspi_status_t QSPIFBlockDevice::_qspiSendEraseCommand(unsigned int eraseInst, bd_addr_t addr, bd_size_t size)
JimCarver 0:6b753f761943 1268 {
JimCarver 0:6b753f761943 1269 // Check the address and size fit onto the chip.
JimCarver 0:6b753f761943 1270 //MBED_ASSERT(is_valid_erase(addr, size));
JimCarver 0:6b753f761943 1271
JimCarver 0:6b753f761943 1272 qspi_status_t result = QSPI_STATUS_OK;
JimCarver 0:6b753f761943 1273
JimCarver 0:6b753f761943 1274 result = _qspi.command_transfer(eraseInst, // command to send
JimCarver 0:6b753f761943 1275 (((int)addr) & 0x00FFF000), // Align addr to 4096
JimCarver 0:6b753f761943 1276 NULL, // do not transmit
JimCarver 0:6b753f761943 1277 0, // do not transmit
JimCarver 0:6b753f761943 1278 NULL, // just receive two bytes of data
JimCarver 0:6b753f761943 1279 0); // store received values in status_value
JimCarver 0:6b753f761943 1280 if (QSPI_STATUS_OK != result) {
JimCarver 0:6b753f761943 1281 QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: QSPI Erase failed");
JimCarver 0:6b753f761943 1282 }
JimCarver 0:6b753f761943 1283
JimCarver 0:6b753f761943 1284 return result;
JimCarver 0:6b753f761943 1285
JimCarver 0:6b753f761943 1286 }
JimCarver 0:6b753f761943 1287
JimCarver 0:6b753f761943 1288
JimCarver 0:6b753f761943 1289 qspi_status_t QSPIFBlockDevice::_qspiSendGeneralCommand(unsigned int instruction, bd_addr_t addr, const char *tx_buffer,
JimCarver 0:6b753f761943 1290 size_t tx_length, const char *rx_buffer, size_t rx_length)
JimCarver 0:6b753f761943 1291 {
JimCarver 0:6b753f761943 1292
JimCarver 0:6b753f761943 1293
JimCarver 0:6b753f761943 1294 qspi_status_t status = _qspi.command_transfer(instruction, (int)addr, tx_buffer, tx_length, rx_buffer, rx_length);
JimCarver 0:6b753f761943 1295
JimCarver 0:6b753f761943 1296 if (QSPI_STATUS_OK != status) {
JimCarver 0:6b753f761943 1297 QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR:Sending Generic command: %x", instruction);
JimCarver 0:6b753f761943 1298 }
JimCarver 0:6b753f761943 1299
JimCarver 0:6b753f761943 1300 return status;
JimCarver 0:6b753f761943 1301 }
JimCarver 0:6b753f761943 1302
JimCarver 0:6b753f761943 1303
JimCarver 0:6b753f761943 1304 qspi_status_t QSPIFBlockDevice::_qspiConfiureFormat(qspi_bus_width_t inst_width, qspi_bus_width_t address_width,
JimCarver 0:6b753f761943 1305 qspi_address_size_t address_size, qspi_bus_width_t alt_width, qspi_alt_size_t alt_size, qspi_bus_width_t data_width,
JimCarver 0:6b753f761943 1306 int dummy_cycles)
JimCarver 0:6b753f761943 1307 {
JimCarver 0:6b753f761943 1308 _qspi.configure_format( inst_width, address_width, address_size, alt_width, alt_size, data_width, dummy_cycles);
JimCarver 0:6b753f761943 1309
JimCarver 0:6b753f761943 1310 return QSPI_STATUS_OK;
JimCarver 0:6b753f761943 1311 }
JimCarver 0:6b753f761943 1312
JimCarver 0:6b753f761943 1313
JimCarver 0:6b753f761943 1314
JimCarver 0:6b753f761943 1315
JimCarver 0:6b753f761943 1316