* Patch by Mark Jonas, 08 June 2004:
[oweals/u-boot.git] / cpu / at91rm9200 / at45.c
index cf456fb4a54a44b0d5037779ba9906fb3b8feca5..9dfe5609bfaa02d363d8e69f3bfa93f504806aa2 100644 (file)
@@ -26,6 +26,7 @@
 #include <dataflash.h>
 
 #define SPI_CLK 5000000
+#define AT91C_TIMEOUT_WRDY                     200000
 #define AT91C_SPI_PCS0_SERIAL_DATAFLASH                0xE     /* Chip Select 0 : NPCS0 %1110 */
 #define AT91C_SPI_PCS3_DATAFLASH_CARD          0x7     /* Chip Select 3 : NPCS3 %0111 */
 
@@ -145,10 +146,17 @@ AT91S_DataFlashStatus AT91F_DataFlashSendCommand(
 
        /* fill the  command  buffer */
        pDataFlash->pDataFlashDesc->command[0] = OpCode;
-       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;
+       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;
@@ -205,8 +213,7 @@ AT91S_DataFlashStatus AT91F_DataFlashWaitReady(AT91PS_DataflashDesc pDataFlashDe
        do {
                AT91F_DataFlashGetStatus(pDataFlashDesc);
                timeout--;
-       }
-       while( ((pDataFlashDesc->DataFlash_state & 0x80) != 0x80) && (timeout > 0) );
+       } while( ((pDataFlashDesc->DataFlash_state & 0x80) != 0x80) && (timeout > 0) );
 
        if((pDataFlashDesc->DataFlash_state & 0x80) != 0x80)
                return DATAFLASH_ERROR;
@@ -230,6 +237,7 @@ AT91S_DataFlashStatus AT91F_DataFlashContinuousRead (
        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;
@@ -239,8 +247,9 @@ AT91S_DataFlashStatus AT91F_DataFlashContinuousRead (
        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(AT91F_DataFlashSendCommand (pDataFlash, DB_CONTINUOUS_ARRAY_READ, 8, src));
+       return(status);
 }
 
 
@@ -259,13 +268,17 @@ AT91S_DataFlashStatus AT91F_DataFlashPagePgmBuf(
        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 */
-       return(AT91F_DataFlashSendCommand (pDataFlash, DB_PAGE_PGM_BUF1, 4, dest));
+       if (pDataFlash->pDevice->pages_number >= 16384)
+               cmdsize = 5;
+       return(AT91F_DataFlashSendCommand (pDataFlash, DB_PAGE_PGM_BUF1, cmdsize, dest));
 }
 
 
@@ -282,14 +295,17 @@ AT91S_DataFlashStatus AT91F_MainMemoryToBufferTransfert(
        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;
-
-       return(AT91F_DataFlashSendCommand (pDataFlash, BufferCommand, 4, page*pDataFlash->pDevice->pages_size));
+       cmdsize = 4;
+       if (pDataFlash->pDevice->pages_number >= 16384)
+               cmdsize = 5;
+       return(AT91F_DataFlashSendCommand (pDataFlash, BufferCommand, cmdsize, page*pDataFlash->pDevice->pages_size));
 }
 
 
@@ -310,6 +326,7 @@ AT91S_DataFlashStatus AT91F_DataFlashWriteBuffer (
        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;
@@ -324,14 +341,22 @@ AT91S_DataFlashStatus AT91F_DataFlashWriteBuffer (
        /* Send first Write Command */
        pDataFlash->pDataFlashDesc->command[0] = BufferCommand;
        pDataFlash->pDataFlashDesc->command[1] = 0;
-       pDataFlash->pDataFlashDesc->command[2] = (unsigned char)(((unsigned int)(bufferAddress &  pDataFlash->pDevice->byte_mask)) >> 8) ;
-       pDataFlash->pDataFlashDesc->command[3] = (unsigned char)((unsigned int)bufferAddress  & 0x00FF) ;
-
+       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 = 4 ;
+       pDataFlash->pDataFlashDesc->tx_cmd_size = cmdsize ;
        pDataFlash->pDataFlashDesc->rx_cmd_pt    = pDataFlash->pDataFlashDesc->command ;
-       pDataFlash->pDataFlashDesc->rx_cmd_size = 4 ;
+       pDataFlash->pDataFlashDesc->rx_cmd_size = cmdsize ;
 
        pDataFlash->pDataFlashDesc->rx_data_pt  = dataBuffer ;
        pDataFlash->pDataFlashDesc->tx_data_pt  = dataBuffer ;
@@ -341,6 +366,51 @@ AT91S_DataFlashStatus AT91F_DataFlashWriteBuffer (
        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                               */
@@ -355,6 +425,7 @@ AT91S_DataFlashStatus AT91F_WriteBufferToMain (
        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) &&
@@ -365,8 +436,11 @@ AT91S_DataFlashStatus AT91F_WriteBufferToMain (
        /* 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, 4, dest));
+       return(AT91F_DataFlashSendCommand (pDataFlash, BufferCommand, cmdsize, dest));
 }
 
 
@@ -391,10 +465,18 @@ AT91S_DataFlashStatus AT91F_PartialPageWrite (
 
        /* Read the contents of the page in the Sram Buffer */
        AT91F_MainMemoryToBufferTransfert(pDataFlash, DB_PAGE_2_BUF1_TRF, page);
-       AT91F_DataFlashWaitReady(pDataFlash->pDataFlashDesc, 1000);
+       AT91F_DataFlashWaitReady(pDataFlash->pDataFlashDesc, AT91C_TIMEOUT_WRDY);
        /*Update the SRAM buffer */
        AT91F_DataFlashWriteBuffer(pDataFlash, DB_BUF1_WRITE, src, AdrInPage, size);
-       AT91F_DataFlashWaitReady(pDataFlash->pDataFlashDesc, 1000);
+
+       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)));
@@ -402,7 +484,7 @@ AT91S_DataFlashStatus AT91F_PartialPageWrite (
 
 
 /*------------------------------------------------------------------------------*/
-/* Function Name       : AT91F_DataFlashWrite_Overloaded                       */
+/* Function Name       : AT91F_DataFlashWrite                                  */
 /* Object              :                                                       */
 /* Input Parameters    : <*src> = Source buffer                                        */
 /*                     : <dest> = dataflash adress                             */
@@ -415,6 +497,8 @@ AT91S_DataFlashStatus AT91F_DataFlashWrite(
        int size )
 {
        unsigned int length;
+       unsigned int page;
+       unsigned int status;
 
        AT91F_SpiEnable(pDataFlash->pDevice->cs);
 
@@ -431,7 +515,7 @@ AT91S_DataFlashStatus AT91F_DataFlashWrite(
                if(!AT91F_PartialPageWrite(pDataFlash,src, dest, length))
                        return DATAFLASH_ERROR;
 
-               AT91F_DataFlashWaitReady(pDataFlash->pDataFlashDesc, 1000);
+               AT91F_DataFlashWaitReady(pDataFlash->pDataFlashDesc, AT91C_TIMEOUT_WRDY);
 
                /* Update size, source and destination pointers */
                size -= length;
@@ -441,10 +525,21 @@ AT91S_DataFlashStatus AT91F_DataFlashWrite(
 
        while (( size - pDataFlash->pDevice->pages_size ) >= 0 ) {
                /* program dataflash page */
-               if(!AT91F_DataFlashPagePgmBuf(pDataFlash, src, dest, pDataFlash->pDevice->pages_size ))
+               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, 1000);
+               AT91F_DataFlashWaitReady(pDataFlash->pDataFlashDesc, AT91C_TIMEOUT_WRDY);
 
                /* Update size, source and destination pointers */
                size -= pDataFlash->pDevice->pages_size ;
@@ -458,7 +553,7 @@ AT91S_DataFlashStatus AT91F_DataFlashWrite(
                if(!AT91F_PartialPageWrite(pDataFlash, src, dest, size) )
                        return DATAFLASH_ERROR;
 
-               AT91F_DataFlashWaitReady(pDataFlash->pDataFlashDesc, 1000);
+               AT91F_DataFlashWaitReady(pDataFlash->pDataFlashDesc, AT91C_TIMEOUT_WRDY);
        }
        return DATAFLASH_OK;
 }
@@ -480,13 +575,13 @@ int AT91F_DataFlashRead(
 
        AT91F_SpiEnable(pDataFlash->pDevice->cs);
 
-       if(AT91F_DataFlashWaitReady(pDataFlash->pDataFlashDesc, 1000) != DATAFLASH_OK)
+       if(AT91F_DataFlashWaitReady(pDataFlash->pDataFlashDesc, AT91C_TIMEOUT_WRDY) != DATAFLASH_OK)
                return -1;
 
        while (size) {
                SizeToRead = (size < 0x8000)? size:0x8000;
 
-               if (AT91F_DataFlashWaitReady(pDataFlash->pDataFlashDesc, 1000) != DATAFLASH_OK)
+               if (AT91F_DataFlashWaitReady(pDataFlash->pDataFlashDesc, AT91C_TIMEOUT_WRDY) != DATAFLASH_OK)
                        return -1;
 
                if (AT91F_DataFlashContinuousRead (pDataFlash, addr, buffer, SizeToRead) != DATAFLASH_OK)