546 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			546 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			C
		
	
	
	
| /* Driver for ATMEL DataFlash support
 | |
|  * Author : Hamid Ikdoumi (Atmel)
 | |
|  *
 | |
|  * SPDX-License-Identifier:	GPL-2.0+
 | |
|  */
 | |
| 
 | |
| #include <config.h>
 | |
| #include <common.h>
 | |
| #include <dataflash.h>
 | |
| 
 | |
| /*
 | |
|  * spi.c API
 | |
|  */
 | |
| extern unsigned int AT91F_SpiWrite(AT91PS_DataflashDesc pDesc);
 | |
| extern void AT91F_SpiEnable(int cs);
 | |
| 
 | |
| #define AT91C_TIMEOUT_WRDY			200000
 | |
| 
 | |
| /*----------------------------------------------------------------------*/
 | |
| /* \fn    AT91F_DataFlashSendCommand					*/
 | |
| /* \brief Generic function to send a command to the dataflash		*/
 | |
| /*----------------------------------------------------------------------*/
 | |
| AT91S_DataFlashStatus AT91F_DataFlashSendCommand(AT91PS_DataFlash pDataFlash,
 | |
| 						 unsigned char OpCode,
 | |
| 						 unsigned int CmdSize,
 | |
| 						 unsigned int DataflashAddress)
 | |
| {
 | |
| 	unsigned int adr;
 | |
| 
 | |
| 	if ((pDataFlash->pDataFlashDesc->state) != IDLE)
 | |
| 		return DATAFLASH_BUSY;
 | |
| 
 | |
| 	/* process the address to obtain page address and byte address */
 | |
| 	adr = ((DataflashAddress / (pDataFlash->pDevice->pages_size)) <<
 | |
| 		pDataFlash->pDevice->page_offset) +
 | |
| 			(DataflashAddress % (pDataFlash->pDevice->pages_size));
 | |
| 
 | |
| 	/* fill the command buffer */
 | |
| 	pDataFlash->pDataFlashDesc->command[0] = OpCode;
 | |
| 	if (pDataFlash->pDevice->pages_number >= 16384) {
 | |
| 		pDataFlash->pDataFlashDesc->command[1] =
 | |
| 			(unsigned char)((adr & 0x0F000000) >> 24);
 | |
| 		pDataFlash->pDataFlashDesc->command[2] =
 | |
| 			(unsigned char)((adr & 0x00FF0000) >> 16);
 | |
| 		pDataFlash->pDataFlashDesc->command[3] =
 | |
| 			(unsigned char)((adr & 0x0000FF00) >> 8);
 | |
| 		pDataFlash->pDataFlashDesc->command[4] =
 | |
| 			(unsigned char)(adr & 0x000000FF);
 | |
| 	} else {
 | |
| 		pDataFlash->pDataFlashDesc->command[1] =
 | |
| 			(unsigned char)((adr & 0x00FF0000) >> 16);
 | |
| 		pDataFlash->pDataFlashDesc->command[2] =
 | |
| 			(unsigned char)((adr & 0x0000FF00) >> 8);
 | |
| 		pDataFlash->pDataFlashDesc->command[3] =
 | |
| 			(unsigned char)(adr & 0x000000FF);
 | |
| 		pDataFlash->pDataFlashDesc->command[4] = 0;
 | |
| 	}
 | |
| 	pDataFlash->pDataFlashDesc->command[5] = 0;
 | |
| 	pDataFlash->pDataFlashDesc->command[6] = 0;
 | |
| 	pDataFlash->pDataFlashDesc->command[7] = 0;
 | |
| 
 | |
| 	/* Initialize the SpiData structure for the spi write fuction */
 | |
| 	pDataFlash->pDataFlashDesc->tx_cmd_pt =
 | |
| 		pDataFlash->pDataFlashDesc->command;
 | |
| 	pDataFlash->pDataFlashDesc->tx_cmd_size = CmdSize;
 | |
| 	pDataFlash->pDataFlashDesc->rx_cmd_pt =
 | |
| 		pDataFlash->pDataFlashDesc->command;
 | |
| 	pDataFlash->pDataFlashDesc->rx_cmd_size = CmdSize;
 | |
| 
 | |
| 	/* send the command and read the data */
 | |
| 	return AT91F_SpiWrite(pDataFlash->pDataFlashDesc);
 | |
| }
 | |
