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/*----------------------------------------------------------------------------*/
29void 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/*----------------------------------------------------------------------------*/
62static 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/*----------------------------------------------------------------------------*/
88static 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/*----------------------------------------------------------------------*/
132static 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/*----------------------------------------------------------------------*/
179static 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 */
206static 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/*------------------------------------------------------------------------------*/
233static 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/*------------------------------------------------------------------------------*/
264static 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/*------------------------------------------------------------------------------*/
295static 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/*------------------------------------------------------------------------------*/
351static 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/*------------------------------------------------------------------------------*/
376static 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/*------------------------------------------------------------------------------*/
407static 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/*------------------------------------------------------------------------------*/
447AT91S_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/*------------------------------------------------------------------------------*/
523int 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/*------------------------------------------------------------------------------*/
563int 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/*------------------------------------------------------------------------------*/
575AT91S_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
596