ocf: update to version 20120127
[15.05/openwrt.git] / target / linux / generic / files / crypto / ocf / kirkwood / mvHal / mv_hal / sflash / mvSFlash.c
1 /*******************************************************************************
2 Copyright (C) Marvell International Ltd. and its affiliates
3
4 This software file (the "File") is owned and distributed by Marvell
5 International Ltd. and/or its affiliates ("Marvell") under the following
6 alternative licensing terms.  Once you have made an election to distribute the
7 File under one of the following license alternatives, please (i) delete this
8 introductory statement regarding license alternatives, (ii) delete the two
9 license alternatives that you have not elected to use and (iii) preserve the
10 Marvell copyright notice above.
11
12 ********************************************************************************
13 Marvell Commercial License Option
14
15 If you received this File from Marvell and you have entered into a commercial
16 license agreement (a "Commercial License") with Marvell, the File is licensed
17 to you under the terms of the applicable Commercial License.
18
19 ********************************************************************************
20 Marvell GPL License Option
21
22 If you received this File from Marvell, you may opt to use, redistribute and/or
23 modify this File in accordance with the terms and conditions of the General
24 Public License Version 2, June 1991 (the "GPL License"), a copy of which is
25 available along with the File in the license.txt file or by writing to the Free
26 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
27 on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
28
29 THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
30 WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
31 DISCLAIMED.  The GPL License provides additional details about this warranty
32 disclaimer.
33 ********************************************************************************
34 Marvell BSD License Option
35
36 If you received this File from Marvell, you may opt to use, redistribute and/or
37 modify this File under the following licensing terms.
38 Redistribution and use in source and binary forms, with or without modification,
39 are 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
52 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
53 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
54 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
55 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
56 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
57 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
58 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
59 ANY 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
61 SOFTWARE, 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 */
79 static 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 */
203 static MV_STATUS    mvWriteEnable   (MV_SFLASH_INFO * pFlinfo);
204 static MV_STATUS    mvStatusRegGet  (MV_SFLASH_INFO * pFlinfo, MV_U8 * pStatReg);
205 static MV_STATUS    mvStatusRegSet  (MV_SFLASH_INFO * pFlinfo, MV_U8 sr);
206 static MV_STATUS    mvWaitOnWipClear(MV_SFLASH_INFO * pFlinfo);
207 static MV_STATUS    mvSFlashPageWr  (MV_SFLASH_INFO * pFlinfo, MV_U32 offset, \
208                                                                  MV_U8* pPageBuff, MV_U32 buffSize);
209 static 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 ********************************************************************************/
219 static 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 ********************************************************************************/
236 static 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 ********************************************************************************/
263 static 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 ********************************************************************************/
291 static 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 ********************************************************************************/
317 static 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 *******************************************************************************/
350 static 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 ********************************************************************************/
399 static 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 *******************************************************************************/
453 MV_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 *******************************************************************************/
537 MV_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 *******************************************************************************/
624 MV_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 *******************************************************************************/
679 MV_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 *******************************************************************************/
727 MV_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 *******************************************************************************/
796 MV_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 *******************************************************************************/
897 MV_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 *******************************************************************************/
946 MV_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 *******************************************************************************/
1133 MV_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 *******************************************************************************/
1316 MV_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 *******************************************************************************/
1364 MV_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 *******************************************************************************/
1393 MV_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 *******************************************************************************/
1446 MV_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 *******************************************************************************/
1502 const 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