/******************************************************************************* Copyright (C) Marvell International Ltd. and its affiliates This software file (the "File") is owned and distributed by Marvell International Ltd. and/or its affiliates ("Marvell") under the following alternative licensing terms. Once you have made an election to distribute the File under one of the following license alternatives, please (i) delete this introductory statement regarding license alternatives, (ii) delete the two license alternatives that you have not elected to use and (iii) preserve the Marvell copyright notice above. ******************************************************************************** Marvell Commercial License Option If you received this File from Marvell and you have entered into a commercial license agreement (a "Commercial License") with Marvell, the File is licensed to you under the terms of the applicable Commercial License. ******************************************************************************** Marvell GPL License Option If you received this File from Marvell, you may opt to use, redistribute and/or modify this File in accordance with the terms and conditions of the General Public License Version 2, June 1991 (the "GPL License"), a copy of which is available along with the File in the license.txt file or by writing to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY DISCLAIMED. The GPL License provides additional details about this warranty disclaimer. ******************************************************************************** Marvell BSD License Option If you received this File from Marvell, you may opt to use, redistribute and/or modify this File under the following licensing terms. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Marvell nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *******************************************************************************/ #include "mflash/mvMFlash.h" #include "mflash/mvPMFlash.h" #include "mflash/mvSMFlash.h" #include "mflash/mvMFlashSpec.h" #include "mflash/mvPMFlashSpec.h" #include "mflash/mvSMFlashSpec.h" /*#define MV_DEBUG*/ #ifdef MV_DEBUG #define DB(x) x #else #define DB(x) #endif /* Static Functions */ static MV_STATUS mvMFlashBlockByRegionWr(MV_MFLASH_INFO *pFlash, MV_U32 offset, \ MV_U32 blockSize, MV_U8 *pBlock, MV_BOOL verify, \ MV_BOOL main); static MV_STATUS mvMFlash64bInfWr (MV_MFLASH_INFO *pFlash, MV_U32 offset, \ MV_U8 *pBuff, MV_BOOL verify); static MV_STATUS mvMFlash64bWr (MV_MFLASH_INFO *pFlash, MV_U32 offset, \ MV_U8 *pBuff, MV_BOOL verify); /******************************************************************************* * mvMFlashInit - Initialize a Marvell Flash device * * DESCRIPTION: * This function performs the necessary initialization for a Marvell * Sunol flash. * * INPUT: * pFlash: Structure with Marvell Flash information * pFlash->baseAddr: flash base address. * pFlash->ifMode: The mode used SPI or Parallel. * * OUTPUT: * pFlash: pointer to the tructure with Marvell Flash information detected * pFlash->flashModel: flash model deteced * pFlash->sectorSize: Size of each sector (unified sector size) * pFlash->sectorNumber: Number of sectors in the flash * pFlash->infoSize: Size of the Information region. * * RETURN: * Success or Error code. * * *******************************************************************************/ MV_STATUS mvMFlashInit (MV_MFLASH_INFO *pFlash) { MV_U32 manufId; MV_U16 devId; MV_U8 reg; MV_STATUS ret; /* check for NULL pointer */ if (pFlash == NULL) { mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__); return MV_BAD_PARAM; } if (pFlash->ifMode == MV_MFLASH_PARALLEL) { /* perform the basic initialization */ if ((ret = mvPMFlashInit(pFlash)) != MV_OK) return ret; /* Try to read the device ID and decide the device model */ if ((ret = mvPMFlashIdGet(pFlash, &manufId, &devId)) != MV_OK) return ret; /* Get the Serial interface configuration register to check sector size */ if ((ret = mvPMFlashReadConfig4(pFlash, ®)) != MV_OK) return ret; } else if (pFlash->ifMode == MV_MFLASH_SPI) { /* perform the basic initialization */ if ((ret = mvSMFlashInit(pFlash)) != MV_OK) return ret; /* Try to read the device ID and decide the device model */ if ((ret = mvSMFlashIdGet(pFlash, &manufId, &devId)) != MV_OK) return ret; /* Get the Serial interface configuration register to check sector size */ if ((ret = mvSMFlashReadConfig4(pFlash, ®)) != MV_OK) return ret; } else { mvOsPrintf("%s ERROR: Invalid interface mode!\n", __FUNCTION__); return MV_BAD_PARAM; } /* check the manufacturer Id to be the same as MARVELL */ if (manufId != MV_MFLASH_MANUFACTURER_ID) { mvOsPrintf("%s ERROR: Flash unknown manufacturer ID!\n", __FUNCTION__); return MV_NOT_SUPPORTED; } /* based on device ID and the PAGE4K bit fill model, sector size and number */ switch (devId & MV_MFLASH_DEVICE_ID_MASK) { case MV_MFLASH_DEVICE_ID_SUNOL_1: pFlash->flashModel = MV_MFLASH_SUNOL_1; pFlash->infoSize = MV_MFLASH_INF_MEM_SZ_SUNOL_1; if (reg & MV_SMFLASH_SRL_CFG4_PG_SIZE_MASK) /* 1 - page is 4K */ { pFlash->sectorSize = MV_MFLASH_SECTOR_SIZE_SMALL; pFlash->sectorNumber = MV_MFLASH_SMALL_SEC_NUM_SUNOL_1; } else /* 0 - page is 32K */ { pFlash->sectorSize = MV_MFLASH_SECTOR_SIZE_BIG; pFlash->sectorNumber = MV_MFLASH_BIG_SEC_NUM_SUNOL_1; } break; case MV_MFLASH_DEVICE_ID_SUNOL_2: pFlash->flashModel = MV_MFLASH_SUNOL_2; pFlash->infoSize = MV_MFLASH_INF_MEM_SZ_SUNOL_2_3; if (reg & MV_SMFLASH_SRL_CFG4_PG_SIZE_MASK) /* 1 - page is 4K */ { pFlash->sectorSize = MV_MFLASH_SECTOR_SIZE_SMALL; pFlash->sectorNumber = MV_MFLASH_SMALL_SEC_NUM_SUNOL_2; } else /* 0 - page is 32K */ { pFlash->sectorSize = MV_MFLASH_SECTOR_SIZE_BIG; pFlash->sectorNumber = MV_MFLASH_BIG_SEC_NUM_SUNOL_2; } break; case MV_MFLASH_DEVICE_ID_SUNOL_3: pFlash->flashModel = MV_MFLASH_SUNOL_3; pFlash->infoSize = MV_MFLASH_INF_MEM_SZ_SUNOL_2_3; if (reg & MV_SMFLASH_SRL_CFG4_PG_SIZE_MASK) /* 1 - page is 4K */ { pFlash->sectorSize = MV_MFLASH_SECTOR_SIZE_SMALL; pFlash->sectorNumber = MV_MFLASH_SMALL_SEC_NUM_SUNOL_3; } else /* 0 - page is 32K */ { pFlash->sectorSize = MV_MFLASH_SECTOR_SIZE_BIG; pFlash->sectorNumber = MV_MFLASH_BIG_SEC_NUM_SUNOL_3; } break; default: mvOsPrintf("%s ERROR: Unknown Flash Device ID!\n", __FUNCTION__); pFlash->flashModel = MV_MFLASH_MODEL_UNKNOWN; return MV_NOT_SUPPORTED; } return MV_OK; } /******************************************************************************* * mvMFlashChipErase - Erase the whole flash * * DESCRIPTION: * Erase the whole flash (both the Main and Information region) * * INPUT: * pFlash: pointer to the MFlash information structure * * OUTPUT: * None. * * RETURN: * Success or Error code. * * *******************************************************************************/ MV_STATUS mvMFlashChipErase (MV_MFLASH_INFO *pFlash) { /* check for NULL pointer */ if (pFlash == NULL) { mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__); return MV_BAD_PARAM; } if (pFlash->ifMode == MV_MFLASH_PARALLEL) return mvPMFlashChipErase(pFlash); else if (pFlash->ifMode == MV_MFLASH_SPI) return mvSMFlashChipErase(pFlash); mvOsPrintf("%s ERROR: Invalid interface mode!\n", __FUNCTION__); return MV_BAD_PARAM; } /******************************************************************************* * mvMFlashMainErase - Erase the main flash region only * * DESCRIPTION: * Erase the Main flash region * * INPUT: * pFlash: pointer to the MFlash information structure * * OUTPUT: * None. * * RETURN: * Success or Error code. * * *******************************************************************************/ MV_STATUS mvMFlashMainErase (MV_MFLASH_INFO *pFlash) { /* check for NULL pointer */ if (pFlash == NULL) { mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__); return MV_BAD_PARAM; } if (pFlash->ifMode == MV_MFLASH_PARALLEL) return mvPMFlashMainErase(pFlash); else if (pFlash->ifMode == MV_MFLASH_SPI) return mvSMFlashMainErase(pFlash); mvOsPrintf("%s ERROR: Invalid interface mode!\n", __FUNCTION__); return MV_BAD_PARAM; } /******************************************************************************* * mvMFlashInfErase - Erase the information flash region only * * DESCRIPTION: * Erase the information flash region * * INPUT: * pFlash: pointer to the MFlash information structure * * OUTPUT: * None. * * RETURN: * Success or Error code. * * *******************************************************************************/ MV_STATUS mvMFlashInfErase (MV_MFLASH_INFO *pFlash) { /* check for NULL pointer */ if (pFlash == NULL) { mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__); return MV_BAD_PARAM; } if (pFlash->ifMode == MV_MFLASH_PARALLEL) return mvPMFlashInfErase(pFlash); else if (pFlash->ifMode == MV_MFLASH_SPI) return mvSMFlashInfErase(pFlash); mvOsPrintf("%s ERROR: Invalid interface mode!\n", __FUNCTION__); return MV_BAD_PARAM; } /******************************************************************************* * mvMFlashSecErase - Erase the single sector of the main flash region * * DESCRIPTION: * Erase one sector of the main flash region * * INPUT: * pFlash: pointer to the MFlash information structure * secOffset: sector offset within the MFlash * * OUTPUT: * None. * * RETURN: * Success or Error code. * * *******************************************************************************/ MV_STATUS mvMFlashSecErase (MV_MFLASH_INFO *pFlash, MV_U32 secNumber) { MV_U32 i; MV_U32 * pW = (MV_U32*) ((secNumber * pFlash->sectorSize) + pFlash->baseAddr); MV_U32 erasedWord = 0xFFFFFFFF; MV_U32 wordsPerSector = (pFlash->sectorSize / sizeof(MV_U32)); MV_BOOL eraseNeeded = MV_FALSE; /* check for NULL pointer */ if (pFlash == NULL) { mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__); return MV_BAD_PARAM; } /* First compare to FF and check if erase is needed */ for (i=0; iifMode == MV_MFLASH_PARALLEL) return mvPMFlashSecErase(pFlash, secNumber); else if (pFlash->ifMode == MV_MFLASH_SPI) return mvSMFlashSecErase(pFlash, secNumber); mvOsPrintf("%s ERROR: Invalid interface mode!\n", __FUNCTION__); return MV_BAD_PARAM; } /******************************************************************************* * mvMFlash64bWr - Perform the alligned write according to the SPI mode and verify * type. * * DESCRIPTION: * Select the appropriate write api according to the SPI mode and the * verify flag. * *******************************************************************************/ static MV_STATUS mvMFlash64bWr (MV_MFLASH_INFO *pFlash, MV_U32 offset, MV_U8 *pBuff, MV_BOOL verify) { MV_STATUS ret; /* check for NULL pointer */ #ifndef CONFIG_MARVELL if(NULL == pBuff) { mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__); return MV_BAD_PARAM; } #endif if (pFlash == NULL) { mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__); return MV_BAD_PARAM; } /* call the api based on the SPI mode and the verify option */ if (pFlash->ifMode == MV_MFLASH_PARALLEL) { if (verify) { if ((ret = mvPMFlash64bWrVerify(pFlash, offset, pBuff)) != MV_OK) return ret; } else { if ((ret = mvPMFlash64bWr(pFlash, offset, pBuff)) != MV_OK) return ret; } } else if (pFlash->ifMode == MV_MFLASH_SPI) { if (verify) { if ((ret = mvSMFlash64bWrVerify(pFlash, offset, pBuff)) != MV_OK) return ret; } else { if ((ret = mvSMFlash64bWr(pFlash, offset, pBuff)) != MV_OK) return ret; } } else { mvOsPrintf("%s ERROR: Invalid interface mode!\n", __FUNCTION__); return MV_BAD_PARAM; } return MV_OK; } /******************************************************************************* * mvMFlash64bInfWr - Perform the alligned write to the information region based * on the SPI mode and verify type. * * DESCRIPTION: * Select the appropriate write api according to the SPI mode and the * verify flag. * *******************************************************************************/ static MV_STATUS mvMFlash64bInfWr (MV_MFLASH_INFO *pFlash, MV_U32 offset, MV_U8 *pBuff, MV_BOOL verify) { MV_STATUS ret; /* check for NULL pointer */ #ifndef CONFIG_MARVELL if(NULL == pBuff) { mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__); return MV_BAD_PARAM; } #endif if (pFlash == NULL) { mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__); return MV_BAD_PARAM; } /* call the api based on the SPI mode and the verify option */ if (pFlash->ifMode == MV_MFLASH_PARALLEL) { if (verify) { if ((ret = mvPMFlash64bInfWrVerify(pFlash, offset, pBuff)) != MV_OK) return ret; } else { if ((ret = mvPMFlash64bInfWr(pFlash, offset, pBuff)) != MV_OK) return ret; } } else if (pFlash->ifMode == MV_MFLASH_SPI) { if (verify) { if ((ret = mvSMFlash64bInfWrVerify(pFlash, offset, pBuff)) != MV_OK) return ret; } else { if ((ret = mvSMFlash64bInfWr(pFlash, offset, pBuff)) != MV_OK) return ret; } } else { mvOsPrintf("%s ERROR: Invalid interface mode!\n", __FUNCTION__); return MV_BAD_PARAM; } return MV_OK; } /******************************************************************************* * mvMFlashBlockByRegionWr - Write a buffer with a custom length and allignment * based on the region (main or information) * * DESCRIPTION: * Program a varient sized block in the selected region of the MFlash * and perform the verify based on flag. * *******************************************************************************/ static MV_STATUS mvMFlashBlockByRegionWr(MV_MFLASH_INFO *pFlash, MV_U32 offset, MV_U32 blockSize, MV_U8 *pBlock, MV_BOOL verify, MV_BOOL main) { MV_U8 tempBuff[MV_MFLASH_PROG_CHUNK_SIZE]; MV_U32 data2write = blockSize; MV_U32 preAllOfst = (offset & MV_MFLASH_PROG_ALIGN_MASK); MV_U32 preAllSz = (preAllOfst ? (MV_MFLASH_PROG_CHUNK_SIZE - preAllOfst) : 0); MV_U32 writeOffset = (offset & ~MV_MFLASH_PROG_ALIGN_MASK); MV_STATUS ret; /* check for NULL pointer */ #ifndef CONFIG_MARVELL if(NULL == pBlock) { mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__); return MV_BAD_PARAM; } #endif if (pFlash == NULL) { mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__); return MV_BAD_PARAM; } /* verify that the write commands does not exceed the size */ if ((offset + blockSize) > (pFlash->sectorNumber * pFlash->sectorSize)) { DB(mvOsPrintf("%s WARNING: Exceeded flash size!!\n", __FUNCTION__);) return MV_BAD_PARAM; } /* check if the total block size is less than the first chunk remainder */ if (data2write < preAllSz) preAllSz = data2write; /* check if programing does not start at a 64byte alligned offset */ if (preAllSz) { /* first copy the original data */ if (main) { if ((ret = mvMFlashBlockRd(pFlash, writeOffset, MV_MFLASH_PROG_CHUNK_SIZE, tempBuff)) != MV_OK) return ret; } else { if ((ret = mvMFlashBlockInfRd(pFlash, writeOffset, MV_MFLASH_PROG_CHUNK_SIZE, tempBuff)) != MV_OK) return ret; } /* overwrite the data to be changed */ mvOsMemcpy((MV_VOID*)&tempBuff[preAllOfst], pBlock, preAllSz); /* Perform the 64 bytes write based on the mode and verify type */ if (main) { if ((ret = mvMFlash64bWr(pFlash, writeOffset, tempBuff, verify)) != MV_OK) return ret; } else { if ((ret = mvMFlash64bInfWr(pFlash, writeOffset, tempBuff, verify)) != MV_OK) return ret; } /* increment pointers and counters */ writeOffset += MV_MFLASH_PROG_CHUNK_SIZE; data2write -= preAllSz; pBlock += preAllSz; } /* program the data that fits in complete 64bytes chunks */ while (data2write >= MV_MFLASH_PROG_CHUNK_SIZE) { /* Perform the 64 bytes write based on the mode and verify type */ if (main) { if ((ret = mvMFlash64bWr(pFlash, writeOffset, pBlock, verify)) != MV_OK) return ret; } else { if ((ret = mvMFlash64bInfWr(pFlash, writeOffset, pBlock, verify)) != MV_OK) return ret; } /* increment pointers and counters */ writeOffset += MV_MFLASH_PROG_CHUNK_SIZE; data2write -= MV_MFLASH_PROG_CHUNK_SIZE; pBlock += MV_MFLASH_PROG_CHUNK_SIZE; } /* program the last partial chunk */ if (data2write) { /* first copy the original data */ if (main) { if ((ret = mvMFlashBlockRd(pFlash, writeOffset, MV_MFLASH_PROG_CHUNK_SIZE, tempBuff)) != MV_OK) return ret; } else { if ((ret = mvMFlashBlockInfRd(pFlash, writeOffset, MV_MFLASH_PROG_CHUNK_SIZE, tempBuff)) != MV_OK) return ret; } /* overwrite the data to be changed */ mvOsMemcpy(tempBuff, pBlock, data2write); /* Perform the 64 bytes write based on the mode and verify type */ if (main) { if ((ret = mvMFlash64bWr(pFlash, writeOffset, tempBuff, verify)) != MV_OK) return ret; } else { if ((ret = mvMFlash64bInfWr(pFlash, writeOffset, tempBuff, verify)) != MV_OK) return ret; } } return MV_OK; } /******************************************************************************* * mvMFlashBlockWr - Write a buffer with a custom length and allignment * * DESCRIPTION: * Program a varient sized block in the Main region of the MFlash. * * INPUT: * pFlash: pointer to the MFlash information structure * offset: offset within the Information region (limited to 1024) * blockSize: size in bytes of the buffer to be programmed. * pBlock: pointer to the 64 bytes buffer to be programed * verify: bollean flag controlling the compare after program feature * * OUTPUT: * None. * * RETURN: * Success or Error code. * * *******************************************************************************/ MV_STATUS mvMFlashBlockWr(MV_MFLASH_INFO *pFlash, MV_U32 offset, MV_U32 blockSize, MV_U8 *pBlock, MV_BOOL verify) { /* check for NULL pointers */ #ifndef CONFIG_MARVELL if(NULL == pBlock) { mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__); return MV_BAD_PARAM; } #endif if (NULL == pFlash) { mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__); return MV_BAD_PARAM; } return mvMFlashBlockByRegionWr(pFlash, offset, blockSize, pBlock, verify, MV_TRUE /* main region */); } /******************************************************************************* * mvMFlashInfBlockWr - Write a buffer with a custom length and allignment to * the information region of the flash * * DESCRIPTION: * Program a varient sized block in the Information region of the MFlash. * * INPUT: * pFlash: pointer to the MFlash information structure * offset: offset within the Information region (limited to 1024) * blockSize: size in bytes of the buffer to be programmed. * pBlock: pointer to the 64 bytes buffer to be programed * verify: bollean flag controlling the compare after program feature * * OUTPUT: * None. * * RETURN: * Success or Error code. * * *******************************************************************************/ MV_STATUS mvMFlashInfBlockWr(MV_MFLASH_INFO *pFlash, MV_U32 offset, MV_U32 blockSize, MV_U8 *pBlock, MV_BOOL verify) { /* check for NULL pointers */ if ((pFlash == NULL) || (pBlock == NULL)) { mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__); return MV_BAD_PARAM; } return mvMFlashBlockByRegionWr(pFlash, offset, blockSize, pBlock, verify, MV_FALSE /* info region */); } /******************************************************************************* * mvMFlashBlockRd - Read a block of Memory from the Main Flash * * DESCRIPTION: * Read a block of Memory from the Main Flash region * * INPUT: * pFlash: pointer to the MFlash information structure * offset: offset to read from the main region of the MFlash * blockSize: number of bytes to read from the offset * pBlock: pointer of the buffer to fill * * OUTPUT: * pBlock: pointer of the buffer holding the data read from flash. * * RETURN: * Success or Error code. * * *******************************************************************************/ MV_STATUS mvMFlashBlockRd (MV_MFLASH_INFO *pFlash, MV_U32 offset, MV_U32 blockSize, MV_U8 *pBlock) { /* check for NULL pointers */ if ((pFlash == NULL) || (pBlock == NULL)) { mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__); return MV_BAD_PARAM; } if (pFlash->ifMode == MV_MFLASH_PARALLEL) return mvPMFlashBlockRd(pFlash, offset, blockSize, pBlock); else if (pFlash->ifMode == MV_MFLASH_SPI) return mvSMFlashBlockRd(pFlash, offset, blockSize, pBlock); mvOsPrintf("%s ERROR: Invalid interface mode!\n", __FUNCTION__); return MV_BAD_PARAM; } /******************************************************************************* * mvMFlashSecErase - Erase the single sector of the main flash region * * DESCRIPTION: * Erase one sector of the main flash region * * INPUT: * pFlash: pointer to the MFlash information structure * secOffset: sector offset within the MFlash * * OUTPUT: * None. * * RETURN: * Success or Error code. * * *******************************************************************************/ MV_STATUS mvMFlashBlockInfRd (MV_MFLASH_INFO *pFlash, MV_U32 offset, MV_U32 blockSize, MV_U8 *pBlock) { /* check for NULL pointers */ if ((pFlash == NULL) || (pBlock == NULL)) { mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__); return MV_BAD_PARAM; } if (pFlash->ifMode == MV_MFLASH_PARALLEL) return mvPMFlashBlockInfRd(pFlash, offset, blockSize, pBlock); else if (pFlash->ifMode == MV_MFLASH_SPI) return mvSMFlashBlockInfRd(pFlash, offset, blockSize, pBlock); mvOsPrintf("%s ERROR: Invalid interface mode!\n", __FUNCTION__); return MV_BAD_PARAM; } /******************************************************************************* * mvMFlashReadConfig - Read the Configuration register * * DESCRIPTION: * Perform the Read CONFIGx register RAB * * INPUT: * pFlash: pointer to the MFlash information structure * regNum: register number to read (1-4 in parallel and 3-4 in spi) * pConfigReg: pointer to read in the configuration register * * OUTPUT: * pConfigReg: pointer with the data read from the configuration register * * RETURN: * Success or Error code. * * *******************************************************************************/ MV_STATUS mvMFlashReadConfig (MV_MFLASH_INFO *pFlash, MV_U32 regNum, MV_U8 * pConfigReg) { /* check for NULL pointer */ if ((pFlash == NULL) || (pConfigReg == NULL)) { mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__); return MV_BAD_PARAM; } if (pFlash->ifMode == MV_MFLASH_PARALLEL) { switch (regNum) { case 1: return mvPMFlashReadConfig1(pFlash, pConfigReg); case 2: return mvPMFlashReadConfig2(pFlash, pConfigReg); case 3: return mvPMFlashReadConfig3(pFlash, pConfigReg); case 4: return mvPMFlashReadConfig4(pFlash, pConfigReg); default: DB(mvOsPrintf("%s WARNING: Not supported in parallel mode!!\n", __FUNCTION__);) return MV_NOT_SUPPORTED; } } else if (pFlash->ifMode == MV_MFLASH_SPI) { switch (regNum) { case 3: return mvSMFlashReadConfig3(pFlash, pConfigReg); case 4: return mvSMFlashReadConfig4(pFlash, pConfigReg); default: DB(mvOsPrintf("%s WARNING: Not supported in SPI mode!!\n", __FUNCTION__);) return MV_NOT_SUPPORTED; } } mvOsPrintf("%s ERROR: Invalid interface mode!\n", __FUNCTION__); return MV_BAD_PARAM; } /******************************************************************************* * mvMFlashSetConfig - Write to the Configuration register * * DESCRIPTION: * Perform the write CONFIGx register RAB * * INPUT: * pFlash: pointer to the MFlash information structure * regNum: register number to write (1-4 in parallel and 3-4 in spi) * configReg: Data to write in the configuration register * * OUTPUT: * None. * * RETURN: * Success or Error code. * * *******************************************************************************/ MV_STATUS mvMFlashSetConfig (MV_MFLASH_INFO *pFlash, MV_U32 regNum, MV_U8 configReg) { /* check for NULL pointer */ if (pFlash == NULL) { mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__); return MV_BAD_PARAM; } if (pFlash->ifMode == MV_MFLASH_PARALLEL) { switch (regNum) { case 1: return mvPMFlashSetConfig1(pFlash, configReg); case 2: return mvPMFlashSetConfig2(pFlash, configReg); case 3: return mvPMFlashSetConfig3(pFlash, configReg); case 4: return mvPMFlashSetConfig4(pFlash, configReg); default: DB(mvOsPrintf("%s WARNING: Not supported in parallel mode!!\n", __FUNCTION__);) return MV_NOT_SUPPORTED; } } else if (pFlash->ifMode == MV_MFLASH_SPI) { switch (regNum) { case 3: return mvSMFlashSetConfig3(pFlash, configReg); case 4: return mvSMFlashSetConfig4(pFlash, configReg); default: DB(mvOsPrintf("%s WARNING: Not supported in SPI mode!!\n", __FUNCTION__);) return MV_NOT_SUPPORTED; } } mvOsPrintf("%s ERROR: Invalid interface mode!\n", __FUNCTION__); return MV_BAD_PARAM; } /******************************************************************************* * mvMFlashSetSlewRate - Set the slew rate for parallel interface * * DESCRIPTION: * Perform the set slew rate register RAB * * INPUT: * pFlash: pointer to the MFlash information structure * configReg: Data to write in the slew rate register * * OUTPUT: * None. * * RETURN: * Success or Error code. * * *******************************************************************************/ MV_STATUS mvMFlashSetSlewRate (MV_MFLASH_INFO *pFlash, MV_U8 configReg) { /* check for NULL pointer */ if (pFlash == NULL) { mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__); return MV_BAD_PARAM; } if (pFlash->ifMode == MV_MFLASH_PARALLEL) return mvPMFlashSetSlewRate(pFlash, configReg); DB(mvOsPrintf("%s WARNING: Invalid interface mode!\n", __FUNCTION__);) return MV_BAD_PARAM; } /******************************************************************************* * mvMFlashWriteProtectSet - Set the write protection feature status * * DESCRIPTION: * Enable or disable the write protection * * INPUT: * pFlash: pointer to the MFlash information structure * wp: write protection status (enable = MV_TRUE, disable = MVFALSE) * * OUTPUT: * None. * * RETURN: * Success or Error code. * * *******************************************************************************/ MV_STATUS mvMFlashWriteProtectSet (MV_MFLASH_INFO *pFlash, MV_BOOL wp) { MV_U32 reg; /* check for NULL pointer */ if (pFlash == NULL) { mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__); return MV_BAD_PARAM; } /* read, modify then write the register */ reg = MV_REG_READ(MV_PMFLASH_IF_CFG_REG); if (wp) /* active low */ reg &= ~MV_PMFLASH_WP_PROTECT_MASK; else reg |= MV_PMFLASH_WP_PROTECT_MASK; MV_REG_WRITE(MV_PMFLASH_IF_CFG_REG, reg); return MV_OK; #if 0 if (pFlash->ifMode == MV_MFLASH_PARALLEL) return mvPMFlashWriteProtectSet(pFlash, wp); else if (pFlash->ifMode == MV_MFLASH_SPI) return mvSMFlashWriteProtectSet(pFlash, wp); mvOsPrintf("%s ERROR: Invalid interface mode!\n", __FUNCTION__); return MV_BAD_PARAM; #endif } /******************************************************************************* * mvMFlashWriteProtectGet - Get the write protection feature status * * DESCRIPTION: * Retreive the write protection status from the hardware (from the MFlash * controller and not from the flash device configuration register) * * INPUT: * pFlash: pointer to the MFlash information structure * wp: pointer to the variable to retreive the write protection status in * * OUTPUT: * None. * wp: pointer to the variable holding the write protection status * (enable = MV_TRUE, disable = MVFALSE) * * RETURN: * Success or Error code. * * *******************************************************************************/ MV_STATUS mvMFlashWriteProtectGet(MV_MFLASH_INFO *pFlash, MV_BOOL * pWp) { MV_U32 reg; /* check for NULL pointer */ if (pFlash == NULL) { mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__); return MV_BAD_PARAM; } /* read the register and check the bit status */ reg = MV_REG_READ(MV_PMFLASH_IF_CFG_REG); if (reg & MV_PMFLASH_WP_PROTECT_MASK) *pWp = MV_FALSE; else *pWp = MV_TRUE; return MV_OK; } /******************************************************************************* * mvMFlashSectorSizeSet - Set the sector size * * DESCRIPTION: * Set the sector size of the MFLASH main region * * INPUT: * pFlash: pointer to the MFlash information structure * secSize: size of sector in bytes (either 4K or 32K) * * OUTPUT: * None. * * RETURN: * Success or Error code. * * *******************************************************************************/ MV_STATUS mvMFlashSectorSizeSet (MV_MFLASH_INFO *pFlash, MV_U32 secSize) { MV_STATUS ret; /* check for NULL pointer */ if (pFlash == NULL) { mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__); return MV_BAD_PARAM; } if (pFlash->ifMode == MV_MFLASH_PARALLEL) ret = mvPMFlashSectorSizeSet(pFlash, secSize); else if (pFlash->ifMode == MV_MFLASH_SPI) ret = mvSMFlashSectorSizeSet(pFlash, secSize); else { mvOsPrintf("%s ERROR: Invalid interface mode!\n", __FUNCTION__); return MV_BAD_PARAM; } if (ret != MV_OK) return ret; /* update the sector size and number in the structure */ switch (pFlash->flashModel) { case MV_MFLASH_SUNOL_1: if (secSize == MV_MFLASH_SECTOR_SIZE_SMALL) { pFlash->sectorSize = MV_MFLASH_SECTOR_SIZE_SMALL; pFlash->sectorNumber = MV_MFLASH_SMALL_SEC_NUM_SUNOL_1; } else { pFlash->sectorSize = MV_MFLASH_SECTOR_SIZE_BIG; pFlash->sectorNumber = MV_MFLASH_BIG_SEC_NUM_SUNOL_1; } break; case MV_MFLASH_SUNOL_2: if (secSize == MV_MFLASH_SECTOR_SIZE_SMALL) { pFlash->sectorSize = MV_MFLASH_SECTOR_SIZE_SMALL; pFlash->sectorNumber = MV_MFLASH_SMALL_SEC_NUM_SUNOL_2; } else { pFlash->sectorSize = MV_MFLASH_SECTOR_SIZE_BIG; pFlash->sectorNumber = MV_MFLASH_BIG_SEC_NUM_SUNOL_2; } break; case MV_MFLASH_SUNOL_3: if (secSize == MV_MFLASH_SECTOR_SIZE_SMALL) { pFlash->sectorSize = MV_MFLASH_SECTOR_SIZE_SMALL; pFlash->sectorNumber = MV_MFLASH_SMALL_SEC_NUM_SUNOL_3; } else { pFlash->sectorSize = MV_MFLASH_SECTOR_SIZE_BIG; pFlash->sectorNumber = MV_MFLASH_BIG_SEC_NUM_SUNOL_3; } break; default: mvOsPrintf("%s ERROR: Unknown Flash Type!\n", __FUNCTION__); return MV_NOT_SUPPORTED; } return MV_OK; } /******************************************************************************* * mvMFlashPrefetchSet - Set the Prefetch mode enable/disable * * DESCRIPTION: * Enable (MV_TRUE) or Disable (MV_FALSE) the prefetch mode * * INPUT: * pFlash: pointer to the MFlash information structure * prefetch: enable/disable (MV_TRUE/MV_FALSE) * * OUTPUT: * None. * * RETURN: * Success or Error code. * * *******************************************************************************/ MV_STATUS mvMFlashPrefetchSet (MV_MFLASH_INFO *pFlash, MV_BOOL prefetch) { /* check for NULL pointer */ if (pFlash == NULL) { mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__); return MV_BAD_PARAM; } if (pFlash->ifMode == MV_MFLASH_PARALLEL) return mvPMFlashPrefetchSet(pFlash, prefetch); DB(mvOsPrintf("%s WARNING: Invalid interface mode!\n", __FUNCTION__);) return MV_BAD_PARAM; } /******************************************************************************* * mvMFlashShutdownSet - Shutdown the voltage regulator in the flash device * * DESCRIPTION: * Causes the device to enter in a power save mode untill the next access * to the flash. * * INPUT: * pFlash: pointer to the MFlash information structure * * OUTPUT: * None. * * RETURN: * Success or Error code. * * *******************************************************************************/ MV_STATUS mvMFlashShutdownSet(MV_MFLASH_INFO *pFlash) { /* check for NULL pointer */ if (pFlash == NULL) { mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__); return MV_BAD_PARAM; } if (pFlash->ifMode == MV_MFLASH_PARALLEL) return mvPMFlashShutdownSet(pFlash); else if (pFlash->ifMode == MV_MFLASH_SPI) return mvSMFlashShutdownSet(pFlash); mvOsPrintf("%s ERROR: Invalid interface mode!\n", __FUNCTION__); return MV_BAD_PARAM; } /******************************************************************************* * mvMFlashIdGet - Retreive the MFlash's manufacturer and device IDs * * DESCRIPTION: * Read from the flash the 32bit manufacturer Id and the 16bit device ID * * INPUT: * pFlash: pointer to the MFlash information structure * pManfId: pointer to the 32bit variable to read the manufacturer ID in * pDevId: pointer to the 16bit variable to read the device ID in * * OUTPUT: * pManfId: pointer to the 32bit variable holding the manufacturer ID * pDevId: pointer to the 16bit variable holding the device ID * * RETURN: * Success or Error code. * * *******************************************************************************/ MV_STATUS mvMFlashIdGet (MV_MFLASH_INFO *pFlash, MV_U32 * pManfId, MV_U16 * pDevId) { /* check for NULL pointer */ if ((pFlash == NULL) || (pManfId == NULL) || (pDevId == NULL)) { mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__); return MV_BAD_PARAM; } if (pFlash->ifMode == MV_MFLASH_PARALLEL) return mvPMFlashIdGet(pFlash, pManfId, pDevId); else if (pFlash->ifMode == MV_MFLASH_SPI) return mvSMFlashIdGet(pFlash, pManfId, pDevId); mvOsPrintf("%s ERROR: Invalid interface mode!\n", __FUNCTION__); return MV_BAD_PARAM; } /******************************************************************************* * mvMFlashReset - Reset the flash device and the MFlash glue logic * * DESCRIPTION: * Perfom a hard reset for the Marvell Flash and the controller interface * * INPUT: * pFlash: pointer to the MFlash information structure * * OUTPUT: * None. * * RETURN: * Success or Error code. * * *******************************************************************************/ MV_STATUS mvMFlashReset(MV_MFLASH_INFO *pFlash) { MV_U32 reg; /* check for NULL pointer */ if (pFlash == NULL) { mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__); return MV_BAD_PARAM; } /* set both bits 4 and 5 */ reg = MV_REG_READ(MV_PMFLASH_IF_CFG_REG); reg |= (MV_PMFLASH_RESET_MASK | MV_PMFLASH_IF_RESET_MASK); MV_REG_WRITE(MV_PMFLASH_IF_CFG_REG, reg); /* Insert a short delay */ mvOsDelay(1); /* 1ms */ /* reset both bits 4 and 5 */ reg = MV_REG_READ(MV_PMFLASH_IF_CFG_REG); reg &= ~(MV_PMFLASH_RESET_MASK | MV_PMFLASH_IF_RESET_MASK); MV_REG_WRITE(MV_PMFLASH_IF_CFG_REG, reg); return MV_OK; }