• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7800-V1.0.2.28/target/linux/generic/files/crypto/ocf/kirkwood/mvHal/mv_hal/sflash/
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, &reg)) != 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, &reg)) != 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