blob: 42fb602ea1ad16d50e1e56827e651707efb73bf8 [file] [log] [blame]
b.liue9582032025-04-17 19:18:16 +08001/******************************************************************************
2 *
3 * (C)Copyright 2013 Marvell Hefei Branch. 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 "spi.h"
21#include "SPINOR.h"
22#include "GPIO.h"
23#include "Typedef.h"
24#include "Errors.h"
25#include "PlatformConfig.h"
26#include "xllp_dmac.h"
27#include "timer.h"
28#include "SPINOR_extened.h"
29
30extern UINT_T Flash_size;
31
32SPINOR_T G_spinor_info;
33P_SPINOR_T pGspinor_info = &G_spinor_info;
34
35UINT_T Spansion_SPINOR_Flash = 0;
36
37P_SPINOR_T getSPINor_Info(void) {
38 return pGspinor_info;
39}
40
41__attribute__ ((aligned(16))) XLLP_DMAC_DESCRIPTOR_T pRX_data, pTX_cmd;
42__attribute__ ((aligned(16)))unsigned char tx_command_spinor[SIZE_4KB];
43
44UINT_T InitializeSPIDevice(UINT8_T FlashNum, UINT8_T* P_DefaultPartitionNum)
45{
46 UINT_T Retval = NoError;
47 UINT_T i, ID, status;
48 UINT_T status_value, config_value;
49 unsigned char mid, status2;
50 unsigned short did;
51 P_SPINOR_T spinor_info = getSPINor_Info();
52
53 P_FlashProperties_T pFlashP = GetFlashProperties(BOOT_FLASH);
54
55 memset(spinor_info, 0, sizeof(SPINOR_T));
56
57 ChipSelectSPINOR();
58 SPI_ConfigCS();
59 SPINOR_Reset();
60 SPINOR_ReadId(&mid, &did);
61 obm_printf("Manufacturer ID: %x, device ID: %x\n\r", mid, did);
62
63 SetCurrentFlashBootType(BOOT_FLASH);
64
65 //setup Flash Properties info
66 pFlashP->BlockSize = 0x10000; // 64KB
67 pFlashP->PageSize = 0x100; // 256B
68 pFlashP->NumBlocks = 0x100; // 256
69 pFlashP->ResetFlash = NULL;
70 pFlashP->FlashSettings.UseBBM = 0;
71 pFlashP->FlashSettings.UseSpareArea = 0;
72 pFlashP->FlashSettings.SASize = 0;
73 pFlashP->FlashSettings.UseHwEcc = 0;
74 pFlashP->StreamingFlash = FALSE;
75 pFlashP->StagedInitRequired = FALSE;
76 pFlashP->FlashType = SPI_FLASH;
77 pFlashP->FinalizeFlash = NULL;
78 pFlashP->TimFlashAddress = 0;
79
80 *P_DefaultPartitionNum = 0;
81
82 switch (mid)
83 {
84 case SPANSION_ID:
85 obm_printf("Spansion SPI-Nor\n\r");
86 switch (did)
87 {
88 case 0x0219:
89 spinor_info->large_capacity = 0x01;
90 spinor_info->enable_4bytes = 0x00;
91 //spinor_info->write_enable_4enable_4bytes = 0x00;
92 //spinor_info->read_4bytes_status_cmd = 0x00;
93 //spinor_info->spi_4bytes_enabled_bit = 0x00;
94 spinor_info->read_4bytes_cmd = SPINOR_READ_4Bytes_CMD1;
95 spinor_info->write_4bytes_cmd = SPINOR_PROGRAM_4Bytes_CMD1;
96 spinor_info->erase_4bytes_cmd = SPINOR_SECTOR_ERASE_4Bytes_CMD1;
97 Spansion_SPINOR_Flash = 1;
98 break;
99
100 case 0x0218:
101 Spansion_SPINOR_Flash = 1;
102 default:
103 break;
104 }
105 break;
106
107 case MACRONIX_ID:
108 obm_printf("Macronix SPI-Nor\n\r");
109 switch (did)
110 {
111 case 0x2539:
112 spinor_info->large_capacity = 0x01;
113 spinor_info->enable_4bytes = 0x00;
114 //spinor_info->write_enable_4enable_4bytes = 0x00;
115 //spinor_info->read_4bytes_status_cmd = 0x00;
116 //spinor_info->spi_4bytes_enabled_bit = 0x00;
117 spinor_info->read_4bytes_cmd = SPINOR_READ_4Bytes_CMD1;
118 spinor_info->write_4bytes_cmd = SPINOR_PROGRAM_4Bytes_CMD1;
119 spinor_info->erase_4bytes_cmd = SPINOR_SECTOR_ERASE_4Bytes_CMD1;
120 break;
121 default:
122 break;
123 }
124 break;
125 case GIGADEVICE_ID:
126 obm_printf("Giga SPI-Nor\n\r");
127 switch (did)
128 {
129 case 0x6019:
130 spinor_info->large_capacity = 0x01; // need to check spec
131 spinor_info->enable_4bytes = 0x01; // need to check spec
132 spinor_info->write_enable_4enable_4bytes = 0x00; // need to check spec
133 spinor_info->read_4bytes_status_cmd = SPINOR_READ_STATUS_CMD0;
134 spinor_info->spi_4bytes_enabled_bit = BIT3; // need to check spec
135 spinor_info->read_4bytes_cmd = SPINOR_READ_4Bytes_CMD0;
136 spinor_info->write_4bytes_cmd = SPINOR_PROGRAM_4Bytes_CMD0;
137 spinor_info->erase_4bytes_cmd = SPINOR_SECTOR_ERASE_4Bytes_CMD0;
138 break;
139 default:
140 break;
141 }
142 break;
143 case MICRON_ID:
144 obm_printf("Micron SPI-Nor\n\r");
145 switch (did)
146 {
147 case 0xcb19:
148 spinor_info->large_capacity = 0x01; // need to check spec
149 spinor_info->enable_4bytes = 0x01; // need to check spec
150 spinor_info->write_enable_4enable_4bytes = 0x01; // need to check spec
151 spinor_info->read_4bytes_status_cmd = SPINOR_READ_STATUS_CMD1;
152 spinor_info->spi_4bytes_enabled_bit = BIT0; // need to check spec
153 spinor_info->read_4bytes_cmd = SPINOR_READ_4Bytes_CMD1;
154 spinor_info->write_4bytes_cmd = SPINOR_PROGRAM_4Bytes_CMD0;
155 spinor_info->erase_4bytes_cmd = SPINOR_SECTOR_ERASE_4Bytes_CMD0;
156 break;
157 default:
158 break;
159 }
160 break;
161 case FIDELIX_ID:
162 obm_printf("Fidelix SPI-NOR\n\r");
163 switch(did)
164 {
165 case 0x4218:
166 spinor_info->large_capacity = 0x0;
167 break;
168 default:
169 break;
170 }
171 break;
172 default:
173 break;
174 }
175 if (spinor_info->large_capacity == 1) // 1: 32MB, 2: 64MB???
176 {
177 obm_printf("Large capacity\n\r");
178 Flash_size = 0x02000000;
179
180 pFlashP->ReadFromFlash = &SPINOR_Extend_Read;
181 pFlashP->WriteToFlash = &SPINOR_Extend_Write;
182 pFlashP->EraseFlash = &SPINOR_Extend_Erase;
183 SPINOR_Enable4BytesMode();
184 }
185 else
186 {
187 pFlashP->ReadFromFlash = &SPINOR_Read;
188 pFlashP->WriteToFlash = &SPINOR_Write;
189 pFlashP->EraseFlash = &SPINOR_Erase;
190 }
191
192 SPINOR_UnProtectBlocks();
193
194 //fill tx dummy buffer with special pattern
195 memset(tx_command_spinor, 0xA5, sizeof(tx_command_spinor));
196
197 return Retval;
198}
199
200UINT8_T SPINOR_ReadReg(SPINOR_Register reg)
201{
202 UINT_T dummy;
203 UINT8_T status, command;
204
205 P_SPINOR_T spinor_info = getSPINor_Info();
206 switch (reg)
207 {
208 case SPINOR_4bytes_Status_Register:
209 command = spinor_info->read_4bytes_status_cmd;
210 break;
211 case SPINOR_write_enable_Status_Register:
212 command = SPI_CMD_READ_STATUS;
213 break;
214 default:
215 command = SPI_CMD_READ_STATUS;
216 break;
217 }
218
219 SPI_DisableSSP();
220 SPI_ConfigDSS(16);
221
222 Assert_CS();
223 //fire it up
224 SPI_FireUp();
225
226 SPI_WriteData(command << 8);
227 SPI_WaitSSPComplete();
228 dummy = SPI_ReadData();
229 status = dummy & 0xFF; //the status will be in the second byte
230
231 Deassert_CS();
232
233 SPI_DisableSSP();
234
235 //return last known status
236 return status;
237}
238
239void SPINOR_Enable4BytesMode(void)
240{
241 UINT8_T status, cmd[1], data[1];
242
243 P_SPINOR_T spinor_info = getSPINor_Info();
244 if (!spinor_info->enable_4bytes)
245 return;
246
247 status = SPINOR_ReadReg(SPINOR_4bytes_Status_Register);
248 if ((status & spinor_info->spi_4bytes_enabled_bit) == spinor_info->spi_4bytes_enabled_bit)
249 {
250 // It's already 4-Bytes Modes!!!
251 return;
252 }
253
254 if (spinor_info->write_enable_4enable_4bytes)
255 SPINOR_WriteEnable();
256
257 cmd[0] = SPINOR_ENABLE_4BYTE_MODE;
258
259 SPI_DisableSSP();
260 SPI_ConfigDSS(8);
261 Assert_CS();
262 SPI_FireUp();
263
264 SPI_Write_Read(cmd, data, sizeof(cmd));
265
266 Deassert_CS();
267 //make sure SSP is disabled
268 SPI_DisableSSP();
269
270 status = SPINOR_ReadReg(SPINOR_4bytes_Status_Register);
271 if ((status & spinor_info->spi_4bytes_enabled_bit) != spinor_info->spi_4bytes_enabled_bit)
272 {
273 obm_printf("Enter 4-Bytes Modes failed!!!\n\r");
274 }
275
276 return;
277}
278
279void SPINOR_Disable4BytesMode(void)
280{
281 UINT8_T status, cmd[1], data[1];
282
283 P_SPINOR_T spinor_info = getSPINor_Info();
284 if (!spinor_info->enable_4bytes)
285 return;
286
287 status = SPINOR_ReadReg(SPINOR_4bytes_Status_Register);
288 if ((status & spinor_info->spi_4bytes_enabled_bit) == 0x00)
289 {
290 // It's already 3-Bytes Modes!!!
291 return;
292 }
293
294 if (spinor_info->write_enable_4enable_4bytes)
295 SPINOR_WriteEnable();
296
297 cmd[0] = SPINOR_DISABLE_4BYTE_MODE;
298
299 SPI_DisableSSP();
300 Assert_CS();
301 SPI_FireUp();
302
303 SPI_Write_Read(cmd, data, sizeof(cmd));
304
305 Deassert_CS();
306 //make sure SSP is disabled
307 SPI_DisableSSP();
308
309 status = SPINOR_ReadReg(SPINOR_4bytes_Status_Register);
310 if ((status & spinor_info->spi_4bytes_enabled_bit) != 0x00)
311 {
312 obm_printf("Exit 4-Bytes Modes failed!!!\n\r");
313 }
314
315 return;
316}
317
318void SPINOR_Protect_Blocks(void)
319{
320 UINT_T status_value, status1_value;
321
322#if 0
323 // make sure it's ready
324 SPINOR_ReadStatus(TRUE);
325
326 // read out status register and configuration register
327 status_value = Giga_SPINor_ReadReg(Giga_Status_Register);
328 status1_value = Giga_SPINor_ReadReg(Giga_Status_Register1);
329
330 if (((status1_value & GIGA_STATUS_CMP) == 0x0)
331 && ((status_value & (GIGA_STATUS_BP0 |
332 GIGA_STATUS_BP1 |
333 GIGA_STATUS_BP2|
334 GIGA_STATUS_BP3 |
335 GIGA_STATUS_BP4))
336 == (GIGA_STATUS_BP0 | GIGA_STATUS_BP3)))
337 {
338 obm_printf("SPI Nor is already protected\n\r");
339 return;
340 }
341 else
342 {
343 obm_printf("SPI Nor is not protected\n\r");
344 }
345
346 SPINOR_WriteEnable();
347
348 // clear BP0/BP1/BP2/BP3/BP4
349 status_value &= ~(GIGA_STATUS_BP0 |
350 GIGA_STATUS_BP1 |
351 GIGA_STATUS_BP2|
352 GIGA_STATUS_BP3 |
353 GIGA_STATUS_BP4);
354
355 // set BP0/BP3
356 status_value |= GIGA_STATUS_BP0 | GIGA_STATUS_BP3;
357
358 // clear CMP
359 status1_value &= ~GIGA_STATUS_CMP;
360
361 MX_SPINOR_WriteStatus(status_value, status1_value);
362 SPINOR_ReadStatus(TRUE);
363
364 status_value = Giga_SPINor_ReadReg(Giga_Status_Register);
365 status1_value = Giga_SPINor_ReadReg(Giga_Status_Register1);
366
367 obm_printf("SPI Nor protect done\n\r");
368#endif
369}
370
371void SPINOR_UnProtectBlocks(void)
372{
373 UINT_T status_value, status1_value;
374
375 SPINOR_ReadStatus(TRUE);
376
377 status_value = SPINOR_ReadReg(SPINOR_write_enable_Status_Register);
378
379 if (((status_value & (BIT2 | BIT3 | BIT4)) == 0) )
380 {
381 obm_printf("SPI Nor is already unprotected\n\r");
382 return;
383 }
384 else
385 {
386 obm_printf("SPI Nor is not unprotected\n\r");
387 }
388
389 SPINOR_WriteEnable();
390
391 // clear BP0/BP1/BP2, BP3/BP4 doesn't matter
392 status_value &= ~(BIT2 | BIT3 | BIT4);
393
394 SPINOR_WriteStatus(status_value);
395
396 SPINOR_ReadStatus(TRUE);
397
398 obm_printf("SPI Nor unprotect done\n\r");
399}
400
401void SPINOR_Reset(void)
402{
403 UINT8_T status, cmd[1], data[1];
404
405 cmd[0] = SPI_CMD_RELEASE_POWER_DOWN;
406 SPI_DisableSSP();
407 Assert_CS();
408 //fire it up
409 SPI_FireUp();
410
411 SPI_Write_Read(cmd, data, sizeof(cmd));
412
413 Deassert_CS();
414 SPI_DisableSSP();
415 // reset memory
416 SPINOR_ResetEnable();
417 SPINOR_ResetMemory();
418 SPINOR_ReadStatus(TRUE);
419 return;
420}
421
422void SPINOR_ResetEnable(void)
423{
424 UINT8_T status, cmd[1], data[1];
425
426 cmd[0] = 0x66;
427
428 SPI_DisableSSP();
429 Assert_CS();
430 //fire it up
431 SPI_FireUp();
432
433 SPI_Write_Read(cmd, data, sizeof(cmd));
434
435 Deassert_CS();
436 SPI_DisableSSP();
437
438 return;
439}
440
441void SPINOR_ResetMemory(void)
442{
443 UINT8_T status, cmd[1], data[1];
444
445 cmd[0] = 0x99;
446
447 SPI_DisableSSP();
448 Assert_CS();
449 //fire it up
450 SPI_FireUp();
451
452 SPI_Write_Read(cmd, data, sizeof(cmd));
453
454 Deassert_CS();
455
456 SPI_DisableSSP();
457
458 return;
459}
460
461void SPINOR_WriteStatus(unsigned char status)
462{
463 unsigned int temp;
464
465 temp = 0x01 << 8;
466 temp |= status;
467
468 SPI_DisableSSP();
469
470 SPI_ConfigDSS(16);
471
472 Assert_CS();
473 //fire it up
474 SPI_FireUp();
475
476 SPI_WriteData(temp);
477 SPI_WaitSSPComplete();
478
479 Deassert_CS();
480 SPI_DisableSSP();
481
482 return;
483}
484
485
486void SPINOR_ReadStatus(UINT_T Wait)
487{
488 UINT_T i=0, timeout=0;
489 UINT_T read, ready, dummy, status;
490
491 status = NoError;
492 read = FALSE; //this flag gets set when we read first entry from fifo
493 //if the caller waits to 'Wait' for the BUSY to be cleared, start READY off as FALSE
494 //if the caller doesn't wait to wait, set READY as true, so we don't wait on the bit
495 ready = (Wait) ? FALSE : TRUE;
496
497 do{
498 SPI_DisableSSP();
499
500 SPI_ConfigDSS(16);
501 Assert_CS();
502 //fire it up
503 SPI_FireUp();
504
505 //load the command + 1 dummy byte
506 SPI_WriteData(SPI_CMD_READ_STATUS << 8);
507 SPI_WaitSSPComplete();
508 dummy = SPI_ReadData();
509 Deassert_CS();
510
511 //set the READ flag, and read the status
512 read = TRUE;
513 status = dummy & 0xFF; //the status will be in the second byte
514
515 //set the READY flag if the status wait bit is cleared
516 if((status & 1) == 0) // operation complete (eg. not busy)?
517 ready = TRUE;
518
519 SPI_DisableSSP();
520
521 //we need to wait until we read at least 1 valid status entry
522 //if we're waiting for the Write, wait till WIP bits goes to 0
523 }while ((!read) || (!ready));
524
525
526 //return last known status
527 return;
528}
529
530void SPINOR_WriteEnable(void)
531{
532 UINT8_T status, cmd[1], data[1];
533
534 cmd[0] = SPI_CMD_WRITE_ENABLE;
535
536 P_SPINOR_T spinor_info = getSPINor_Info();
537
538 SPI_DisableSSP();
539
540 Assert_CS();
541 SPI_FireUp();
542
543 SPI_Write_Read(cmd, data, sizeof(cmd));
544
545 Deassert_CS();
546 //make sure SSP is disabled
547 SPI_DisableSSP();
548
549 status = SPINOR_ReadReg(SPINOR_write_enable_Status_Register);
550 if (status & BIT1 !=BIT1)
551 {
552 obm_printf("Write enable failed!!!\n\r");
553 }
554
555 return;
556}
557
558void SPINOR_ReadId(unsigned char *mid, unsigned short *did)
559{
560 UINT8_T cmd[4], data[4];
561
562 cmd[0] = SPI_CMD_JEDEC_ID;
563 cmd[1] = 0;
564 cmd[2] = 0;
565 cmd[3] = 0;
566
567 SPI_DisableSSP();
568
569 Assert_CS();
570 //fire it up
571 SPI_FireUp();
572
573 SPI_Write_Read(cmd, data, sizeof(cmd));
574
575 Deassert_CS();
576 SPI_DisableSSP();
577
578
579 *mid = data[1];
580 *did = data[3] | (data[2] << 8);
581
582 return;
583}
584
585unsigned int SPINOR_Page_Program_DMA(unsigned int Address, unsigned int Buffer, unsigned int Size)
586{
587 unsigned int dummy, start_time, Retval = NoError;
588 DMA_CMDx_T TX_data;
589 UINT8_T cmd[4], data[4];
590 INT_T i;
591 volatile int timeout = 0xFFFFF;
592
593 cmd[0] = SPI_CMD_PROGRAM;
594 cmd[1] = ((Address & 0x00FFFFFF) >> 16) & 0xff;
595 cmd[2] = ((Address & 0x00FFFFFF) >> 8) & 0xff;
596 cmd[3] = Address & 0xFF;
597
598 TX_data.value = 0;
599 TX_data.bits.IncSrcAddr = 1;
600 TX_data.bits.FlowTrg = 1;
601 TX_data.bits.Width = 1; //Don't need to convert Endian if transmit by byte
602 TX_data.bits.MaxBurstSize = 1;
603 TX_data.bits.Length = Size;
604
605 //setup DMA
606 //Map Device to Channels
607 XllpDmacMapDeviceToChannel(SSP_TX_DMA_DEVICE, SSP_TX_CHANNEL);
608 XllpDmacNoDescriptorFetch(SSP_TX_CHANNEL );
609
610 //turn ON user alignment - in case buffer address is 64bit aligned
611 alignChannel(SSP_TX_CHANNEL, 1);
612
613 loadNonDescriptor((unsigned int)Buffer, (unsigned int) SSP_DR, &TX_data, SSP_TX_CHANNEL);
614
615 SPI_DisableSSP();
616
617 //setup for DMA: TX and RX DMA request + DMA handles Trailing bytes
618 SPI_ConfigDMA(4, 3, 0, 0, 0);
619
620 //setup IER
621 SPI_ConfigInt(0);
622 Assert_CS();
623 //fire it up
624 SPI_FireUp();
625
626 SPI_Write_Read(cmd, data, sizeof(cmd));
627
628 //fire it up
629 SPI_FireUp();
630 //Kick off DMA's
631 XllpDmacStartTransfer(SSP_TX_CHANNEL);
632
633 //wait until the TX channel gets the stop interrupt
634 timeout = 0xFFFFFF;
635 while( (readDmaStatusRegister(SSP_TX_CHANNEL) & XLLP_DMAC_DCSR_STOP_INTR) != XLLP_DMAC_DCSR_STOP_INTR )
636 {
637 ROW_DELAY(DEFAULT_TIMEOUT);
638
639 //if we've waited long enough, fail
640 if((timeout--) <= 0)
641 {
642 obm_printf("TX channel gets the stop interrupt timeout\n\r");
643 break;
644 }
645 }
646
647 SPI_WaitSSPComplete();
648
649 Deassert_CS();
650 SPI_DisableSSP();
651
652 //clear out DMA settings
653 XllpDmacUnMapDeviceToChannel(SSP_TX_DMA_DEVICE, SSP_TX_CHANNEL);
654
655 return Retval;
656
657}
658
659unsigned int SPINOR_Read_DMA(unsigned int Offset, unsigned int Buffer, unsigned int Size)
660{
661 unsigned int i;
662 DMA_CMDx_T RX_data, TX_cmd;
663 UINT8_T data[4];
664 UINT_T command, dummy, timeout;
665
666 unsigned int * buff = (unsigned int *) Buffer;
667
668 command = SPI_CMD_READ;
669 command |= (((Offset >> 16) & 0xFF) << 8);
670 command |= (((Offset >> 8) & 0xFF) << 16);
671 command |= (((Offset >> 0) & 0xFF) << 24);
672
673 //fill out commands
674 RX_data.value = 0;
675 RX_data.bits.IncTrgAddr = 1;
676 RX_data.bits.FlowSrc = 1;
677 RX_data.bits.Width = 3;
678 RX_data.bits.MaxBurstSize = 2;
679
680 TX_cmd.value = 0;
681 TX_cmd.bits.IncSrcAddr = 1;
682 TX_cmd.bits.FlowTrg = 1;
683 TX_cmd.bits.Width = 3;
684 TX_cmd.bits.MaxBurstSize = 2;
685
686 //Map Device to Channels
687 XllpDmacMapDeviceToChannel(SSP_RX_DMA_DEVICE, SSP_RX_CHANNEL);
688 XllpDmacMapDeviceToChannel(SSP_TX_DMA_DEVICE, SSP_TX_CHANNEL);
689
690 //turn ON user alignment - in case buffer address is 64bit aligned
691 alignChannel(SSP_RX_CHANNEL, 1);
692
693 // * configure RX & TX descriptors * //
694 configDescriptor(&pRX_data, NULL, (unsigned int)SSP_DR, (unsigned int)Buffer, &RX_data, Size, 1);
695 configDescriptor(&pTX_cmd,
696 NULL,
697 (unsigned int)&tx_command_spinor[0],
698 (unsigned int)SSP_DR,
699 &TX_cmd,
700 Size,
701 1);
702
703 //Load descriptors
704 loadDescriptor (&pRX_data, SSP_RX_CHANNEL);
705 loadDescriptor (&pTX_cmd, SSP_TX_CHANNEL);
706
707 SPI_DisableSSP();
708
709 //setup in 32 bit mode
710 SPI_ConfigDSS(32);
711
712 //setup for DMA: TX and RX DMA request + DMA handles Trailing bytes + FIFO RX Thresh+1
713 //SSP controller does endian convert, enable RX FIFO Auto Full Control
714 SPI_ConfigDMA(3, 3, 2, 2, 1);
715
716 //setup IER
717 SPI_ConfigInt(0);
718
719 #if ENABLE_MMU
720 dcache_clean_range(&pRX_data, sizeof(XLLP_DMAC_DESCRIPTOR_T));
721 dcache_clean_range(&pTX_cmd, sizeof(XLLP_DMAC_DESCRIPTOR_T));
722 dcache_clean_range(&tx_command_spinor[0], sizeof(tx_command_spinor));
723 dcache_invalidate_range(Buffer, Size);
724 #endif
725
726 Assert_CS();
727 //fire it up
728 SPI_FireUp();
729
730 SPI_WriteData(command);
731 SPI_WaitSSPComplete();
732 dummy = SPI_ReadData();
733
734 //Kick off DMA's
735 XllpDmacStartTransfer(SSP_TX_CHANNEL);
736 XllpDmacStartTransfer(SSP_RX_CHANNEL);
737
738 //wait until the RX channel gets the stop interrupt
739 timeout = 0xFFFFF;
740 while( (readDmaStatusRegister(SSP_RX_CHANNEL) & XLLP_DMAC_DCSR_STOP_INTR) != XLLP_DMAC_DCSR_STOP_INTR )
741 {
742 ROW_DELAY(DEFAULT_TIMEOUT);
743
744 if((timeout--) <= 0)
745 {
746 obm_printf("RX channel gets the stop interrupt timeout\n\r");
747 break;
748 }
749 }
750
751 timeout = 0xFFFFF;
752 while( (readDmaStatusRegister(SSP_TX_CHANNEL) & XLLP_DMAC_DCSR_STOP_INTR) != XLLP_DMAC_DCSR_STOP_INTR )
753 {
754 ROW_DELAY(DEFAULT_TIMEOUT);
755
756 if((timeout--) <= 0)
757 {
758 obm_printf("TX channel gets the stop interrupt timeout\n\r");
759 break;
760 }
761 }
762
763 SPI_WaitSSPComplete();
764
765 Deassert_CS();
766 SPI_DisableSSP();
767
768 //clear out DMA settings
769 XllpDmacUnMapDeviceToChannel(SSP_RX_DMA_DEVICE, SSP_RX_CHANNEL);
770 XllpDmacUnMapDeviceToChannel(SSP_TX_DMA_DEVICE, SSP_TX_CHANNEL);
771
772 return NoError;
773}
774
775
776UINT_T SPINOR_Read(UINT_T FlashOffset, UINT_T Buffer, UINT_T Size)
777{
778 UINT_T Retval = NoError, i, total_size, read_size, status;
779
780 do {
781
782 read_size = Size > SIZE_4KB ? SIZE_4KB : Size;
783
784 Retval = SPINOR_Read_DMA(FlashOffset, Buffer, SIZE_4KB);
785
786 //update counters
787 FlashOffset+=read_size;
788 Buffer+=read_size;
789 Size-=read_size;
790
791 } while( (Size > 0) && (Retval == NoError) );
792
793 return Retval;
794}
795
796UINT_T SPINOR_EraseSector(UINT_T secAddr, UINT_T cmdSel)
797{
798 UINT_T temp, command, CMDSelect;
799
800 SPINOR_ReadStatus(TRUE);
801 SPINOR_WriteEnable();
802 SPINOR_ReadStatus(TRUE);
803
804 switch (cmdSel)
805 {
806 case 0:
807 //obm_printf("4KB erase command 0x20\n\r");
808 CMDSelect = 0x20;
809 break;
810
811 case 1:
812 //obm_printf("32KB erase command 0xd8\n\r");
813 CMDSelect = 0xd8;
814 break;
815
816 default:
817 //obm_printf("64KB erase command 0xd8\n\r");
818 CMDSelect = 0xd8;
819 break;
820 }
821
822 if (Spansion_SPINOR_Flash)
823 command = CMDSelect << 24;
824 else
825 command = SPI_CMD_SECTOR_ERASE << 24;
826
827 command |= secAddr & 0xFFFFFF;
828
829 SPI_DisableSSP();
830
831 SPI_ConfigDSS(32);
832
833 Assert_CS();
834 SPI_FireUp();
835
836 SPI_WriteData(command);
837 SPI_WaitSSPComplete();
838
839 Deassert_CS();
840 //make sure SSP is disabled
841 SPI_DisableSSP();
842
843 SPINOR_ReadStatus(TRUE);
844
845 return NoError;
846}
847
848UINT_T SPINOR_Wipe(void)
849{
850 UINT8_T cmd[1], data[1];
851
852 cmd[0] = SPI_CMD_CHIP_ERASE;
853
854 //make sure the device is ready for the command
855 SPINOR_ReadStatus(TRUE);
856 SPINOR_WriteEnable();
857 SPINOR_ReadStatus(TRUE);
858
859 SPI_DisableSSP();
860
861 Assert_CS();
862 SPI_FireUp();
863
864 SPI_Write_Read(cmd, data, sizeof(cmd));
865
866 Deassert_CS();
867 //make sure SSP is disabled
868 SPI_DisableSSP();
869
870 SPINOR_ReadStatus(TRUE);
871
872 return NoError;
873}
874
875UINT_T SPINOR_Write(UINT_T Address, UINT_T Buffer, UINT_T Size)
876{
877 UINT_T Retval, i, total_size, write_size, status;
878 UINT_T *buff = (UINT_T *) Buffer;
879
880 if(Size & 0x3) //make size 4bytes-align
881 Size = (Size+4)&(~3);
882
883 total_size = Size >> 2;
884
885 //postprocessing... endian convert
886 if ((Address + Size) > 0x1000000)
887 return FlashAddrOutOfRange;
888
889 do {
890 //make sure the device is ready to be written to
891 SPINOR_ReadStatus(TRUE);
892 //get device ready to Program
893 SPINOR_WriteEnable();
894
895 SPINOR_ReadStatus(TRUE);
896
897 write_size = Size > WRITE_SIZE ? WRITE_SIZE : Size;
898
899 //write a byte
900 if (write_size == WRITE_SIZE)
901 {
902 Retval = SPINOR_Page_Program_DMA(Address, Buffer, WRITE_SIZE);
903
904 //update counters
905 Address+=WRITE_SIZE;
906 Buffer+=WRITE_SIZE;
907 Size-=WRITE_SIZE;
908 }
909 else
910 {
911 Retval = SPINOR_Page_Program_DMA(Address, Buffer, WRITE_SIZE);
912 Size=0;
913 }
914
915 SPINOR_ReadStatus(TRUE);
916
917 } while( (Size > 0) && (Retval == NoError) );
918
919 return Retval;
920}
921
922UINT_T SPINOR_Erase(UINT_T Address, UINT_T Size)
923{
924 UINT_T numSectors, i, sector_size, Retval = NoError, zero_address = 0;
925
926 P_FlashProperties_T pFlashP = GetFlashProperties(BOOT_FLASH);
927
928 if ((Address + Size) > 0x1000000)
929 return FlashAddrOutOfRange;
930
931 if ((Spansion_SPINOR_Flash) && (Address == 0))
932 zero_address = 1;
933
934 if (zero_address)
935 {
936 for (i = 0; i < 8; i++)
937 {
938 SPINOR_EraseSector(Address, 0);
939 Address += 0x1000;
940 }
941
942 SPINOR_EraseSector(Address, 1);
943 Address += 0x8000;
944 }
945
946 sector_size = pFlashP->BlockSize;
947
948 if (Size % pFlashP->BlockSize == 0)
949 numSectors = Size / pFlashP->BlockSize;
950 else
951 numSectors = Size / pFlashP->BlockSize + 1;
952
953 if (zero_address)
954 numSectors -= 1;
955
956 for (i = 0; i < numSectors; i++)
957 {
958 //erase this sector
959 Retval = SPINOR_EraseSector(Address, 2);
960
961 Address += sector_size;
962
963 if (Retval != NoError)
964 break;
965 }
966
967 return Retval;
968}
969