From 044ad7c3987460ede48ff27afd6bdb0ca05a0432 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Mon, 4 Jul 2011 20:52:54 +0200 Subject: import at91lib from at91lib_20100901_softpack_1_9_v_1_0_svn_v15011 it's sad to see that atmel doesn't publish their svn repo or has a centralized location or even puts proper version/release info into the library itself --- memories/MEDDdram.c | 290 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 290 insertions(+) create mode 100644 memories/MEDDdram.c (limited to 'memories/MEDDdram.c') diff --git a/memories/MEDDdram.c b/memories/MEDDdram.c new file mode 100644 index 0000000..6ebaf42 --- /dev/null +++ b/memories/MEDDdram.c @@ -0,0 +1,290 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2008, Atmel Corporation + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Atmel's name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * ---------------------------------------------------------------------------- + */ + +//------------------------------------------------------------------------------ +// Headers +//------------------------------------------------------------------------------ + +#include "MEDDdram.h" +#include +#include +#include + +#if defined(AT91C_BASE_ADDRESS_DDR) +#undef AT91C_BASE_ADDRESS_DDR +#endif +#if defined(AT91C_BASE_DDR2C) && defined(AT91C_DDR2) +#define AT91C_BASE_ADDRESS_DDR AT91C_DDR2 +#endif + +#if defined(AT91C_BASE_SDDRC) && defined(AT91C_EBI_DDRAM) +#define AT91C_BASE_ADDRESS_DDR AT91C_EBI_DDRAM +#endif + +#if defined(AT91C_BASE_ADDRESS_DDR) + +//------------------------------------------------------------------------------ +// Types +//------------------------------------------------------------------------------ + +/// Do copy and modify pointer +typedef void copyFunction(unsigned char **, unsigned char **, unsigned int); + +//------------------------------------------------------------------------------ +// Internal Functions +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +/// Do copy for 8-byte aligned data +//------------------------------------------------------------------------------ +static void AlignedCopy(unsigned char * *src, + unsigned char * *dst, + unsigned int len) +{ + unsigned int *src32, *dst32; + src32 = (unsigned int*)*src; + dst32 = (unsigned int*)*dst; + for (;len > 0; len -= 8) { + *dst32 ++ = *src32 ++; + *dst32 ++ = *src32 ++; + } + *src = (unsigned char*)src32; + *dst = (unsigned char*)dst32; +} + +//------------------------------------------------------------------------------ +/// Do copy for byte-aligned data +//------------------------------------------------------------------------------ +static void UnalignedCopy(unsigned char * *src, + unsigned char * *dst, + unsigned int len) +{ + for (;len > 0; len --) { + *(*dst) ++ = *(*src) ++; + } +} + +//------------------------------------------------------------------------------ +//! \brief Reads a specified amount of data from a DDRAM memory +//! \param media Pointer to a Media instance +//! \param address Address of the data to read +//! \param data Pointer to the buffer in which to store the retrieved +//! data +//! \param length Length of the buffer +//! \param callback Optional pointer to a callback function to invoke when +//! the operation is finished +//! \param argument Optional pointer to an argument for the callback +//! \return Operation result code +//------------------------------------------------------------------------------ +static unsigned char MEDDdram_Read(Media *media, + unsigned int address, + void *data, + unsigned int length, + MediaCallback callback, + void *argument) +{ + unsigned char *source; + unsigned char *dest; + copyFunction *pCpy; + + // Check that the media is ready + if (media->state != MED_STATE_READY) { + + TRACE_INFO("Media busy\n\r"); + return MED_STATUS_BUSY; + } + + // Check that the data to read is not too big + if ((length + address) > media->size) { + + TRACE_WARNING("MEDDdram_Read: Data too big: %u, 0x%08X\n\r", + length, address); + return MED_STATUS_ERROR; + } + + // Enter Busy state + media->state = MED_STATE_BUSY; + + // Source & Destination + source = (unsigned char *)(media->blockSize + * (address + media->baseAddress)); + dest = (unsigned char *)data; + + // Align/Unaligned copy + pCpy = (((unsigned int)source%4) == 0 && (media->blockSize%8) == 0) + ? AlignedCopy : UnalignedCopy; + + for (; length > 0; length --) { + pCpy(&source, &dest, media->blockSize); + } + + // Leave the Busy state + media->state = MED_STATE_READY; + + // Invoke callback + if (callback != 0) { + + callback(argument, MED_STATUS_SUCCESS, 0, 0); + } + + return MED_STATUS_SUCCESS; +} + +//------------------------------------------------------------------------------ +//! \brief Writes data on a DDRAM media +//! \param media Pointer to a Media instance +//! \param address Address at which to write +//! \param data Pointer to the data to write +//! \param length Size of the data buffer +//! \param callback Optional pointer to a callback function to invoke when +//! the write operation terminates +//! \param argument Optional argument for the callback function +//! \return Operation result code +//! \see Media +//! \see MediaCallback +//------------------------------------------------------------------------------ +static unsigned char MEDDdram_Write(Media *media, + unsigned int address, + void *data, + unsigned int length, + MediaCallback callback, + void *argument) +{ + unsigned char *source; + unsigned char *dest; + copyFunction *pCpy; + + //TRACE_DEBUG("MEDDdram_Write\n\r"); + + // Check that the media if ready + if (media->state != MED_STATE_READY) { + + TRACE_INFO("MEDDdram_Write: Busy\n\r"); + return MED_STATUS_BUSY; + } + + // Check that the data to write is not too big + if ((length + address) > media->size) { + + TRACE_WARNING("MEDDdram_Write: Data too big\n\r"); + return MED_STATUS_ERROR; + } + + // Put the media in Busy state + media->state = MED_STATE_BUSY; + + // Compute function parameters + source = (unsigned char *) data; + dest = (unsigned char *) (media->blockSize * + (media->baseAddress + address)); + + // Align/Unaligned copy + pCpy = (((unsigned int)source%4) == 0 && (media->blockSize%8) == 0) + ? AlignedCopy : UnalignedCopy; + + for (; length > 0; length --) { + pCpy(&source, &dest, media->blockSize); + } + + // Leave the Busy state + media->state = MED_STATE_READY; + + // Invoke the callback if it exists + if (callback != 0) { + + callback(argument, MED_STATUS_SUCCESS, 0, 0); + } + + return MED_STATUS_SUCCESS; +} + +//------------------------------------------------------------------------------ +// Exported Functions +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ +//! \brief Initializes a Media instance and the associated physical interface +//! \param media Pointer to the Media instance to initialize +//! \param blockSize Block size of the media, in bytes. +//! \param baseAddress Basic address of the media, in number of blocks. +//! \param size Size of the media, in number of blocks. +//! \see Media +//------------------------------------------------------------------------------ +void MEDDdram_Initialize(Media *media, + unsigned int blockSize, + unsigned int baseAddress, + unsigned int size) +{ + unsigned int value; + + TRACE_INFO("MEDDdram init\n\r"); + + // Initialize DDRAM if not already done + //-------------------------------------------------------------------------- + value = *((volatile unsigned int *) AT91C_BASE_ADDRESS_DDR); + *((volatile unsigned int *) AT91C_BASE_ADDRESS_DDR) = 0xDEADBEEF; + + if (*((volatile unsigned int *) AT91C_BASE_ADDRESS_DDR) == 0xDEADBEEF) { + + *((volatile unsigned int *) AT91C_BASE_ADDRESS_DDR) = value; + TRACE_INFO("DDRAM initialized\n\r"); + } + else { + + *((volatile unsigned int *) AT91C_BASE_ADDRESS_DDR) = value; + TRACE_INFO("Initialize DDRAM ...\n\r"); + BOARD_ConfigureDdram(0, BOARD_DDRAM_BUSWIDTH); + } + + // Initialize media fields + //-------------------------------------------------------------------------- + media->write = MEDDdram_Write; + media->read = MEDDdram_Read; + media->lock = 0; + media->unlock = 0; + media->handler = 0; + media->flush = 0; + + media->blockSize = blockSize; + media->baseAddress = baseAddress; + media->size = size; + + media->mappedRD = 1; + media->mappedWR = 1; + media->protected = 0; + media->removable = 0; + media->state = MED_STATE_READY; + + media->transfer.data = 0; + media->transfer.address = 0; + media->transfer.length = 0; + media->transfer.callback = 0; + media->transfer.argument = 0; +} +#endif //#if defined(AT91C_BASE_ADDRESS_DDR) + -- cgit v1.2.3