All of lore.kernel.org
 help / color / mirror / Atom feed
From: Ulf Samuelsson <ulf@atmel.com>
To: u-boot@lists.denx.de
Subject: [U-Boot-Users] AT91 NAND om AT91SAM9260EK
Date: Thu, 08 Feb 2007 23:20:55 +0100	[thread overview]
Message-ID: <45CBA247.209@atmel.com> (raw)
In-Reply-To: <1defaf580702081258j5566c646yf2808b8795b14bbe@mail.gmail.com>

Haavard Skinnemoen skrev:
> On 2/8/07, Ulf Samuelsson <ulf@atmel.com> wrote:
>> Additional boards coming from Atmel will use the same dataflash driver.
>
> Hopefully including any AVR32 boards featuring DataFlash.
>
>> The "board/at91rm9200dk/at45.c" functionality is split
>> into a CPU dependent part located in "cpu/arm926ejs/at91sam926x/spi.c"
>> and the "board/at45.c" file.
>>
>> I tried to start the process of merging with mainstream U-boot
>> by sending in a patch which split the at45.c located in
>> board/at91rm9200dk into
>> * drivers/at45.c
>> * cpu/arm920t/at91rm9200/spi.c
>
> Any chance the SPI driver could move into drivers/ as well? The
> at32ap7000 has pretty much the same SPI hardware built in, and IMO
> there shouldn't really be anything chip-specific about it apart from
> pin configuration, register base address and interrupt line (if it
> even uses that.)
>
> I'm willing to review the driver if you send it inline as a single
> patch, and perhaps help you clean it up as well, if needed. Please Cc
> hskinnemoen at atmel.com so I receive it in my mail client at work.
>
>> There has been a discussion about how dataflash should be supported
>> but the things people do not like are not in this file, they
>> are in the "board/dataflash.c" file so I have no clue
>> why nothing is happening.
>
> It could have something to do with the tarball submission format not
> being particularly reviewer-friendly...
>
> Haavard
Here is it again, was not sent as a tarball, but as an attachement.
This was a patchset of three patches, the remaining
two patches just removes
"board/at91rm9200dk/at45.c"     and
"board/cmc_pu2/at45.c"
They are not used any longer.

I do  think that it is better to submit the AT91SAM9 patches
first and  only then create a common driver.

-------------------------------------------------------------
DESCRIPTION

The at45.c dataflash driver is currently duplicated in
* board/at91rm9200dk
* board/cmc_pu2

This patch splits the at45 dataflash driver into a 
* cpu-dependent   part located in cpu/arm920t/at91rm9200
* cpu-independent part located in drivers/at45.c

making AT45 Dataflash available to all boards with an
appropriate SPI driver.

All new AT91 boards use this driver, so if/when patches
for these boards are accepted into mainline, having
a common driver will reduce the size of the U-boot source 
and make the board support more maintainable.

The "drivers/at45.c" is compiled for all boards
but contain a configuration test:
#ifdef CONFIG_HAS_DATAFLASH
...
#endif
around the code, so if this is not set, the at45
driver will not add code to the system.

------
The current at45.c contains both the cpu specific
spi access routines and a higher layer 
dataflash access routine which calls the lower layer
spi routines to read/write dataflash.

To make the at45 independent on the CPU, the
spi layer has been removed from the driver
and placed in the cpu/arm920t/at91rm9200/spi.c.
CPU specific "includes" are moved inside the 
CONFIG_HAS_DATAFLASH test

Makefile changes

at45.o has been removed from the Makefiles in
* "board/at91rm9200dk"
* "board/cmc_pu2"

at45.o has been added to the "drivers" Makefile.
spi.o has been added to "cpu/arm920t/at91rm9200/Makefile"

-------------------------------------------------------------
CHANGELOG:
Author: Ulf Samuelsson <ulf <at> atmel.com>
Date:   Thu Feb  1 21:18:53 CET 2007

    Make at45 driver available to all boards.
    Move SPI low level part to cpu/arm920t/at91rm9200

