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