1
0
uboot-1.1.4-kirkwood/board/mv_feroceon/USP/mv_flash.c

1686 lines
49 KiB
C
Raw Permalink Normal View History

2024-01-07 23:58:22 +01:00
/*******************************************************************************
Copyright (C) Marvell International Ltd. and its affiliates
********************************************************************************
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.
*******************************************************************************/
#include <common.h>
#include <command.h>
#include <config.h>
#if (CONFIG_COMMANDS & CFG_CMD_FLASH)
#include <console.h>
#include "norflash/mvFlash.h"
#include "device/mvDeviceRegs.h"
#include "mvBoardEnvSpec.h"
#include "mvOs.h"
#include "mvCtrlEnvLib.h"
#include "mvSysHwConfig.h"
#include "mvCpuIf.h"
#if defined (MV_INCLUDE_INTEG_MFLASH)
#include "mvMFlash.h"
#include "mvMFlashSpec.h"
#include "mvSMFlash.h"
#include "mvPMFlash.h"
#endif
#if defined (MV_INC_BOARD_SPI_FLASH)
#include "sflash/mvSFlash.h"
#endif
/* #define MV_DEBUG */
#ifdef MV_DEBUG
#define DB(x) x
#else
#define DB(x)
#endif
#define FLASH_ROM 0xFFFD /* unknown flash type */
#define FLASH_RAM 0xFFFE /* unknown flash type */
#define FLASH_MAN_UNKNOWN 0xFFFF0000
#define NL_HASHES_PER_LINE 65
#define CFI_CMDSET_INTEL_EXTENDED 1
#define CFI_CMDSET_AMD_STANDARD 2
#define CFI_CMDSET_INTEL_STANDARD 3
#define CFI_CMDSET_AMD_EXTENDED 4
void flashInfoCopy(flash_info_t *flash_info, MV_FLASH_INFO *pFlash);
MV_U32 getMvFlashInfoNum(flash_info_t *flash_info);
MV_FLASH_INFO* getMvFlashInfo(int index);
int mv_flash_real_protect(flash_info_t *info, long sector, int prot);
int mv_flash_real_protect_bank(flash_info_t *info, int prot);
#if defined (MV_INCLUDE_INTEG_MFLASH)
void mflash_print_info (MV_MFLASH_INFO * pInfo);
unsigned long mflash_init (MV_MFLASH_INFO * mflInfo);
#endif
#if defined (MV_INC_BOARD_SPI_FLASH)
void sflash_print_info (MV_SFLASH_INFO * pInfo);
unsigned long sflash_init (MV_SFLASH_INFO * sflInfo);
#endif
/* use CFG_MAX_FLASH_BANKS_DETECT if defined */
#ifdef CFG_MAX_FLASH_BANKS_DETECT
static MV_FLASH_INFO mvFlashInfo[CFG_MAX_FLASH_BANKS_DETECT];
extern flash_info_t flash_info[CFG_MAX_FLASH_BANKS_DETECT]; /* FLASH chips info */
extern int mv_board_num_flash_banks;
#else
static MV_FLASH_INFO mvFlashInfo[CFG_MAX_FLASH_BANKS];
extern flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips */
#endif
/* Static Variables */
#if defined (MV_INCLUDE_INTEG_MFLASH)
static MV_MFLASH_INFO mflash;
#endif
#if defined (MV_INC_BOARD_SPI_FLASH)
static MV_SFLASH_INFO sflash = {0x0, 0, 0, 0, 0, 0, MV_INVALID_DEVICE_NUMBER};
#endif
static unsigned long norFlashBanksNum = 0;
static unsigned long mFlashBanksNum = 0;
static unsigned long sFlashBanksNum = 0;
typedef enum
{
MV_UNKNOWN_FLASH = 0,
MV_NOR_FLASH,
MV_MARVELL_FLASH,
MV_SPI_FLASH
} MV_FLASH_TYPE;
/* return NULL in case didn't find a matching mvFlashInfo */
MV_FLASH_INFO* getMvFlashInfo(int index)
{
if (CFG_MAX_FLASH_BANKS < index)
return NULL;
return &mvFlashInfo[index];
}
/* based on index get the type of flash */
static MV_FLASH_TYPE mvFlashTypeFromIndexGet(MV_U32 indx)
{
if ((indx >= 0) && (indx < norFlashBanksNum))
return MV_NOR_FLASH;
else if ((indx >= norFlashBanksNum) && \
(indx < (norFlashBanksNum + mFlashBanksNum)))
return MV_MARVELL_FLASH;
else if ((indx >= (norFlashBanksNum + mFlashBanksNum)) &&
(indx < (norFlashBanksNum + mFlashBanksNum + sFlashBanksNum)))
return MV_SPI_FLASH;
return MV_UNKNOWN_FLASH;
}
/* return 0xFFFFFFFF in case didn't find a matching mvFlashInfo */
MV_U32
getMvFlashInfoNum(flash_info_t * pFlash_info)
{
MV_U32 i;
DB(mvOsPrintf("%s\n", __FUNCTION__));
if( pFlash_info->flash_id == FLASH_UNKNOWN )
{
DB(printf("%s : ERROR didn't find mvFlashInfo matching to flash_info_t.\n", __FUNCTION__));
return 0xFFFFFFFF;
}
for (i = 0; i < CFG_MAX_FLASH_BANKS; i++)
{
if (&flash_info[i] == pFlash_info)
{
DB(printf("getMvFlashInfoNum found mvFlashInfo %d \n",i));
return i;
}
DB(mvOsPrintf(" %x %x \n",mvFlashBaseAddrGet(&mvFlashInfo[i]), mvFlashVenIdGet(&mvFlashInfo[i])));
}
DB(mvOsPrintf("%s(%d): ERROR didn't find mvFlashInfo matching to flash_info_t.\n", __FUNCTION__));
return 0xFFFFFFFF;
}
/* make sure that #define CFG_FLASH_PROTECTION present in MV64xx.h */
int
mv_flash_real_protect(flash_info_t *info, long sector, int prot)
{
MV_U32 s;
s = getMvFlashInfoNum(info);
if(s >= CFG_MAX_FLASH_BANKS)
{
DB(printf("mv_flash_real_protect illegal mvFlashInfo \n"));
return 1;
}
switch(mvFlashTypeFromIndexGet(s))
{
#if defined (MV_INC_BOARD_NOR_FLASH)
case MV_NOR_FLASH:
if( mvFlashSecLockSet(&mvFlashInfo[s],sector,prot) != MV_OK)
return 1; /* Write was not completed */
info->protect[sector] = prot;
break;
#endif
#if defined (MV_INCLUDE_INTEG_MFLASH)
case MV_MARVELL_FLASH:
/* printf("MFlash WP modification per sector is not supported by this command!!\n"); */
if(mv_flash_real_protect_bank(info, prot) != MV_OK)
return 1;
break;
#endif
#if defined (MV_INC_BOARD_SPI_FLASH)
case MV_SPI_FLASH:
/* printf("SPI Flash WP modification per sector is not supported by this command!!\n"); */
if(mv_flash_real_protect_bank(info, prot) != MV_OK)
return 1;
break;
#endif
default:
return 1;
}
return 0; /* write completed succefully */
}
int
mv_flash_real_protect_bank(flash_info_t *info, int prot)
{
MV_U32 s;
MV_U32 i;
s = getMvFlashInfoNum(info);
if(s >= CFG_MAX_FLASH_BANKS)
{
DB(printf("mv_flash_real_protect_bank illegal mvFlashInfo \n"));
return 1;
}
switch(mvFlashTypeFromIndexGet(s))
{
#if defined (MV_INC_BOARD_NOR_FLASH)
case MV_NOR_FLASH:
for (i=0; i<info->sector_count; ++i)
{
if( mvFlashSecLockSet(&mvFlashInfo[s],i,prot) != MV_OK)
return 1; /* Write was not completed */
info->protect[i] = prot;
putc ('.');
}
break;
#endif
#if defined (MV_INCLUDE_INTEG_MFLASH)
case MV_MARVELL_FLASH:
if (mvMFlashWriteProtectSet(&mflash, prot) != MV_OK)
return 1;
for (i=0; i<info->sector_count; ++i)
{
info->protect[i] = prot;
/* putc ('.');
if (((i+1)%64) == 0)
printf("\n"); */
}
break;
#endif
#if defined (MV_INC_BOARD_SPI_FLASH)
case MV_SPI_FLASH:
if (prot)
{
if (mvSFlashWpRegionSet(&sflash, MV_WP_ALL) != MV_OK)
return 1;
}
else
{
if (mvSFlashWpRegionSet(&sflash, MV_WP_NONE) != MV_OK)
return 1;
}
for (i=0; i<info->sector_count; ++i)
{
info->protect[i] = prot;
putc ('.');
if (((i+1)%64) == 0)
printf("\n");
}
break;
#endif
default:
return 1;
}
return 0; /* write completed succefully */
}
/********************************************************************
* Copy global CFI info into Marvell FLash info
********************************************************************/
void flashMvInfoCopy(flash_info_t *flash_info, MV_FLASH_INFO *pFlash)
{
MV_U32 i;
/* Check if flash_info containe CFI data */
if(mvFlashVenIdGet(pFlash) != FLASH_UNKNOWN)
{
return;
}
if(flash_info->flash_id == FLASH_UNKNOWN)
{
pFlash->flashSpec.flashVen = FLASH_UNKNOWN;
return;
}
/* convert to MV_FLASH_INFO manufactor Id */
switch (flash_info->vendor)
{
case CFI_CMDSET_INTEL_STANDARD:
case CFI_CMDSET_INTEL_EXTENDED:
pFlash->flashSpec.flashVen = INTEL_MANUF;
break;
case CFI_CMDSET_AMD_STANDARD:
case CFI_CMDSET_AMD_EXTENDED:
pFlash->flashSpec.flashVen = AMD_MANUF;
break;
default:
pFlash->flashSpec.flashVen = 0;
break;
}
/* convert to MV_FLASH_INFO flash Id */
pFlash->flashSpec.flashId = (flash_info->flash_id & FLASH_TYPEMASK);
/* other flash info parameters */
pFlash->flashSpec.size = (flash_info->size / (flash_info->portwidth / flash_info->chipwidth));
pFlash->flashSpec.sectorNum = flash_info->sector_count;
pFlash->busWidth = flash_info->portwidth;
pFlash->devWidth = flash_info->chipwidth;
/* sectors parameters */
for(i = 0; i < flash_info->sector_count; i++)
{
pFlash->sector[i].baseOffs = flash_info->start[i] - flash_info->start[0];
pFlash->sector[i].protect = flash_info->protect[i];
if (i + 1 < flash_info->sector_count)
pFlash->sector[i].size = flash_info->start[i+1] - flash_info->start[i];
else
pFlash->sector[i].size = (flash_info->start[0] + flash_info->size) - flash_info->start[i];
}
pFlash->baseAddr = flash_info->start[0];
return;
}
void
flashInfoCopy(flash_info_t *flash_info, MV_FLASH_INFO *pFlash)
{
MV_U32 i;
/* Check if flash_info containe CFI data */
if(flash_info->flash_id != FLASH_UNKNOWN)
{
return;
}
if(mvFlashVenIdGet(pFlash) == FLASH_UNKNOWN)
{
flash_info->flash_id = FLASH_UNKNOWN;
return;
}
/* convert to U-Boot manufactor Id */
flash_info->flash_id = ((mvFlashVenIdGet(pFlash) << 16) & FLASH_VENDMASK);
/* convert to U-Boot flash Id */
flash_info->flash_id |= (mvFlashDevIdGet(pFlash) & FLASH_TYPEMASK);
/* other flash info parameters */
flash_info->size = mvFlashSizeGet(pFlash);
flash_info->sector_count = mvFlashNumOfSecsGet(pFlash);
flash_info->portwidth = mvFlashBusWidthGet(pFlash);
flash_info->chipwidth = mvFlashDevWidthGet(pFlash);
/* sectors parameters */
for(i = 0; i < mvFlashNumOfSecsGet(pFlash); i++)
{
flash_info->start[i] = mvFlashSecOffsGet(pFlash,i) + mvFlashBaseAddrGet(pFlash);
flash_info->protect[i] = mvFlashSecLockGet(pFlash,i);
}
return;
}
#if defined (MV_INCLUDE_INTEG_MFLASH)
void
mflashInfoCopy(flash_info_t *flash_info, MV_MFLASH_INFO *pFlash)
{
MV_U32 i;
MV_U32 mfId;
MV_U16 devId;
MV_BOOL wp;
/* Check if the Model was detected during the init stage and read the WP status */
if ((pFlash->flashModel == MV_MFLASH_MODEL_UNKNOWN) ||
(mvMFlashIdGet(pFlash, &mfId, &devId) != MV_OK) ||
(mvMFlashWriteProtectGet(pFlash, &wp) != MV_OK))
{
flash_info->flash_id = FLASH_UNKNOWN;
return;
}
/* Discard the manufacturer ID and use the device ID alnoe because we lack 16 bits */
flash_info->flash_id = devId;
/* other flash info parameters */
flash_info->size = (pFlash->sectorSize * pFlash->sectorNumber);
flash_info->sector_count = pFlash->sectorNumber;
flash_info->portwidth = 1; /* Assuming 8bit although that this parameter is not used */
flash_info->chipwidth = 1; /* Assuming 8bit although that this parameter is not used */
/* sectors parameters */
for(i = 0; i < pFlash->sectorNumber; i++)
{
flash_info->start[i] = (pFlash->baseAddr + (i * pFlash->sectorSize));
flash_info->protect[i] = wp;
}
return;
}
#endif /* #if defined (MV_INCLUDE_INTEG_MFLASH) */
#if defined (MV_INC_BOARD_SPI_FLASH)
void
sflashInfoCopy(flash_info_t *flash_info, MV_SFLASH_INFO *pFlash)
{
MV_U32 i;
MV_SFLASH_WP_REGION wp;
MV_BOOL wpVal;
/* Check if the Model was detected during the init stage and read thw WP status */
if ((pFlash->manufacturerId == 0) ||
(mvSFlashWpRegionGet(pFlash, &wp) != MV_OK))
{
flash_info->flash_id = FLASH_UNKNOWN;
return;
}
/* Discard the manufacturer ID and use the device ID alnoe because we lack 16 bits */
flash_info->flash_id = ((pFlash->manufacturerId << 16) | pFlash->deviceId);
/* other flash info parameters */
flash_info->size = (pFlash->sectorSize * pFlash->sectorNumber);
flash_info->sector_count = pFlash->sectorNumber;
flash_info->portwidth = 0; /* Serial interface */
flash_info->chipwidth = 0; /* Serial interface */
if (wp == MV_WP_ALL)
wpVal = MV_TRUE;
else
wpVal = MV_FALSE;
/* sectors parameters */
for(i = 0; i < pFlash->sectorNumber; i++)
{
flash_info->start[i] = (pFlash->baseAddr + (i * pFlash->sectorSize));
flash_info->protect[i] = wpVal;
}
return;
}
#endif
unsigned long
mvFlash_init (void)
{
MV_U32 i;
unsigned long current_bank_size=0;
unsigned long flash_size=0;
#if defined (MV_INC_BOARD_SPI_FLASH) || defined (MV_INCLUDE_INTEG_MFLASH)
MV_U32 bankIndx;
#endif /* defined (MV_INC_BOARD_SPI_FLASH) || defined (MV_INCLUDE_INTEG_MFLASH) */
/* Init: no FLASHes known */
for (i=0; i<CFG_MAX_FLASH_BANKS; ++i) {
mvFlashInfo[i].flashSpec.flashVen = FLASH_UNKNOWN;
}
#if defined (MV_INC_BOARD_NOR_FLASH)
/* Get the number of devices of each Flash type */
norFlashBanksNum = mvBoardGetDevicesNumber(BOARD_DEV_NOR_FLASH);
DB(printf("Number of NOR flashes on board %d\n",norFlashBanksNum);)
if (norFlashBanksNum > CFG_MAX_FLASH_BANKS)
{
printf("%s ERROR: Number of flash devices exceeds the CFG_MAX_FLASH_BANKS=0x%x\n", __FUNCTION__,CFG_MAX_FLASH_BANKS);
return 0;
}
for (i=0; i < norFlashBanksNum; ++i)
{
/* CFI driver detected the device */
if (flash_info[i].flash_id != FLASH_UNKNOWN)
{
printf("[%ldkB@%x] ", flash_info[i].size/1024, flash_info[i].start[0]);
continue;
}
mvFlashInfo[i].baseAddr = mvBoardGetDeviceBaseAddr(i, BOARD_DEV_NOR_FLASH);
DB(printf("mvFlashInfo[%d].baseAddr %x\n",i,mvFlashInfo[i].baseAddr);)
mvFlashInfo[i].busWidth = mvBoardGetDeviceBusWidth(i, BOARD_DEV_NOR_FLASH)/8;
DB(printf("mvFlashInfo[%d].busWidth %x\n",i,mvFlashInfo[i].busWidth);)
mvFlashInfo[i].devWidth = mvBoardGetDeviceWidth(i, BOARD_DEV_NOR_FLASH)/8;
DB(printf("mvFlashInfo[%d].devWidth %x\n",i,mvFlashInfo[i].devWidth);)
if (mvFlashInfo[i].baseAddr == 0xffffffff) continue;
current_bank_size = mvFlashInit(&mvFlashInfo[i]);
flashInfoCopy(&flash_info[i], &mvFlashInfo[i]);
printf("[%ldkB@%x] ", flash_info[i].size/1024, flash_info[i].start[0]);
if (flash_info[i].flash_id == FLASH_UNKNOWN)
{
printf ("## Unknown FLASH at %08x: Size = 0x%08lx = %ld MB\n",
mvFlashInfo[i].baseAddr, current_bank_size, current_bank_size<<20);
}
flash_size += current_bank_size;
}
/* Copy from CFI to MV_FLASH_INFO the CFI data */
for (i=0; i < norFlashBanksNum; ++i)
flashMvInfoCopy(&flash_info[i], &mvFlashInfo[i]);
#endif /* #if defined (MV_INC_BOARD_NOR_FLASH) */
#if defined (MV_INCLUDE_INTEG_MFLASH)
#ifdef MV_INCLUDE_INTEG_MFLASH_SPI
if (mvCtrlSpiBusModeSet(MV_SPI_CONN_TO_MFLASH) != MV_OK)
{
printf("Failed to set the SPI bus to the MFlash mode\n");
}
#endif
mflash.ifMode = MV_SPI_CONN_UNKNOWN; /* to be detected from H/W */
mflash.baseAddr = mvCpuIfTargetWinBaseLowGet(MFLASH_CS);
mflash.flashModel = MV_MFLASH_MODEL_UNKNOWN; /* will be detected in init */
mflash.sectorSize = 0; /* will be detected in init */
mflash.sectorNumber = 0; /* will be detected in init */
mflash.infoSize = 0; /* will be detected in init */
/* Try to initialize the Marvell Flash - returns the size of flash detected */
if (mflash_init(&mflash) != 0)
{
/* update the number of Marvell flashes detected to be used in index calculation */
mFlashBanksNum = 1;
DB(printf("Number of Marvell flashes on board %d\n", mFlashBanksNum);)
/* check that we did not exceed the MAX flash banks supported */
if ((norFlashBanksNum + mFlashBanksNum) > CFG_MAX_FLASH_BANKS)
{
printf("%s ERROR: Number of flash devices exceeds the CFG_MAX_FLASH_BANKS\n", __FUNCTION__);
return 0;
}
/* Set the default sector size to small - needed for saveenv in the UBoot */
if (mvMFlashSectorSizeSet(&mflash, MV_MFLASH_SECTOR_SIZE_SMALL) != MV_OK)
{
printf("%s ERROR: Failed to set MFlash sector size to SMALL\n", __FUNCTION__);
return 0;
}
current_bank_size = (mflash.sectorSize * mflash.sectorNumber);
bankIndx = norFlashBanksNum;
mflashInfoCopy(&flash_info[bankIndx], &mflash);
printf("[%ldkB@%x] ", current_bank_size/1024, mflash.baseAddr);
if (mflash.flashModel == MV_MFLASH_MODEL_UNKNOWN)
{
printf ("## Unknown MFLASH at %08x: Size = 0x%08lx = %ld MB\n",
mflash.baseAddr, current_bank_size, current_bank_size<<20);
}
flash_size += current_bank_size;
}
else
{
DB(printf("Failed to initialize the Marvell Flash!\n");)
}
#endif /* #if defined (MV_INCLUDE_INTEG_MFLASH) */
#if defined (MV_INC_BOARD_SPI_FLASH)
sflash.baseAddr = mvCpuIfTargetWinBaseLowGet(SPI_CS);
sflash.manufacturerId = 0; /* will be detected in init */
sflash.deviceId = 0; /* will be detected in init */
sflash.sectorSize = 0; /* will be detected in init */
sflash.sectorNumber = 0; /* will be detected in init */
sflash.pageSize = 0; /* will be detected in init */
sflash.index = MV_INVALID_DEVICE_NUMBER; /* will be detected in init */
/* Try to initialize an external SPI flash and retreive the size in case of success */
if ((current_bank_size = sflash_init(&sflash)) != 0)
{
/* update the number of SPI flashes detected to be used in index calculation */
sFlashBanksNum = 1;
DB(printf("Number of SPI flashes on board %d\n", sFlashBanksNum);)
/* check that we did not exceed the MAX flash banks supported */
if ((norFlashBanksNum + mFlashBanksNum + sFlashBanksNum) > CFG_MAX_FLASH_BANKS)
{
printf("%s ERROR: Number of flash devices exceeds the CFG_MAX_FLASH_BANKS\n", __FUNCTION__);
return 0;
}
/* convert the SFlash structure into the Uboot structre */
bankIndx = (norFlashBanksNum + mFlashBanksNum);
sflashInfoCopy(&flash_info[bankIndx], &sflash);
printf("[%ldkB@%x] ", current_bank_size/1024, sflash.baseAddr);
/* verify that the manufacturer Id was detected */
if (sflash.manufacturerId == 0)
{
printf ("## Unknown SFLASH at %08x: Size = 0x%08lx = %ld MB\n",
sflash.baseAddr, current_bank_size, current_bank_size<<20);
}
flash_size += current_bank_size;
}
else
{
DB(printf("Failed to initialize the SPI Flash!\n");)
}
#endif /* #if defined (MV_INC_BOARD_SPI_FLASH) */
/* Set the write protection */
if (norFlashBanksNum >= 1)
{
flash_protect (FLAG_PROTECT_SET,
CFG_MONITOR_BASE,
CFG_MONITOR_BASE + CFG_MONITOR_LEN - 1,
&flash_info[0]);
flash_protect(FLAG_PROTECT_SET,
CFG_ENV_ADDR,CFG_ENV_ADDR + CFG_ENV_SECT_SIZE,
&flash_info[0]);
}
//modfiy by QNAP: protect off all SPI flash
#if defined (MV_INC_BOARD_SPI_FLASH)
if (mvSFlashWpRegionSet(&sflash, MV_WP_NONE) != 0)
printf("\nIn mvFlash_init:Failed to set the write protection to NONE.\n");
#endif
///////////
return flash_size;
}
/*-----------------------------------------------------------------------
*/
void
mv_flash_print_info (flash_info_t *info)
{
MV_U32 s;
s = getMvFlashInfoNum(info);
if(s >= CFG_MAX_FLASH_BANKS)
{
printf("missing or unknown FLASH type\n");
return;
}
switch(mvFlashTypeFromIndexGet(s))
{
#if defined (MV_INC_BOARD_NOR_FLASH)
case MV_NOR_FLASH:
flashPrint(&mvFlashInfo[s]);
break;
#endif
#if defined (MV_INCLUDE_INTEG_MFLASH)
case MV_MARVELL_FLASH:
mflash_print_info(&mflash);
break;
#endif
#if defined (MV_INC_BOARD_SPI_FLASH)
case MV_SPI_FLASH:
sflash_print_info(&sflash);
break;
#endif
default:
printf("Unknown flash type on selected bank!\n");
}
return;
}
/*-----------------------------------------------------------------------
*/
int
mv_flash_erase (flash_info_t *info, int s_first, int s_last)
{
MV_U32 i,s;
MV_STATUS ret;
#if defined (MV_INCLUDE_INTEG_MFLASH)
MV_BOOL mvMFstatus;
#endif
#if defined (MV_INC_BOARD_SPI_FLASH)
MV_SFLASH_WP_REGION mvSFstatus;
#endif
DB(printf("%s: sectors %d - %d \n", __FUNCTION__, s_first, s_last));
s = getMvFlashInfoNum(info);
if(s >= CFG_MAX_FLASH_BANKS)
{
DB(printf("%s: illegal mvFlashInfo \n", __FUNCTION__));
return 1;
}
printf("\n");
for(i = s_first; i <= s_last; i++)
{
switch(mvFlashTypeFromIndexGet(s))
{
#if defined (MV_INC_BOARD_NOR_FLASH)
case MV_NOR_FLASH:
DB(printf("%s: calling mvFlashSecErase sector %d, base=%x, sec=%x\n", __FUNCTION__, i,mvFlashInfo[s].baseAddr, mvFlashInfo[s].sector[i].baseOffs));
ret = mvFlashSecErase(&mvFlashInfo[s],i);
break;
#endif
#if defined (MV_INCLUDE_INTEG_MFLASH)
case MV_MARVELL_FLASH:
DB(printf("%s: calling mvMFlashSecErase sector %d, base=%x, sec=%x\n", __FUNCTION__, i,mvFlashInfo[s].baseAddr, mvFlashInfo[s].sector[i].baseOffs));
/* Check protect on/off */
mvMFlashWriteProtectGet(&mflash,&mvMFstatus);
if (mvMFstatus == MV_TRUE)
{
ret = MV_FAIL;
break;
}
ret = mvMFlashSecErase(&mflash, i);
break;
#endif
#if defined (MV_INC_BOARD_SPI_FLASH)
case MV_SPI_FLASH:
DB(printf("%s: calling mvSFlashSectorErase sector %d, base=%x, sec=%x\n", __FUNCTION__, i,mvFlashInfo[s].baseAddr, mvFlashInfo[s].sector[i].baseOffs));
/* Check protect on/off */
mvSFlashWpRegionGet (&sflash, &mvSFstatus);
if (mvSFstatus == MV_WP_ALL)
{
ret = MV_FAIL;
break;
}
ret = mvSFlashSectorErase(&sflash, i);
break;
#endif
default:
mv_flash_print_info(info);
return 1;
}
if(ret != MV_OK)
{
printf("Erase fail!\n");
mv_flash_print_info(info);
return 1;
}
putc ('.');
if (((i+1) % (NL_HASHES_PER_LINE)) == 0)
{
puts ("\n");
}
}
puts("\n");
return 0;
}
/*-----------------------------------------------------------------------
* Copy memory to flash, returns:
* 0 - OK
* 1 - write timeout
* 2 - Flash not erased
*/
int
mv_write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
{
unsigned int s = 0;
s = getMvFlashInfoNum(info);
if(s >= CFG_MAX_FLASH_BANKS)
{
DB(printf("mv_write_buff illegal mvFlashInfo \n"));
return 1;
}
switch(mvFlashTypeFromIndexGet(s))
{
#if defined (MV_INC_BOARD_NOR_FLASH)
char *env;
case MV_NOR_FLASH:
env = getenv("enaFlashBuf");
if(( (strcmp(env,"yes") == 0) || (strcmp(env,"Yes") == 0) ))
{
if( mvFlashBlockWr(&mvFlashInfo[s],addr - mvFlashBaseAddrGet(&mvFlashInfo[s]) ,cnt,src) != cnt)
return 1; /* Write was not completed */
}
else
{
if( mvFlashBlockUnbufWr(&mvFlashInfo[s],addr - mvFlashBaseAddrGet(&mvFlashInfo[s]) ,cnt,src) != cnt)
return 1; /* Write was not completed */
}
break;
#endif
#if defined (MV_INCLUDE_INTEG_MFLASH)
case MV_MARVELL_FLASH:
if (mvMFlashBlockWr(&mflash, (addr - mflash.baseAddr), cnt, src, MV_FALSE /* no compare */) != MV_OK)
return 1; /* Write was not completed */
break;
#endif
#if defined (MV_INC_BOARD_SPI_FLASH)
case MV_SPI_FLASH:
if (mvSFlashBlockWr(&sflash, (addr - sflash.baseAddr), src, cnt) != MV_OK)
return 1; /* Write was not completed */
break;
#endif
default:
return 1;
}
return 0; /* write completed succefully */
}
#if (defined (MV_INCLUDE_INTEG_MFLASH)|| defined (MV_INC_BOARD_SPI_FLASH))
/*******************************************************************************
* rangeStrDecode - Decode a range string into 2 integers
*
* DESCRIPTION:
* Decode a string indicating a range like M-N into 2 integers M and N.
*
********************************************************************************/
static int rangeStrDecode (char * str, int * first, int * last, unsigned int sectNum)
{
char * sl, * ep;
if ((sl = strchr (str, '-')) == NULL) /* a single sector */
{
/* only a single bank is specified */
*first = simple_strtoul (str, &ep, 10);
if ((ep == str) || (*ep != '\0') || (*first >= sectNum) || (*first < 0))
return -1;
*last = *first;
return 0;
}
else /* we have a complete range M-N */
{
*sl++ = '\0';
*first = simple_strtoul (str, &ep, 10);
if ((ep == str) || (*ep != '\0') || (*first >= sectNum) || (*first < 0))
return -1;
*last = simple_strtoul (sl, &ep, 10);
if ((ep == str) || (*ep != '\0') || (*last >= sectNum) || (*last < 0))
return -1;
}
if (*first > *last)
return -1;
return 0;
}
#endif /* (defined (MV_INCLUDE_INTEG_MFLASH)|| defined (MV_INC_BOARD_SPI_FLASH)) */
/*#############################################################################*/
/*#############################################################################*/
/*###################### MFLASH COMMANDS #############################*/
/*#############################################################################*/
/*#############################################################################*/
#if defined (MV_INCLUDE_INTEG_MFLASH)
/*******************************************************************************
* mflash_init - Detect and Initialize the Integrated Marvell Flash
*
* DESCRIPTION:
* Try to detect the Marvell Flash integrated in the SOC. Based on the
* model detected, determine the flash size
*
* INPUT:
* None.
*
* OUTPUT:
* None.
*
* RETURN:
* Success or Error code.
*
*
*******************************************************************************/
unsigned long mflash_init (MV_MFLASH_INFO * mflInfo)
{
/* based on the SPI mode try to detect the Mflash device interface type */
if (mvCtrlSpiBusModeDetect() == MV_SPI_CONN_TO_MFLASH)
mflInfo->ifMode = MV_MFLASH_SPI;
else
mflInfo->ifMode = MV_MFLASH_PARALLEL;
/* Try to detect the flash and initialize it over the IF deteced */
if (mvMFlashInit(mflInfo) != MV_OK)
{
printf("%s ERROR: MFlash init failed\n", __FUNCTION__);
return 0;
}
return (mflInfo->sectorSize * mflInfo->sectorNumber);
}
/*******************************************************************************
* mflash_print_info - Print the Marvell flash info
*
* DESCRIPTION:
* Print the flash information of the specified instance
*
* INPUT:
* pInfo: pointer to the instance flash information structure.
*
* OUTPUT:
* None.
*
* RETURN:
* Success or Error code.
*
*
*******************************************************************************/
void mflash_print_info (MV_MFLASH_INFO * pInfo)
{
MV_U32 manf = 0;
MV_U16 dev = 0;
MV_BOOL wp;
printf("\nFlash Base Address : 0x%08x",pInfo->baseAddr);
if (pInfo->ifMode == MV_MFLASH_SPI)
printf("\nFlash Mode : SPI");
else if (pInfo->ifMode == MV_MFLASH_PARALLEL)
printf("\nFlash Mode : Parallel");
else
printf("\nFlash Mode : Unknown");
if (pInfo->flashModel != 0)
printf("\nFlash Model : SUNOL %d",(MV_U32)pInfo->flashModel);
else
printf("\nFlash Model : Unknown");
printf("\nSector Size : %dK", (pInfo->sectorSize / 1024));
printf("\nNumber of sectors : %d", pInfo->sectorNumber);
/* Get the Flash ID from the chip */
if (mvMFlashIdGet(pInfo, &manf, &dev) != MV_OK)
{
printf("\n\nFailed to get the Manufacturer and Device IDs!\n");
return;
}
/* Get the WP status from the chip */
if (mvMFlashWriteProtectGet(pInfo, &wp) != MV_OK)
{
printf("\n\nFailed to get the WP status!\n");
return;
}
printf("\nManufacturer ID : %08x", manf);
printf("\nDevice ID : %03x", (dev >> 4));
printf("\nDevice Revision : %01x", (dev & 0xF));
if (wp)
printf("\nWrite Protection : Enabled");
else
printf("\nWrite Protection : Disabled");
printf("\n\n");
}
/*******************************************************************************
* mflash_erase - Erase a set of sectors
*
* DESCRIPTION:
* Erase a set of sectors in the main flash region.
*
* INPUT:
* pInfo: pointer to the instance flash information structure.
* s_first: first sector to erase.
* s_last: last sector to erase.
*
* OUTPUT:
* None.
*
* RETURN:
* Success or Error code.
*
*
*******************************************************************************/
int mflash_erase (MV_MFLASH_INFO *pInfo, MV_U32 s_first, MV_U32 s_last)
{
MV_U32 i;
for (i=s_first; i<=s_last; i++)
{
/* perform the erase in serial mode */
if (mvMFlashSecErase(pInfo, i) != MV_OK)
return 1;
}
return 0;
}
/*******************************************************************************
* mflash_cmd - mflash command implimentation
*
* DESCRIPTION:
* parse and decode the mflash command
*
* INPUT:
* cmdtp: command table pointer
* flag: flags
* argc: command argument count
* argv: command argument vector
*
* OUTPUT:
* None.
*
* RETURN:
* Success or Error code.
*
*******************************************************************************/
int mflash_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
int first, last;
MV_U32 source, offset, size, dest;
MV_BOOL verify;
char * cp;
if (mFlashBanksNum < 1)
{
printf ("No Marvell Flash detected!\n");
return 1;
}
if (argc < 2)
{
printf ("Usage:\n%s\n", cmdtp->usage);
return 1;
}
if (strcmp(argv[1], "info") == 0)
{
/* check that we have the correct number of parameters */
if (argc != 2)
{
printf ("Usage:\n%s\n", cmdtp->usage);
return 1;
}
mflash_print_info(&mflash);
}
else if (strcmp(argv[1], "protect") == 0)
{
/* check that we have the correct number of parameters */
if (argc != 3)
{
printf ("Usage:\n%s\n", cmdtp->usage);
return 1;
}
if (strcmp(argv[2], "on") == 0) /* the whole chip */
{
if (mvMFlashWriteProtectSet(&mflash, MV_TRUE) != 0)
printf("\nFailed to enable write protection!\n");
}
else if (strcmp(argv[2], "off") == 0) /* the whole chip */
{
if (mvMFlashWriteProtectSet(&mflash, MV_FALSE) != 0)
printf("\nFailed to disable write protection!\n");
}
else
{
printf ("Usage:\n%s\n", cmdtp->usage);
return 1;
}
}
else if (strcmp(argv[1], "sector") == 0)
{
MV_U32 i,j;
/* check that we have the correct number of parameters */
if (argc != 3)
{
printf ("Usage:\n%s\n", cmdtp->usage);
return 1;
}
if (strcmp(argv[2], "small") == 0) /* the whole chip */
{
if (mvMFlashSectorSizeSet(&mflash, 0x1000) != 0)
{
printf("\nFailed to enable write protection!\n");
return 1;
}
}
else if (strcmp(argv[2], "large") == 0) /* the whole chip */
{
if (mvMFlashSectorSizeSet(&mflash, 0x8000) != 0)
{
printf("\nFailed to disable write protection!\n");
return 1;
}
}
else
{
printf ("Usage:\n%s\n", cmdtp->usage);
return 1;
}
/* Find the Mflash entry and update the sector count and protection status */
for (i=0; i<CFG_MAX_FLASH_BANKS; i++)
{
if (mvFlashTypeFromIndexGet(i) == MV_MARVELL_FLASH)
{
MV_BOOL wp = MV_FALSE;
flash_info[i].sector_count = mflash.sectorNumber;
if (mvMFlashWriteProtectGet(&mflash, &wp) != MV_OK)
{
printf("\nFailed to get the WP status!\n");
return 1;
}
/* update the WP status and sector offsets */
for (j=0; j<flash_info[i].sector_count; j++)
{
flash_info[i].protect[j] = wp;
flash_info[i].start[j] = (mflash.baseAddr + (j * mflash.sectorSize));
}
break;
}
}
}
else if (strcmp(argv[1], "erase") == 0) /* erase command */
{
/* check that we have the correct number of parameters */
if (argc != 3)
{
printf ("Usage:\n%s\n", cmdtp->usage);
return 1;
}
if (strcmp(argv[2], "chip") == 0) /* the whole chip */
{
if (mvMFlashChipErase(&mflash) != 0)
printf("\nFailed to erase the whole MFlash chip.\n", first, last);
}
else if (strcmp(argv[2], "main") == 0) /* only the main region */
{
if (mvMFlashMainErase(&mflash) != 0)
printf("\nFailed to erase the main region.\n", first, last);
}
else if (strcmp(argv[2], "info") == 0) /* ony the information region */
{
if (mvMFlashInfErase(&mflash) != 0)
printf("\nFailed to erase the information region\n", first, last);
}
else /* check if a range of sectors is specified */
{
if (rangeStrDecode(argv[2], &first, &last, mflash.sectorNumber) == 0)
{
if (mflash_erase(&mflash, first, last) != 0)
printf("\nFailed to erase sectors %d-%d\n", first, last);
}
else
{
printf ("Usage:\n%s\n", cmdtp->usage);
return 1;
}
}
}
else if (strcmp(argv[1], "read") == 0)
{
/* check that we have the correct number of parameters */
if (argc != 6)
{
printf ("Usage:\n%s\n", cmdtp->usage);
return 1;
}
offset = simple_strtoul (argv[3], &cp, 16);
if ((cp == argv[3]) || (*cp != '\0') || (offset < 0))
{
printf ("Invalid offset.");
return 1;
}
dest = simple_strtoul (argv[4], &cp, 16);
if ((cp == argv[4]) || (*cp != '\0') || (size < 0))
{
printf ("Invalid dest.");
return 1;
}
size = simple_strtoul (argv[5], &cp, 16);
if ((cp == argv[5]) || (*cp != '\0') || (size < 0))
{
printf ("Invalid size.");
return 1;
}
if (strcmp(argv[2], "main") == 0) /* ony the information region */
{
if (mvMFlashBlockRd(&mflash, offset, size, (MV_U8*) dest) != MV_OK)
printf ("Failed to read from the MFlash main region!\n");
}
else if (strcmp(argv[2], "info") == 0) /* ony the information region */
{
if (mvMFlashBlockInfRd(&mflash, offset, size, (MV_U8*) dest) != MV_OK)
printf ("Failed to read from the MFlash information region!\n");
}
else
{
printf ("Usage:\n%s\n", cmdtp->usage);
return 1;
}
}
else if (strcmp(argv[1], "write") == 0)
{
/* check that we have the correct number of parameters */
if ((argc != 6) && (argc != 7))
{
printf ("Usage:\n%s\n", cmdtp->usage);
return 1;
}
source = simple_strtoul (argv[3], &cp, 16);
if ((cp == argv[3]) || (*cp != '\0') || (source < 0))
{
printf ("Invalid size!\n");
return 1;
}
offset = simple_strtoul (argv[4], &cp, 16);
if ((cp == argv[4]) || (*cp != '\0') || (offset < 0))
{
printf ("Invalid offset!\n");
return 1;
}
size = simple_strtoul (argv[5], &cp, 16);
if ((cp == argv[5]) || (*cp != '\0') || (size < 0))
{
printf ("Invalid size!\n");
return 1;
}
/* check if the verify flag was used */
if (argc == 7)
{
if (strcmp(argv[6], "verify") != 0)
{
printf("Invalid verify flag!\n");
return 1;
}
verify = MV_TRUE;
}
else
verify = MV_FALSE;
if (strcmp(argv[2], "main") == 0) /* ony the information region */
{
if (mvMFlashBlockWr(&mflash,offset, size, (MV_U8*) source, verify) != MV_OK)
{
printf ("Failed to write to the MFlash main region!\n");
return 1;
}
}
else if (strcmp(argv[2], "info") == 0) /* ony the information region */
{
if (mvMFlashInfBlockWr(&mflash,offset, size, (MV_U8*) source, verify) != MV_OK)
{
printf ("Failed to write to the MFlash information region!\n");
return 1;
}
}
else
{
printf ("Usage:\n%s\n", cmdtp->usage);
return 1;
}
}
else
{
printf ("Usage:\n%s\n", cmdtp->usage);
return 1;
}
return 1;
}
/*U_BOOT_CMD(name,maxargs,rep,cmd,usage,help)*/
U_BOOT_CMD(
mflash, 8, 1, mflash_cmd,
"mflash\t- read, write or erase the Marvell Flash.\n",
"info\n - Retreive the Marvell flash infomation.\n"
"mflash protect <on | off> \n - Enable or disable write protect over the whole MFlash chip.\n"
"mflash sector <small | large> \n - Set the sector size to small (4K).\n"
"mflash erase <chip | main | info> \n - Erase the whole chip, main or information region.\n"
"mflash erase SF[-SL]\n - Erase (set back to 0xFF) sectors SF-SL in main region.\n"
"mflash read <main | info> offset dest size\n - Read data from the main or info region into the destination address.\n"
"mflash write <main | info> source offset size [verify]\n - Write a buffer into the main or information region.\n"
);
#endif /* #if defined (MV_INCLUDE_INTEG_MFLASH) */
/*#############################################################################*/
/*#############################################################################*/
/*###################### SFLASH COMMANDS #############################*/
/*#############################################################################*/
/*#############################################################################*/
#if defined (MV_INC_BOARD_SPI_FLASH)
/*******************************************************************************
* sflash_init - Detect and Initialize an external SPI flash device
*
* DESCRIPTION:
* Try to detect the SPI Flash. Based on the model detected, determine
* the flash size.
*
* INPUT:
* None.
*
* OUTPUT:
* None.
*
* RETURN:
* Success or Error code.
*
*
*******************************************************************************/
unsigned long sflash_init (MV_SFLASH_INFO * sflInfo)
{
#if (defined (MV_INCLUDE_SPI) && defined (MV_INCLUDE_INTEG_MFLASH))
/* First check that SIP mode is configured */
if (mvCtrlSpiBusModeDetect() != MV_SPI_CONN_TO_EXT_FLASH)
{
mvOsPrintf("%s ERROR: SPI interface is not routed to external SPI flash!\n", __FUNCTION__);
return 0;
}
#endif
/* Try to detect the flash and initialize it over SPI */
if (mvSFlashInit(sflInfo) != MV_OK)
{
mvOsPrintf("%s ERROR: SFlash init falied!\n", __FUNCTION__);
return 0;
}
/* return the size of the detected SFLash */
return (mvSFlashSizeGet(sflInfo));
}
/*******************************************************************************
* sflash_print_info - Print the SPI flash info
*
* DESCRIPTION:
* Print the flash information of the specified instance
*
* INPUT:
* pInfo: pointer to the instance flash information structure.
*
* OUTPUT:
* None.
*
* RETURN:
* Success or Error code.
*
*
*******************************************************************************/
void sflash_print_info (MV_SFLASH_INFO * pInfo)
{
MV_SFLASH_WP_REGION wp;
printf("\nFlash Base Address : 0x%08x", pInfo->baseAddr);
printf("\nFlash Model : %s", mvSFlashModelGet(pInfo));
printf("\nManufacturer ID : 0x%02x", pInfo->manufacturerId);
printf("\nDevice Id : 0x%04x", pInfo->deviceId);
printf("\nSector Size : %dK", (pInfo->sectorSize / 1024));
printf("\nNumber of sectors : %d", pInfo->sectorNumber);
printf("\nPage Size : %d", pInfo->pageSize);
if (mvSFlashWpRegionGet(pInfo, &wp) != MV_OK)
{
DB(mvOsPrintf("%s WARNING: Failed to get write protect mode!\n", __FUNCTION__);)
printf("\nWrite Protection : UNKNOWN");
}
else
{
switch (wp)
{
case MV_WP_NONE:
printf("\nWrite Protection : Off");
break;
case MV_WP_UPR_1OF64:
printf("\nWrite Protection : Upper 1 of 64");
break;
case MV_WP_UPR_1OF32:
printf("\nWrite Protection : Upper 1 of 32");
break;
case MV_WP_UPR_1OF16:
printf("\nWrite Protection : Upper 1 of 16");
break;
case MV_WP_UPR_1OF8:
printf("\nWrite Protection : Upper 1 of 8");
break;
case MV_WP_UPR_1OF4:
printf("\nWrite Protection : Upper 1 of 4");
break;
case MV_WP_UPR_1OF2:
printf("\nWrite Protection : Upper 1 of 2");
break;
case MV_WP_ALL:
printf("\nWrite Protection : All");
break;
default:
DB(mvOsPrintf("%s WARNING: Invalid Write protect mode!\n", __FUNCTION__);)
printf("\nWrite Protection : UNKNOWN");
break;
}
}
printf("\n\n");
}
/*******************************************************************************
* sflash_erase - Erase a set of sectors
*
* DESCRIPTION:
* Erase a set of sectors in the SPI flash
*
* INPUT:
* pInfo: pointer to the instance flash information structure.
* s_first: first sector to erase.
* s_last: last sector to erase.
*
* OUTPUT:
* None.
*
* RETURN:
* Success or Error code.
*
*
*******************************************************************************/
int sflash_erase (MV_SFLASH_INFO *pInfo, MV_U32 s_first, MV_U32 s_last)
{
MV_U32 i;
for (i=s_first; i<=s_last; i++)
{
/* perform the erase in serial mode */
if (mvSFlashSectorErase(pInfo, i) != MV_OK)
{
DB(mvOsPrintf("%s WARNING: Failed to erase sector %d in SFlash %s!\n", \
__FUNCTION__, i, mvSFlashModelGet(pInfo));)
return 1;
}
2024-01-08 00:01:56 +01:00
mvOsDelay(10); // add for fix "Error: sflash_erase - mvSFlashSectorErase on sector 199" from Tom's advice, wait 10 ms
2024-01-07 23:58:22 +01:00
}
return 0;
}
/***********************************************************************/
/************************ U-Boot Commands ******************************/
/***********************************************************************/
/*******************************************************************************
* sflash_cmd - sflash command implimentation
*
* DESCRIPTION:
* parse and decode the sflash command
*
* INPUT:
* cmdtp: command table pointer
* flag: flags
* argc: command argument count
* argv: command argument vector
*
* OUTPUT:
* None.
*
* RETURN:
* Success or Error code.
*
*******************************************************************************/
int sflash_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
int first, last;
MV_U32 source, offset, size, dest;
char * cp;
if (sFlashBanksNum < 1)
{
printf ("No SPI Flash detected!\n");
return 1;
}
if (argc < 2)
{
printf ("Usage:\n%s\n", cmdtp->usage);
return 1;
}
if (strcmp(argv[1], "info") == 0)
{
/* check that we have the correct number of parameters */
if (argc != 2)
{
printf ("Usage:\n%s\n", cmdtp->usage);
return 1;
}
sflash_print_info(&sflash);
}
else if (strcmp(argv[1], "protect") == 0)
{
/* check that we have the correct number of parameters */
if (argc != 3)
{
printf ("Usage:\n%s\n", cmdtp->usage);
return 1;
}
if (strcmp(argv[2], "off") == 0)
{
if (mvSFlashWpRegionSet(&sflash, MV_WP_NONE) != 0)
printf("\nFailed to set the write protection to NONE.\n", first, last);
}
else if (strcmp(argv[2], "on") == 0)
{
if (mvSFlashWpRegionSet(&sflash, MV_WP_ALL) != 0)
printf("\nFailed to set the write protection to ALL.\n", first, last);
}
else
{
printf ("Usage:\n%s\n", cmdtp->usage);
return 1;
}
}
else if (strcmp(argv[1], "erase") == 0) /* erase command */
{
/* check that we have the correct number of parameters */
if (argc != 3)
{
printf ("Usage:\n%s\n", cmdtp->usage);
return 1;
}
if (strcmp(argv[2], "all") == 0) /* the whole chip */
{
if (mvSFlashChipErase(&sflash) != 0)
printf("\nFailed to erase the whole SPI flash chip.\n", first, last);
}
else /* check if a range of sectors is specified */
{
if (rangeStrDecode(argv[2], &first, &last, sflash.sectorNumber) == 0)
{
if (sflash_erase(&sflash, first, last) != 0)
printf("\nFailed to erase sectors %d-%d\n", first, last);
}
else
{
printf ("Usage:\n%s\n", cmdtp->usage);
return 1;
}
}
}
else if (strcmp(argv[1], "read") == 0)
{
/* check that we have the correct number of parameters */
if (argc != 5)
{
printf ("Usage:\n%s\n", cmdtp->usage);
return 1;
}
offset = simple_strtoul (argv[2], &cp, 16);
if ((cp == argv[2]) || (*cp != '\0') || (offset < 0))
{
printf ("Invalid offset.");
return 1;
}
dest = simple_strtoul (argv[3], &cp, 16);
if ((cp == argv[3]) || (*cp != '\0') || (size < 0))
{
printf ("Invalid size.");
return 1;
}
size = simple_strtoul (argv[4], &cp, 16);
if ((cp == argv[4]) || (*cp != '\0') || (size < 0))
{
printf ("Invalid size.");
return 1;
}
if (mvSFlashBlockRd(&sflash, offset, (MV_U8*)dest, size) != MV_OK)
{
printf ("Failed to read from the SPI flash!\n");
return 1;
}
}
else if (strcmp(argv[1], "write") == 0)
{
/* check that we have the correct number of parameters */
if (argc != 5)
{
printf ("Usage:\n%s\n", cmdtp->usage);
return 1;
}
source = simple_strtoul (argv[2], &cp, 16);
if ((cp == argv[2]) || (*cp != '\0') || (source < 0))
{
printf ("Invalid size.");
return 1;
}
offset = simple_strtoul (argv[3], &cp, 16);
if ((cp == argv[3]) || (*cp != '\0') || (offset < 0))
{
printf ("Invalid offset.");
return 1;
}
size = simple_strtoul (argv[4], &cp, 16);
if ((cp == argv[4]) || (*cp != '\0') || (size < 0))
{
printf ("Invalid size!\n");
return 1;
}
if (mvSFlashBlockWr(&sflash, offset, (MV_U8*) source, size) != MV_OK)
{
printf ("Failed to write to the SPI flash!\n");
return 1;
}
}
else
{
printf ("Usage:\n%s\n", cmdtp->usage);
return 1;
}
return 1;
}
/*U_BOOT_CMD(name,maxargs,rep,cmd,usage,help)*/
U_BOOT_CMD(
sflash, 6, 1, sflash_cmd,
"sflash\t- read, write or erase the external SPI Flash.\n",
"info\n - Retreive the SPI flash infomation.\n"
"sflash protect <on | off> \n - Enable or diasble write protection over the whole SPI flash.\n"
"sflash erase all \n - Erase (set back to 0xFF) the whole chip.\n"
"sflash erase SF[-SL]\n - Erase (set back to 0xFF) sectors SF-SL.\n"
"sflash read offset dest size\n - Read data from the flash into the destination address.\n"
"sflash write source offset size\n - Program a buffer from the source address into the flash offset (size in bytes).\n"
);
#endif
#endif /* #if (CONFIG_COMMANDS & CFG_CMD_FLASH) */