-------------------------------------------------------------
No new configuration options
-------------------------------------------------------------
Patch:
        Attached in plaintext
        Consists of three parts.
        1.      Split and move
        2.      Removal of at45.c from board/at91rm9200dk
        3.      Removal of at45.c from board/cmc_pu2

-------------------------------------------------------------
Patch generated by 
        diff -purN \
        u-boot-2007-02-01-0rig \
        u-boot-2007-02-01 > \
        u-boot-2007-02-01-at45_split.1_3.patch
from the parent directory
-------------------------------------------------------------
Tested on PPC and ARM


diff -purN u-boot-2007-02-01-0rig/board/at91rm9200dk/Makefile
u-boot-2007-02-01/board/at91rm9200dk/Makefile
--- u-boot-2007-02-01-0rig/board/at91rm9200dk/Makefile    2007-02-01
20:18:38.000000000 +0100
+++ u-boot-2007-02-01/board/at91rm9200dk/Makefile    2007-02-01
20:43:49.000000000 +0100
@@ -25,7 +25,7 @@ include $(TOPDIR)/config.mk
 
 LIB    = $(obj)lib$(BOARD).a
 
-COBJS    := at91rm9200dk.o at45.o flash.o
+COBJS    := at91rm9200dk.o flash.o
 
 SRCS    := $(SOBJS:.o=.S) $(COBJS:.o=.c)
 OBJS    := $(addprefix $(obj),$(COBJS))
diff -purN u-boot-2007-02-01-0rig/board/cmc_pu2/Makefile
u-boot-2007-02-01/board/cmc_pu2/Makefile
--- u-boot-2007-02-01-0rig/board/cmc_pu2/Makefile    2007-02-01
20:23:23.000000000 +0100
+++ u-boot-2007-02-01/board/cmc_pu2/Makefile    2007-02-01
20:44:27.000000000 +0100
@@ -25,7 +25,7 @@ include $(TOPDIR)/config.mk
 
 LIB    = $(obj)lib$(BOARD).a
 
-COBJS    := cmc_pu2.o at45.o flash.o load_sernum_ethaddr.o
+COBJS    := cmc_pu2.o flash.o load_sernum_ethaddr.o
 
 SRCS    := $(SOBJS:.o=.S) $(COBJS:.o=.c)
 OBJS    := $(addprefix $(obj),$(COBJS))
diff -purN u-boot-2007-02-01-0rig/cpu/arm920t/at91rm9200/Makefile
u-boot-2007-02-01/cpu/arm920t/at91rm9200/Makefile
--- u-boot-2007-02-01-0rig/cpu/arm920t/at91rm9200/Makefile    2007-02-01
20:18:49.000000000 +0100
+++ u-boot-2007-02-01/cpu/arm920t/at91rm9200/Makefile    2007-02-01
20:42:50.000000000 +0100
@@ -26,7 +26,7 @@ include $(TOPDIR)/config.mk
 LIB    = $(obj)lib$(SOC).a
 
 COBJS    = bcm5221.o dm9161.o ether.o i2c.o interrupts.o \
-      lxt972.o serial.o usb_ohci.o
+      lxt972.o serial.o spi.o usb_ohci.o
 SOBJS    = lowlevel_init.o
 
 SRCS    := $(SOBJS:.o=.S) $(COBJS:.o=.c)