| 
 | |
| /*----------------------------------------------------------------------*/
 | |
| /* \fn    AT91F_DataFlashGetStatus					*/
 | |
| /* \brief Read the status register of the dataflash			*/
 | |
| /*----------------------------------------------------------------------*/
 | |
| AT91S_DataFlashStatus AT91F_DataFlashGetStatus(AT91PS_DataflashDesc pDesc)
 | |
| {
 | |
| 	AT91S_DataFlashStatus status;
 | |
| 
 | |
| 	/* if a transfert is in progress ==> return 0 */
 | |
| 	if ((pDesc->state) != IDLE)
 | |
| 		return DATAFLASH_BUSY;
 | |
| 
 | |
| 	/* first send the read status command (D7H) */
 | |
| 	pDesc->command[0] = DB_STATUS;
 | |
| 	pDesc->command[1] = 0;
 | |
| 
 | |
| 	pDesc->DataFlash_state = GET_STATUS;
 | |
| 	pDesc->tx_data_size = 0;	/* Transmit the command */
 | |
| 	/* and receive response */
 | |
| 	pDesc->tx_cmd_pt = pDesc->command;
 | |
| 	pDesc->rx_cmd_pt = pDesc->command;
 | |
| 	pDesc->rx_cmd_size = 2;
 | |
| 	pDesc->tx_cmd_size = 2;
 | |
| 	status = AT91F_SpiWrite(pDesc);
 | |
| 
 | |
| 	pDesc->DataFlash_state = *((unsigned char *)(pDesc->rx_cmd_pt) + 1);
 | |
| 
 | |
| 	return status;
 | |
| }
 | |
| 
 | |
| /*----------------------------------------------------------------------*/
 | |
| /* \fn    AT91F_DataFlashWaitReady					*/
 | |
| /* \brief wait for dataflash ready (bit7 of the status register == 1)	*/
 | |
| /*----------------------------------------------------------------------*/
 | |
| AT91S_DataFlashStatus AT91F_DataFlashWaitReady(AT91PS_DataflashDesc
 | |
| 						pDataFlashDesc,
 | |
| 						unsigned int timeout)
 | |
| {
 | |
| 	pDataFlashDesc->DataFlash_state = IDLE;
 | |
| 
 | |
| 	do {
 | |
| 		AT91F_DataFlashGetStatus(pDataFlashDesc);
 | |
| 		timeout--;
 | |
| 	} while (((pDataFlashDesc->DataFlash_state & 0x80) != 0x80) &&
 | |
| 		 (timeout > 0));
 | |
| 
 | |
| 	if ((pDataFlashDesc->DataFlash_state & 0x80) != 0x80)
 | |
| 		return DATAFLASH_ERROR;
 | |
| 
 | |
| 	return DATAFLASH_OK;
 | |
| }
 | |
| 
 | |
| /*--------------------------------------------------------------------------*/
 | |
| /* Function Name       : AT91F_DataFlashContinuousRead			    */
 | |
| /* Object              : Continuous stream Read			    */
 | |
| /* Input Parameters    : DataFlash Service				    */
 | |
| /*						: <src> = dataflash address */
 | |
| /*                     : <*dataBuffer> = data buffer pointer		    */
 | |
| /*                     : <sizeToRead> = data buffer size		    */
 | |
| /* Return value		: State of the dataflash			    */
 | |
| /*--------------------------------------------------------------------------*/
 | |
