blob: 91e72ab4a5d1e54ad68cd05b9e1fd28d46011944 [file] [log] [blame]
b.liue9582032025-04-17 19:18:16 +08001/******************************************************************************
2 *
3 * (C)Copyright 2013 Marvell. All Rights Reserved.
4 *
5 * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MARVELL.
6 * The copyright notice above does not evidence any actual or intended
7 * publication of such source code.
8 * This Module contains Proprietary Information of Marvell and should be
9 * treated as Confidential.
10 * The information in this file is provided for the exclusive use of the
11 * licensees of Marvell.
12 * Such users have the right to use, modify, and incorporate this code into
13 * products for purposes authorized by the license agreement provided they
14 * include this notice and the associated copyright notice with any such
15 * product.
16 * The information in this file is provided "AS IS" without warranty.
17 *
18 ******************************************************************************/
19
20#include "SPINAND.h"
21#include "spi.h"
22#include "Errors.h"
23#include "misc.h"
24#include "timer.h"
25#include "PlatformConfig.h"
26#include "platform_interrupts.h"
27#include "xllp_dmac.h"
28
29#define DEFAULT_TIMEOUT 3000
30#define DEFAULT_WAIT_TIME 1000
31#define WRITE_SIZE (256)
32extern UINT_T MPUFlag;
33
34//limited for timing and stack concerns (see SPI_page_write routine)
35#define SSP_READ_TIME_OUT_MILLI 0x2000
36#define SSP_READ_DMA_DESC 0x10 //total RX descriptors
37#define SSP_READ_DMA_SIZE 0x1ff8 //bytes per descriptor
38#define SSP_MAX_TX_SIZE_WORDS 64
39#define SSP_MAX_TX_SIZE_BYTES SSP_MAX_TX_SIZE_WORDS << 2
40
41
42__attribute__ ((aligned(32))) XLLP_DMAC_DESCRIPTOR_T pRX_data, pTX_cmd;
43__attribute__ ((aligned(32)))unsigned int tx_command[2112] = {0};
44/***********************************************************
45* InitializeSPINAND()
46* Initializes the SSP port on the platform and issues
47* a Read ID command to see if a device is connected
48* returns:
49* NoError - on a successful read ID
50* NotFoundError - when read ID value is bogus (0xFFFF or 0x0000)
51************************************************************/
52UINT_T InitializeSPINAND(UINT8_T FlashNum, UINT8_T* P_DefaultPartitionNum)
53{
54 unsigned char mid, did, sn_feature;
55 P_FlashProperties_T pFlashP = GetFlashProperties(BOOT_FLASH);
56 int retval;
57 UINT_T ID;
58
59 ChipSelectSPINAND();
60
61 SPI_ConfigCS();
62
63 SPINAND_Reset(BOOT_FLASH);
64 retval = SPINAND_CheckReady();
65 if(retval != NoError)
66 {
67 obm_printf("SPINAND_Reset error\n\r");
68 }
69
70 SPINAND_ReadID(&mid, &did);
71
72 obm_printf("Manufactory and Device ID: 0x%08x\n\r", (mid<<8)|(did));
73
74 SPINAND_UnProtectBlocks();
75
76 sn_feature = SPINAND_GetFeatures(SN_FEATURE);
77 obm_printf("SN_FEATURE: 0x%x\n\r", sn_feature);
78
79 if ((sn_feature & GIGA_SPINAND_FEATURE_ECC_EN) == 0)
80 SPINAND_SetFeatures(SN_FEATURE, (sn_feature | GIGA_SPINAND_FEATURE_ECC_EN));
81
82 //define functions
83 pFlashP->ReadFromFlash = &SPINAND_Read;
84 pFlashP->WriteToFlash = &SPINAND_Write;
85 pFlashP->EraseFlash = &SPINAND_Erase;
86 pFlashP->ResetFlash = &SPINAND_Reset;
87 pFlashP->FlashSettings.UseBBM = 1;
88 pFlashP->FlashSettings.UseSpareArea = 0;
89 pFlashP->PageSize = 2048;
90 pFlashP->BlockSize = 128*1024;
91 pFlashP->FlashSettings.SASize = 0;
92 pFlashP->FlashSettings.UseHwEcc = 0;
93 pFlashP->StreamingFlash = FALSE;
94 pFlashP->FlashType = SPI_NAND;
95 pFlashP->FinalizeFlash = NULL;
96 pFlashP->TimFlashAddress = 0;
97 pFlashP->NumBlocks = 1020;
98
99 *P_DefaultPartitionNum = 0;
100
101 //fill tx dummy buffer with special pattern
102 memset(tx_command, 0xA5, sizeof(tx_command));
103
104 return NoError;
105}
106
107/***********************************************************
108* SPINAND_ReadID
109* Reads the 16 bit MID and DID
110* Returns:
111* None
112*************************************************************/
113void SPINAND_ReadID(unsigned char *mid, unsigned char *did)
114{
115 unsigned char cmd[4], data[4];
116
117 cmd[0] = SN_READ_ID;
118 cmd[1] = 0;
119 cmd[2] = 0;
120 cmd[3] = 0;
121
122 SPI_DisableSSP();
123
124 Assert_CS();
125 //fire it up
126 SPI_FireUp();
127
128 SPI_Write_Read(cmd, data, sizeof(cmd));
129
130 Deassert_CS();
131
132 SPI_DisableSSP();
133
134 *mid = data[2];
135 *did = data[3];
136
137 return;
138}
139
140
141// SPI NAND READ: using DMA
142unsigned int SPINAND_Read(unsigned int FlashOffset, unsigned int Buffer, unsigned int Size)
143{
144 unsigned int retval = NoError, read_size;
145 unsigned char status;
146
147 //calculate the initial read size (for the first page)
148 read_size = SN_PAGE_SIZE - (FlashOffset & (SN_PAGE_SIZE - 1)); //whole page - pre_bytes
149
150 //for each loop iteration, one page of flash will be read into internal memory
151 while (Size > 0)
152 { //update read_size if there are post_bytes (i.e. leftover for the last page)
153 read_size = read_size > Size ? Size : read_size;
154
155 /** Step 1: Cache Load: Load the correct page into cache **/
156 SPINAND_CacheLoad(FlashOffset);
157
158 /** Step 2: Get Features: wait for OIP to be cleared **/
159 retval = SPINAND_CheckReady();
160 if(retval != NoError)
161 break;
162
163 /** Step 3: Cache Read: Read the page in cache to memory (DMA) **/
164 retval = SPINAND_CacheRead_4Bytes(FlashOffset, Buffer, read_size);
165 if(retval != NoError)
166 break;
167
168 retval = SPINAND_CheckReady();
169 if(retval != NoError)
170 break;
171
172 /** Step 4: Update counters: make sure to adjust up to a page boundary each iteration **/
173 FlashOffset += read_size;
174 Buffer += read_size;
175 Size -= read_size;
176 read_size = SN_PAGE_SIZE;
177 }
178
179 return retval;
180}
181
182
183/***********************************************************
184* SPINAND_CacheLoad
185* Issues command to read a page of NAND into the cache
186* Inputs:
187* The flash address of the page to be loaded
188* Returns:
189* no returns
190*************************************************************/
191void SPINAND_CacheLoad(unsigned int Address)
192{
193 SN_ADDRESS_FIELD_T addr;
194 unsigned int input;
195
196 //store the command into the highest byte
197 input = SN_CACHE_LOAD << 24;
198 //put the 16 bits of Row Address (RA) into the lowest two bytes
199 addr.value = Address;
200 input |= (addr.fields.RA & 0xFFFF);
201
202 SPI_DisableSSP();
203
204 //setup in 32 bit mode
205 SPI_ConfigDSS(32);
206
207 Assert_CS();
208 //fire it up
209 SPI_FireUp();
210
211 //load the input data
212 SPI_WriteData(input);
213 SPI_WaitSSPComplete();
214
215 SPI_DisableSSP();
216 Deassert_CS();
217
218 return;
219}
220
221/***********************************************************
222* SPINAND_GetFeatures
223* Reads the corresponding feature value of SPI device.
224* Inputs:
225* The feature type to be read out
226* Returns:
227* status value
228*************************************************************/
229unsigned char SPINAND_GetFeatures(SN_Feature_E feature_type)
230{
231 UINT status, i;
232 UINT8 cmd[3], data[3];
233 //fill out the command (2 bytes) plus dummy bytes for the readback
234 cmd[0] = SN_GET_FEATURES;
235 cmd[1] = feature_type;
236 cmd[2] = 0;
237
238 //make sure SSP is disabled
239 SPI_DisableSSP();
240
241 Assert_CS();
242 //fire it up
243 SPI_FireUp();
244
245 SPI_Write_Read(cmd, data, sizeof(cmd));
246
247 //make sure SSP is disabled
248 SPI_DisableSSP();
249 Deassert_CS();
250
251 //return last known status
252 return data[2];
253}
254
255unsigned char SPINAND_SetFeatures(SN_Feature_E feature_type, unsigned char feature)
256{
257 UINT i;
258 UINT8 cmd[3], data[3];;
259
260 //fill out the command (2 bytes) plus data byte
261 cmd[0] = SN_SET_FEATURES;
262 cmd[1] = feature_type;
263 cmd[2] = feature;
264
265 //make sure SSP is disabled
266 SPI_DisableSSP();
267
268 Assert_CS();
269 //fire it up
270 SPI_FireUp();
271
272 SPI_Write_Read(cmd, data, sizeof(cmd));
273
274 //make sure SSP is disabled
275 SPI_DisableSSP();
276 Deassert_CS();
277
278 return 0;
279}
280
281/***********************************************************
282* SPINAND_CacheRead
283* Reads the loaded page from Cache to internal memory using DMA
284* Inputs:
285* Offset into page
286* Buffer location
287* Size to be read
288* Returns:
289* error status
290*************************************************************/
291unsigned int SPINAND_CacheRead_4Bytes(unsigned int Offset, unsigned int Buffer, unsigned int Size)
292{
293 unsigned int command, dummy, start_time, i, Retval = NoError;
294 SN_ADDRESS_FIELD_T addr;
295 DMA_CMDx_T RX_data, TX_cmd;
296 unsigned int timeout = 0xFFFFF;
297 unsigned int recv_buf = 0;
298
299#ifndef HW_ENDIAN_CONVERT
300 unsigned int * convert_buff, * orginal_buff, convert_size;
301 recv_buf = malloc(Size);
302 if(recv_buf == 0)
303 return HeapExhaustedError;
304#else
305 recv_buf = Buffer;
306#endif
307
308 //fill out the "command" sequence: CMD + Column Address (CA) + dummy byte
309 addr.value = Offset;
310 command = SN_CACHE_READ << 24;
311 command |= (addr.fields.CA << 8); //(upper bits will be 0's for the 'wrap')
312 command |= 0xA5; //0xA5 is a dummy byte that easily seen on a scope
313
314 //fill out commands
315 RX_data.value = 0;
316 RX_data.bits.IncTrgAddr = 1;
317 RX_data.bits.FlowSrc = 1;
318 RX_data.bits.Width = 3;
319 RX_data.bits.MaxBurstSize = 1;
320
321 TX_cmd.value = 0;
322 TX_cmd.bits.IncSrcAddr = 1;
323 TX_cmd.bits.FlowTrg = 1;
324 TX_cmd.bits.Width = 3;
325 TX_cmd.bits.MaxBurstSize = 1;
326
327 //Map Device to Channels
328 XllpDmacMapDeviceToChannel(SSP_RX_DMA_DEVICE, SSP_RX_CHANNEL);
329 XllpDmacMapDeviceToChannel(SSP_TX_DMA_DEVICE, SSP_TX_CHANNEL);
330
331 //turn ON user alignment - in case buffer address is 64bit aligned
332 alignChannel(SSP_RX_CHANNEL, 1);
333
334 // * configure RX & TX descriptors * //
335 configDescriptor(&pRX_data, NULL, (unsigned int)SSP_DR, recv_buf, &RX_data, Size, 1);
336 configDescriptor(&pTX_cmd,
337 NULL,
338 (unsigned int)&tx_command[0],
339 (unsigned int)SSP_DR,
340 &TX_cmd,
341 Size,
342 1);
343
344 //Load descriptors
345 loadDescriptor (&pRX_data, SSP_RX_CHANNEL);
346 loadDescriptor (&pTX_cmd, SSP_TX_CHANNEL);
347
348 SPI_DisableSSP();
349
350 //setup in 32 bit mode
351 SPI_ConfigDSS(32);
352
353 //setup for DMA: TX and RX DMA request + DMA handles Trailing bytes
354#ifdef HW_ENDIAN_CONVERT
355 SPI_ConfigDMA(4, 3, 2, 0, 1);
356#else
357 SPI_ConfigDMA(4, 3, 0, 0, 0);
358#endif
359
360 //setup IER
361 SPI_ConfigInt(0);
362
363 Assert_CS();
364 //fire it up
365 SPI_FireUp();
366
367#if ENABLE_MMU
368 dcache_clean_range(&pRX_data, sizeof(XLLP_DMAC_DESCRIPTOR_T));
369 dcache_clean_range(&pTX_cmd, sizeof(XLLP_DMAC_DESCRIPTOR_T));
370 dcache_clean_range(&tx_command[0], sizeof(tx_command));
371 dcache_invalidate_range(recv_buf, Size);
372#endif
373
374 SPI_WriteData(command);
375 SPI_WaitSSPComplete();
376 dummy = SPI_ReadData();
377
378 //Kick off DMA's
379 XllpDmacStartTransfer(SSP_TX_CHANNEL);
380 XllpDmacStartTransfer(SSP_RX_CHANNEL);
381
382 //wait until the RX channel gets the stop interrupt
383 timeout = 0xFFFFF;
384 while( (readDmaStatusRegister(SSP_RX_CHANNEL) & XLLP_DMAC_DCSR_STOP_INTR) != XLLP_DMAC_DCSR_STOP_INTR )
385 {
386 ROW_DELAY(DEFAULT_TIMEOUT);
387
388 if((timeout--) <= 0)
389 {
390 obm_printf("RX channel gets the stop interrupt timeout\n\r");
391
392 break;
393 }
394 }
395
396 timeout = 0xFFFFF;
397 while( (readDmaStatusRegister(SSP_TX_CHANNEL) & XLLP_DMAC_DCSR_STOP_INTR) != XLLP_DMAC_DCSR_STOP_INTR )
398 {
399 ROW_DELAY(DEFAULT_TIMEOUT);
400
401 if((timeout--) <= 0)
402 {
403 obm_printf("TX channel gets the stop interrupt timeout\n\r");
404
405 break;
406 }
407 }
408
409 SPI_WaitSSPComplete();
410 Deassert_CS();
411 SPI_DisableSSP();
412
413 //clear out DMA settings
414 XllpDmacUnMapDeviceToChannel(SSP_RX_DMA_DEVICE, SSP_RX_CHANNEL);
415 XllpDmacUnMapDeviceToChannel(SSP_TX_DMA_DEVICE, SSP_TX_CHANNEL);
416
417#if LZMA_SUPPORT
418 //if (MPUFlag == 1) // only for boot
419 // CacheInvalidateMemory(Buffer, Size + 4);
420#endif
421
422#ifndef HW_ENDIAN_CONVERT
423 //postprocessing... endian convert
424 convert_buff = (unsigned int *) Buffer;
425 orginal_buff = (unsigned int *) recv_buf;
426 convert_size = Size >> 2; //convert Size from bytes to words
427 for(i = 0; i < convert_size; i++)
428 convert_buff[i] = Endian_Convert(orginal_buff[i]);
429 free(recv_buf);
430#endif
431
432 return Retval;
433}
434
435// SPI NAND WRITE: using DMA
436unsigned int SPINAND_Write(unsigned int FlashOffset, unsigned int Buffer, unsigned int Size)
437{
438 unsigned int retval = NoError, write_size;
439
440 //calculate the initial write size (for the first page)
441 //write_size = SN_PAGE_SIZE - (FlashOffset & (SN_PAGE_SIZE - 1)); //whole page - pre_bytes
442 //unlock all blocks before programming any thing
443 SPINAND_SetFeatures(SN_PROTECTION, 0x00);
444
445 //for each loop iteration, one page of flash will be written
446 while (Size > 0)
447 { //update write_size if there are post_bytes (i.e. leftover for the last page)
448 write_size = Size > SN_PAGE_SIZE ? SN_PAGE_SIZE : Size;
449
450 /** Step 0: Write Enable: set the write enable bit **/
451 SPINAND_WriteEnable();
452
453 /** Step 1: Program Load: Load the data into cache (DMA) **/
454 retval = SPINAND_ProgramLoad_4Bytes(FlashOffset, Buffer, write_size);
455 //retval = SPINAND_ProgramLoadPIO(FlashOffset, Buffer, write_size);
456 if(retval != NoError)
457 break;
458
459 retval = SPINAND_CheckReady();
460 if(retval != NoError)
461 break;
462
463 /** Step 2: Write Enable: set the write enable bit **/
464 SPINAND_WriteEnable();
465
466 /** Step 3: Program Execute: Write the page in cache to flash **/
467 SPINAND_ProgramExecute(FlashOffset);
468
469 /** Step 4: Get Features: wait for OIP to be cleared **/
470 retval = SPINAND_CheckReady();
471 if(retval != NoError)
472 break;
473
474 /** Step 5: Update counters: make sure to adjust up to a page boundary each iteration **/
475 FlashOffset += write_size;
476 Buffer += write_size;
477 Size -= write_size;
478 write_size = SN_PAGE_SIZE;
479 }
480
481 return retval;
482}
483
484unsigned int SPINAND_ProgramLoad_4Bytes(unsigned int Address, unsigned int Buffer, unsigned int Size)
485{
486 unsigned int Retval = NoError, i;
487 DMA_CMDx_T TX_data;
488 unsigned char cmd[3], data[3];
489 unsigned int convert_size = Size;
490 volatile int timeout = 0xFFFFF;
491
492 cmd[0] = SN_PROGRAM_LOAD;
493 cmd[1] = 0;
494 cmd[2] = 0;
495
496 TX_data.value = 0;
497 TX_data.bits.IncSrcAddr = 1;
498 TX_data.bits.FlowTrg = 1;
499 TX_data.bits.Width = 1; //Don't need to convert Endian if transmit by byte
500 TX_data.bits.MaxBurstSize = 1;
501 TX_data.bits.Length = Size;
502
503 //Map Device to Channels
504 XllpDmacMapDeviceToChannel(SSP_TX_DMA_DEVICE, SSP_TX_CHANNEL);
505 XllpDmacNoDescriptorFetch( SSP_TX_CHANNEL );
506
507 //turn ON user alignment - in case buffer address is 64bit aligned
508 alignChannel(SSP_TX_CHANNEL, 1);
509
510 loadNonDescriptor((unsigned int)Buffer, (unsigned int) SSP_DR, &TX_data, SSP_TX_CHANNEL);
511
512 SPI_DisableSSP();
513
514 //setup for DMA: TX and RX DMA request + DMA handles Trailing bytes
515 SPI_ConfigDMA(4, 3, 0, 0, 0);
516 SPI_ConfigInt(0);
517
518 //setup IER
519 Assert_CS();
520 //fire it up
521 SPI_FireUp();
522
523 SPI_Write_Read(cmd, data, sizeof(cmd));
524
525 //Kick off DMA's
526 XllpDmacStartTransfer(SSP_TX_CHANNEL);
527
528 //wait until the TX channel gets the stop interrupt
529 timeout = 0xFFFFFF;
530 while( (readDmaStatusRegister(SSP_TX_CHANNEL) & XLLP_DMAC_DCSR_STOP_INTR) != XLLP_DMAC_DCSR_STOP_INTR )
531 {
532 ROW_DELAY(DEFAULT_TIMEOUT);
533
534 //if we've waited long enough, fail
535 if((timeout--) <= 0)
536 {
537 obm_printf("TX channel gets the stop interrupt timeout\n\r");
538
539 break;
540 }
541 }
542
543 SPI_WaitSSPComplete();
544
545 Deassert_CS();
546
547 SPI_DisableSSP();
548
549 //clear out DMA settings
550 XllpDmacUnMapDeviceToChannel(SSP_TX_DMA_DEVICE, SSP_TX_CHANNEL);
551
552 return Retval;
553
554}
555
556/***********************************************************
557* SPINAND_ProgramLoad
558* Writes a page of data to Cache from internal memory using DMA
559* Inputs:
560* Offset into page
561* Buffer location
562* Size to be write
563* Returns:
564* error status
565*************************************************************/
566unsigned int SPINAND_ProgramLoadPIO(unsigned int Address, unsigned int Buffer, unsigned int Size)
567{
568 int i = 0;
569 unsigned int Retval = NoError;
570 unsigned char cmd[3], dummy, *data;
571
572#if 0
573 P_FlashProperties_T pFlashP = GetFlashProperties(BOOT_FLASH);
574
575 //fill out the command (2 bytes) plus data byte
576 cmd[0] = SN_PROGRAM_LOAD;
577 cmd[1] = ((Address & (pFlashP->PageSize - 1)) >> 8) & 0xFF;
578 cmd[2] = Address & 0xFF;
579#else
580 cmd[0] = SN_PROGRAM_LOAD;
581 cmd[1] = 0;
582 cmd[2] = 0;
583#endif
584
585 //make sure SSP is disabled
586 SPI_DisableSSP();
587
588 //fire it up
589 SPI_FireUp();
590
591 Assert_CS();
592
593 for(i = 0; i < 3; i++)
594 {
595 *SSP_DR = cmd[i];
596
597 SPI_WaitSSPComplete();
598
599 dummy = *SSP_DR;
600 }
601
602 data = (UINT8 *)Buffer;
603 for(i = 0; i < Size; i++)
604 {
605 *SSP_DR = data[i];
606
607 SPI_WaitSSPComplete();
608
609 dummy = *SSP_DR;
610 }
611
612 Deassert_CS();
613
614 //make sure SSP is disabled
615 SPI_DisableSSP();
616
617 return Retval;
618}
619
620
621/***********************************************************
622* SPINAND_WriteEnable
623* Sets the WEL bit in the SPI NAND status register,
624* allowing the device to be programmed or erased
625* Returns:
626* none
627*************************************************************/
628void SPINAND_WriteEnable(void)
629{
630 unsigned char cmd[1], data[1];
631
632 cmd[0] = SN_WRITE_ENABLE;
633
634 SPI_DisableSSP();
635
636 Assert_CS();
637 //fire it up
638 SPI_FireUp();
639
640 SPI_Write_Read(cmd, data, sizeof(cmd));
641
642 Deassert_CS();
643
644 SPI_DisableSSP();
645}
646
647/***********************************************************
648* SPINAND_ProgramExecute
649* Issues command to program a page of NAND from the cache
650* Inputs:
651* The flash address of the page to be loaded
652* Returns:
653* no returns
654*************************************************************/
655void SPINAND_ProgramExecute(unsigned int Address)
656{
657 unsigned char cmd[4], data[4];
658
659 cmd[0] = SN_PROGRAM_EXECUTE;
660 cmd[1] = ((Address>>11)&0xffff) >> 16;
661 cmd[2] = ((Address>>11)&0xffff) >> 8;
662 cmd[3] = ((Address>>11)&0xffff);
663
664 SPI_DisableSSP();
665
666 Assert_CS();
667 //fire it up
668 SPI_FireUp();
669
670 SPI_Write_Read(cmd, data, sizeof(cmd));
671
672 Deassert_CS();
673
674 SPI_DisableSSP();
675
676 return;
677}
678
679// SPI NAND ERASE: Erases 1 whole block at a time
680unsigned int SPINAND_Erase(unsigned int FlashOffset, unsigned int Size)
681{
682 unsigned int retval = NoError;
683
684 //adjust the size/offset fields to start on a block boundary
685 Size += FlashOffset & (SN_BLOCK_SIZE - 1);
686 FlashOffset &= ~(SN_BLOCK_SIZE - 1);
687
688 //unlock all blocks before erase
689 SPINAND_SetFeatures(SN_PROTECTION, 0x00);
690
691 //for each loop iteration, one block of flash will be erased
692 while (Size > 0)
693 { /** Step 1: Write Enable: set the write enable bit **/
694 SPINAND_WriteEnable();
695
696 /** Step 2: Block Erase: erase 1 block **/
697 SPINAND_BlockErase(FlashOffset);
698
699 /** Step 3: Get Features: wait for OIP to be cleared **/
700 retval = SPINAND_CheckReady();
701 if(retval != NoError)
702 break;
703
704
705 /** Step 4: Update counters **/
706 FlashOffset += SN_BLOCK_SIZE;
707 Size = (Size > SN_BLOCK_SIZE) ? (Size - SN_BLOCK_SIZE) : 0;
708 }
709
710 return retval;
711
712}
713
714/***********************************************************
715* SPINAND_BlockErase
716* Issues command to erase 1 block of flash
717* Inputs:
718* The flash address of the block to be erased
719* Returns:
720* no returns
721*************************************************************/
722void SPINAND_BlockErase(unsigned int Address)
723{
724 unsigned char cmd[4], data[4];
725
726 cmd[0] = SN_BLOCK_ERASE;
727 cmd[1] = ((Address>>11)&0xffff) >> 16;
728 cmd[2] = ((Address>>11)&0xffff) >> 8;
729 cmd[3] = ((Address>>11)&0xffff);
730
731 SPI_DisableSSP();
732
733 Assert_CS();
734 //fire it up
735 SPI_FireUp();
736
737 SPI_Write_Read(cmd, data, sizeof(cmd));
738
739 Deassert_CS();
740 SPI_DisableSSP();
741
742 return;
743}
744
745/***********************************************************
746* SPINAND_Reset
747* Issues command to reset flash
748* Inputs:
749* The flash boot type
750* Returns:
751* no error
752*************************************************************/
753unsigned int SPINAND_Reset(FlashBootType_T fbt)
754{
755 unsigned char cmd[1], data[1];
756
757 cmd[0] = SN_RESET;
758
759 SPI_DisableSSP();
760
761 Assert_CS();
762 //fire it up
763 SPI_FireUp();
764
765 SPI_Write_Read(cmd, data, sizeof(cmd));
766
767 Deassert_CS();
768 SPI_DisableSSP();
769
770 return NoError;
771}
772
773/***********************************************************
774* SPINAND_UnProtectBlocks
775* unprotect the protected flash blocks
776* Inputs:
777* none
778* Returns:
779* none
780*************************************************************/
781void SPINAND_UnProtectBlocks(void)
782{
783 unsigned char protection;
784
785 protection = SPINAND_GetFeatures(SN_PROTECTION);
786
787 obm_printf("SN_PROTECTION: 0x%x\n\r", protection);
788 if ((protection & (GIGA_SPINAND_PROTECTION_BP3 |
789 GIGA_SPINAND_PROTECTION_BP2 |
790 GIGA_SPINAND_PROTECTION_BP1 |
791 GIGA_SPINAND_PROTECTION_BP0)) == 0)
792 {
793 obm_printf("SPINAND is already unprotected\n\r");
794 return;
795 }
796 else
797 {
798 obm_printf("SPINAND is not unprotected\n\r");
799 }
800
801 // clear BP0/BP1/BP2
802 protection &= ~(GIGA_SPINAND_PROTECTION_BP3 |
803 GIGA_SPINAND_PROTECTION_BP2 |
804 GIGA_SPINAND_PROTECTION_BP1 |
805 GIGA_SPINAND_PROTECTION_BP0);
806
807 //SPINAND_SetFeatures(SN_PROTECTION, protection);
808 SPINAND_SetFeatures(SN_PROTECTION, 0);
809
810 obm_printf("SPINAND unprotect done\n\r");
811}
812
813UINT_T SPINAND_CheckReady(void)
814{
815 unsigned int start_time, retval = NoError;
816 unsigned char status;
817
818 start_time = GetOSCR0();
819 do
820 { //Read the Status register on the device
821 status = SPINAND_GetFeatures(SN_STATUS);
822
823 //Check for timeout
824 if( OSCR0IntervalInMilli(start_time, GetOSCR0()) > 5 )
825 {
826 obm_printf("SPINAND_CheckReady: SPINANDCheckReadyTimeOutError\n\r");
827 retval = SPINANDCheckReadyTimeOutError;
828 }
829
830 if (status & GIGA_SPINAND_STATUS_P_FAIL)
831 {
832 obm_printf("SPINAND_CheckReady: SPI_PROGRAMFAIL\n\r");
833 retval = SPI_PROGRAMFAIL;
834 }
835
836 if (status & GIGA_SPINAND_STATUS_E_FAIL)
837 {
838 obm_printf("SPINAND_CheckReady: SPI_ERASEFAIL\n\r");
839 retval = SPI_ERASEFAIL;
840 }
841 //stay in loop if OIP bit is still high AND no timeout error has occured
842 } while( (status & GIGA_SPINAND_STATUS_OIP) && (retval == NoError) );
843
844 return retval;
845}
846