]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - cpu/at91rm9200/at45.c
* Patch by Nicolas Lacressonnière, 12 Nov 2003:
[karo-tx-uboot.git] / cpu / at91rm9200 / at45.c
1 /* Driver for ATMEL DataFlash support
2  * Author : Hamid Ikdoumi (Atmel)
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of
7  * the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
17  * MA 02111-1307 USA
18  *
19  */
20
21 #include <config.h>
22 #include <common.h>
23 #include <asm/hardware.h>
24
25 #ifdef CONFIG_HAS_DATAFLASH
26 #include <dataflash.h>
27
28 #define SPI_CLK 5000000
29 #define AT91C_TIMEOUT_WRDY                      200000
30 #define AT91C_SPI_PCS0_SERIAL_DATAFLASH         0xE     /* Chip Select 0 : NPCS0 %1110 */
31 #define AT91C_SPI_PCS3_DATAFLASH_CARD           0x7     /* Chip Select 3 : NPCS3 %0111 */
32
33 void AT91F_SpiInit(void) {
34
35 /*-------------------------------------------------------------------*/
36 /*      SPI DataFlash Init                                                              */
37 /*-------------------------------------------------------------------*/
38         /* Configure PIOs */
39         AT91C_BASE_PIOA->PIO_ASR = AT91C_PA3_NPCS0 | AT91C_PA4_NPCS1 | AT91C_PA1_MOSI | AT91C_PA5_NPCS2 |
40                                    AT91C_PA6_NPCS3 | AT91C_PA0_MISO | AT91C_PA2_SPCK;
41         AT91C_BASE_PIOA->PIO_PDR = AT91C_PA3_NPCS0 | AT91C_PA4_NPCS1 | AT91C_PA1_MOSI | AT91C_PA5_NPCS2 |
42                                    AT91C_PA6_NPCS3 | AT91C_PA0_MISO | AT91C_PA2_SPCK;
43         /* Enable CLock */
44         AT91C_BASE_PMC->PMC_PCER = 1 << AT91C_ID_SPI;
45
46         /* Reset the SPI */
47         AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SWRST;
48
49         /* Configure SPI in Master Mode with No CS selected !!! */
50         AT91C_BASE_SPI->SPI_MR = AT91C_SPI_MSTR | AT91C_SPI_MODFDIS | AT91C_SPI_PCS;
51
52         /* Configure CS0 and CS3 */
53         *(AT91C_SPI_CSR + 0) = AT91C_SPI_CPOL | (AT91C_SPI_DLYBS & 0x100000) | ((AT91C_MASTER_CLOCK / (2*SPI_CLK)) << 8);
54
55         *(AT91C_SPI_CSR + 3) = AT91C_SPI_CPOL | (AT91C_SPI_DLYBS & 0x100000) | ((AT91C_MASTER_CLOCK / (2*SPI_CLK)) << 8);
56
57 }
58
59 void AT91F_SpiEnable(int cs) {
60         switch(cs) {
61         case 0: /* Configure SPI CS0 for Serial DataFlash AT45DBxx */
62                 AT91C_BASE_SPI->SPI_MR &= 0xFFF0FFFF;
63                 AT91C_BASE_SPI->SPI_MR |= ((AT91C_SPI_PCS0_SERIAL_DATAFLASH<<16) & AT91C_SPI_PCS);
64                 break;
65         case 3: /* Configure SPI CS3 for Serial DataFlash Card */
66                 /* Set up PIO SDC_TYPE to switch on DataFlash Card and not MMC/SDCard */
67                 AT91C_BASE_PIOB->PIO_PER = AT91C_PIO_PB7;       /* Set in PIO mode */
68                 AT91C_BASE_PIOB->PIO_OER = AT91C_PIO_PB7;       /* Configure in output */
69                 /* Clear Output */
70                 AT91C_BASE_PIOB->PIO_CODR = AT91C_PIO_PB7;
71                 /* Configure PCS */
72                 AT91C_BASE_SPI->SPI_MR &= 0xFFF0FFFF;
73                 AT91C_BASE_SPI->SPI_MR |= ((AT91C_SPI_PCS3_DATAFLASH_CARD<<16) & AT91C_SPI_PCS);
74                 break;
75         }
76
77         /* SPI_Enable */
78         AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SPIEN;
79 }
80
81 /*----------------------------------------------------------------------------*/
82 /* \fn    AT91F_SpiWrite                                                      */
83 /* \brief Set the PDC registers for a transfert                               */
84 /*----------------------------------------------------------------------------*/
85 unsigned int AT91F_SpiWrite ( AT91PS_DataflashDesc pDesc )
86 {
87         unsigned int timeout;
88
89         pDesc->state = BUSY;
90
91         AT91C_BASE_SPI->SPI_PTCR = AT91C_PDC_TXTDIS + AT91C_PDC_RXTDIS;
92
93         /* Initialize the Transmit and Receive Pointer */
94         AT91C_BASE_SPI->SPI_RPR = (unsigned int)pDesc->rx_cmd_pt ;
95         AT91C_BASE_SPI->SPI_TPR = (unsigned int)pDesc->tx_cmd_pt ;
96
97         /* Intialize the Transmit and Receive Counters */
98         AT91C_BASE_SPI->SPI_RCR = pDesc->rx_cmd_size;
99         AT91C_BASE_SPI->SPI_TCR = pDesc->tx_cmd_size;
100
101         if ( pDesc->tx_data_size != 0 ) {
102                 /* Initialize the Next Transmit and Next Receive Pointer */
103                 AT91C_BASE_SPI->SPI_RNPR = (unsigned int)pDesc->rx_data_pt ;
104                 AT91C_BASE_SPI->SPI_TNPR = (unsigned int)pDesc->tx_data_pt ;
105
106                 /* Intialize the Next Transmit and Next Receive Counters */
107                 AT91C_BASE_SPI->SPI_RNCR = pDesc->rx_data_size ;
108                 AT91C_BASE_SPI->SPI_TNCR = pDesc->tx_data_size ;
109         }
110
111         /* arm simple, non interrupt dependent timer */
112         reset_timer_masked();
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) && ((timeout = get_timer_masked() ) < CFG_SPI_WRITE_TOUT));
117         AT91C_BASE_SPI->SPI_PTCR = AT91C_PDC_TXTDIS + AT91C_PDC_RXTDIS;
118         pDesc->state = IDLE;
119
120         if (timeout >= CFG_SPI_WRITE_TOUT){
121                 printf("Error Timeout\n\r");
122                 return DATAFLASH_ERROR;
123         }
124
125         return DATAFLASH_OK;
126 }
127
128
129 /*----------------------------------------------------------------------*/
130 /* \fn    AT91F_DataFlashSendCommand                                    */
131 /* \brief Generic function to send a command to the dataflash           */
132 /*----------------------------------------------------------------------*/
133 AT91S_DataFlashStatus AT91F_DataFlashSendCommand(
134         AT91PS_DataFlash pDataFlash,
135         unsigned char OpCode,
136         unsigned int CmdSize,
137         unsigned int DataflashAddress)
138 {
139     unsigned int adr;
140
141         if ( (pDataFlash->pDataFlashDesc->state) != IDLE)
142                 return DATAFLASH_BUSY;
143
144         /* process the address to obtain page address and byte address */
145         adr = ((DataflashAddress / (pDataFlash->pDevice->pages_size)) << pDataFlash->pDevice->page_offset) + (DataflashAddress % (pDataFlash->pDevice->pages_size));
146
147         /* fill the  command  buffer */
148         pDataFlash->pDataFlashDesc->command[0] = OpCode;
149         if (pDataFlash->pDevice->pages_number >= 16384) {
150                 pDataFlash->pDataFlashDesc->command[1] = (unsigned char)((adr & 0x0F000000) >> 24);
151                 pDataFlash->pDataFlashDesc->command[2] = (unsigned char)((adr & 0x00FF0000) >> 16);
152                 pDataFlash->pDataFlashDesc->command[3] = (unsigned char)((adr & 0x0000FF00) >> 8);
153                 pDataFlash->pDataFlashDesc->command[4] = (unsigned char)(adr & 0x000000FF);
154         } else {
155                 pDataFlash->pDataFlashDesc->command[1] = (unsigned char)((adr & 0x00FF0000) >> 16);
156                 pDataFlash->pDataFlashDesc->command[2] = (unsigned char)((adr & 0x0000FF00) >> 8);
157                 pDataFlash->pDataFlashDesc->command[3] = (unsigned char)(adr & 0x000000FF) ;
158                 pDataFlash->pDataFlashDesc->command[4] = 0;
159         }
160         pDataFlash->pDataFlashDesc->command[5] = 0;
161         pDataFlash->pDataFlashDesc->command[6] = 0;
162         pDataFlash->pDataFlashDesc->command[7] = 0;
163
164         /* Initialize the SpiData structure for the spi write fuction */
165         pDataFlash->pDataFlashDesc->tx_cmd_pt   =  pDataFlash->pDataFlashDesc->command ;
166         pDataFlash->pDataFlashDesc->tx_cmd_size =  CmdSize ;
167         pDataFlash->pDataFlashDesc->rx_cmd_pt   =  pDataFlash->pDataFlashDesc->command ;
168         pDataFlash->pDataFlashDesc->rx_cmd_size =  CmdSize ;
169
170         /* send the command and read the data */
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 AT91S_DataFlashStatus AT91F_DataFlashGetStatus(AT91PS_DataflashDesc pDesc)
180 {
181         AT91S_DataFlashStatus status;
182
183         /* if a transfert is in progress ==> return 0 */
184         if( (pDesc->state) != IDLE)
185                 return DATAFLASH_BUSY;
186
187         /* first send the read status command (D7H) */
188         pDesc->command[0] = DB_STATUS;
189         pDesc->command[1] = 0;
190
191         pDesc->DataFlash_state  = GET_STATUS;
192         pDesc->tx_data_size     = 0 ;   /* Transmit the command and receive response */
193         pDesc->tx_cmd_pt                = pDesc->command ;
194         pDesc->rx_cmd_pt                = pDesc->command ;
195         pDesc->rx_cmd_size              = 2 ;
196         pDesc->tx_cmd_size              = 2 ;
197         status = AT91F_SpiWrite (pDesc);
198
199         pDesc->DataFlash_state = *( (unsigned char *) (pDesc->rx_cmd_pt) +1);
200
201         return status;
202 }
203
204
205 /*----------------------------------------------------------------------*/
206 /* \fn    AT91F_DataFlashWaitReady                                      */
207 /* \brief wait for dataflash ready (bit7 of the status register == 1)   */
208 /*----------------------------------------------------------------------*/
209 AT91S_DataFlashStatus AT91F_DataFlashWaitReady(AT91PS_DataflashDesc pDataFlashDesc, unsigned int timeout)
210 {
211         pDataFlashDesc->DataFlash_state = IDLE;
212
213         do {
214                 AT91F_DataFlashGetStatus(pDataFlashDesc);
215                 timeout--;
216         } while( ((pDataFlashDesc->DataFlash_state & 0x80) != 0x80) && (timeout > 0) );
217
218         if((pDataFlashDesc->DataFlash_state & 0x80) != 0x80)
219                 return DATAFLASH_ERROR;
220
221         return DATAFLASH_OK;
222 }
223
224
225 /*------------------------------------------------------------------------------*/
226 /* Function Name       : AT91F_DataFlashContinuousRead                          */
227 /* Object              : Continuous stream Read                                 */
228 /* Input Parameters    : DataFlash Service                                      */
229 /*                                              : <src> = dataflash address     */
230 /*                     : <*dataBuffer> = data buffer pointer                    */
231 /*                     : <sizeToRead> = data buffer size                        */
232 /* Return value         : State of the dataflash                                */
233 /*------------------------------------------------------------------------------*/
234 AT91S_DataFlashStatus AT91F_DataFlashContinuousRead (
235         AT91PS_DataFlash pDataFlash,
236         int src,
237         unsigned char *dataBuffer,
238         int sizeToRead )
239 {
240         AT91S_DataFlashStatus status;
241         /* Test the size to read in the device */
242         if ( (src + sizeToRead) > (pDataFlash->pDevice->pages_size * (pDataFlash->pDevice->pages_number)))
243                 return DATAFLASH_MEMORY_OVERFLOW;
244
245         pDataFlash->pDataFlashDesc->rx_data_pt = dataBuffer;
246         pDataFlash->pDataFlashDesc->rx_data_size = sizeToRead;
247         pDataFlash->pDataFlashDesc->tx_data_pt = dataBuffer;
248         pDataFlash->pDataFlashDesc->tx_data_size = sizeToRead;
249
250         status = AT91F_DataFlashSendCommand (pDataFlash, DB_CONTINUOUS_ARRAY_READ, 8, src);
251         /* Send the command to the dataflash */
252         return(status);
253 }
254
255
256 /*------------------------------------------------------------------------------*/
257 /* Function Name       : AT91F_DataFlashPagePgmBuf                              */
258 /* Object              : Main memory page program through buffer 1 or buffer 2  */
259 /* Input Parameters    : DataFlash Service                                      */
260 /*                                              : <*src> = Source buffer        */
261 /*                     : <dest> = dataflash destination address                 */
262 /*                     : <SizeToWrite> = data buffer size                       */
263 /* Return value         : State of the dataflash                                */
264 /*------------------------------------------------------------------------------*/
265 AT91S_DataFlashStatus AT91F_DataFlashPagePgmBuf(
266         AT91PS_DataFlash pDataFlash,
267         unsigned char *src,
268         unsigned int dest,
269         unsigned int SizeToWrite)
270 {
271         int cmdsize;
272         pDataFlash->pDataFlashDesc->tx_data_pt = src ;
273         pDataFlash->pDataFlashDesc->tx_data_size = SizeToWrite ;
274         pDataFlash->pDataFlashDesc->rx_data_pt = src;
275         pDataFlash->pDataFlashDesc->rx_data_size = SizeToWrite;
276
277         cmdsize = 4;
278         /* Send the command to the dataflash */
279         if (pDataFlash->pDevice->pages_number >= 16384)
280                 cmdsize = 5;
281         return(AT91F_DataFlashSendCommand (pDataFlash, DB_PAGE_PGM_BUF1, cmdsize, dest));
282 }
283
284
285 /*------------------------------------------------------------------------------*/
286 /* Function Name       : AT91F_MainMemoryToBufferTransfert                      */
287 /* Object              : Read a page in the SRAM Buffer 1 or 2                  */
288 /* Input Parameters    : DataFlash Service                                      */
289 /*                     : Page concerned                                         */
290 /*                     :                                                        */
291 /* Return value         : State of the dataflash                                */
292 /*------------------------------------------------------------------------------*/
293 AT91S_DataFlashStatus AT91F_MainMemoryToBufferTransfert(
294         AT91PS_DataFlash pDataFlash,
295         unsigned char BufferCommand,
296         unsigned int page)
297 {
298         int cmdsize;
299         /* Test if the buffer command is legal */
300         if ((BufferCommand != DB_PAGE_2_BUF1_TRF) && (BufferCommand != DB_PAGE_2_BUF2_TRF))
301                 return DATAFLASH_BAD_COMMAND;
302
303         /* no data to transmit or receive */
304         pDataFlash->pDataFlashDesc->tx_data_size = 0;
305         cmdsize = 4;
306         if (pDataFlash->pDevice->pages_number >= 16384)
307                 cmdsize = 5;
308         return(AT91F_DataFlashSendCommand (pDataFlash, BufferCommand, cmdsize, page*pDataFlash->pDevice->pages_size));
309 }
310
311
312 /*----------------------------------------------------------------------------- */
313 /* Function Name       : AT91F_DataFlashWriteBuffer                             */
314 /* Object              : Write data to the internal sram buffer 1 or 2          */
315 /* Input Parameters    : DataFlash Service                                      */
316 /*                      : <BufferCommand> = command to write buffer1 or buffer2 */
317 /*                     : <*dataBuffer> = data buffer to write                   */
318 /*                     : <bufferAddress> = address in the internal buffer       */
319 /*                     : <SizeToWrite> = data buffer size                       */
320 /* Return value         : State of the dataflash                                */
321 /*------------------------------------------------------------------------------*/
322 AT91S_DataFlashStatus AT91F_DataFlashWriteBuffer (
323         AT91PS_DataFlash pDataFlash,
324         unsigned char BufferCommand,
325         unsigned char *dataBuffer,
326         unsigned int bufferAddress,
327         int SizeToWrite )
328 {
329         int cmdsize;
330         /* Test if the buffer command is legal */
331         if ((BufferCommand != DB_BUF1_WRITE) && (BufferCommand != DB_BUF2_WRITE))
332                 return DATAFLASH_BAD_COMMAND;
333
334         /* buffer address must be lower than page size */
335         if (bufferAddress > pDataFlash->pDevice->pages_size)
336                 return DATAFLASH_BAD_ADDRESS;
337
338         if ( (pDataFlash->pDataFlashDesc->state)  != IDLE)
339                 return DATAFLASH_BUSY;
340
341         /* Send first Write Command */
342         pDataFlash->pDataFlashDesc->command[0] = BufferCommand;
343         pDataFlash->pDataFlashDesc->command[1] = 0;
344         if (pDataFlash->pDevice->pages_number >= 16384) {
345                 pDataFlash->pDataFlashDesc->command[2] = 0;
346                 pDataFlash->pDataFlashDesc->command[3] = (unsigned char)(((unsigned int)(bufferAddress &  pDataFlash->pDevice->byte_mask)) >> 8) ;
347                 pDataFlash->pDataFlashDesc->command[4] = (unsigned char)((unsigned int)bufferAddress  & 0x00FF) ;
348                 cmdsize = 5;
349         } else {
350                 pDataFlash->pDataFlashDesc->command[2] = (unsigned char)(((unsigned int)(bufferAddress &  pDataFlash->pDevice->byte_mask)) >> 8) ;
351                 pDataFlash->pDataFlashDesc->command[3] = (unsigned char)((unsigned int)bufferAddress  & 0x00FF) ;
352                 pDataFlash->pDataFlashDesc->command[4] = 0;
353                 cmdsize = 4;
354         }
355
356         pDataFlash->pDataFlashDesc->tx_cmd_pt    = pDataFlash->pDataFlashDesc->command ;
357         pDataFlash->pDataFlashDesc->tx_cmd_size = cmdsize ;
358         pDataFlash->pDataFlashDesc->rx_cmd_pt    = pDataFlash->pDataFlashDesc->command ;
359         pDataFlash->pDataFlashDesc->rx_cmd_size = cmdsize ;
360
361         pDataFlash->pDataFlashDesc->rx_data_pt  = dataBuffer ;
362         pDataFlash->pDataFlashDesc->tx_data_pt  = dataBuffer ;
363         pDataFlash->pDataFlashDesc->rx_data_size        = SizeToWrite ;
364         pDataFlash->pDataFlashDesc->tx_data_size        = SizeToWrite ;
365
366         return AT91F_SpiWrite(pDataFlash->pDataFlashDesc);
367 }
368
369 /*------------------------------------------------------------------------------*/
370 /* Function Name       : AT91F_PageErase                                        */
371 /* Object              : Erase a page                                           */
372 /* Input Parameters    : DataFlash Service                                      */
373 /*                     : Page concerned                                         */
374 /*                     :                                                        */
375 /* Return value         : State of the dataflash                                */
376 /*------------------------------------------------------------------------------*/
377 AT91S_DataFlashStatus AT91F_PageErase(
378         AT91PS_DataFlash pDataFlash,
379         unsigned int page)
380 {
381         int cmdsize;
382         /* Test if the buffer command is legal */
383         /* no data to transmit or receive */
384         pDataFlash->pDataFlashDesc->tx_data_size = 0;
385
386         cmdsize = 4;
387         if (pDataFlash->pDevice->pages_number >= 16384)
388                 cmdsize = 5;
389         return(AT91F_DataFlashSendCommand (pDataFlash, DB_PAGE_ERASE, cmdsize, page*pDataFlash->pDevice->pages_size));
390 }
391
392
393 /*------------------------------------------------------------------------------*/
394 /* Function Name       : AT91F_BlockErase                                       */
395 /* Object              : Erase a Block                                          */
396 /* Input Parameters    : DataFlash Service                                      */
397 /*                     : Page concerned                                         */
398 /*                     :                                                        */
399 /* Return value         : State of the dataflash                                */
400 /*------------------------------------------------------------------------------*/
401 AT91S_DataFlashStatus AT91F_BlockErase(
402         AT91PS_DataFlash pDataFlash,
403         unsigned int block)
404 {
405         int cmdsize;
406         /* Test if the buffer command is legal */
407         /* no data to transmit or receive */
408         pDataFlash->pDataFlashDesc->tx_data_size = 0;
409         cmdsize = 4;
410         if (pDataFlash->pDevice->pages_number >= 16384)
411                 cmdsize = 5;
412         return(AT91F_DataFlashSendCommand (pDataFlash, DB_BLOCK_ERASE,cmdsize, block*8*pDataFlash->pDevice->pages_size));
413 }
414
415 /*------------------------------------------------------------------------------*/
416 /* Function Name       : AT91F_WriteBufferToMain                                */
417 /* Object              : Write buffer to the main memory                        */
418 /* Input Parameters    : DataFlash Service                                      */
419 /*              : <BufferCommand> = command to send to buffer1 or buffer2       */
420 /*                     : <dest> = main memory address                           */
421 /* Return value         : State of the dataflash                                */
422 /*------------------------------------------------------------------------------*/
423 AT91S_DataFlashStatus AT91F_WriteBufferToMain (
424         AT91PS_DataFlash pDataFlash,
425         unsigned char BufferCommand,
426         unsigned int dest )
427 {
428         int cmdsize;
429         /* Test if the buffer command is correct */
430         if ((BufferCommand != DB_BUF1_PAGE_PGM) &&
431             (BufferCommand != DB_BUF1_PAGE_ERASE_PGM) &&
432             (BufferCommand != DB_BUF2_PAGE_PGM) &&
433             (BufferCommand != DB_BUF2_PAGE_ERASE_PGM) )
434                 return DATAFLASH_BAD_COMMAND;
435
436         /* no data to transmit or receive */
437         pDataFlash->pDataFlashDesc->tx_data_size = 0;
438
439         cmdsize = 4;
440         if (pDataFlash->pDevice->pages_number >= 16384)
441                 cmdsize = 5;
442         /* Send the command to the dataflash */
443         return(AT91F_DataFlashSendCommand (pDataFlash, BufferCommand, cmdsize, dest));
444 }
445
446
447 /*------------------------------------------------------------------------------*/
448 /* Function Name       : AT91F_PartialPageWrite                                 */
449 /* Object              : Erase partielly a page                                 */
450 /* Input Parameters    : <page> = page number                                   */
451 /*                      : <AdrInpage> = adr to begin the fading                 */
452 /*                     : <length> = Number of bytes to erase                    */
453 /*------------------------------------------------------------------------------*/
454 AT91S_DataFlashStatus AT91F_PartialPageWrite (
455         AT91PS_DataFlash pDataFlash,
456         unsigned char *src,
457         unsigned int dest,
458         unsigned int size)
459 {
460         unsigned int page;
461         unsigned int AdrInPage;
462
463         page = dest / (pDataFlash->pDevice->pages_size);
464         AdrInPage = dest % (pDataFlash->pDevice->pages_size);
465
466         /* Read the contents of the page in the Sram Buffer */
467         AT91F_MainMemoryToBufferTransfert(pDataFlash, DB_PAGE_2_BUF1_TRF, page);
468         AT91F_DataFlashWaitReady(pDataFlash->pDataFlashDesc, AT91C_TIMEOUT_WRDY);
469         /*Update the SRAM buffer */
470         AT91F_DataFlashWriteBuffer(pDataFlash, DB_BUF1_WRITE, src, AdrInPage, size);
471
472         AT91F_DataFlashWaitReady(pDataFlash->pDataFlashDesc, AT91C_TIMEOUT_WRDY);
473
474         /* Erase page if a 128 Mbits device */
475         if (pDataFlash->pDevice->pages_number >= 16384) {
476                 AT91F_PageErase(pDataFlash, page);
477                 /* Rewrite the modified Sram Buffer in the main memory */
478                 AT91F_DataFlashWaitReady(pDataFlash->pDataFlashDesc, AT91C_TIMEOUT_WRDY);
479         }
480
481         /* Rewrite the modified Sram Buffer in the main memory */
482         return(AT91F_WriteBufferToMain(pDataFlash, DB_BUF1_PAGE_ERASE_PGM, (page*pDataFlash->pDevice->pages_size)));
483 }
484
485
486 /*------------------------------------------------------------------------------*/
487 /* Function Name       : AT91F_DataFlashWrite                                   */
488 /* Object              :                                                        */
489 /* Input Parameters    : <*src> = Source buffer                                 */
490 /*                     : <dest> = dataflash adress                              */
491 /*                     : <size> = data buffer size                              */
492 /*------------------------------------------------------------------------------*/
493 AT91S_DataFlashStatus AT91F_DataFlashWrite(
494         AT91PS_DataFlash pDataFlash,
495         unsigned char *src,
496         int dest,
497         int size )
498 {
499         unsigned int length;
500         unsigned int page;
501         unsigned int status;
502
503         AT91F_SpiEnable(pDataFlash->pDevice->cs);
504
505         if ( (dest + size) > (pDataFlash->pDevice->pages_size * (pDataFlash->pDevice->pages_number)))
506                 return DATAFLASH_MEMORY_OVERFLOW;
507
508         /* If destination does not fit a page start address */
509         if ((dest % ((unsigned int)(pDataFlash->pDevice->pages_size)))  != 0 ) {
510                 length = pDataFlash->pDevice->pages_size - (dest % ((unsigned int)(pDataFlash->pDevice->pages_size)));
511
512                 if (size < length)
513                         length = size;
514
515                 if(!AT91F_PartialPageWrite(pDataFlash,src, dest, length))
516                         return DATAFLASH_ERROR;
517
518                 AT91F_DataFlashWaitReady(pDataFlash->pDataFlashDesc, AT91C_TIMEOUT_WRDY);
519
520                 /* Update size, source and destination pointers */
521                 size -= length;
522                 dest += length;
523                 src += length;
524         }
525
526         while (( size - pDataFlash->pDevice->pages_size ) >= 0 ) {
527                 /* program dataflash page */
528                 page = (unsigned int)dest / (pDataFlash->pDevice->pages_size);
529
530                 status = AT91F_DataFlashWriteBuffer(pDataFlash, DB_BUF1_WRITE, src, 0, pDataFlash->pDevice->pages_size);
531                 AT91F_DataFlashWaitReady(pDataFlash->pDataFlashDesc, AT91C_TIMEOUT_WRDY);
532
533                 status = AT91F_PageErase(pDataFlash, page);
534                 AT91F_DataFlashWaitReady(pDataFlash->pDataFlashDesc, AT91C_TIMEOUT_WRDY);
535                 if (!status)
536                         return DATAFLASH_ERROR;
537
538                 status = AT91F_WriteBufferToMain (pDataFlash, DB_BUF1_PAGE_PGM, dest);
539                 if(!status)
540                         return DATAFLASH_ERROR;
541
542                 AT91F_DataFlashWaitReady(pDataFlash->pDataFlashDesc, AT91C_TIMEOUT_WRDY);
543
544                 /* Update size, source and destination pointers */
545                 size -= pDataFlash->pDevice->pages_size ;
546                 dest += pDataFlash->pDevice->pages_size ;
547                 src  += pDataFlash->pDevice->pages_size ;
548         }
549
550         /* If still some bytes to read */
551         if ( size > 0 ) {
552                 /* program dataflash page */
553                 if(!AT91F_PartialPageWrite(pDataFlash, src, dest, size) )
554                         return DATAFLASH_ERROR;
555
556                 AT91F_DataFlashWaitReady(pDataFlash->pDataFlashDesc, AT91C_TIMEOUT_WRDY);
557         }
558         return DATAFLASH_OK;
559 }
560
561
562 /*------------------------------------------------------------------------------*/
563 /* Function Name       : AT91F_DataFlashRead                                    */
564 /* Object              : Read a block in dataflash                              */
565 /* Input Parameters    :                                                        */
566 /* Return value         :                                                       */
567 /*------------------------------------------------------------------------------*/
568 int AT91F_DataFlashRead(
569         AT91PS_DataFlash pDataFlash,
570         unsigned long addr,
571         unsigned long size,
572         char *buffer)
573 {
574         unsigned long SizeToRead;
575
576         AT91F_SpiEnable(pDataFlash->pDevice->cs);
577
578         if(AT91F_DataFlashWaitReady(pDataFlash->pDataFlashDesc, AT91C_TIMEOUT_WRDY) != DATAFLASH_OK)
579                 return -1;
580
581         while (size) {
582                 SizeToRead = (size < 0x8000)? size:0x8000;
583
584                 if (AT91F_DataFlashWaitReady(pDataFlash->pDataFlashDesc, AT91C_TIMEOUT_WRDY) != DATAFLASH_OK)
585                         return -1;
586
587                 if (AT91F_DataFlashContinuousRead (pDataFlash, addr, buffer, SizeToRead) != DATAFLASH_OK)
588                         return -1;
589
590                 size -= SizeToRead;
591                 addr += SizeToRead;
592                 buffer += SizeToRead;
593         }
594
595         return DATAFLASH_OK;
596 }
597
598
599 /*------------------------------------------------------------------------------*/
600 /* Function Name       : AT91F_DataflashProbe                                   */
601 /* Object              :                                                        */
602 /* Input Parameters    :                                                        */
603 /* Return value        : Dataflash status register                              */
604 /*------------------------------------------------------------------------------*/
605 int AT91F_DataflashProbe(int cs, AT91PS_DataflashDesc pDesc)
606 {
607         AT91F_SpiEnable(cs);
608         AT91F_DataFlashGetStatus(pDesc);
609         return((pDesc->command[1] == 0xFF)? 0: pDesc->command[1] & 0x3C);
610 }
611
612 #endif