| AT91S_DataFlashStatus AT91F_DataFlashContinuousRead(
 | |
| 				AT91PS_DataFlash pDataFlash,
 | |
| 				int src,
 | |
| 				unsigned char *dataBuffer,
 | |
| 				int sizeToRead)
 | |
| {
 | |
| 	AT91S_DataFlashStatus status;
 | |
| 	/* Test the size to read in the device */
 | |
| 	if ((src + sizeToRead) >
 | |
| 			(pDataFlash->pDevice->pages_size *
 | |
| 				(pDataFlash->pDevice->pages_number)))
 | |
| 		return DATAFLASH_MEMORY_OVERFLOW;
 | |
| 
 | |
| 	pDataFlash->pDataFlashDesc->rx_data_pt = dataBuffer;
 | |
| 	pDataFlash->pDataFlashDesc->rx_data_size = sizeToRead;
 | |
| 	pDataFlash->pDataFlashDesc->tx_data_pt = dataBuffer;
 | |
| 	pDataFlash->pDataFlashDesc->tx_data_size = sizeToRead;
 | |
| 
 | |
| 	status = AT91F_DataFlashSendCommand(
 | |
| 			pDataFlash, DB_CONTINUOUS_ARRAY_READ, 8, src);
 | |
| 	/* Send the command to the dataflash */
 | |
| 	return (status);
 | |
| }
 | |
| 
 | |
| /*---------------------------------------------------------------------------*/
 | |
| /* Function Name       : AT91F_DataFlashPagePgmBuf			     */
 | |
| /* Object              : Main memory page program thru buffer 1 or buffer 2  */
 | |
| /* Input Parameters    : DataFlash Service				     */
 | |
| /*						: <*src> = Source buffer     */
 | |
| /*                     : <dest> = dataflash destination address		     */
 | |
| /*                     : <SizeToWrite> = data buffer size		     */
 | |
| /* Return value		: State of the dataflash			     */
 | |
| /*---------------------------------------------------------------------------*/
 | |
| AT91S_DataFlashStatus AT91F_DataFlashPagePgmBuf(AT91PS_DataFlash pDataFlash,
 | |
| 						unsigned char *src,
 | |
| 						unsigned int dest,
 | |
| 						unsigned int SizeToWrite)
 | |
| {
 | |
| 	int cmdsize;
 | |
| 	pDataFlash->pDataFlashDesc->tx_data_pt = src;
 | |
| 	pDataFlash->pDataFlashDesc->tx_data_size = SizeToWrite;
 | |
| 	pDataFlash->pDataFlashDesc->rx_data_pt = src;
 | |
| 	pDataFlash->pDataFlashDesc->rx_data_size = SizeToWrite;
 | |
| 
 | |
| 	cmdsize = 4;
 | |
| 	/* Send the command to the dataflash */
 | |
| 	if (pDataFlash->pDevice->pages_number >= 16384)
 | |
| 		cmdsize = 5;
 | |
| 	return (AT91F_DataFlashSendCommand(
 | |
| 			pDataFlash, DB_PAGE_PGM_BUF1, cmdsize, dest));
 | |
| }
 | |
| 
 | |
| /*---------------------------------------------------------------------------*/
 | |
| /* Function Name       : AT91F_MainMemoryToBufferTransfert		     */
 | |
| /* Object              : Read a page in the SRAM Buffer 1 or 2		     */
 | |
| /* Input Parameters    : DataFlash Service				     */
 | |
| /*                     : Page concerned					     */
 | |
| /*                     :						     */
 | |
| /* Return value		: State of the dataflash			     */
 | |
| /*---------------------------------------------------------------------------*/
 | |
| AT91S_DataFlashStatus AT91F_MainMemoryToBufferTransfert(
 | |
| 					AT91PS_DataFlash
 | |
| 					pDataFlash,
 | |
| 					unsigned char
 | |
| 					BufferCommand,
 | |
| 					unsigned int page)
 | |
