1/******************************************************************************* 2Copyright (C) Marvell International Ltd. and its affiliates 3 4This software file (the "File") is owned and distributed by Marvell 5International Ltd. and/or its affiliates ("Marvell") under the following 6alternative licensing terms. Once you have made an election to distribute the 7File under one of the following license alternatives, please (i) delete this 8introductory statement regarding license alternatives, (ii) delete the two 9license alternatives that you have not elected to use and (iii) preserve the 10Marvell copyright notice above. 11 12******************************************************************************** 13Marvell Commercial License Option 14 15If you received this File from Marvell and you have entered into a commercial 16license agreement (a "Commercial License") with Marvell, the File is licensed 17to you under the terms of the applicable Commercial License. 18 19******************************************************************************** 20Marvell GPL License Option 21 22If you received this File from Marvell, you may opt to use, redistribute and/or 23modify this File in accordance with the terms and conditions of the General 24Public License Version 2, June 1991 (the "GPL License"), a copy of which is 25available along with the File in the license.txt file or by writing to the Free 26Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 27on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 28 29THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 30WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 31DISCLAIMED. The GPL License provides additional details about this warranty 32disclaimer. 33******************************************************************************** 34Marvell BSD License Option 35 36If you received this File from Marvell, you may opt to use, redistribute and/or 37modify this File under the following licensing terms. 38Redistribution and use in source and binary forms, with or without modification, 39are permitted provided that the following conditions are met: 40 41 * Redistributions of source code must retain the above copyright notice, 42 this list of conditions and the following disclaimer. 43 44 * Redistributions in binary form must reproduce the above copyright 45 notice, this list of conditions and the following disclaimer in the 46 documentation and/or other materials provided with the distribution. 47 48 * Neither the name of Marvell nor the names of its contributors may be 49 used to endorse or promote products derived from this software without 50 specific prior written permission. 51 52THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 53ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 54WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 55DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 56ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 57(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 58LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 59ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 60(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 61SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 62 63*******************************************************************************/ 64#include "mvOs.h" 65#include "sflash/mvSFlash.h" 66#include "sflash/mvSFlashSpec.h" 67#include "spi/mvSpi.h" 68#include "spi/mvSpiCmnd.h" 69#include "ctrlEnv/mvCtrlEnvLib.h" 70 71/*#define MV_DEBUG*/ 72#ifdef MV_DEBUG 73#define DB(x) x 74#else 75#define DB(x) 76#endif 77 78/* Globals */ 79static MV_SFLASH_DEVICE_PARAMS sflash[] = { 80 /* ST M25P32 SPI flash, 4MB, 64 sectors of 64K each */ 81 { 82 MV_M25P_WREN_CMND_OPCD, 83 MV_M25P_WRDI_CMND_OPCD, 84 MV_M25P_RDID_CMND_OPCD, 85 MV_M25P_RDSR_CMND_OPCD, 86 MV_M25P_WRSR_CMND_OPCD, 87 MV_M25P_READ_CMND_OPCD, 88 MV_M25P_FAST_RD_CMND_OPCD, 89 MV_M25P_PP_CMND_OPCD, 90 MV_M25P_SE_CMND_OPCD, 91 MV_M25P_BE_CMND_OPCD, 92 MV_M25P_RES_CMND_OPCD, 93 MV_SFLASH_NO_SPECIFIC_OPCD, /* power save not supported */ 94 MV_M25P32_SECTOR_SIZE, 95 MV_M25P32_SECTOR_NUMBER, 96 MV_M25P_PAGE_SIZE, 97 "ST M25P32", 98 MV_M25PXXX_ST_MANF_ID, 99 MV_M25P32_DEVICE_ID, 100 MV_M25P32_MAX_SPI_FREQ, 101 MV_M25P32_MAX_FAST_SPI_FREQ, 102 MV_M25P32_FAST_READ_DUMMY_BYTES 103 }, 104 /* ST M25P64 SPI flash, 8MB, 128 sectors of 64K each */ 105 { 106 MV_M25P_WREN_CMND_OPCD, 107 MV_M25P_WRDI_CMND_OPCD, 108 MV_M25P_RDID_CMND_OPCD, 109 MV_M25P_RDSR_CMND_OPCD, 110 MV_M25P_WRSR_CMND_OPCD, 111 MV_M25P_READ_CMND_OPCD, 112 MV_M25P_FAST_RD_CMND_OPCD, 113 MV_M25P_PP_CMND_OPCD, 114 MV_M25P_SE_CMND_OPCD, 115 MV_M25P_BE_CMND_OPCD, 116 MV_M25P_RES_CMND_OPCD, 117 MV_SFLASH_NO_SPECIFIC_OPCD, /* power save not supported */ 118 MV_M25P64_SECTOR_SIZE, 119 MV_M25P64_SECTOR_NUMBER, 120 MV_M25P_PAGE_SIZE, 121 "ST M25P64", 122 MV_M25PXXX_ST_MANF_ID, 123 MV_M25P64_DEVICE_ID, 124 MV_M25P64_MAX_SPI_FREQ, 125 MV_M25P64_MAX_FAST_SPI_FREQ, 126 MV_M25P64_FAST_READ_DUMMY_BYTES 127 }, 128 /* ST M25P128 SPI flash, 16MB, 64 sectors of 256K each */ 129 { 130 MV_M25P_WREN_CMND_OPCD, 131 MV_M25P_WRDI_CMND_OPCD, 132 MV_M25P_RDID_CMND_OPCD, 133 MV_M25P_RDSR_CMND_OPCD, 134 MV_M25P_WRSR_CMND_OPCD, 135 MV_M25P_READ_CMND_OPCD, 136 MV_M25P_FAST_RD_CMND_OPCD, 137 MV_M25P_PP_CMND_OPCD, 138 MV_M25P_SE_CMND_OPCD, 139 MV_M25P_BE_CMND_OPCD, 140 MV_M25P_RES_CMND_OPCD, 141 MV_SFLASH_NO_SPECIFIC_OPCD, /* power save not supported */ 142 MV_M25P128_SECTOR_SIZE, 143 MV_M25P128_SECTOR_NUMBER, 144 MV_M25P_PAGE_SIZE, 145 "ST M25P128", 146 MV_M25PXXX_ST_MANF_ID, 147 MV_M25P128_DEVICE_ID, 148 MV_M25P128_MAX_SPI_FREQ, 149 MV_M25P128_MAX_FAST_SPI_FREQ, 150 MV_M25P128_FAST_READ_DUMMY_BYTES 151 }, 152 /* Macronix MXIC MX25L6405 SPI flash, 8MB, 128 sectors of 64K each */ 153 { 154 MV_MX25L_WREN_CMND_OPCD, 155 MV_MX25L_WRDI_CMND_OPCD, 156 MV_MX25L_RDID_CMND_OPCD, 157 MV_MX25L_RDSR_CMND_OPCD, 158 MV_MX25L_WRSR_CMND_OPCD, 159 MV_MX25L_READ_CMND_OPCD, 160 MV_MX25L_FAST_RD_CMND_OPCD, 161 MV_MX25L_PP_CMND_OPCD, 162 MV_MX25L_SE_CMND_OPCD, 163 MV_MX25L_BE_CMND_OPCD, 164 MV_MX25L_RES_CMND_OPCD, 165 MV_MX25L_DP_CMND_OPCD, 166 MV_MX25L6405_SECTOR_SIZE, 167 MV_MX25L6405_SECTOR_NUMBER, 168 MV_MXIC_PAGE_SIZE, 169 "MXIC MX25L6405", 170 MV_MXIC_MANF_ID, 171 MV_MX25L6405_DEVICE_ID, 172 MV_MX25L6405_MAX_SPI_FREQ, 173 MV_MX25L6405_MAX_FAST_SPI_FREQ, 174 MV_MX25L6405_FAST_READ_DUMMY_BYTES 175 }, 176 /* SPANSION S25FL128P SPI flash, 16MB, 64 sectors of 256K each */ 177 { 178 MV_S25FL_WREN_CMND_OPCD, 179 MV_S25FL_WRDI_CMND_OPCD, 180 MV_S25FL_RDID_CMND_OPCD, 181 MV_S25FL_RDSR_CMND_OPCD, 182 MV_S25FL_WRSR_CMND_OPCD, 183 MV_S25FL_READ_CMND_OPCD, 184 MV_S25FL_FAST_RD_CMND_OPCD, 185 MV_S25FL_PP_CMND_OPCD, 186 MV_S25FL_SE_CMND_OPCD, 187 MV_S25FL_BE_CMND_OPCD, 188 MV_S25FL_RES_CMND_OPCD, 189 MV_S25FL_DP_CMND_OPCD, 190 MV_S25FL128_SECTOR_SIZE, 191 MV_S25FL128_SECTOR_NUMBER, 192 MV_S25FL_PAGE_SIZE, 193 "SPANSION S25FL128", 194 MV_SPANSION_MANF_ID, 195 MV_S25FL128_DEVICE_ID, 196 MV_S25FL128_MAX_SPI_FREQ, 197 MV_M25P128_MAX_FAST_SPI_FREQ, 198 MV_M25P128_FAST_READ_DUMMY_BYTES 199 } 200}; 201 202/* Static Functions */ 203static MV_STATUS mvWriteEnable (MV_SFLASH_INFO * pFlinfo); 204static MV_STATUS mvStatusRegGet (MV_SFLASH_INFO * pFlinfo, MV_U8 * pStatReg); 205static MV_STATUS mvStatusRegSet (MV_SFLASH_INFO * pFlinfo, MV_U8 sr); 206static MV_STATUS mvWaitOnWipClear(MV_SFLASH_INFO * pFlinfo); 207static MV_STATUS mvSFlashPageWr (MV_SFLASH_INFO * pFlinfo, MV_U32 offset, \ 208 MV_U8* pPageBuff, MV_U32 buffSize); 209static MV_STATUS mvSFlashWithDefaultsIdGet (MV_SFLASH_INFO * pFlinfo, \ 210 MV_U8* manId, MV_U16* devId); 211 212/******************************************************************************* 213* mvWriteEnable - serialize the write enable sequence 214* 215* DESCRIPTION: 216* transmit the sequence for write enable 217* 218********************************************************************************/ 219static MV_STATUS mvWriteEnable(MV_SFLASH_INFO * pFlinfo) 220{ 221 MV_U8 cmd[MV_SFLASH_WREN_CMND_LENGTH]; 222 223 224 cmd[0] = sflash[pFlinfo->index].opcdWREN; 225 226 return mvSpiWriteThenRead(cmd, MV_SFLASH_WREN_CMND_LENGTH, NULL, 0, 0); 227} 228 229/******************************************************************************* 230* mvStatusRegGet - Retrieve the value of the status register 231* 232* DESCRIPTION: 233* perform the RDSR sequence to get the 8bit status register 234* 235********************************************************************************/ 236static MV_STATUS mvStatusRegGet(MV_SFLASH_INFO * pFlinfo, MV_U8 * pStatReg) 237{ 238 MV_STATUS ret; 239 MV_U8 cmd[MV_SFLASH_RDSR_CMND_LENGTH]; 240 MV_U8 sr[MV_SFLASH_RDSR_REPLY_LENGTH]; 241 242 243 244 245 cmd[0] = sflash[pFlinfo->index].opcdRDSR; 246 247 if ((ret = mvSpiWriteThenRead(cmd, MV_SFLASH_RDSR_CMND_LENGTH, sr, 248 MV_SFLASH_RDSR_REPLY_LENGTH,0)) != MV_OK) 249 return ret; 250 251 *pStatReg = sr[0]; 252 253 return MV_OK; 254} 255 256/******************************************************************************* 257* mvWaitOnWipClear - Block waiting for the WIP (write in progress) to be cleared 258* 259* DESCRIPTION: 260* Block waiting for the WIP (write in progress) to be cleared 261* 262********************************************************************************/ 263static MV_STATUS mvWaitOnWipClear(MV_SFLASH_INFO * pFlinfo) 264{ 265 MV_STATUS ret; 266 MV_U32 i; 267 MV_U8 stat; 268 269 for (i=0; i<MV_SFLASH_MAX_WAIT_LOOP; i++) 270 { 271 if ((ret = mvStatusRegGet(pFlinfo, &stat)) != MV_OK) 272 return ret; 273 274 if ((stat & MV_SFLASH_STATUS_REG_WIP_MASK) == 0) 275 return MV_OK; 276 } 277 278 DB(mvOsPrintf("%s WARNING: Write Timeout!\n", __FUNCTION__);) 279 return MV_TIMEOUT; 280} 281 282/******************************************************************************* 283* mvWaitOnChipEraseDone - Block waiting for the WIP (write in progress) to be 284* cleared after a chip erase command which is supposed 285* to take about 2:30 minutes 286* 287* DESCRIPTION: 288* Block waiting for the WIP (write in progress) to be cleared 289* 290********************************************************************************/ 291static MV_STATUS mvWaitOnChipEraseDone(MV_SFLASH_INFO * pFlinfo) 292{ 293 MV_STATUS ret; 294 MV_U32 i; 295 MV_U8 stat; 296 297 for (i=0; i<MV_SFLASH_CHIP_ERASE_MAX_WAIT_LOOP; i++) 298 { 299 if ((ret = mvStatusRegGet(pFlinfo, &stat)) != MV_OK) 300 return ret; 301 302 if ((stat & MV_SFLASH_STATUS_REG_WIP_MASK) == 0) 303 return MV_OK; 304 } 305 306 DB(mvOsPrintf("%s WARNING: Write Timeout!\n", __FUNCTION__);) 307 return MV_TIMEOUT; 308} 309 310/******************************************************************************* 311* mvStatusRegSet - Set the value of the 8bit status register 312* 313* DESCRIPTION: 314* Set the value of the 8bit status register 315* 316********************************************************************************/ 317static MV_STATUS mvStatusRegSet(MV_SFLASH_INFO * pFlinfo, MV_U8 sr) 318{ 319 MV_STATUS ret; 320 MV_U8 cmd[MV_SFLASH_WRSR_CMND_LENGTH]; 321 322 323 /* Issue the Write enable command prior the WRSR command */ 324 if ((ret = mvWriteEnable(pFlinfo)) != MV_OK) 325 return ret; 326 327 /* Write the SR with the new values */ 328 cmd[0] = sflash[pFlinfo->index].opcdWRSR; 329 cmd[1] = sr; 330 331 if ((ret = mvSpiWriteThenRead(cmd, MV_SFLASH_WRSR_CMND_LENGTH, NULL, 0, 0)) != MV_OK) 332 return ret; 333 334 if ((ret = mvWaitOnWipClear(pFlinfo)) != MV_OK) 335 return ret; 336 337 mvOsDelay(1); 338 339 return MV_OK; 340} 341 342/******************************************************************************* 343* mvSFlashPageWr - Write up to 256 Bytes in the same page 344* 345* DESCRIPTION: 346* Write a buffer up to the page size in length provided that the whole address 347* range is within the same page (alligned to page bounderies) 348* 349*******************************************************************************/ 350static MV_STATUS mvSFlashPageWr (MV_SFLASH_INFO * pFlinfo, MV_U32 offset, 351 MV_U8* pPageBuff, MV_U32 buffSize) 352{ 353 MV_STATUS ret; 354 MV_U8 cmd[MV_SFLASH_PP_CMND_LENGTH]; 355 356 357 /* Protection - check if the model was detected */ 358 if (pFlinfo->index >= MV_ARRAY_SIZE(sflash)) 359 { 360 DB(mvOsPrintf("%s WARNING: Invalid parameter device index!\n", __FUNCTION__);) 361 return MV_BAD_PARAM; 362 } 363 364 /* check that we do not cross the page bounderies */ 365 if (((offset & (sflash[pFlinfo->index].pageSize - 1)) + buffSize) > 366 sflash[pFlinfo->index].pageSize) 367 { 368 DB(mvOsPrintf("%s WARNING: Page allignment problem!\n", __FUNCTION__);) 369 return MV_OUT_OF_RANGE; 370 } 371 372 /* Issue the Write enable command prior the page program command */ 373 if ((ret = mvWriteEnable(pFlinfo)) != MV_OK) 374 return ret; 375 376 cmd[0] = sflash[pFlinfo->index].opcdPP; 377 cmd[1] = ((offset >> 16) & 0xFF); 378 cmd[2] = ((offset >> 8) & 0xFF); 379 cmd[3] = (offset & 0xFF); 380 381 if ((ret = mvSpiWriteThenWrite(cmd, MV_SFLASH_PP_CMND_LENGTH, pPageBuff, buffSize)) != MV_OK) 382 return ret; 383 384 if ((ret = mvWaitOnWipClear(pFlinfo)) != MV_OK) 385 return ret; 386 387 return MV_OK; 388} 389 390/******************************************************************************* 391* mvSFlashWithDefaultsIdGet - Try to read the manufacturer and Device IDs from 392* the device using the default RDID opcode and the default WREN opcode. 393* 394* DESCRIPTION: 395* This is used to detect a generic device that uses the default opcodes 396* for the WREN and RDID. 397* 398********************************************************************************/ 399static MV_STATUS mvSFlashWithDefaultsIdGet (MV_SFLASH_INFO * pFlinfo, MV_U8* manId, MV_U16* devId) 400{ 401 MV_STATUS ret; 402 MV_U8 cmdRDID[MV_SFLASH_RDID_CMND_LENGTH]; 403 MV_U8 id[MV_SFLASH_RDID_REPLY_LENGTH]; 404 405 406 407 /* Use the default RDID opcode to read the IDs */ 408 cmdRDID[0] = MV_SFLASH_DEFAULT_RDID_OPCD; /* unknown model try default */ 409 if ((ret = mvSpiWriteThenRead(cmdRDID, MV_SFLASH_RDID_CMND_LENGTH, id, MV_SFLASH_RDID_REPLY_LENGTH, 0)) != MV_OK) 410 return ret; 411 412 *manId = id[0]; 413 *devId = 0; 414 *devId |= (id[1] << 8); 415 *devId |= id[2]; 416 417 return MV_OK; 418} 419 420/* 421##################################################################################### 422##################################################################################### 423*/ 424 425/******************************************************************************* 426* mvSFlashInit - Initialize the serial flash device 427* 428* DESCRIPTION: 429* Perform the neccessary initialization and configuration 430* 431* INPUT: 432* pFlinfo: pointer to the Flash information structure 433* pFlinfo->baseAddr: base address in fast mode. 434* pFlinfo->index: Index of the flash in the sflash tabel. If the SPI 435* flash device does not support read Id command with 436* the standard opcode, then the user should supply this 437* as an input to skip the autodetection process!!!! 438* 439* OUTPUT: 440* pFlinfo: pointer to the Flash information structure after detection 441* pFlinfo->manufacturerId: Manufacturer ID 442* pFlinfo->deviceId: Device ID 443* pFlinfo->sectorSize: size of the sector (all sectors are the same). 444* pFlinfo->sectorNumber: number of sectors. 445* pFlinfo->pageSize: size of the page. 446* pFlinfo->index: Index of the detected flash in the sflash tabel 447* 448* RETURN: 449* Success or Error code. 450* 451* 452*******************************************************************************/ 453MV_STATUS mvSFlashInit (MV_SFLASH_INFO * pFlinfo) 454{ 455 MV_STATUS ret; 456 MV_U8 manf; 457 MV_U16 dev; 458 MV_U32 indx; 459 MV_BOOL detectFlag = MV_FALSE; 460 461 /* check for NULL pointer */ 462 if (pFlinfo == NULL) 463 { 464 mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__); 465 return MV_BAD_PARAM; 466 } 467 468 /* Initialize the SPI interface with low frequency to make sure that the read ID succeeds */ 469 if ((ret = mvSpiInit(MV_SFLASH_BASIC_SPI_FREQ)) != MV_OK) 470 { 471 mvOsPrintf("%s ERROR: Failed to initialize the SPI interface!\n", __FUNCTION__); 472 return ret; 473 } 474 475 /* First try to read the Manufacturer and Device IDs */ 476 if ((ret = mvSFlashIdGet(pFlinfo, &manf, &dev)) != MV_OK) 477 { 478 mvOsPrintf("%s ERROR: Failed to get the SFlash ID!\n", __FUNCTION__); 479 return ret; 480 } 481 482 /* loop over the whole table and look for the appropriate SFLASH */ 483 for (indx=0; indx<MV_ARRAY_SIZE(sflash); indx++) 484 { 485 if ((manf == sflash[indx].manufacturerId) && (dev == sflash[indx].deviceId)) 486 { 487 pFlinfo->manufacturerId = manf; 488 pFlinfo->deviceId = dev; 489 pFlinfo->index = indx; 490 detectFlag = MV_TRUE; 491 } 492 } 493 494 if(!detectFlag) 495 { 496 mvOsPrintf("%s ERROR: Unknown SPI flash device!\n", __FUNCTION__); 497 return MV_FAIL; 498 } 499 500 /* fill the info based on the model detected */ 501 pFlinfo->sectorSize = sflash[pFlinfo->index].sectorSize; 502 pFlinfo->sectorNumber = sflash[pFlinfo->index].sectorNumber; 503 pFlinfo->pageSize = sflash[pFlinfo->index].pageSize; 504 505 /* Set the SPI frequency to the MAX allowed for the device for best performance */ 506 if ((ret = mvSpiBaudRateSet(sflash[pFlinfo->index].spiMaxFreq)) != MV_OK) 507 { 508 mvOsPrintf("%s ERROR: Failed to set the SPI frequency!\n", __FUNCTION__); 509 return ret; 510 } 511 512 /* As default lock the SR */ 513 if ((ret = mvSFlashStatRegLock(pFlinfo, MV_TRUE)) != MV_OK) 514 return ret; 515 516 return MV_OK; 517} 518 519/******************************************************************************* 520* mvSFlashSectorErase - Erasse a single sector of the serial flash 521* 522* DESCRIPTION: 523* Issue the erase sector command and address 524* 525* INPUT: 526* pFlinfo: pointer to the Flash information structure 527* secNumber: sector Number to erase (0 -> (sectorNumber-1)) 528* 529* OUTPUT: 530* None 531* 532* RETURN: 533* Success or Error code. 534* 535* 536*******************************************************************************/ 537MV_STATUS mvSFlashSectorErase (MV_SFLASH_INFO * pFlinfo, MV_U32 secNumber) 538{ 539 MV_STATUS ret; 540 MV_U8 cmd[MV_SFLASH_SE_CMND_LENGTH]; 541 542 MV_U32 secAddr = (secNumber * pFlinfo->sectorSize); 543#if 0 544 MV_U32 i; 545 MV_U32 * pW = (MV_U32*) (secAddr + pFlinfo->baseAddr); 546 MV_U32 erasedWord = 0xFFFFFFFF; 547 MV_U32 wordsPerSector = (pFlinfo->sectorSize / sizeof(MV_U32)); 548 MV_BOOL eraseNeeded = MV_FALSE; 549#endif 550 /* check for NULL pointer */ 551 if (pFlinfo == NULL) 552 { 553 mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__); 554 return MV_BAD_PARAM; 555 } 556 557 /* Protection - check if the model was detected */ 558 if (pFlinfo->index >= MV_ARRAY_SIZE(sflash)) 559 { 560 DB(mvOsPrintf("%s WARNING: Invaild parameter index!\n", __FUNCTION__);) 561 return MV_BAD_PARAM; 562 } 563 564 /* check that the sector number is valid */ 565 if (secNumber >= pFlinfo->sectorNumber) 566 { 567 DB(mvOsPrintf("%s WARNING: Invaild parameter sector number!\n", __FUNCTION__);) 568 return MV_BAD_PARAM; 569 } 570 571 /* we don't want to access SPI in direct mode from in-direct API, 572 becasue of timing issue between CS asserts. */ 573#if 0 574 /* First compare to FF and check if erase is needed */ 575 for (i=0; i<wordsPerSector; i++) 576 { 577 if (memcmp(pW, &erasedWord, sizeof(MV_U32)) != 0) 578 { 579 eraseNeeded = MV_TRUE; 580 break; 581 } 582 583 ++pW; 584 } 585 if (!eraseNeeded) 586 return MV_OK; 587#endif 588 589 cmd[0] = sflash[pFlinfo->index].opcdSE; 590 cmd[1] = ((secAddr >> 16) & 0xFF); 591 cmd[2] = ((secAddr >> 8) & 0xFF); 592 cmd[3] = (secAddr & 0xFF); 593 594 /* Issue the Write enable command prior the sector erase command */ 595 if ((ret = mvWriteEnable(pFlinfo)) != MV_OK) 596 return ret; 597 598 if ((ret = mvSpiWriteThenWrite(cmd, MV_SFLASH_SE_CMND_LENGTH, NULL, 0)) != MV_OK) 599 return ret; 600 601 if ((ret = mvWaitOnWipClear(pFlinfo)) != MV_OK) 602 return ret; 603 604 return MV_OK; 605} 606 607/******************************************************************************* 608* mvSFlashChipErase - Erasse the whole serial flash 609* 610* DESCRIPTION: 611* Issue the bulk (chip) erase command 612* 613* INPUT: 614* pFlinfo: pointer to the Flash information structure 615* 616* OUTPUT: 617* None 618* 619* RETURN: 620* Success or Error code. 621* 622* 623*******************************************************************************/ 624MV_STATUS mvSFlashChipErase (MV_SFLASH_INFO * pFlinfo) 625{ 626 MV_STATUS ret; 627 MV_U8 cmd[MV_SFLASH_BE_CMND_LENGTH]; 628 629 630 /* check for NULL pointer */ 631 if (pFlinfo == NULL) 632 { 633 mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__); 634 return MV_BAD_PARAM; 635 } 636 637 /* Protection - check if the model was detected */ 638 if (pFlinfo->index >= MV_ARRAY_SIZE(sflash)) 639 { 640 DB(mvOsPrintf("%s WARNING: Invaild parameter index!\n", __FUNCTION__);) 641 return MV_BAD_PARAM; 642 } 643 644 cmd[0] = sflash[pFlinfo->index].opcdBE; 645 646 /* Issue the Write enable command prior the Bulk erase command */ 647 if ((ret = mvWriteEnable(pFlinfo)) != MV_OK) 648 return ret; 649 650 if ((ret = mvSpiWriteThenWrite(cmd, MV_SFLASH_BE_CMND_LENGTH, NULL, 0)) != MV_OK) 651 return ret; 652 653 if ((ret = mvWaitOnChipEraseDone(pFlinfo)) != MV_OK) 654 return ret; 655 656 return MV_OK; 657} 658 659/******************************************************************************* 660* mvSFlashBlockRd - Read from the serial flash 661* 662* DESCRIPTION: 663* Issue the read command and address then perfom the needed read 664* 665* INPUT: 666* pFlinfo: pointer to the Flash information structure 667* offset: byte offset with the flash to start reading from 668* pReadBuff: pointer to the buffer to read the data in 669* buffSize: size of the buffer to read. 670* 671* OUTPUT: 672* pReadBuff: pointer to the buffer containing the read data 673* 674* RETURN: 675* Success or Error code. 676* 677* 678*******************************************************************************/ 679MV_STATUS mvSFlashBlockRd (MV_SFLASH_INFO * pFlinfo, MV_U32 offset, 680 MV_U8* pReadBuff, MV_U32 buffSize) 681{ 682 MV_U8 cmd[MV_SFLASH_READ_CMND_LENGTH]; 683 684 685 /* check for NULL pointer */ 686 if ((pFlinfo == NULL) || (pReadBuff == NULL)) 687 { 688 mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__); 689 return MV_BAD_PARAM; 690 } 691 692 /* Protection - check if the model was detected */ 693 if (pFlinfo->index >= MV_ARRAY_SIZE(sflash)) 694 { 695 DB(mvOsPrintf("%s WARNING: Invaild parameter index!\n", __FUNCTION__);) 696 return MV_BAD_PARAM; 697 } 698 699 cmd[0] = sflash[pFlinfo->index].opcdREAD; 700 cmd[1] = ((offset >> 16) & 0xFF); 701 cmd[2] = ((offset >> 8) & 0xFF); 702 cmd[3] = (offset & 0xFF); 703 704 return mvSpiWriteThenRead(cmd, MV_SFLASH_READ_CMND_LENGTH, pReadBuff, buffSize, 0); 705} 706 707/******************************************************************************* 708* mvSFlashFastBlockRd - Fast read from the serial flash 709* 710* DESCRIPTION: 711* Issue the fast read command and address then perfom the needed read 712* 713* INPUT: 714* pFlinfo: pointer to the Flash information structure 715* offset: byte offset with the flash to start reading from 716* pReadBuff: pointer to the buffer to read the data in 717* buffSize: size of the buffer to read. 718* 719* OUTPUT: 720* pReadBuff: pointer to the buffer containing the read data 721* 722* RETURN: 723* Success or Error code. 724* 725* 726*******************************************************************************/ 727MV_STATUS mvSFlashFastBlockRd (MV_SFLASH_INFO * pFlinfo, MV_U32 offset, 728 MV_U8* pReadBuff, MV_U32 buffSize) 729{ 730 MV_U8 cmd[MV_SFLASH_READ_CMND_LENGTH]; 731 MV_STATUS ret; 732 733 /* check for NULL pointer */ 734 if ((pFlinfo == NULL) || (pReadBuff == NULL)) 735 { 736 mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__); 737 return MV_BAD_PARAM; 738 } 739 740 /* Protection - check if the model was detected */ 741 if (pFlinfo->index >= MV_ARRAY_SIZE(sflash)) 742 { 743 DB(mvOsPrintf("%s WARNING: Invaild parameter index!\n", __FUNCTION__);) 744 return MV_BAD_PARAM; 745 } 746 747 /* Set the SPI frequency to the MAX allowed for fast-read operations */ 748 mvOsPrintf("Setting freq to %d.\n",sflash[pFlinfo->index].spiMaxFastFreq); 749 if ((ret = mvSpiBaudRateSet(sflash[pFlinfo->index].spiMaxFastFreq)) != MV_OK) 750 { 751 mvOsPrintf("%s ERROR: Failed to set the SPI fast frequency!\n", __FUNCTION__); 752 return ret; 753 } 754 755 cmd[0] = sflash[pFlinfo->index].opcdFSTRD; 756 cmd[1] = ((offset >> 16) & 0xFF); 757 cmd[2] = ((offset >> 8) & 0xFF); 758 cmd[3] = (offset & 0xFF); 759 760 761 ret = mvSpiWriteThenRead(cmd, MV_SFLASH_READ_CMND_LENGTH, pReadBuff, buffSize, 762 sflash[pFlinfo->index].spiFastRdDummyBytes); 763 764 /* Reset the SPI frequency to the MAX allowed for the device for best performance */ 765 if ((ret = mvSpiBaudRateSet(sflash[pFlinfo->index].spiMaxFreq)) != MV_OK) 766 { 767 mvOsPrintf("%s ERROR: Failed to set the SPI frequency!\n", __FUNCTION__); 768 return ret; 769 } 770 771 return ret; 772} 773 774 775/******************************************************************************* 776* mvSFlashBlockWr - Write a buffer with any size 777* 778* DESCRIPTION: 779* write regardless of the page boundaries and size limit per Page 780* program command 781* 782* INPUT: 783* pFlinfo: pointer to the Flash information structure 784* offset: byte offset within the flash region 785* pWriteBuff: pointer to the buffer holding the data to program 786* buffSize: size of the buffer to write 787* 788* OUTPUT: 789* None 790* 791* RETURN: 792* Success or Error code. 793* 794* 795*******************************************************************************/ 796MV_STATUS mvSFlashBlockWr (MV_SFLASH_INFO * pFlinfo, MV_U32 offset, 797 MV_U8* pWriteBuff, MV_U32 buffSize) 798{ 799 MV_STATUS ret; 800 MV_U32 data2write = buffSize; 801 MV_U32 preAllOffset = (offset & MV_SFLASH_PAGE_ALLIGN_MASK(MV_M25P_PAGE_SIZE)); 802 MV_U32 preAllSz = (preAllOffset ? (MV_M25P_PAGE_SIZE - preAllOffset) : 0); 803 MV_U32 writeOffset = offset; 804 805 /* check for NULL pointer */ 806#ifndef CONFIG_MARVELL 807 if(NULL == pWriteBuff) 808 { 809 mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__); 810 return MV_BAD_PARAM; 811 } 812#endif 813 814 if (pFlinfo == NULL) 815 { 816 mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__); 817 return MV_BAD_PARAM; 818 } 819 820 /* Protection - check if the model was detected */ 821 if (pFlinfo->index >= MV_ARRAY_SIZE(sflash)) 822 { 823 DB(mvOsPrintf("%s WARNING: Invaild parameter index!\n", __FUNCTION__);) 824 return MV_BAD_PARAM; 825 } 826 827 /* check that the buffer size does not exceed the flash size */ 828 if ((offset + buffSize) > mvSFlashSizeGet(pFlinfo)) 829 { 830 DB(mvOsPrintf("%s WARNING: Write exceeds flash size!\n", __FUNCTION__);) 831 return MV_OUT_OF_RANGE; 832 } 833 834 /* check if the total block size is less than the first chunk remainder */ 835 if (data2write < preAllSz) 836 preAllSz = data2write; 837 838 /* check if programing does not start at a 64byte alligned offset */ 839 if (preAllSz) 840 { 841 if ((ret = mvSFlashPageWr(pFlinfo, writeOffset, pWriteBuff, preAllSz)) != MV_OK) 842 return ret; 843 844 /* increment pointers and counters */ 845 writeOffset += preAllSz; 846 data2write -= preAllSz; 847 pWriteBuff += preAllSz; 848 } 849 850 /* program the data that fits in complete page chunks */ 851 while (data2write >= sflash[pFlinfo->index].pageSize) 852 { 853 if ((ret = mvSFlashPageWr(pFlinfo, writeOffset, pWriteBuff, sflash[pFlinfo->index].pageSize)) != MV_OK) 854 return ret; 855 856 /* increment pointers and counters */ 857 writeOffset += sflash[pFlinfo->index].pageSize; 858 data2write -= sflash[pFlinfo->index].pageSize; 859 pWriteBuff += sflash[pFlinfo->index].pageSize; 860 } 861 862 /* program the last partial chunk */ 863 if (data2write) 864 { 865 if ((ret = mvSFlashPageWr(pFlinfo, writeOffset, pWriteBuff, data2write)) != MV_OK) 866 return ret; 867 } 868 869 return MV_OK; 870} 871 872/******************************************************************************* 873* mvSFlashIdGet - Get the manufacturer and device IDs. 874* 875* DESCRIPTION: 876* Get the Manufacturer and device IDs from the serial flash through 877* writing the RDID command then reading 3 bytes of data. In case that 878* this command was called for the first time in order to detect the 879* manufacturer and device IDs, then the default RDID opcode will be used 880* unless the device index is indicated by the user (in case the SPI flash 881* does not use the default RDID opcode). 882* 883* INPUT: 884* pFlinfo: pointer to the Flash information structure 885* pManId: pointer to the 8bit variable to hold the manufacturing ID 886* pDevId: pointer to the 16bit variable to hold the device ID 887* 888* OUTPUT: 889* pManId: pointer to the 8bit variable holding the manufacturing ID 890* pDevId: pointer to the 16bit variable holding the device ID 891* 892* RETURN: 893* Success or Error code. 894* 895* 896*******************************************************************************/ 897MV_STATUS mvSFlashIdGet (MV_SFLASH_INFO * pFlinfo, MV_U8* pManId, MV_U16* pDevId) 898{ 899 MV_STATUS ret; 900 MV_U8 cmd[MV_SFLASH_RDID_CMND_LENGTH]; 901 MV_U8 id[MV_SFLASH_RDID_REPLY_LENGTH]; 902 903 904 905 /* check for NULL pointer */ 906 if ((pFlinfo == NULL) || (pManId == NULL) || (pDevId == NULL)) 907 { 908 mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__); 909 return MV_BAD_PARAM; 910 } 911 912 if (pFlinfo->index >= MV_ARRAY_SIZE(sflash)) 913 return mvSFlashWithDefaultsIdGet(pFlinfo, pManId, pDevId); 914 else 915 cmd[0] = sflash[pFlinfo->index].opcdRDID; 916 917 if ((ret = mvSpiWriteThenRead(cmd, MV_SFLASH_RDID_CMND_LENGTH, id, MV_SFLASH_RDID_REPLY_LENGTH, 0)) != MV_OK) 918 return ret; 919 920 *pManId = id[0]; 921 *pDevId = 0; 922 *pDevId |= (id[1] << 8); 923 *pDevId |= id[2]; 924 925 return MV_OK; 926} 927 928/******************************************************************************* 929* mvSFlashWpRegionSet - Set the Write-Protected region 930* 931* DESCRIPTION: 932* Set the Write-Protected region 933* 934* INPUT: 935* pFlinfo: pointer to the Flash information structure 936* wpRegion: which region will be protected 937* 938* OUTPUT: 939* None 940* 941* RETURN: 942* Success or Error code. 943* 944* 945*******************************************************************************/ 946MV_STATUS mvSFlashWpRegionSet (MV_SFLASH_INFO * pFlinfo, MV_SFLASH_WP_REGION wpRegion) 947{ 948 MV_U8 wpMask; 949 950 /* check for NULL pointer */ 951 if (pFlinfo == NULL) 952 { 953 mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__); 954 return MV_BAD_PARAM; 955 } 956 957 /* Protection - check if the model was detected */ 958 if (pFlinfo->index >= MV_ARRAY_SIZE(sflash)) 959 { 960 DB(mvOsPrintf("%s WARNING: Invaild parameter index!\n", __FUNCTION__);) 961 return MV_BAD_PARAM; 962 } 963 964 /* Check if the chip is an ST flash; then WP supports only 3 bits */ 965 if (pFlinfo->manufacturerId == MV_M25PXXX_ST_MANF_ID) 966 { 967 switch (wpRegion) 968 { 969 case MV_WP_NONE: 970 wpMask = MV_M25P_STATUS_BP_NONE; 971 break; 972 973 case MV_WP_UPR_1OF128: 974 DB(mvOsPrintf("%s WARNING: Invaild option for this flash chip!\n", __FUNCTION__);) 975 return MV_NOT_SUPPORTED; 976 977 case MV_WP_UPR_1OF64: 978 wpMask = MV_M25P_STATUS_BP_1_OF_64; 979 break; 980 981 case MV_WP_UPR_1OF32: 982 wpMask = MV_M25P_STATUS_BP_1_OF_32; 983 break; 984 985 case MV_WP_UPR_1OF16: 986 wpMask = MV_M25P_STATUS_BP_1_OF_16; 987 break; 988 989 case MV_WP_UPR_1OF8: 990 wpMask = MV_M25P_STATUS_BP_1_OF_8; 991 break; 992 993 case MV_WP_UPR_1OF4: 994 wpMask = MV_M25P_STATUS_BP_1_OF_4; 995 break; 996 997 case MV_WP_UPR_1OF2: 998 wpMask = MV_M25P_STATUS_BP_1_OF_2; 999 break; 1000 1001 case MV_WP_ALL: 1002 wpMask = MV_M25P_STATUS_BP_ALL; 1003 break; 1004 1005 default: 1006 DB(mvOsPrintf("%s WARNING: Invaild parameter WP region!\n", __FUNCTION__);) 1007 return MV_BAD_PARAM; 1008 } 1009 } 1010 /* check if the manufacturer is MXIC then the WP is 4bits */ 1011 else if (pFlinfo->manufacturerId == MV_MXIC_MANF_ID) 1012 { 1013 switch (wpRegion) 1014 { 1015 case MV_WP_NONE: 1016 wpMask = MV_MX25L_STATUS_BP_NONE; 1017 break; 1018 1019 case MV_WP_UPR_1OF128: 1020 wpMask = MV_MX25L_STATUS_BP_1_OF_128; 1021 break; 1022 1023 case MV_WP_UPR_1OF64: 1024 wpMask = MV_MX25L_STATUS_BP_1_OF_64; 1025 break; 1026 1027 case MV_WP_UPR_1OF32: 1028 wpMask = MV_MX25L_STATUS_BP_1_OF_32; 1029 break; 1030 1031 case MV_WP_UPR_1OF16: 1032 wpMask = MV_MX25L_STATUS_BP_1_OF_16; 1033 break; 1034 1035 case MV_WP_UPR_1OF8: 1036 wpMask = MV_MX25L_STATUS_BP_1_OF_8; 1037 break; 1038 1039 case MV_WP_UPR_1OF4: 1040 wpMask = MV_MX25L_STATUS_BP_1_OF_4; 1041 break; 1042 1043 case MV_WP_UPR_1OF2: 1044 wpMask = MV_MX25L_STATUS_BP_1_OF_2; 1045 break; 1046 1047 case MV_WP_ALL: 1048 wpMask = MV_MX25L_STATUS_BP_ALL; 1049 break; 1050 1051 default: 1052 DB(mvOsPrintf("%s WARNING: Invaild parameter WP region!\n", __FUNCTION__);) 1053 return MV_BAD_PARAM; 1054 } 1055 } 1056 /* check if the manufacturer is SPANSION then the WP is 4bits */ 1057 else if (pFlinfo->manufacturerId == MV_SPANSION_MANF_ID) 1058 { 1059 switch (wpRegion) 1060 { 1061 case MV_WP_NONE: 1062 wpMask = MV_S25FL_STATUS_BP_NONE; 1063 break; 1064 1065 case MV_WP_UPR_1OF128: 1066 DB(mvOsPrintf("%s WARNING: Invaild option for this flash chip!\n", __FUNCTION__);) 1067 return MV_NOT_SUPPORTED; 1068 1069 case MV_WP_UPR_1OF64: 1070 wpMask = MV_S25FL_STATUS_BP_1_OF_64; 1071 break; 1072 1073 case MV_WP_UPR_1OF32: 1074 wpMask = MV_S25FL_STATUS_BP_1_OF_32; 1075 break; 1076 1077 case MV_WP_UPR_1OF16: 1078 wpMask = MV_S25FL_STATUS_BP_1_OF_16; 1079 break; 1080 1081 case MV_WP_UPR_1OF8: 1082 wpMask = MV_S25FL_STATUS_BP_1_OF_8; 1083 break; 1084 1085 case MV_WP_UPR_1OF4: 1086 wpMask = MV_S25FL_STATUS_BP_1_OF_4; 1087 break; 1088 1089 case MV_WP_UPR_1OF2: 1090 wpMask = MV_S25FL_STATUS_BP_1_OF_2; 1091 break; 1092 1093 case MV_WP_ALL: 1094 wpMask = MV_S25FL_STATUS_BP_ALL; 1095 break; 1096 1097 1098 default: 1099 DB(mvOsPrintf("%s WARNING: Invaild parameter WP region!\n", __FUNCTION__);) 1100 return MV_BAD_PARAM; 1101 } 1102 } 1103 else 1104 { 1105 DB(mvOsPrintf("%s WARNING: Invaild parameter Manufacturer ID!\n", __FUNCTION__);) 1106 return MV_BAD_PARAM; 1107 } 1108 1109 /* Verify that the SRWD bit is always set - register is s/w locked */ 1110 wpMask |= MV_SFLASH_STATUS_REG_SRWD_MASK; 1111 1112 return mvStatusRegSet(pFlinfo, wpMask); 1113} 1114 1115/******************************************************************************* 1116* mvSFlashWpRegionGet - Get the Write-Protected region configured 1117* 1118* DESCRIPTION: 1119* Get from the chip the Write-Protected region configured 1120* 1121* INPUT: 1122* pFlinfo: pointer to the Flash information structure 1123* pWpRegion: pointer to the variable to return the WP region in 1124* 1125* OUTPUT: 1126* wpRegion: pointer to the variable holding the WP region configured 1127* 1128* RETURN: 1129* Success or Error code. 1130* 1131* 1132*******************************************************************************/ 1133MV_STATUS mvSFlashWpRegionGet (MV_SFLASH_INFO * pFlinfo, MV_SFLASH_WP_REGION * pWpRegion) 1134{ 1135 MV_STATUS ret; 1136 MV_U8 reg; 1137 1138 /* check for NULL pointer */ 1139 if ((pFlinfo == NULL) || (pWpRegion == NULL)) 1140 { 1141 mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__); 1142 return MV_BAD_PARAM; 1143 } 1144 1145 /* Protection - check if the model was detected */ 1146 if (pFlinfo->index >= MV_ARRAY_SIZE(sflash)) 1147 { 1148 DB(mvOsPrintf("%s WARNING: Invaild parameter index!\n", __FUNCTION__);) 1149 return MV_BAD_PARAM; 1150 } 1151 1152 if ((ret = mvStatusRegGet(pFlinfo, ®)) != MV_OK) 1153 return ret; 1154 1155 /* Check if the chip is an ST flash; then WP supports only 3 bits */ 1156 if (pFlinfo->manufacturerId == MV_M25PXXX_ST_MANF_ID) 1157 { 1158 switch ((reg & MV_M25P_STATUS_REG_WP_MASK)) 1159 { 1160 case MV_M25P_STATUS_BP_NONE: 1161 *pWpRegion = MV_WP_NONE; 1162 break; 1163 1164 case MV_M25P_STATUS_BP_1_OF_64: 1165 *pWpRegion = MV_WP_UPR_1OF64; 1166 break; 1167 1168 case MV_M25P_STATUS_BP_1_OF_32: 1169 *pWpRegion = MV_WP_UPR_1OF32; 1170 break; 1171 1172 case MV_M25P_STATUS_BP_1_OF_16: 1173 *pWpRegion = MV_WP_UPR_1OF16; 1174 break; 1175 1176 case MV_M25P_STATUS_BP_1_OF_8: 1177 *pWpRegion = MV_WP_UPR_1OF8; 1178 break; 1179 1180 case MV_M25P_STATUS_BP_1_OF_4: 1181 *pWpRegion = MV_WP_UPR_1OF4; 1182 break; 1183 1184 case MV_M25P_STATUS_BP_1_OF_2: 1185 *pWpRegion = MV_WP_UPR_1OF2; 1186 break; 1187 1188 case MV_M25P_STATUS_BP_ALL: 1189 *pWpRegion = MV_WP_ALL; 1190 break; 1191 1192 default: 1193 DB(mvOsPrintf("%s WARNING: Unidentified WP region in h/w!\n", __FUNCTION__);) 1194 return MV_BAD_VALUE; 1195 } 1196 } 1197 /* check if the manufacturer is MXIC then the WP is 4bits */ 1198 else if (pFlinfo->manufacturerId == MV_MXIC_MANF_ID) 1199 { 1200 switch ((reg & MV_MX25L_STATUS_REG_WP_MASK)) 1201 { 1202 case MV_MX25L_STATUS_BP_NONE: 1203 *pWpRegion = MV_WP_NONE; 1204 break; 1205 1206 case MV_MX25L_STATUS_BP_1_OF_128: 1207 *pWpRegion = MV_WP_UPR_1OF128; 1208 break; 1209 1210 case MV_MX25L_STATUS_BP_1_OF_64: 1211 *pWpRegion = MV_WP_UPR_1OF64; 1212 break; 1213 1214 case MV_MX25L_STATUS_BP_1_OF_32: 1215 *pWpRegion = MV_WP_UPR_1OF32; 1216 break; 1217 1218 case MV_MX25L_STATUS_BP_1_OF_16: 1219 *pWpRegion = MV_WP_UPR_1OF16; 1220 break; 1221 1222 case MV_MX25L_STATUS_BP_1_OF_8: 1223 *pWpRegion = MV_WP_UPR_1OF8; 1224 break; 1225 1226 case MV_MX25L_STATUS_BP_1_OF_4: 1227 *pWpRegion = MV_WP_UPR_1OF4; 1228 break; 1229 1230 case MV_MX25L_STATUS_BP_1_OF_2: 1231 *pWpRegion = MV_WP_UPR_1OF2; 1232 break; 1233 1234 case MV_MX25L_STATUS_BP_ALL: 1235 *pWpRegion = MV_WP_ALL; 1236 break; 1237 1238 default: 1239 DB(mvOsPrintf("%s WARNING: Unidentified WP region in h/w!\n", __FUNCTION__);) 1240 return MV_BAD_VALUE; 1241 } 1242 } 1243 /* Check if the chip is an SPANSION flash; then WP supports only 3 bits */ 1244 else if (pFlinfo->manufacturerId == MV_SPANSION_MANF_ID) 1245 { 1246 switch ((reg & MV_S25FL_STATUS_REG_WP_MASK)) 1247 { 1248 case MV_S25FL_STATUS_BP_NONE: 1249 *pWpRegion = MV_WP_NONE; 1250 break; 1251 1252 case MV_S25FL_STATUS_BP_1_OF_64: 1253 *pWpRegion = MV_WP_UPR_1OF64; 1254 break; 1255 1256 case MV_S25FL_STATUS_BP_1_OF_32: 1257 *pWpRegion = MV_WP_UPR_1OF32; 1258 break; 1259 1260 case MV_S25FL_STATUS_BP_1_OF_16: 1261 *pWpRegion = MV_WP_UPR_1OF16; 1262 break; 1263 1264 case MV_S25FL_STATUS_BP_1_OF_8: 1265 *pWpRegion = MV_WP_UPR_1OF8; 1266 break; 1267 1268 case MV_S25FL_STATUS_BP_1_OF_4: 1269 *pWpRegion = MV_WP_UPR_1OF4; 1270 break; 1271 1272 case MV_S25FL_STATUS_BP_1_OF_2: 1273 *pWpRegion = MV_WP_UPR_1OF2; 1274 break; 1275 1276 case MV_S25FL_STATUS_BP_ALL: 1277 *pWpRegion = MV_WP_ALL; 1278 break; 1279 1280 default: 1281 DB(mvOsPrintf("%s WARNING: Unidentified WP region in h/w!\n", __FUNCTION__);) 1282 return MV_BAD_VALUE; 1283 } 1284 } 1285 else 1286 { 1287 DB(mvOsPrintf("%s WARNING: Invaild parameter Manufacturer ID!\n", __FUNCTION__);) 1288 return MV_BAD_PARAM; 1289 } 1290 1291 return MV_OK; 1292} 1293 1294/******************************************************************************* 1295* mvSFlashStatRegLock - Lock the status register for writing - W/Vpp 1296* pin should be low to take effect 1297* 1298* DESCRIPTION: 1299* Lock the access to the Status Register for writing. This will 1300* cause the flash to enter the hardware protection mode if the W/Vpp 1301* is low. If the W/Vpp is hi, the chip will be in soft protection mode, but 1302* the register will continue to be writable if WREN sequence was used. 1303* 1304* INPUT: 1305* pFlinfo: pointer to the Flash information structure 1306* srLock: enable/disable (MV_TRUE/MV_FALSE) status registor lock mechanism 1307* 1308* OUTPUT: 1309* None 1310* 1311* RETURN: 1312* Success or Error code. 1313* 1314* 1315*******************************************************************************/ 1316MV_STATUS mvSFlashStatRegLock (MV_SFLASH_INFO * pFlinfo, MV_BOOL srLock) 1317{ 1318 MV_STATUS ret; 1319 MV_U8 reg; 1320 1321 /* check for NULL pointer */ 1322 if (pFlinfo == NULL) 1323 { 1324 mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__); 1325 return MV_BAD_PARAM; 1326 } 1327 1328 /* Protection - check if the model was detected */ 1329 if (pFlinfo->index >= MV_ARRAY_SIZE(sflash)) 1330 { 1331 DB(mvOsPrintf("%s WARNING: Invaild parameter index!\n", __FUNCTION__);) 1332 return MV_BAD_PARAM; 1333 } 1334 1335 if ((ret = mvStatusRegGet(pFlinfo, ®)) != MV_OK) 1336 return ret; 1337 1338 if (srLock) 1339 reg |= MV_SFLASH_STATUS_REG_SRWD_MASK; 1340 else 1341 reg &= ~MV_SFLASH_STATUS_REG_SRWD_MASK; 1342 1343 return mvStatusRegSet(pFlinfo, reg); 1344} 1345 1346/******************************************************************************* 1347* mvSFlashSizeGet - Get the size of the SPI flash 1348* 1349* DESCRIPTION: 1350* based on the sector number and size of each sector calculate the total 1351* size of the flash memory. 1352* 1353* INPUT: 1354* pFlinfo: pointer to the Flash information structure 1355* 1356* OUTPUT: 1357* None. 1358* 1359* RETURN: 1360* Size of the flash in bytes. 1361* 1362* 1363*******************************************************************************/ 1364MV_U32 mvSFlashSizeGet (MV_SFLASH_INFO * pFlinfo) 1365{ 1366 /* check for NULL pointer */ 1367 if (pFlinfo == NULL) 1368 { 1369 mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__); 1370 return 0; 1371 } 1372 1373 return (pFlinfo->sectorSize * pFlinfo->sectorNumber); 1374} 1375 1376/******************************************************************************* 1377* mvSFlashPowerSaveEnter - Cause the falsh device to go into power save mode 1378* 1379* DESCRIPTION: 1380* Enter a special power save mode. 1381* 1382* INPUT: 1383* pFlinfo: pointer to the Flash information structure 1384* 1385* OUTPUT: 1386* None. 1387* 1388* RETURN: 1389* Size of the flash in bytes. 1390* 1391* 1392*******************************************************************************/ 1393MV_STATUS mvSFlashPowerSaveEnter(MV_SFLASH_INFO * pFlinfo) 1394{ 1395 MV_STATUS ret; 1396 MV_U8 cmd[MV_SFLASH_DP_CMND_LENGTH]; 1397 1398 1399 /* check for NULL pointer */ 1400 if (pFlinfo == NULL) 1401 { 1402 mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__); 1403 return 0; 1404 } 1405 1406 /* Protection - check if the model was detected */ 1407 if (pFlinfo->index >= MV_ARRAY_SIZE(sflash)) 1408 { 1409 DB(mvOsPrintf("%s WARNING: Invaild parameter index!\n", __FUNCTION__);) 1410 return MV_BAD_PARAM; 1411 } 1412 1413 /* check that power save mode is supported in the specific device */ 1414 if (sflash[pFlinfo->index].opcdPwrSave == MV_SFLASH_NO_SPECIFIC_OPCD) 1415 { 1416 DB(mvOsPrintf("%s WARNING: Power save not supported for this device!\n", __FUNCTION__);) 1417 return MV_NOT_SUPPORTED; 1418 } 1419 1420 cmd[0] = sflash[pFlinfo->index].opcdPwrSave; 1421 1422 if ((ret = mvSpiWriteThenWrite(cmd, MV_SFLASH_DP_CMND_LENGTH, NULL, 0)) != MV_OK) 1423 return ret; 1424 1425 return MV_OK; 1426 1427} 1428 1429/******************************************************************************* 1430* mvSFlashPowerSaveExit - Cause the falsh device to exit the power save mode 1431* 1432* DESCRIPTION: 1433* Exit the deep power save mode. 1434* 1435* INPUT: 1436* pFlinfo: pointer to the Flash information structure 1437* 1438* OUTPUT: 1439* None. 1440* 1441* RETURN: 1442* Size of the flash in bytes. 1443* 1444* 1445*******************************************************************************/ 1446MV_STATUS mvSFlashPowerSaveExit (MV_SFLASH_INFO * pFlinfo) 1447{ 1448 MV_STATUS ret; 1449 MV_U8 cmd[MV_SFLASH_RES_CMND_LENGTH]; 1450 1451 1452 /* check for NULL pointer */ 1453 if (pFlinfo == NULL) 1454 { 1455 mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__); 1456 return 0; 1457 } 1458 1459 /* Protection - check if the model was detected */ 1460 if (pFlinfo->index >= MV_ARRAY_SIZE(sflash)) 1461 { 1462 DB(mvOsPrintf("%s WARNING: Invaild parameter index!\n", __FUNCTION__);) 1463 return MV_BAD_PARAM; 1464 } 1465 1466 /* check that power save mode is supported in the specific device */ 1467 if (sflash[pFlinfo->index].opcdRES == MV_SFLASH_NO_SPECIFIC_OPCD) 1468 { 1469 DB(mvOsPrintf("%s WARNING: Read Electronic Signature not supported for this device!\n", __FUNCTION__);) 1470 return MV_NOT_SUPPORTED; 1471 } 1472 1473 cmd[0] = sflash[pFlinfo->index].opcdRES; 1474 1475 if ((ret = mvSpiWriteThenWrite(cmd, MV_SFLASH_RES_CMND_LENGTH, NULL, 0)) != MV_OK) 1476 return ret; 1477 1478 /* add the delay needed for the device to wake up */ 1479 mvOsDelay(MV_MXIC_DP_EXIT_DELAY); /* 30 ms */ 1480 1481 return MV_OK; 1482 1483} 1484 1485/******************************************************************************* 1486* mvSFlashModelGet - Retreive the string with the device manufacturer and model 1487* 1488* DESCRIPTION: 1489* Retreive the string with the device manufacturer and model 1490* 1491* INPUT: 1492* pFlinfo: pointer to the Flash information structure 1493* 1494* OUTPUT: 1495* None. 1496* 1497* RETURN: 1498* pointer to the string indicating the device manufacturer and model 1499* 1500* 1501*******************************************************************************/ 1502const MV_8 * mvSFlashModelGet (MV_SFLASH_INFO * pFlinfo) 1503{ 1504 static const MV_8 * unknModel = (const MV_8 *)"Unknown"; 1505 1506 /* check for NULL pointer */ 1507 if (pFlinfo == NULL) 1508 { 1509 mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__); 1510 return 0; 1511 } 1512 1513 /* Protection - check if the model was detected */ 1514 if (pFlinfo->index >= MV_ARRAY_SIZE(sflash)) 1515 { 1516 DB(mvOsPrintf("%s WARNING: Invaild parameter index!\n", __FUNCTION__);) 1517 return unknModel; 1518 } 1519 1520 return sflash[pFlinfo->index].deviceModel; 1521} 1522 1523