blob: 87afb01f1689cd8637c92f201d6c363fb6a8f770 [file] [log] [blame]
b.liue9582032025-04-17 19:18:16 +08001/******************************************************************************
2 *
3 * (C)Copyright 2014 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 "SPINOR_extened.h"
21
22extern __attribute__ ((aligned(16))) XLLP_DMAC_DESCRIPTOR_T pRX_data, pTX_cmd;
23extern VUINT_T ssp_52mhz;
24extern UINT_T Spansion_SPINOR_Flash;
25__attribute__ ((aligned(16)))unsigned char tx_command_spinor[SIZE_4KB] = {0};
26extern UINT_T spi_tx_dma, spi_rx_dma;
27
28unsigned int Extend_Read(unsigned int Offset, unsigned int Buffer, unsigned int Size)
29{
30 unsigned int i;
31 DMA_CMDx_T RX_data, TX_cmd;
32 UINT8_T data[5];
33
34 unsigned int * buff = (unsigned int *) Buffer;
35
36 P_SPINOR_T spinor_info = getSPINor_Info();
37
38 tx_command_spinor[0] = spinor_info->read_4bytes_cmd;
39 tx_command_spinor[1] = (Offset >> 24) & 0xFF;
40 tx_command_spinor[2] = (Offset >> 16) & 0xFF;
41 tx_command_spinor[3] = (Offset >> 8) & 0xFF;
42 tx_command_spinor[4] = (Offset >> 0) & 0xFF;
43
44
45 //fill out commands
46 RX_data.value = 0;
47 RX_data.bits.IncTrgAddr = 1;
48 RX_data.bits.FlowSrc = 1;
49 RX_data.bits.Width = 3;
50 RX_data.bits.MaxBurstSize = 2;
51
52 TX_cmd.value = 0;
53 TX_cmd.bits.IncSrcAddr = 1;
54 TX_cmd.bits.FlowTrg = 1;
55 TX_cmd.bits.Width = 3;
56 TX_cmd.bits.MaxBurstSize = 2;
57
58 //Map Device to Channels
59 XllpDmacMapDeviceToChannel(spi_rx_dma, SSP_RX_CHANNEL);
60 XllpDmacMapDeviceToChannel(spi_tx_dma, SSP_TX_CHANNEL);
61
62 //turn ON user alignment - in case buffer address is 64bit aligned
63 alignChannel(SSP_RX_CHANNEL, 1);
64
65 // * configure RX & TX descriptors * //
66 configDescriptor(&pRX_data, NULL, (unsigned int)SSP_DR, (unsigned int)Buffer, &RX_data, Size, 1);
67 configDescriptor(&pTX_cmd,
68 NULL,
69 (unsigned int)&tx_command_spinor[0],
70 (unsigned int)SSP_DR,
71 &TX_cmd,
72 Size,
73 1);
74
75 //Load descriptors
76 loadDescriptor (&pRX_data, SSP_RX_CHANNEL);
77 loadDescriptor (&pTX_cmd, SSP_TX_CHANNEL);
78
79 SPI_DisableSSP();
80
81 // workaround for 52MHz SPI bit shift
82 if (ssp_52mhz)
83 reg_bit_set(SSP_CR0, SSP_SSCR0_52MM);
84 //setup for DMA: TX and RX DMA request + DMA handles Trailing bytes
85 reg_bit_set(SSP_CR1, SSP_SSCR1_TRAIL |
86 SSP_SSCR1_TSRE |
87 SSP_SSCR1_RSRE |
88 SSP_SSCR1_TINTE|
89 (8 << SSP_SSCR1_TFT_BASE) | // TFT: 3
90 (3 << SSP_SSCR1_RFT_BASE)); // RFT: 4
91
92 reg_write(SSP_TO, 0x400);
93
94 #if ENABLE_MMU
95 dcache_clean_range(&pRX_data, sizeof(XLLP_DMAC_DESCRIPTOR_T));
96 dcache_clean_range(&pTX_cmd, sizeof(XLLP_DMAC_DESCRIPTOR_T));
97 dcache_clean_range(&tx_command_spinor[0], sizeof(tx_command_spinor));
98 dcache_invalidate_range(Buffer, Size);
99 #endif
100
101 //fire it up
102 reg_bit_set(SSP_CR0, SSP_CR0_SSE);
103
104 Assert_CS();
105
106 SPI_Write_Read(tx_command_spinor, data, 5);
107
108 SPI_DisableSSP();
109
110 //setup in 32 bit mode
111 reg_bit_set(SSP_CR0, SSP_CR0_DSS_32);
112
113 // workaround for 52MHz SPI bit shift
114 if (ssp_52mhz)
115 reg_bit_set(SSP_CR0, SSP_SSCR0_52MM);
116 //setup for DMA: TX and RX DMA request
117 reg_bit_set(SSP_CR1, SSP_SSCR1_TRAIL |
118 SSP_SSCR1_TSRE |
119 SSP_SSCR1_RSRE |
120 SSP_SSCR1_TINTE|
121 (8 << SSP_SSCR1_TFT_BASE) | // TFT: 3
122 (3 << SSP_SSCR1_RFT_BASE)); // RFT: 4
123
124 reg_write(SSP_TO, 0x400);
125
126 //fire it up
127 reg_bit_set(SSP_CR0, SSP_CR0_SSE);
128
129 //Kick off DMA's
130 XllpDmacStartTransfer(SSP_TX_CHANNEL);
131 XllpDmacStartTransfer(SSP_RX_CHANNEL);
132
133 //wait until the RX channel gets the stop interrupt
134 while( (readDmaStatusRegister(SSP_RX_CHANNEL) & XLLP_DMAC_DCSR_STOP_INTR) != XLLP_DMAC_DCSR_STOP_INTR )
135 ROW_DELAY(DEFAULT_TIMEOUT);
136
137 while( (readDmaStatusRegister(SSP_TX_CHANNEL) & XLLP_DMAC_DCSR_STOP_INTR) != XLLP_DMAC_DCSR_STOP_INTR )
138 ROW_DELAY(DEFAULT_TIMEOUT);
139
140 SPI_WaitSSPComplete();
141
142 Deassert_CS();
143
144 SPI_DisableSSP();
145
146 //clear out DMA settings
147 XllpDmacUnMapDeviceToChannel(spi_rx_dma, SSP_RX_CHANNEL);
148 XllpDmacUnMapDeviceToChannel(spi_tx_dma, SSP_TX_CHANNEL);
149
150 //postprocessing... endian convert
151 Size >>= 2; //convert Size from bytes to words
152 for(i = 0; i < Size; i++)
153 buff[i] = Endian_Convert(buff[i]);
154
155 return NoError;
156}
157
158UINT_T SPINOR_Extend_Read(UINT_T FlashOffset, UINT_T Buffer, UINT_T Size)
159{
160 UINT_T Retval, i, total_size, read_size, status;
161
162 do {
163
164 read_size = Size > SIZE_4KB ? SIZE_4KB : Size;
165
166 Retval = Extend_Read(FlashOffset, Buffer, SIZE_4KB);
167
168 //update counters
169 FlashOffset+=read_size;
170 Buffer+=read_size;
171 Size-=read_size;
172
173 } while( (Size > 0) && (Retval == NoError) );
174
175 return Retval;
176}
177
178unsigned int Extend_Write(unsigned int Address, unsigned int Buffer, unsigned int Size)
179{
180 unsigned int i;
181 DMA_CMDx_T TX_data;
182 unsigned char cmd[5], data[5];
183 P_SPINOR_T spinor_info = getSPINor_Info();
184 unsigned int convert_size = Size;
185
186 unsigned int * convert_buff = NULL;
187 unsigned int * orginal_buff = (unsigned int *) Buffer;
188
189 convert_buff = (unsigned int *) malloc(Size);
190 if(convert_buff == NULL)
191 return HeapExhaustedError;
192
193#if 1
194 //postprocessing... endian convert
195 convert_size >>= 2; //convert Size from bytes to words
196 for(i = 0; i < convert_size; i++)
197 convert_buff[i] = Endian_Convert(orginal_buff[i]);
198
199 cmd[0] = spinor_info->write_4bytes_cmd;
200 cmd[1] = (Address >> 24) & 0xFF;
201 cmd[2] = (Address >> 16) & 0xFF;
202 cmd[3] = (Address >> 8) & 0xFF;
203 cmd[4] = (Address >> 0) & 0xFF;
204
205 TX_data.value = 0;
206 TX_data.bits.IncSrcAddr = 1;
207 TX_data.bits.FlowTrg = 1;
208 TX_data.bits.Width = 3;
209 TX_data.bits.MaxBurstSize = 2;
210 TX_data.bits.Length = Size;
211
212 //setup DMA
213 //Map Device to Channels
214 XllpDmacMapDeviceToChannel(spi_tx_dma, SSP_TX_CHANNEL);
215 XllpDmacNoDescriptorFetch( SSP_TX_CHANNEL );
216
217 //turn ON user alignment - in case buffer address is 64bit aligned
218 alignChannel(SSP_TX_CHANNEL, 1);
219
220 loadNonDescriptor((unsigned int)convert_buff, (unsigned int) SSP_DR, &TX_data, SSP_TX_CHANNEL);
221
222 SPI_DisableSSP();
223
224 // workaround for 52MHz SPI bit shift
225 if (ssp_52mhz)
226 reg_bit_set(SSP_CR0, SSP_SSCR0_52MM);
227 //setup for DMA: TX and RX DMA request
228 reg_bit_set(SSP_CR1, SSP_SSCR1_TRAIL |
229 SSP_SSCR1_TSRE |
230 SSP_SSCR1_RSRE |
231 SSP_SSCR1_TINTE|
232 (3 << SSP_SSCR1_TFT_BASE) |
233 (4 << SSP_SSCR1_RFT_BASE));
234
235 reg_write(SSP_TO, 0x400);
236
237 //fire it up
238 reg_bit_set(SSP_CR0, SSP_CR0_SSE);
239
240 Assert_CS();
241
242 SPI_Write_Read(cmd, data, sizeof(cmd));
243
244 SPI_DisableSSP();
245
246 //setup in 32 bit mode
247 reg_bit_set(SSP_CR0, SSP_CR0_DSS_32);
248
249 // workaround for 52MHz SPI bit shift
250 if (ssp_52mhz)
251 reg_bit_set(SSP_CR0, SSP_SSCR0_52MM);
252 //setup for DMA: TX and RX DMA request
253 reg_bit_set(SSP_CR1, SSP_SSCR1_TRAIL |
254 SSP_SSCR1_TSRE |
255 SSP_SSCR1_RSRE |
256 SSP_SSCR1_TINTE|
257 (3 << SSP_SSCR1_TFT_BASE) |
258 (4 << SSP_SSCR1_RFT_BASE));
259
260 reg_write(SSP_TO, 0x400);
261
262 //fire it up
263 reg_bit_set(SSP_CR0, SSP_CR0_SSE);
264
265 //Kick off DMA's
266 XllpDmacStartTransfer(SSP_TX_CHANNEL);
267
268 //wait until the RX channel gets the stop interrupt
269 while( (readDmaStatusRegister(SSP_TX_CHANNEL) & XLLP_DMAC_DCSR_STOP_INTR) != XLLP_DMAC_DCSR_STOP_INTR )
270 ROW_DELAY(DEFAULT_TIMEOUT);
271
272 SPI_WaitSSPComplete();
273
274 Deassert_CS();
275
276 SPI_DisableSSP();
277
278 //clear out DMA settings
279 XllpDmacUnMapDeviceToChannel(spi_tx_dma, SSP_TX_CHANNEL);
280
281 free(convert_buff);
282 return NoError;
283
284}
285
286UINT_T SPINOR_Extend_Write(UINT_T Address, UINT_T Buffer, UINT_T Size)
287{
288 UINT_T Retval = NoError, i, total_size, write_size, status;
289 UINT_T *buff = (UINT_T *) Buffer;
290 UINT8_T status1;
291
292 if(Size & 0x3) //make size 4bytes-align
293 Size = (Size+4)&(~3);
294
295 total_size = Size >> 2;
296
297 if ((Address + Size) > 0x2000000)
298 return FlashAddrOutOfRange;
299
300 do {
301 //make sure the device is ready to be written to
302 SPINOR_ReadStatus(TRUE);
303 //get device ready to Program
304 SPINOR_WriteEnable();
305 SPINOR_ReadStatus(TRUE);
306
307 write_size = Size > WRITE_SIZE ? WRITE_SIZE : Size;
308
309 //write a byte
310 if (write_size == WRITE_SIZE)
311 {
312 Retval = Extend_Write(Address, Buffer, WRITE_SIZE);
313
314 //update counters
315 Address+=WRITE_SIZE;
316 Buffer+=WRITE_SIZE;
317 Size-=WRITE_SIZE;
318 }
319 else
320 {
321 Retval = Extend_Write(Address, Buffer, WRITE_SIZE);
322 Size=0;
323 }
324
325 SPINOR_ReadStatus(TRUE);
326 } while( (Size > 0) && (Retval == NoError) );
327
328 return Retval;
329}
330
331UINT_T Extend_EraseSector(UINT_T secAddr, UINT_T cmdSel)
332{
333 UINT_T Retval = NoError, CMDSelect;
334 unsigned char cmd[5], data[5];
335
336 P_SPINOR_T spinor_info = getSPINor_Info();
337
338 switch (cmdSel)
339 {
340 case 0:
341 //obm_printf("4KB erase command 0x21\n\r");
342 CMDSelect = 0x21;
343 break;
344
345 case 1:
346 //obm_printf("32KB erase command 0xdc\n\r");
347 CMDSelect = 0xdc;
348 break;
349
350 default:
351 //obm_printf("64KB erase command 0xdc\n\r");
352 CMDSelect = 0xdc;
353 break;
354 }
355
356 SPINOR_ReadStatus(TRUE);
357 SPINOR_WriteEnable();
358 SPINOR_ReadStatus(TRUE);
359
360 if (Spansion_SPINOR_Flash)
361 cmd[0] = CMDSelect;
362 else
363 cmd[0] = spinor_info->erase_4bytes_cmd;
364
365 cmd[1] = (secAddr >> 24) & 0xFF;
366 cmd[2] = (secAddr >> 16) & 0xFF;
367 cmd[3] = (secAddr >> 8) & 0xFF;
368 cmd[4] = (secAddr >> 0) & 0xFF;
369
370 SPI_DisableSSP();
371
372 // workaround for 52MHz SPI bit shift
373 if (ssp_52mhz)
374 reg_bit_set(SSP_CR0, SSP_SSCR0_52MM);
375 //fire it up
376 reg_bit_set(SSP_CR0, SSP_CR0_SSE);
377
378 Assert_CS();
379
380 SPI_Write_Read(cmd, data, sizeof(cmd));
381
382 SPI_WaitSSPComplete();
383
384 Deassert_CS();
385
386 //make sure SSP is disabled
387 SPI_DisableSSP();
388
389 return Retval;
390}
391
392
393UINT_T SPINOR_Extend_Erase(UINT_T Address, UINT_T Size)
394{
395 UINT_T numSectors, i, sector_size, Retval = NoError, zero_address = 0;
396
397 P_FlashProperties_T pFlashP = GetFlashProperties(BOOT_FLASH);
398
399 if ((Address + Size) > 0x2000000)
400 return FlashAddrOutOfRange;
401
402 if ((Spansion_SPINOR_Flash) && (Address == 0))
403 zero_address = 1;
404
405 if (zero_address)
406 {
407 for (i = 0; i < 8; i++)
408 {
409 Extend_EraseSector(Address, 0);
410 Address += 0x1000;
411 }
412
413 Extend_EraseSector(Address, 1);
414 Address += 0x8000;
415 }
416
417 sector_size = pFlashP->BlockSize;
418
419 if (Size % pFlashP->BlockSize == 0)
420 numSectors = Size / pFlashP->BlockSize;
421 else
422 numSectors = Size / pFlashP->BlockSize + 1;
423
424 if (zero_address)
425 numSectors -= 1;
426
427 for (i = 0; i < numSectors; i++)
428 {
429 Retval = Extend_EraseSector(Address, 2);
430
431 Address += sector_size;
432
433 if (Retval != NoError)
434 break;
435 }
436
437 return Retval;
438}
439