| {
 | |
| 	int cmdsize;
 | |
| 	/* Test if the buffer command is legal */
 | |
| 	if ((BufferCommand != DB_PAGE_2_BUF1_TRF) &&
 | |
| 			(BufferCommand != DB_PAGE_2_BUF2_TRF)) {
 | |
| 		return DATAFLASH_BAD_COMMAND;
 | |
| 	}
 | |
| 
 | |
| 	/* no data to transmit or receive */
 | |
| 	pDataFlash->pDataFlashDesc->tx_data_size = 0;
 | |
| 	cmdsize = 4;
 | |
| 	if (pDataFlash->pDevice->pages_number >= 16384)
 | |
| 		cmdsize = 5;
 | |
| 	return (AT91F_DataFlashSendCommand(
 | |
| 			pDataFlash, BufferCommand, cmdsize,
 | |
| 			page * pDataFlash->pDevice->pages_size));
 | |
| }
 | |
| 
 | |
| /*-------------------------------------------------------------------------- */
 | |
| /* Function Name       : AT91F_DataFlashWriteBuffer			     */
 | |
| /* Object              : Write data to the internal sram buffer 1 or 2	     */
 | |
| /* Input Parameters    : DataFlash Service				     */
 | |
| /*			: <BufferCommand> = command to write buffer1 or 2    */
 | |
| /*                     : <*dataBuffer> = data buffer to write		     */
 | |
| /*                     : <bufferAddress> = address in the internal buffer    */
 | |
| /*                     : <SizeToWrite> = data buffer size		     */
 | |
| /* Return value		: State of the dataflash			     */
 | |
| /*---------------------------------------------------------------------------*/
 | |
| AT91S_DataFlashStatus AT91F_DataFlashWriteBuffer(
 | |
| 					AT91PS_DataFlash pDataFlash,
 | |
| 					unsigned char BufferCommand,
 | |
| 					unsigned char *dataBuffer,
 | |
| 					unsigned int bufferAddress,
 | |
| 					int SizeToWrite)
 | |
| {
 | |
| 	int cmdsize;
 | |
| 	/* Test if the buffer command is legal */
 | |
| 	if ((BufferCommand != DB_BUF1_WRITE) &&
 | |
| 			(BufferCommand != DB_BUF2_WRITE)) {
 | |
| 		return DATAFLASH_BAD_COMMAND;
 | |
| 	}
 | |
| 
 | |
| 	/* buffer address must be lower than page size */
 | |
| 	if (bufferAddress > pDataFlash->pDevice->pages_size)
 | |
| 		return DATAFLASH_BAD_ADDRESS;
 | |
| 
 | |
| 	if ((pDataFlash->pDataFlashDesc->state) != IDLE)
 | |
| 		return DATAFLASH_BUSY;
 | |
| 
 | |
| 	/* Send first Write Command */
 | |
| 	pDataFlash->pDataFlashDesc->command[0] = BufferCommand;
 | |
| 	pDataFlash->pDataFlashDesc->command[1] = 0;
 | |
| 	if (pDataFlash->pDevice->pages_number >= 16384) {
 | |
| 		pDataFlash->pDataFlashDesc->command[2] = 0;
 | |
| 		pDataFlash->pDataFlashDesc->command[3] =
 | |
| 			(unsigned char)(((unsigned int)(bufferAddress &
 | |
| 							pDataFlash->pDevice->
 | |
| 							byte_mask)) >> 8);
 | |
| 		pDataFlash->pDataFlashDesc->command[4] =
 | |
| 			(unsigned char)((unsigned int)bufferAddress & 0x00FF);
 | |
| 		cmdsize = 5;
 | |
| 	} else {
 | |
| 		pDataFlash->pDataFlashDesc->command[2] =
 | |
| 			(unsigned char)(((unsigned int)(bufferAddress &
 | |
| 							pDataFlash->pDevice->
 | |
| 							byte_mask)) >> 8);
 | |
| 		pDataFlash->pDataFlashDesc->command[3] =
 | |
| 			(unsigned char)((unsigned int)bufferAddress & 0x00FF);
 | |
| 		pDataFlash->pDataFlashDesc->command[4] = 0;
 | |
| 		cmdsize = 4;
 | |
| 	}
 | |
| 
 | |
| 	pDataFlash->pDataFlashDesc->tx_cmd_pt =
 | |
| 		pDataFlash->pDataFlashDesc->command;
 | |
| 	pDataFlash->pDataFlashDesc->tx_cmd_size = cmdsize;
 | |
| 	pDataFlash->pDataFlashDesc->rx_cmd_pt =
 | |
| 		pDataFlash->pDataFlashDesc->command;
 | |
| 	pDataFlash->pDataFlashDesc->rx_cmd_size = cmdsize;
 | |
| 
 | |
| 	pDataFlash->pDataFlashDesc->rx_data_pt = dataBuffer;
 | |
| 	pDataFlash->pDataFlashDesc->tx_data_pt = dataBuffer;
 | |
| 	pDataFlash->pDataFlashDesc->rx_data_size = SizeToWrite;
 | |
| 	pDataFlash->pDataFlashDesc->tx_data_size = SizeToWrite;
 | |
| 
 | |
| 	return AT91F_SpiWrite(pDataFlash->pDataFlashDesc);
 | |
| }
 | |
