remove linux 2.4 specific build system code
[openwrt/staging/wigyori.git] / target / linux / generic-2.6 / 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