strip the kernel version suffix from target directories, except for brcm-2.4 (the...
[openwrt.git] / target / linux / at91 / image / dfboot / src / at45.c
1 /*----------------------------------------------------------------------------
2  *      ATMEL Microcontroller Software Support  -  ROUSSET  -
3  *----------------------------------------------------------------------------
4  * The software is delivered "AS IS" without warranty or condition of any
5  * kind, either express, implied or statutory. This includes without
6  * limitation any warranty or condition with respect to merchantability or
7  * fitness for any particular purpose, or against the infringements of
8  * intellectual property rights of others.
9  *----------------------------------------------------------------------------
10  * File Name           : at45c.h
11  * Object              : 
12  *
13  * 1.0  10/12/03 HIi    : Creation.
14  * 1.01 03/05/04 HIi    : Bug Fix in AT91F_DataFlashWaitReady() Function.
15  *----------------------------------------------------------------------------
16  */
17 #include "config.h"
18 #include "stdio.h"
19 #include "AT91RM9200.h"
20 #include "lib_AT91RM9200.h"
21 #include "dataflash.h"
22 #include "main.h"
23
24
25 /*----------------------------------------------------------------------------*/
26 /* \fn    AT91F_SpiInit                                                       */
27 /* \brief SPI Low level Init                                                  */
28 /*----------------------------------------------------------------------------*/
29 void AT91F_SpiInit(void) {
30         /* Configure PIOs */
31         AT91C_BASE_PIOA->PIO_ASR = AT91C_PA3_NPCS0 | AT91C_PA4_NPCS1 | 
32                                    AT91C_PA1_MOSI | AT91C_PA5_NPCS2 |
33                                    AT91C_PA6_NPCS3 | AT91C_PA0_MISO |
34                                    AT91C_PA2_SPCK;
35         AT91C_BASE_PIOA->PIO_PDR = AT91C_PA3_NPCS0 | AT91C_PA4_NPCS1 |
36                                    AT91C_PA1_MOSI | AT91C_PA5_NPCS2 |
37                                    AT91C_PA6_NPCS3 | AT91C_PA0_MISO |
38                                    AT91C_PA2_SPCK;
39         /* Enable CLock */
40         AT91C_BASE_PMC->PMC_PCER = 1 << AT91C_ID_SPI;
41
42         /* Reset the SPI */
43         AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SWRST;
44
45         /* Configure SPI in Master Mode with No CS selected !!! */
46         AT91C_BASE_SPI->SPI_MR = AT91C_SPI_MSTR | AT91C_SPI_MODFDIS | AT91C_SPI_PCS;
47
48         /* Configure CS0 and CS3 */
49         *(AT91C_SPI_CSR + 0) = AT91C_SPI_CPOL | (AT91C_SPI_DLYBS & DATAFLASH_TCSS) |
50                                (AT91C_SPI_DLYBCT & DATAFLASH_TCHS) |
51                                ((AT91C_MASTER_CLOCK / (2*AT91C_SPI_CLK)) << 8);
52         *(AT91C_SPI_CSR + 3) = AT91C_SPI_CPOL | (AT91C_SPI_DLYBS & DATAFLASH_TCSS) |
53                                (AT91C_SPI_DLYBCT & DATAFLASH_TCHS) |
54                                ((AT91C_MASTER_CLOCK / (2*AT91C_SPI_CLK)) << 8);
55 }
56
57
58 /*----------------------------------------------------------------------------*/
59 /* \fn    AT91F_SpiEnable                                                     */
60 /* \brief Enable SPI chip select                                              */
61 /*----------------------------------------------------------------------------*/
62 static void AT91F_SpiEnable(int cs) {
63         switch(cs) {
64         case 0: /* Configure SPI CS0 for Serial DataFlash AT45DBxx */
65                 AT91C_BASE_SPI->SPI_MR &= 0xFFF0FFFF;
66                 AT91C_BASE_SPI->SPI_MR |= ((AT91C_SPI_PCS0_SERIAL_DATAFLASH << 16) & AT91C_SPI_PCS);
67                 break;
68         case 3: /* Configure SPI CS3 for Serial DataFlash Card */
69                 /* Set up PIO SDC_TYPE to switch on DataFlash Card and not MMC/SDCard */
70                 AT91C_BASE_PIOB->PIO_PER = AT91C_PIO_PB7;       /* Set in PIO mode */
71                 AT91C_BASE_PIOB->PIO_OER = AT91C_PIO_PB7;       /* Configure in output */
72                 /* Clear Output */
73                 AT91C_BASE_PIOB->PIO_CODR = AT91C_PIO_PB7;
74                 /* Configure PCS */
75                 AT91C_BASE_SPI->SPI_MR &= 0xFFF0FFFF;
76                 AT91C_BASE_SPI->SPI_MR |= ((AT91C_SPI_PCS3_DATAFLASH_CARD<<16) & AT91C_SPI_PCS);
77                 break;
78         }
79
80         /* SPI_Enable */
81         AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SPIEN;
82 }
83
84 /*----------------------------------------------------------------------------*/
85 /* \fn    AT91F_SpiWrite                                                      */
86 /* \brief Set the PDC registers for a transfert                               */
87 /*----------------------------------------------------------------------------*/
88 static unsigned int AT91F_SpiWrite(AT91PS_DataflashDesc pDesc)
89 {
90         unsigned int timeout;
91         
92         AT91C_BASE_SPI->SPI_PTCR = AT91C_PDC_TXTDIS + AT91C_PDC_RXTDIS;
93
94         /* Initialize the Transmit and Receive Pointer */
95         AT91C_BASE_SPI->SPI_RPR = (unsigned int)pDesc->rx_cmd_pt ;
96         AT91C_BASE_SPI->SPI_TPR = (unsigned int)pDesc->tx_cmd_pt ;
97
98         /* Intialize the Transmit and Receive Counters */
99         AT91C_BASE_SPI->SPI_RCR = pDesc->rx_cmd_size;
100         AT91C_BASE_SPI->SPI_TCR = pDesc->tx_cmd_size;
101
102         if ( pDesc->tx_data_size != 0 ) {
103                 /* Initialize the Next Transmit and Next Receive Pointer */
104                 AT91C_BASE_SPI->SPI_RNPR = (unsigned int)pDesc->rx_data_pt ;
105                 AT91C_BASE_SPI->SPI_TNPR = (unsigned int)pDesc->tx_data_pt ;
106
107                 /* Intialize the Next Transmit and Next Receive Counters */
108                 AT91C_BASE_SPI->SPI_RNCR = pDesc->rx_data_size ;
109                 AT91C_BASE_SPI->SPI_TNCR = pDesc->tx_data_size ;
110         }
111
112         /* ARM simple, non interrupt dependent timer */
113         timeout = 0;
114
115         AT91C_BASE_SPI->SPI_PTCR = AT91C_PDC_TXTEN + AT91C_PDC_RXTEN;
116         while(!(AT91C_BASE_SPI->SPI_SR & AT91C_SPI_RXBUFF));
117
118         AT91C_BASE_SPI->SPI_PTCR = AT91C_PDC_TXTDIS + AT91C_PDC_RXTDIS;
119
120         if (timeout >= AT91C_DATAFLASH_TIMEOUT){
121                 return AT91C_DATAFLASH_ERROR;
122         }
123
124         return AT91C_DATAFLASH_OK;
125 }
126
127
128 /*----------------------------------------------------------------------*/
129 /* \fn    AT91F_DataFlashSendCommand                                    */
130 /* \brief Generic function to send a command to the dataflash           */
131 /*----------------------------------------------------------------------*/
132 static AT91S_DataFlashStatus AT91F_DataFlashSendCommand(
133         AT91PS_DataFlash pDataFlash,
134         unsigned char OpCode,
135         unsigned int CmdSize,
136         unsigned int DataflashAddress)
137 {
138         unsigned int adr;
139
140         /* process the address to obtain page address and byte address */
141         adr = ((DataflashAddress / (pDataFlash->pDevice->pages_size)) 
142                 << pDataFlash->pDevice->page_offset) +
143                 (DataflashAddress % (pDataFlash->pDevice->pages_size));
144
145         /* fill the  command  buffer */
146         pDataFlash->pDataFlashDesc->command[0] = OpCode;
147         if (pDataFlash->pDevice->pages_number >= 16384)
148         {
149                 pDataFlash->pDataFlashDesc->command[1] = (unsigned char)((adr & 0x0F000000) >> 24);
150                 pDataFlash->pDataFlashDesc->command[2] = (unsigned char)((adr & 0x00FF0000) >> 16);
151                 pDataFlash->pDataFlashDesc->command[3] = (unsigned char)((adr & 0x0000FF00) >> 8);
152                 pDataFlash->pDataFlashDesc->command[4] = (unsigned char)(adr & 0x000000FF);
153         }
154         else
155         {       
156                 pDataFlash->pDataFlashDesc->command[1] = (unsigned char)((adr & 0x00FF0000) >> 16);
157                 pDataFlash->pDataFlashDesc->command[2] = (unsigned char)((adr & 0x0000FF00) >> 8);
158                 pDataFlash->pDataFlashDesc->command[3] = (unsigned char)(adr & 0x000000FF) ;
159                 pDataFlash->pDataFlashDesc->command[4] = 0;
160         }
161         pDataFlash->pDataFlashDesc->command[5] = 0;
162         pDataFlash->pDataFlashDesc->command[6] = 0;
163         pDataFlash->pDataFlashDesc->command[7] = 0;
164
165         /* Initialize the SpiData structure for the spi write fuction */
166         pDataFlash->pDataFlashDesc->tx_cmd_pt   =  pDataFlash->pDataFlashDesc->command ;
167         pDataFlash->pDataFlashDesc->tx_cmd_size =  CmdSize ;
168         pDataFlash->pDataFlashDesc->rx_cmd_pt   =  pDataFlash->pDataFlashDesc->command ;
169         pDataFlash->pDataFlashDesc->rx_cmd_size =  CmdSize ;
170
171         return AT91F_SpiWrite(pDataFlash->pDataFlashDesc);                      
172 }
173
174
175 /*----------------------------------------------------------------------*/
176 /* \fn    AT91F_DataFlashGetStatus                                      */
177 /* \brief Read the status register of the dataflash                     */
178 /*----------------------------------------------------------------------*/
179 static AT91S_DataFlashStatus AT91F_DataFlashGetStatus(AT91PS_DataflashDesc pDesc)
180 {
181         AT91S_DataFlashStatus status;
182
183         /* first send the read status command (D7H) */
184         pDesc->command[0] = DB_STATUS;
185         pDesc->command[1] = 0;
186
187         pDesc->DataFlash_state = GET_STATUS;
188         pDesc->tx_data_size    = 0 ; /* Transmit the command and receive response */
189         pDesc->tx_cmd_pt       = pDesc->command ;
190         pDesc->rx_cmd_pt       = pDesc->command ;
191         pDesc->rx_cmd_size     = 2 ;
192         pDesc->tx_cmd_size     = 2 ;
193         status = AT91F_SpiWrite (pDesc);
194
195         pDesc->DataFlash_state = *( (unsigned char *) (pDesc->rx_cmd_pt) +1);
196         return status;
197 }
198
199 /*-----------------------------------------------------------------------------
200  * Function Name       : AT91F_DataFlashWaitReady
201  * Object              : wait for dataflash ready (bit7 of the status register == 1)
202  * Input Parameters    : DataFlash Service and timeout
203  * Return value        : DataFlash status "ready or not"
204  *-----------------------------------------------------------------------------
205  */
206 static AT91S_DataFlashStatus AT91F_DataFlashWaitReady(
207         AT91PS_DataflashDesc pDataFlashDesc,
208         unsigned int timeout)
209 {
210         pDataFlashDesc->DataFlash_state = IDLE;
211         do {
212                 AT91F_DataFlashGetStatus(pDataFlashDesc);
213                 timeout--;
214         }
215         while(((pDataFlashDesc->DataFlash_state & 0x80) != 0x80) && (timeout > 0));
216
217         if((pDataFlashDesc->DataFlash_state & 0x80) != 0x80)
218                 return AT91C_DATAFLASH_ERROR;
219
220         return AT91C_DATAFLASH_OK;
221 }
222
223
224 /*------------------------------------------------------------------------------*/
225 /* Function Name       : AT91F_DataFlashContinuousRead                          */
226 /* Object              : Continuous stream Read                                 */
227 /* Input Parameters    : DataFlash Service                                      */
228 /*                     : <src> = dataflash address                              */
229 /*                     : <*dataBuffer> = data buffer pointer                    */
230 /*                     : <sizeToRead> = data buffer size                        */
231 /* Return value        : State of the dataflash                                 */
232 /*------------------------------------------------------------------------------*/
233 static AT91S_DataFlashStatus AT91F_DataFlashContinuousRead(
234         AT91PS_DataFlash pDataFlash,
235         int src,
236         unsigned char *dataBuffer,
237         int sizeToRead )
238 {
239         AT91S_DataFlashStatus status;
240         /* Test the size to read in the device */
241         if ( (src + sizeToRead) > (pDataFlash->pDevice->pages_size * (pDataFlash->pDevice->pages_number)))
242                 return AT91C_DATAFLASH_MEMORY_OVERFLOW;
243
244         pDataFlash->pDataFlashDesc->rx_data_pt = dataBuffer;
245         pDataFlash->pDataFlashDesc->rx_data_size = sizeToRead;
246         pDataFlash->pDataFlashDesc->tx_data_pt = dataBuffer;
247         pDataFlash->pDataFlashDesc->tx_data_size = sizeToRead;
248         
249         status = AT91F_DataFlashSendCommand(pDataFlash, DB_CONTINUOUS_ARRAY_READ, 8, src);
250         /* Send the command to the dataflash */
251         return(status);
252 }
253
254
255
256 /*------------------------------------------------------------------------------*/
257 /* Function Name       : AT91F_MainMemoryToBufferTransfer                       */
258 /* Object              : Read a page in the SRAM Buffer 1 or 2                  */
259 /* Input Parameters    : DataFlash Service                                      */
260 /*                     : Page concerned                                         */
261 /*                     :                                                        */
262 /* Return value        : State of the dataflash                                 */
263 /*------------------------------------------------------------------------------*/
264 static AT91S_DataFlashStatus AT91F_MainMemoryToBufferTransfer(
265         AT91PS_DataFlash pDataFlash,
266         unsigned char BufferCommand,
267         unsigned int page)
268 {
269         int cmdsize;
270         /* Test if the buffer command is legal */
271         if ((BufferCommand != DB_PAGE_2_BUF1_TRF) && (BufferCommand != DB_PAGE_2_BUF2_TRF))
272                 return AT91C_DATAFLASH_BAD_COMMAND;
273
274         /* no data to transmit or receive */
275         pDataFlash->pDataFlashDesc->tx_data_size = 0;
276         cmdsize = 4;
277         if (pDataFlash->pDevice->pages_number >= 16384)
278                 cmdsize = 5;
279         return(AT91F_DataFlashSendCommand(pDataFlash, BufferCommand, cmdsize,
280                                           page*pDataFlash->pDevice->pages_size));
281 }
282
283
284
285 /*----------------------------------------------------------------------------- */
286 /* Function Name       : AT91F_DataFlashWriteBuffer                             */
287 /* Object              : Write data to the internal sram buffer 1 or 2          */
288 /* Input Parameters    : DataFlash Service                                      */
289 /*                     : <BufferCommand> = command to write buffer1 or buffer2  */
290 /*                     : <*dataBuffer> = data buffer to write                   */
291 /*                     : <bufferAddress> = address in the internal buffer       */
292 /*                     : <SizeToWrite> = data buffer size                       */
293 /* Return value        : State of the dataflash                                 */
294 /*------------------------------------------------------------------------------*/
295 static AT91S_DataFlashStatus AT91F_DataFlashWriteBuffer(
296         AT91PS_DataFlash pDataFlash,
297         unsigned char BufferCommand,
298         unsigned char *dataBuffer,
299         unsigned int bufferAddress,
300         int SizeToWrite )
301 {
302         int cmdsize;
303         /* Test if the buffer command is legal */
304         if ((BufferCommand != DB_BUF1_WRITE) && (BufferCommand != DB_BUF2_WRITE))
305                 return AT91C_DATAFLASH_BAD_COMMAND;
306
307         /* buffer address must be lower than page size */
308         if (bufferAddress > pDataFlash->pDevice->pages_size)
309                 return AT91C_DATAFLASH_BAD_ADDRESS;
310
311         /* Send first Write Command */
312         pDataFlash->pDataFlashDesc->command[0] = BufferCommand;
313         pDataFlash->pDataFlashDesc->command[1] = 0;
314         if (pDataFlash->pDevice->pages_number >= 16384)
315         {
316                 pDataFlash->pDataFlashDesc->command[2] = 0;
317                 pDataFlash->pDataFlashDesc->command[3] = (unsigned char)(((unsigned int)(bufferAddress &  pDataFlash->pDevice->byte_mask)) >> 8) ;
318                 pDataFlash->pDataFlashDesc->command[4] = (unsigned char)((unsigned int)bufferAddress  & 0x00FF) ;
319                 cmdsize = 5;
320         }
321         else
322         {
323                 pDataFlash->pDataFlashDesc->command[2] = (unsigned char)(((unsigned int)(bufferAddress &  pDataFlash->pDevice->byte_mask)) >> 8) ;
324                 pDataFlash->pDataFlashDesc->command[3] = (unsigned char)((unsigned int)bufferAddress  & 0x00FF) ;
325                 pDataFlash->pDataFlashDesc->command[4] = 0;
326                 cmdsize = 4;
327         }
328                 
329         pDataFlash->pDataFlashDesc->tx_cmd_pt    = pDataFlash->pDataFlashDesc->command ;
330         pDataFlash->pDataFlashDesc->tx_cmd_size  = cmdsize ;
331         pDataFlash->pDataFlashDesc->rx_cmd_pt    = pDataFlash->pDataFlashDesc->command ;
332         pDataFlash->pDataFlashDesc->rx_cmd_size  = cmdsize ;
333
334         pDataFlash->pDataFlashDesc->rx_data_pt   = dataBuffer ;
335         pDataFlash->pDataFlashDesc->tx_data_pt   = dataBuffer ;
336         pDataFlash->pDataFlashDesc->rx_data_size = SizeToWrite ;
337         pDataFlash->pDataFlashDesc->tx_data_size = SizeToWrite ;
338
339         return AT91F_SpiWrite(pDataFlash->pDataFlashDesc);
340 }
341
342
343 /*------------------------------------------------------------------------------*/
344 /* Function Name       : AT91F_PageErase                                        */             
345 /* Object              : Read a page in the SRAM Buffer 1 or 2                  */
346 /* Input Parameters    : DataFlash Service                                      */
347 /*                     : Page concerned                                         */
348 /*                     :                                                        */
349 /* Return value        : State of the dataflash                                 */
350 /*------------------------------------------------------------------------------*/
351 static AT91S_DataFlashStatus AT91F_PageErase(
352         AT91PS_DataFlash pDataFlash,
353         unsigned int page)
354 {
355         int cmdsize;
356         /* Test if the buffer command is legal */       
357         /* no data to transmit or receive */
358         pDataFlash->pDataFlashDesc->tx_data_size = 0;
359         
360         cmdsize = 4;
361         if (pDataFlash->pDevice->pages_number >= 16384)
362                 cmdsize = 5;
363         return(AT91F_DataFlashSendCommand(pDataFlash, DB_PAGE_ERASE, cmdsize,
364                                           page*pDataFlash->pDevice->pages_size));
365 }
366
367
368 /*------------------------------------------------------------------------------*/
369 /* Function Name       : AT91F_WriteBufferToMain                                */
370 /* Object              : Write buffer to the main memory                        */
371 /* Input Parameters    : DataFlash Service                                      */
372 /*                     : <BufferCommand> = command to send to buf1 or buf2      */
373 /*                     : <dest> = main memory address                           */
374 /* Return value        : State of the dataflash                                 */
375 /*------------------------------------------------------------------------------*/
376 static AT91S_DataFlashStatus AT91F_WriteBufferToMain (
377         AT91PS_DataFlash pDataFlash,
378         unsigned char BufferCommand,
379         unsigned int dest )
380 {
381         int cmdsize;
382         /* Test if the buffer command is correct */
383         if ((BufferCommand != DB_BUF1_PAGE_PGM) &&
384             (BufferCommand != DB_BUF1_PAGE_ERASE_PGM) &&
385             (BufferCommand != DB_BUF2_PAGE_PGM) &&
386             (BufferCommand != DB_BUF2_PAGE_ERASE_PGM) )
387                 return AT91C_DATAFLASH_BAD_COMMAND;
388
389         /* no data to transmit or receive */
390         pDataFlash->pDataFlashDesc->tx_data_size = 0;
391
392         cmdsize = 4;
393         if (pDataFlash->pDevice->pages_number >= 16384)
394                 cmdsize = 5;
395         /* Send the command to the dataflash */
396         return(AT91F_DataFlashSendCommand (pDataFlash, BufferCommand, cmdsize, dest));
397 }
398
399
400 /*------------------------------------------------------------------------------*/
401 /* Function Name       : AT91F_PartialPageWrite                                 */
402 /* Object              : Erase partially a page                                 */
403 /* Input Parameters    : <page> = page number                                   */
404 /*                     : <AdrInpage> = adr to begin the fading                  */
405 /*                     : <length> = Number of bytes to erase                    */
406 /*------------------------------------------------------------------------------*/
407 static AT91S_DataFlashStatus AT91F_PartialPageWrite (
408         AT91PS_DataFlash pDataFlash,
409         unsigned char *src,
410         unsigned int dest,
411         unsigned int size)
412 {
413         unsigned int page;
414         unsigned int AdrInPage;
415
416         page = dest / (pDataFlash->pDevice->pages_size);
417         AdrInPage = dest % (pDataFlash->pDevice->pages_size);
418
419         /* Read the contents of the page in the Sram Buffer */
420         AT91F_MainMemoryToBufferTransfer(pDataFlash, DB_PAGE_2_BUF1_TRF, page);
421         AT91F_DataFlashWaitReady(pDataFlash->pDataFlashDesc, AT91C_DATAFLASH_TIMEOUT);
422         
423         /*Update the SRAM buffer */
424         AT91F_DataFlashWriteBuffer(pDataFlash, DB_BUF1_WRITE, src, AdrInPage, size);
425         AT91F_DataFlashWaitReady(pDataFlash->pDataFlashDesc, AT91C_DATAFLASH_TIMEOUT);
426         
427         /* Erase page if a 128 Mbits device */
428         if (pDataFlash->pDevice->pages_number >= 16384)
429         {
430                 AT91F_PageErase(pDataFlash, page);
431                 AT91F_DataFlashWaitReady(pDataFlash->pDataFlashDesc, AT91C_DATAFLASH_TIMEOUT);
432         }
433
434         /* Rewrite the modified Sram Buffer in the main memory */
435         return(AT91F_WriteBufferToMain(pDataFlash, DB_BUF1_PAGE_ERASE_PGM,
436                                        (page*pDataFlash->pDevice->pages_size)));
437 }
438
439
440 /*------------------------------------------------------------------------------*/
441 /* Function Name       : AT91F_DataFlashWrite                                   */
442 /* Object              :                                                        */
443 /* Input Parameters    : <*src> = Source buffer                                 */
444 /*                     : <dest> = dataflash adress                              */
445 /*                     : <size> = data buffer size                              */
446 /*------------------------------------------------------------------------------*/
447 AT91S_DataFlashStatus AT91F_DataFlashWrite(
448         AT91PS_DataFlash pDataFlash,
449         unsigned char *src,
450         int dest,
451         int size )
452 {
453         unsigned int length;
454         unsigned int page;
455         unsigned int status;
456
457         AT91F_SpiEnable(pDataFlash->pDevice->cs);
458
459         if ( (dest + size) > (pDataFlash->pDevice->pages_size * (pDataFlash->pDevice->pages_number)))
460                 return AT91C_DATAFLASH_MEMORY_OVERFLOW;
461
462         /* If destination does not fit a page start address */
463         if ((dest % ((unsigned int)(pDataFlash->pDevice->pages_size)))  != 0 ) {
464                 length = pDataFlash->pDevice->pages_size - (dest % ((unsigned int)(pDataFlash->pDevice->pages_size)));
465
466                 if (size < length)
467                         length = size;
468
469                 if(!AT91F_PartialPageWrite(pDataFlash,src, dest, length))
470                         return AT91C_DATAFLASH_ERROR;
471
472                 AT91F_DataFlashWaitReady(pDataFlash->pDataFlashDesc, AT91C_DATAFLASH_TIMEOUT);
473
474                 /* Update size, source and destination pointers */
475                 size -= length;
476                 dest += length;
477                 src += length;
478         }
479
480         while (( size - pDataFlash->pDevice->pages_size ) >= 0 ) 
481         {
482                 /* program dataflash page */            
483                 page = (unsigned int)dest / (pDataFlash->pDevice->pages_size);
484
485                 status = AT91F_DataFlashWriteBuffer(pDataFlash, DB_BUF1_WRITE, src,
486                                                     0, pDataFlash->pDevice->pages_size);
487                 AT91F_DataFlashWaitReady(pDataFlash->pDataFlashDesc, AT91C_DATAFLASH_TIMEOUT);
488         
489                 status = AT91F_PageErase(pDataFlash, page);
490                 AT91F_DataFlashWaitReady(pDataFlash->pDataFlashDesc, AT91C_DATAFLASH_TIMEOUT);
491                 if (!status)
492                         return AT91C_DATAFLASH_ERROR;
493                 
494                 status = AT91F_WriteBufferToMain (pDataFlash, DB_BUF1_PAGE_PGM, dest);
495                 if(!status)
496                         return AT91C_DATAFLASH_ERROR;
497
498                 AT91F_DataFlashWaitReady(pDataFlash->pDataFlashDesc, AT91C_DATAFLASH_TIMEOUT);
499         
500                 /* Update size, source and destination pointers */
501                 size -= pDataFlash->pDevice->pages_size ;
502                 dest += pDataFlash->pDevice->pages_size ;
503                 src  += pDataFlash->pDevice->pages_size ;
504         }
505
506         /* If still some bytes to read */
507         if ( size > 0 ) {
508                 /* program dataflash page */
509                 if(!AT91F_PartialPageWrite(pDataFlash, src, dest, size) )
510                         return AT91C_DATAFLASH_ERROR;
511                 AT91F_DataFlashWaitReady(pDataFlash->pDataFlashDesc, AT91C_DATAFLASH_TIMEOUT);
512         }
513         return AT91C_DATAFLASH_OK;
514 }
515
516
517 /*------------------------------------------------------------------------------*/
518 /* Function Name       : AT91F_DataFlashRead                                    */
519 /* Object              : Read a block in dataflash                              */
520 /* Input Parameters    :                                                        */
521 /* Return value        :                                                        */
522 /*------------------------------------------------------------------------------*/
523 int AT91F_DataFlashRead(
524         AT91PS_DataFlash pDataFlash,
525         unsigned long addr,
526         unsigned long size,
527         char *buffer)
528 {
529         unsigned long SizeToRead;
530
531         AT91F_SpiEnable(pDataFlash->pDevice->cs);
532
533         if(AT91F_DataFlashWaitReady(pDataFlash->pDataFlashDesc, AT91C_DATAFLASH_TIMEOUT) != AT91C_DATAFLASH_OK)
534                 return -1;
535
536         while (size)
537         {
538                 SizeToRead = (size < 0x8000)? size:0x8000;
539
540                 if (AT91F_DataFlashWaitReady(pDataFlash->pDataFlashDesc, AT91C_DATAFLASH_TIMEOUT)
541                     != AT91C_DATAFLASH_OK)
542                         return -1;
543
544                 if (AT91F_DataFlashContinuousRead (pDataFlash, addr, (unsigned char *)buffer,
545                                                    SizeToRead) != AT91C_DATAFLASH_OK)
546                         return -1;
547
548                 size -= SizeToRead;
549                 addr += SizeToRead;
550                 buffer += SizeToRead;
551         }
552
553         return AT91C_DATAFLASH_OK;
554 }
555
556
557 /*------------------------------------------------------------------------------*/
558 /* Function Name       : AT91F_DataflashProbe                                   */
559 /* Object              :                                                        */
560 /* Input Parameters    :                                                        */
561 /* Return value        : Dataflash status register                              */
562 /*------------------------------------------------------------------------------*/
563 int AT91F_DataflashProbe(int cs, AT91PS_DataflashDesc pDesc)
564 {
565         AT91F_SpiEnable(cs);
566         AT91F_DataFlashGetStatus(pDesc);
567         return ((pDesc->command[1] == 0xFF)? 0: (pDesc->command[1] & 0x3C));
568 }
569
570 /*------------------------------------------------------------------------------*/
571 /* Function Name       : AT91F_DataFlashErase                                   */
572 /* Object              :                                                        */
573 /* Input Parameters    : <*pDataFlash> = Device info                            */
574 /*------------------------------------------------------------------------------*/
575 AT91S_DataFlashStatus AT91F_DataFlashErase(AT91PS_DataFlash pDataFlash)
576 {
577         unsigned int page;
578         unsigned int status;
579
580         AT91F_SpiEnable(pDataFlash->pDevice->cs);
581  
582         for(page=0; page < pDataFlash->pDevice->pages_number; page++)
583             {
584                 /* Erase dataflash page */
585                 if ((page & 0x00FF) == 0)
586                         printf("\rERA %d/%d", page, pDataFlash->pDevice->pages_number);
587                 status = AT91F_PageErase(pDataFlash, page);
588                 AT91F_DataFlashWaitReady(pDataFlash->pDataFlashDesc, AT91C_DATAFLASH_TIMEOUT);
589                 if (!status)
590                         return AT91C_DATAFLASH_ERROR;
591         }
592
593         return AT91C_DATAFLASH_OK;
594 }
595