| 
 | |
| /*---------------------------------------------------------------------------*/
 | |
| /* Function Name       : AT91F_PageErase                                     */
 | |
| /* Object              : Erase a page					     */
 | |
| /* Input Parameters    : DataFlash Service				     */
 | |
| /*                     : Page concerned					     */
 | |
| /*                     :						     */
 | |
| /* Return value		: State of the dataflash			     */
 | |
| /*---------------------------------------------------------------------------*/
 | |
| AT91S_DataFlashStatus AT91F_PageErase(
 | |
| 					AT91PS_DataFlash pDataFlash,
 | |
| 					unsigned int page)
 | |
| {
 | |
| 	int cmdsize;
 | |
| 	/* Test if the buffer command is legal */
 | |
| 	/* no data to transmit or receive */
 | |
| 	pDataFlash->pDataFlashDesc->tx_data_size = 0;
 | |
| 
 | |
| 	cmdsize = 4;
 | |
| 	if (pDataFlash->pDevice->pages_number >= 16384)
 | |
| 		cmdsize = 5;
 | |
| 	return (AT91F_DataFlashSendCommand(pDataFlash,
 | |
| 				DB_PAGE_ERASE, cmdsize,
 | |
| 				page * pDataFlash->pDevice->pages_size));
 | |
| }
 | |
| 
 | |
| /*---------------------------------------------------------------------------*/
 | |
| /* Function Name       : AT91F_BlockErase                                    */
 | |
| /* Object              : Erase a Block					     */
 | |
| /* Input Parameters    : DataFlash Service				     */
 | |
| /*                     : Page concerned					     */
 | |
| /*                     :						     */
 | |
| /* Return value		: State of the dataflash			     */
 | |
| /*---------------------------------------------------------------------------*/
 | |
| AT91S_DataFlashStatus AT91F_BlockErase(
 | |
| 				AT91PS_DataFlash pDataFlash,
 | |
| 				unsigned int block)
 | |
| {
 | |
| 	int cmdsize;
 | |
| 	/* Test if the buffer command is legal */
 | |
| 	/* no data to transmit or receive */
 | |
| 	pDataFlash->pDataFlashDesc->tx_data_size = 0;
 | |
| 	cmdsize = 4;
 | |
| 	if (pDataFlash->pDevice->pages_number >= 16384)
 | |
| 		cmdsize = 5;
 | |
| 	return (AT91F_DataFlashSendCommand(pDataFlash, DB_BLOCK_ERASE, cmdsize,
 | |
| 					block * 8 *
 | |
| 					pDataFlash->pDevice->pages_size));
 | |
| }
 | |