diff -purN u-boot-2007-02-01-0rig/cpu/arm920t/at91rm9200/spi.c
u-boot-2007-02-01/cpu/arm920t/at91rm9200/spi.c
--- u-boot-2007-02-01-0rig/cpu/arm920t/at91rm9200/spi.c    1970-01-01
01:00:00.000000000 +0100
+++ u-boot-2007-02-01/cpu/arm920t/at91rm9200/spi.c    2007-02-01
20:27:37.000000000 +0100
@@ -0,0 +1,136 @@
+/* Driver for ATMEL SPI support
+ * Author : Hamid Ikdoumi (Atmel)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+#include <config.h>
+
+#ifdef CONFIG_HAS_DATAFLASH
+#include <common.h>
+#include <asm/hardware.h>
+#include <dataflash.h>
+
+#define AT91C_SPI_CLK    10000000    /* Max Value = 10MHz to be
compliant to
+the Continuous Array Read function */
+
+/* AC Characteristics */
+/* DLYBS = tCSS = 250ns min and DLYBCT = tCSH = 250ns */
+#define DATAFLASH_TCSS    (0xC << 16)
+#define DATAFLASH_TCHS    (0x1 << 24)
+
+#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 */
+
+void AT91F_SpiInit(void) {
+
+/*-------------------------------------------------------------------*/
+/*    SPI DataFlash Init                                */
+/*-------------------------------------------------------------------*/
+    /* Configure PIOs */
+    AT91C_BASE_PIOA->PIO_ASR = AT91C_PA3_NPCS0 | AT91C_PA4_NPCS1 |
AT91C_PA1_MOSI | AT91C_PA5_NPCS2 |
+                   AT91C_PA6_NPCS3 | AT91C_PA0_MISO | AT91C_PA2_SPCK;
+    AT91C_BASE_PIOA->PIO_PDR = AT91C_PA3_NPCS0 | AT91C_PA4_NPCS1 |
AT91C_PA1_MOSI | AT91C_PA5_NPCS2 |
+                   AT91C_PA6_NPCS3 | AT91C_PA0_MISO | AT91C_PA2_SPCK;
+    /* Enable CLock */
+    AT91C_BASE_PMC->PMC_PCER = 1 << AT91C_ID_SPI;
+
+    /* Reset the SPI */
+    AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SWRST;
+
+    /* Configure SPI in Master Mode with No CS selected !!! */
+    AT91C_BASE_SPI->SPI_MR = AT91C_SPI_MSTR | AT91C_SPI_MODFDIS |
AT91C_SPI_PCS;
+
+    /* Configure CS0 and CS3 */
+    *(AT91C_SPI_CSR + 0) = AT91C_SPI_CPOL | (AT91C_SPI_DLYBS &
DATAFLASH_TCSS) | (AT91C_SPI_DLYBCT &
+    DATAFLASH_TCHS) | ((AT91C_MASTER_CLOCK / (2*AT91C_SPI_CLK)) << 8);
+
+    *(AT91C_SPI_CSR + 3) = AT91C_SPI_CPOL | (AT91C_SPI_DLYBS &
DATAFLASH_TCSS) | (AT91C_SPI_DLYBCT &
+    DATAFLASH_TCHS) | ((AT91C_MASTER_CLOCK / (2*AT91C_SPI_CLK)) << 8);
+
+}
+
+void AT91F_SpiEnable(int cs) {
+    switch(cs) {
+    case 0:    /* Configure SPI CS0 for Serial DataFlash AT45DBxx */
+        AT91C_BASE_SPI->SPI_MR &= 0xFFF0FFFF;
+        AT91C_BASE_SPI->SPI_MR |=
((AT91C_SPI_PCS0_SERIAL_DATAFLASH<<16) & AT91C_SPI_PCS);
+        break;
+    case 3:    /* Configure SPI CS3 for Serial DataFlash Card */
+        /* Set up PIO SDC_TYPE to switch on DataFlash Card and not
MMC/SDCard */
+        AT91C_BASE_PIOB->PIO_PER = AT91C_PIO_PB7;    /* Set in PIO mode */
+        AT91C_BASE_PIOB->PIO_OER = AT91C_PIO_PB7;    /* Configure in
output */
+        /* Clear Output */
+        AT91C_BASE_PIOB->PIO_CODR = AT91C_PIO_PB7;
+        /* Configure PCS */
+        AT91C_BASE_SPI->SPI_MR &= 0xFFF0FFFF;
+        AT91C_BASE_SPI->SPI_MR |= ((AT91C_SPI_PCS3_DATAFLASH_CARD<<16)
& AT91C_SPI_PCS);
+        break;
+    }
+
+    /* SPI_Enable */
+    AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SPIEN;
+}
+
+/*----------------------------------------------------------------------------*/
+/* \fn    AT91F_SpiWrite                              */
+/* \brief Set the PDC registers for a transfert                      */
+/*----------------------------------------------------------------------------*/
+unsigned int AT91F_SpiWrite ( AT91PS_DataflashDesc pDesc )
+{
+    unsigned int timeout;
+
+    pDesc->state = BUSY;
+
+    AT91C_BASE_SPI->SPI_PTCR = AT91C_PDC_TXTDIS + AT91C_PDC_RXTDIS;
+
+    /* Initialize the Transmit and Receive Pointer */
+    AT91C_BASE_SPI->SPI_RPR = (unsigned int)pDesc->rx_cmd_pt ;
+    AT91C_BASE_SPI->SPI_TPR = (unsigned int)pDesc->tx_cmd_pt ;
+
+    /* Intialize the Transmit and Receive Counters */
+    AT91C_BASE_SPI->SPI_RCR = pDesc->rx_cmd_size;
+    AT91C_BASE_SPI->SPI_TCR = pDesc->tx_cmd_size;
+
+    if ( pDesc->tx_data_size != 0 ) {
+        /* Initialize the Next Transmit and Next Receive Pointer */
+        AT91C_BASE_SPI->SPI_RNPR = (unsigned int)pDesc->rx_data_pt ;
+        AT91C_BASE_SPI->SPI_TNPR = (unsigned int)pDesc->tx_data_pt ;
+
+        /* Intialize the Next Transmit and Next Receive Counters */
+        AT91C_BASE_SPI->SPI_RNCR = pDesc->rx_data_size ;
+        AT91C_BASE_SPI->SPI_TNCR = pDesc->tx_data_size ;
+    }
+
+    /* arm simple, non interrupt dependent timer */
+    reset_timer_masked();
+    timeout = 0;
+
+    AT91C_BASE_SPI->SPI_PTCR = AT91C_PDC_TXTEN + AT91C_PDC_RXTEN;
+    while(!(AT91C_BASE_SPI->SPI_SR & AT91C_SPI_RXBUFF) && ((timeout =
get_timer_masked() ) < CFG_SPI_WRITE_TOUT));
+    AT91C_BASE_SPI->SPI_PTCR = AT91C_PDC_TXTDIS + AT91C_PDC_RXTDIS;
+    pDesc->state = IDLE;
+
+    if (timeout >= CFG_SPI_WRITE_TOUT){
+        printf("Error Timeout\n\r");
+        return DATAFLASH_ERROR;
+    }
+
+    return DATAFLASH_OK;
+}
+#endif
diff -purN u-boot-2007-02-01-0rig/drivers/at45.c
u-boot-2007-02-01/drivers/at45.c
--- u-boot-2007-02-01-0rig/drivers/at45.c    1970-01-01
01:00:00.000000000 +0100
+++ u-boot-2007-02-01/drivers/at45.c    2007-02-01 20:34:34.000000000 +0100
@@ -0,0 +1,515 @@
+/* Driver for ATMEL DataFlash support
+ * Author : Hamid Ikdoumi (Atmel)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+#include <config.h>
+#include <common.h>
+
+#ifdef CONFIG_HAS_DATAFLASH
+#include <asm/hardware.h>
+#include <dataflash.h>
+
+
+#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 through 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 buffer2    */
+/*                     : <*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);
+}
+
+#endif
diff -purN u-boot-2007-02-01-0rig/drivers/Makefile
u-boot-2007-02-01/drivers/Makefile
--- u-boot-2007-02-01-0rig/drivers/Makefile    2007-02-01
20:18:50.000000000 +0100
+++ u-boot-2007-02-01/drivers/Makefile    2007-02-01 20:28:50.000000000
+0100
@@ -27,7 +27,7 @@ include $(TOPDIR)/config.mk
 
 LIB    = $(obj)libdrivers.a
 
-COBJS    = 3c589.o 5701rls.o ali512x.o atmel_usart.o \
+COBJS    = 3c589.o 5701rls.o ali512x.o at45.o atmel_usart.o \
       bcm570x.o bcm570x_autoneg.o cfb_console.o cfi_flash.o \
       cs8900.o ct69000.o dataflash.o dc2114x.o dm9000x.o \
       e1000.o eepro100.o \

-- 
Best Regards,
Ulf Samuelsson                ulf at atmel.com
Atmel Nordic AB
Mail:  Box 2033, 174 02 Sundbyberg, Sweden
Visit:  Kavalleriv?gen 24, 174 58 Sundbyberg, Sweden
Phone +46 (8) 441 54 22     Fax +46 (8) 441 54 29
GSM    +46 (706) 22 44 57

Technical support when I am not available:
AT90 AVR Applications Group: mailto:avr at atmel.com
AT91 ARM Applications Group: mailto:at91support at atmel.com 
links: www.avrfreaks.net; www.at91.com; avr32linux.org

-------------- next part --------------
A non-text attachment was scrubbed...
Name: ulf.vcf
Type: text/x-vcard
Size: 301 bytes
Desc: not available
Url : http://lists.denx.de/pipermail/u-boot/attachments/20070208/cc3a1ad4/attachment.vcf 

  reply	other threads:[~2007-02-08 22:20 UTC|newest]

Thread overview: 42+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <c88e466f0702050752t16c18251gcddf40a7ec95469@mail.gmail.com>
2007-02-07 23:17 ` [U-Boot-Users] AT91 NAND om AT91SAM9260EK Ulf Samuelsson
2007-02-08  6:06   ` Stefan Roese
2007-02-08  8:34     ` Michel Benoit
2007-02-08 19:25       ` Ulf Samuelsson
2007-02-08 20:58         ` Haavard Skinnemoen
2007-02-08 22:20           ` Ulf Samuelsson [this message]
2007-02-09 15:45             ` Haavard Skinnemoen
2007-02-09 19:11               ` Ulf Samuelsson
2007-02-09 19:54                 ` Haavard Skinnemoen
2007-02-09 19:39               ` Wolfgang Denk
2007-02-09 22:18                 ` Ulf Samuelsson
2007-02-09 22:58                   ` Haavard Skinnemoen
2007-02-09 23:20                     ` Ulf Samuelsson
2007-02-09 23:42                       ` Haavard Skinnemoen
2007-02-10  0:10                         ` Ulf Samuelsson
2007-02-10  1:18                       ` Wolfgang Denk
2007-02-10  9:05                         ` Ulf Samuelsson
2007-02-10  7:23                     ` Stefan Roese
2007-02-10  1:15                   ` Wolfgang Denk
2007-02-10  7:32                     ` Stefan Roese
2007-02-10  9:29                     ` Ulf Samuelsson
2007-02-10  1:53       ` Ken Watson
     [not found] <mailman.5069.1170973304.16820.u-boot-users@lists.sourceforge.net>
2007-02-08 22:57 ` Ivan Kuten
     [not found] <mailman.12584.1171099992.16820.u-boot-users@lists.sourceforge.net>
2007-02-10 20:31 ` Ivan Kuten
2007-02-11 16:43   ` Ulf Samuelsson
2007-02-11 18:04     ` Haavard Skinnemoen
2007-02-11 19:42       ` Ulf Samuelsson
2007-02-11 20:23         ` Haavard Skinnemoen
2007-02-11 20:29           ` Ulf Samuelsson
2007-02-11 20:54             ` Haavard Skinnemoen
2007-02-11 21:10           ` Wolfgang Denk
2007-02-11 21:39             ` Ulf Samuelsson
2007-02-11 23:45               ` Wolfgang Denk
2007-02-12  0:26                 ` Ulf Samuelsson
2007-02-12 15:18                   ` Haavard Skinnemoen
2007-02-12 18:40                     ` Ulf Samuelsson
2007-02-12 19:36                       ` Stefan Roese
2007-02-12 19:37                       ` Haavard Skinnemoen
2007-02-12 20:05                         ` Ulf Samuelsson
2007-02-11 21:54       ` Ulf Samuelsson
2007-02-11 11:49 Michel Benoit
2007-02-11 16:20 ` Ulf Samuelsson

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=45CBA247.209@atmel.com \
    --to=ulf@atmel.com \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.