| 
 | |
| /*---------------------------------------------------------------------------*/
 | |
| /* Function Name       : AT91F_WriteBufferToMain			     */
 | |
| /* Object              : Write buffer to the main memory		     */
 | |
| /* Input Parameters    : DataFlash Service				     */
 | |
| /*		: <BufferCommand> = command to send to buffer1 or buffer2    */
 | |
| /*                     : <dest> = main memory address			     */
 | |
| /* Return value		: State of the dataflash			     */
 | |
| /*---------------------------------------------------------------------------*/
 | |
| AT91S_DataFlashStatus AT91F_WriteBufferToMain(AT91PS_DataFlash pDataFlash,
 | |
| 					unsigned char BufferCommand,
 | |
| 					unsigned int dest)
 | |
| {
 | |
| 	int cmdsize;
 | |
| 	/* Test if the buffer command is correct */
 | |
| 	if ((BufferCommand != DB_BUF1_PAGE_PGM) &&
 | |
| 			(BufferCommand != DB_BUF1_PAGE_ERASE_PGM) &&
 | |
| 			(BufferCommand != DB_BUF2_PAGE_PGM) &&
 | |
| 			(BufferCommand != DB_BUF2_PAGE_ERASE_PGM))
 | |
| 		return DATAFLASH_BAD_COMMAND;
 | |
| 
 | |
| 	/* no data to transmit or receive */
 | |
| 	pDataFlash->pDataFlashDesc->tx_data_size = 0;
 | |
| 
 | |
| 	cmdsize = 4;
 | |
| 	if (pDataFlash->pDevice->pages_number >= 16384)
 | |
| 		cmdsize = 5;
 | |
| 	/* Send the command to the dataflash */
 | |
| 	return (AT91F_DataFlashSendCommand(pDataFlash, BufferCommand,
 | |
| 						cmdsize, dest));
 | |
| }
 | |
| 
 | |
| /*---------------------------------------------------------------------------*/
 | |
| /* Function Name       : AT91F_PartialPageWrite				     */
 | |
| /* Object              : Erase partielly a page				     */
 | |
| /* Input Parameters    : <page> = page number				     */
 | |
| /*			: <AdrInpage> = adr to begin the fading		     */
 | |
| /*                     : <length> = Number of bytes to erase		     */
 | |
| /*---------------------------------------------------------------------------*/
 | |
| AT91S_DataFlashStatus AT91F_PartialPageWrite(AT91PS_DataFlash pDataFlash,
 | |
| 					unsigned char *src,
 | |
| 					unsigned int dest,
 | |
| 					unsigned int size)
 | |
| {
 | |
| 	unsigned int page;
 | |
| 	unsigned int AdrInPage;
 | |
| 
 | |
| 	page = dest / (pDataFlash->pDevice->pages_size);
 | |
| 	AdrInPage = dest % (pDataFlash->pDevice->pages_size);
 | |
| 
 | |
| 	/* Read the contents of the page in the Sram Buffer */
 | |
| 	AT91F_MainMemoryToBufferTransfert(pDataFlash, DB_PAGE_2_BUF1_TRF, page);
 | |
| 	AT91F_DataFlashWaitReady(pDataFlash->pDataFlashDesc,
 | |
| 				 AT91C_TIMEOUT_WRDY);
 | |
| 	/*Update the SRAM buffer */
 | |
| 	AT91F_DataFlashWriteBuffer(pDataFlash, DB_BUF1_WRITE, src,
 | |
| 					AdrInPage, size);
 | |
| 
 | |
| 	AT91F_DataFlashWaitReady(pDataFlash->pDataFlashDesc,
 | |
| 					AT91C_TIMEOUT_WRDY);
 | |
| 
 | |
| 	/* Erase page if a 128 Mbits device */
 | |
| 	if (pDataFlash->pDevice->pages_number >= 16384) {
 | |
| 		AT91F_PageErase(pDataFlash, page);
 | |
| 		/* Rewrite the modified Sram Buffer in the main memory */
 | |
| 		AT91F_DataFlashWaitReady(pDataFlash->pDataFlashDesc,
 | |
| 					 AT91C_TIMEOUT_WRDY);
 | |
| 	}
 | |
| 
 | |
| 	/* Rewrite the modified Sram Buffer in the main memory */
 | |
| 	return (AT91F_WriteBufferToMain(pDataFlash, DB_BUF1_PAGE_ERASE_PGM,
 | |
| 					(page *
 | |
| 					 pDataFlash->pDevice->pages_size)));
 | |
| }
 | |
| 
 | |
| /*---------------------------------------------------------------------------*/
 | |
| /* Function Name       : AT91F_DataFlashWrite				     */
 | |
| /* Object              :						     */
 | |
| /* Input Parameters    : <*src> = Source buffer				     */
 | |
| /*                     : <dest> = dataflash adress			     */
 | |
| /*                     : <size> = data buffer size			     */
 | |
| /*---------------------------------------------------------------------------*/
 | |
| AT91S_DataFlashStatus AT91F_DataFlashWrite(AT91PS_DataFlash pDataFlash,
 | |
| 						unsigned char *src,
 | |
| 						int dest, int size)
 | |
| {
 | |
| 	unsigned int length;
 | |
| 	unsigned int page;
 | |
| 	unsigned int status;
 | |
| 
 | |
| 	AT91F_SpiEnable(pDataFlash->pDevice->cs);
 | |
| 
 | |
| 	if ((dest + size) > (pDataFlash->pDevice->pages_size *
 | |
| 			(pDataFlash->pDevice->pages_number)))
 | |
| 		return DATAFLASH_MEMORY_OVERFLOW;
 | |
| 
 | |
| 	/* If destination does not fit a page start address */
 | |
| 	if ((dest % ((unsigned int)(pDataFlash->pDevice->pages_size))) != 0) {
 | |
| 		length =
 | |
| 			pDataFlash->pDevice->pages_size -
 | |
| 			(dest % ((unsigned int)(pDataFlash->pDevice->pages_size)));
 | |
| 
 | |
| 		if (size < length)
 | |
| 			length = size;
 | |
| 
 | |
| 		if (!AT91F_PartialPageWrite(pDataFlash, src, dest, length))
 | |
| 			return DATAFLASH_ERROR;
 | |
| 
 | |
| 		AT91F_DataFlashWaitReady(pDataFlash->pDataFlashDesc,
 | |
| 					 AT91C_TIMEOUT_WRDY);
 | |
| 
 | |
| 		/* Update size, source and destination pointers */
 | |
| 		size -= length;
 | |
| 		dest += length;
 | |
| 		src += length;
 | |
| 	}
 | |
| 
 | |
| 	while ((size - pDataFlash->pDevice->pages_size) >= 0) {
 | |
| 		/* program dataflash page */
 | |
| 		page = (unsigned int)dest / (pDataFlash->pDevice->pages_size);
 | |
| 
 | |
| 		status = AT91F_DataFlashWriteBuffer(pDataFlash,
 | |
| 					DB_BUF1_WRITE, src, 0,
 | |
| 					pDataFlash->pDevice->
 | |
| 					pages_size);
 | |
| 		AT91F_DataFlashWaitReady(pDataFlash->pDataFlashDesc,
 | |
| 					 AT91C_TIMEOUT_WRDY);
 | |
| 
 | |
| 		status = AT91F_PageErase(pDataFlash, page);
 | |
| 		AT91F_DataFlashWaitReady(pDataFlash->pDataFlashDesc,
 | |
| 					 AT91C_TIMEOUT_WRDY);
 | |
| 		if (!status)
 | |
| 			return DATAFLASH_ERROR;
 | |
| 
 | |
| 		status = AT91F_WriteBufferToMain(pDataFlash,
 | |
| 					 DB_BUF1_PAGE_PGM, dest);
 | |
| 		if (!status)
 | |
| 			return DATAFLASH_ERROR;
 | |
| 
 | |
| 		AT91F_DataFlashWaitReady(pDataFlash->pDataFlashDesc,
 | |
| 					 AT91C_TIMEOUT_WRDY);
 | |
| 
 | |
| 		/* Update size, source and destination pointers */
 | |
| 		size -= pDataFlash->pDevice->pages_size;
 | |
| 		dest += pDataFlash->pDevice->pages_size;
 | |
| 		src += pDataFlash->pDevice->pages_size;
 | |
| 	}
 | |
| 
 | |
| 	/* If still some bytes to read */
 | |
| 	if (size > 0) {
 | |
| 		/* program dataflash page */
 | |
| 		if (!AT91F_PartialPageWrite(pDataFlash, src, dest, size))
 | |
| 			return DATAFLASH_ERROR;
 | |
| 
 | |
| 		AT91F_DataFlashWaitReady(pDataFlash->pDataFlashDesc,
 | |
| 					 AT91C_TIMEOUT_WRDY);
 | |
| 	}
 | |
| 	return DATAFLASH_OK;
 | |
| }
 | |
| 
 | |
| /*---------------------------------------------------------------------------*/
 | |
| /* Function Name       : AT91F_DataFlashRead				     */
 | |
| /* Object              : Read a block in dataflash			     */
 | |
| /* Input Parameters    :						     */
 | |
| /* Return value		:						     */
 | |
| /*---------------------------------------------------------------------------*/
 | |
| int AT91F_DataFlashRead(AT91PS_DataFlash pDataFlash,
 | |
| 			unsigned long addr, unsigned long size, char *buffer)
 | |
| {
 | |
| 	unsigned long SizeToRead;
 | |
| 
 | |
| 	AT91F_SpiEnable(pDataFlash->pDevice->cs);
 | |
| 
 | |
| 	if (AT91F_DataFlashWaitReady(pDataFlash->pDataFlashDesc,
 | |
| 					AT91C_TIMEOUT_WRDY) != DATAFLASH_OK)
 | |
| 		return -1;
 | |
| 
 | |
| 	while (size) {
 | |
| 		SizeToRead = (size < 0x8000) ? size : 0x8000;
 | |
| 
 | |
| 		if (AT91F_DataFlashWaitReady(pDataFlash->pDataFlashDesc,
 | |
| 					AT91C_TIMEOUT_WRDY) !=
 | |
| 						DATAFLASH_OK)
 | |
| 			return -1;
 | |
| 
 | |
| 		if (AT91F_DataFlashContinuousRead(pDataFlash, addr,
 | |
| 						(uchar *) buffer,
 | |
| 						SizeToRead) != DATAFLASH_OK)
 | |
| 			return -1;
 | |
| 
 | |
| 		size -= SizeToRead;
 | |
| 		addr += SizeToRead;
 | |
| 		buffer += SizeToRead;
 | |
| 	}
 | |
| 
 | |
| 	return DATAFLASH_OK;
 | |
| }
 | |
| 
 | |
| /*---------------------------------------------------------------------------*/
 | |
| /* Function Name       : AT91F_DataflashProbe				     */
 | |
| /* Object              :						     */
 | |
| /* Input Parameters    :						     */
 | |
| /* Return value	       : Dataflash status register			     */
 | |
| /*---------------------------------------------------------------------------*/
 | |
| int AT91F_DataflashProbe(int cs, AT91PS_DataflashDesc pDesc)
 | |
| {
 | |
| 	AT91F_SpiEnable(cs);
 | |
| 	AT91F_DataFlashGetStatus(pDesc);
 | |
| 	return ((pDesc->command[1] == 0xFF) ? 0 : pDesc->command[1] & 0x3C);
 | |
| }
 |