SAMA5: Centralize logic for conversion between physical and virtual addresses

This commit is contained in:
Gregory Nutt 2013-08-09 17:25:53 -06:00
parent ad6b8726c2
commit d8b3921972
6 changed files with 437 additions and 112 deletions

View File

@ -89,8 +89,8 @@ CHIP_ASRCS =
# SAMA5-specific C source files
CHIP_CSRCS = sam_allocateheap.c sam_boot.c sam_clockconfig.c sam_pio.c
CHIP_CSRCS += sam_irq.c sam_lowputc.c sam_serial.c sam_timerisr.c
CHIP_CSRCS = sam_allocateheap.c sam_boot.c sam_clockconfig.c sam_memories.c
CHIP_CSRCS += sam_pio.c sam_irq.c sam_lowputc.c sam_serial.c sam_timerisr.c
# Configuration dependent C and assembly language files

View File

@ -192,7 +192,7 @@
#define SAM_DAP_SIZE (1*1024*1024) /* 0x00900000-0x009fffff: DAP */
#define SAM_NFCCR_SIZE (256*1024*1024) /* 0x70000000-0x7fffffff: NFC Command Registers */
/* 0xf0000000-0xffffffff: Internal Peripherals */
#define SAM_PERIPHA_SIZE (15*1024) /* 0xf0000000-0xf003bfff: Internal Peripherals */
#define SAM_PERIPHA_SIZE (240*1024) /* 0xf0000000-0xf003bfff: Internal Peripherals */
#define SAM_PERIPHB_SIZE (272*1024) /* 0xf8000000-0xf8043fff: Internal Peripherals */
#define SAM_SYSC_SIZE (1*1024*1024) /* 0xfff00000-0x0ffffedf: Internal Peripherals */
@ -312,16 +312,16 @@
#ifdef CONFIG_ARCH_LOWVECTORS
#define SAM_PERIPH_VSECTION 0xf0000000 /* 0xf0000000-0xffffffff: Internal Peripherals */
# define SAM_PERIPHA_VSECTION 0xf0000000 /* 0xf0000000-0xffffffff: Internal Peripherals */
# define SAM_PERIPHB_VSECTION 0xf8000000 /* 0xf8000000-0xffffbfff: Internal Peripherals B */
# define SAM_SYSC_VSECTION 0xfff00000 /* 0xfff00000-0xffffffff: System Controller */
# define SAM_PERIPHA_VSECTION 0xf0000000 /* 0xf0000000-0xf7ffffff: Internal Peripherals A */
# define SAM_PERIPHB_VSECTION 0xf8000000 /* 0xf8000000-0xffefffff: Internal Peripherals B */
# define SAM_SYSC_VSECTION 0xfff00000 /* 0xfff00000-0xffffbfff: System Controller */
# define SAM_SYSC_VADDR 0xffffc000 /* 0xffffc000-0xffffffff: System Controller */
#else
#define SAM_PERIPH_VSECTION 0xf0000000 /* 0xf0000000-0xffffffff: Internal Peripherals */
# define SAM_PERIPHA_VSECTION 0xf1000000 /* 0xf0000000-0xffffffff: Internal Peripherals */
# define SAM_PERIPHB_VSECTION 0xf2000000 /* 0xf8000000-0xffffbfff: Internal Peripherals B */
# define SAM_SYSC_VSECTION 0xf300000 /* 0xfff00000-0xffffffff: System Controller */
# define SAM_SYSC_VADDR 0xf30fc000 /* 0xffffc000-0xffffffff: System Controller */
# define SAM_PERIPHA_VSECTION 0xf0000000 /* 0xf0000000-0xf00fffff: Internal Peripherals A */
# define SAM_PERIPHB_VSECTION 0xf1000000 /* 0xf1000000-0xf10fffff: Internal Peripherals B */
# define SAM_SYSC_VSECTION 0xf2000000 /* 0xf2000000-0xf20fffff: System Controller */
# define SAM_SYSC_VADDR 0xf20fc000 /* 0xf20fc000-0xf20fffff: System Controller */
#endif
#endif

View File

@ -62,8 +62,9 @@
#include "sam_pio.h"
#include "sam_dmac.h"
#include "sam_hsmci.h"
#include "sam_periphclks.h"
#include "sam_memories.h"
#include "sam_hsmci.h"
#include "chip/sam_dmac.h"
#include "chip/sam_pmc.h"
#include "chip/sam_hsmci.h"
@ -420,7 +421,8 @@ static void sam_cmddump(struct sam_dev_s *priv);
/* DMA Helpers **************************************************************/
static void sam_dmacallback(DMA_HANDLE handle, void *arg, int result);
static uint32_t sam_physregaddr(struct sam_dev_s *priv, unsigned int offset);
static inline uintptr_t hsmci_physregaddr(struct sam_dev_s *priv,
unsigned int offset);
/* Data Transfer Helpers ****************************************************/
@ -1074,66 +1076,17 @@ static void sam_dmacallback(DMA_HANDLE handle, void *arg, int result)
}
/****************************************************************************
* Name: sam_physregaddr
* Name: hsmci_physregaddr
*
* Description:
* Return the physical address of an HSMCI register
*
****************************************************************************/
static uint32_t sam_physregaddr(struct sam_dev_s *priv, unsigned int offset)
static inline uintptr_t hsmci_physregaddr(struct sam_dev_s *priv,
unsigned int offset)
{
/* Get the offset into the 1MB section containing the HSMCI registers */
uint32_t pbase = priv->base & 0x000fffff;
#ifdef CONFIG_SAMA5_HSMCI0
/* Add in the physical base for HSMCI0
*
* We only have to check if this is HSMCI0 if either HSMCI1 or HSMCI2 are
* enabled.
*/
#if defined(CONFIG_SAMA5_HSMCI1) || defined(CONFIG_SAMA5_HSMCI2)
if (priv->hsmci == 0)
#endif
{
pbase |= SAM_PERIPHA_PSECTION;
}
#if defined(CONFIG_SAMA5_HSMCI1) || defined(CONFIG_SAMA5_HSMCI2)
else
#endif
#endif
#ifdef CONFIG_SAMA5_HSMCI1
/* Add in the physical base for HSMCI1
*
* We only have to check if this is HSCMCi1 if HSMCI2 is enabled.
*/
#ifdef CONFIG_SAMA5_HSMCI2
if (priv->hsmci == 1)
#endif
{
pbase |= SAM_PERIPHB_PSECTION;
}
#ifdef CONFIG_SAMA5_HSMCI2
else
#endif
#endif
/* Add in the physical base for HSMCI2.
*
* If we get here, we con't have to check.
*/
#ifdef CONFIG_SAMA5_HSMCI2
{
pbase |= SAM_PERIPHB_PSECTION;
}
#endif
return pbase + offset;
return sam_physregaddr(priv->base + offset);
}
/****************************************************************************
@ -2505,14 +2458,18 @@ static int sam_dmarecvsetup(FAR struct sdio_dev_s *dev, FAR uint8_t *buffer,
size_t buflen)
{
struct sam_dev_s *priv = (struct sam_dev_s *)dev;
uint32_t rdr;
uint32_t paddr;
uint32_t maddr;
DEBUGASSERT(priv != NULL && buffer != NULL && buflen > 0);
DEBUGASSERT(((uint32_t)buffer & 3) == 0);
/* Physical address of the HSCMI RDR registr */
/* Physical address of the HSCMI RDR register and of the buffer location
* in RAM.
*/
rdr = sam_physregaddr(priv, SAM_HSMCI_RDR_OFFSET);
paddr = hsmci_physregaddr(priv, SAM_HSMCI_RDR_OFFSET);
maddr = sam_physramaddr((uintptr_t)buffer);
/* Setup register sampling */
@ -2522,7 +2479,7 @@ static int sam_dmarecvsetup(FAR struct sdio_dev_s *dev, FAR uint8_t *buffer,
/* Configure the RX DMA */
sam_enablexfrints(priv, HSMCI_DMARECV_INTS);
sam_dmarxsetup(priv->dma, rdr, (uint32_t)buffer, buflen);
sam_dmarxsetup(priv->dma, paddr, maddr, buflen);
/* Enable DMA handshaking */
@ -2559,14 +2516,16 @@ static int sam_dmasendsetup(FAR struct sdio_dev_s *dev,
FAR const uint8_t *buffer, size_t buflen)
{
struct sam_dev_s *priv = (struct sam_dev_s *)dev;
uint32_t tdr;
uint32_t paddr;
uint32_t maddr;
DEBUGASSERT(priv != NULL && buffer != NULL && buflen > 0);
DEBUGASSERT(((uint32_t)buffer & 3) == 0);
/* Physical address of the HSCMI TDR registr */
tdr = sam_physregaddr(priv, SAM_HSMCI_TDR_OFFSET);
paddr = hsmci_physregaddr(priv, SAM_HSMCI_TDR_OFFSET);
maddr = sam_physramaddr((uintptr_t)buffer);
/* Setup register sampling */
@ -2575,7 +2534,7 @@ static int sam_dmasendsetup(FAR struct sdio_dev_s *dev,
/* Configure the TX DMA */
sam_dmatxsetup(priv->dma, tdr, (uint32_t)buffer, buflen);
sam_dmatxsetup(priv->dma, paddr, maddr, buflen);
/* Enable DMA handshaking */

View File

@ -0,0 +1,289 @@
/****************************************************************************
* arch/arm/src/sama5/sam_memories.c
*
* Copyright (C) 2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS 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.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <stdint.h>
#include <assert.h>
#include <debug.h>
#include "chip.h"
#include "sam_memories.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: peripha_physregaddr
*
* Description:
* Give the virtual address of a peripheral A register, return the
* physical address of the register
*
****************************************************************************/
static uintptr_t peripha_physregaddr(uintptr_t vregaddr)
{
#if SAM_PERIPHA_PSECTION != SAM_PERIPHA_VSECTION
/* Get the offset into the 1MB section containing the register */
uintptr_t sectoffset = vregaddr & 0x000fffff;
/* Return that offset into the virtual peripheral A base address */
return SAM_PERIPHA_PSECTION | sectoffset;
#else
/* 1-to-1 mapping */
return vregaddr;
#endif
}
/****************************************************************************
* Name: periphb_physregaddr
*
* Description:
* Give the virtual address of a peripheral B register, return the
* physical address of the register
*
****************************************************************************/
static uintptr_t periphb_physregaddr(uintptr_t vregaddr)
{
#if SAM_PERIPHB_PSECTION != SAM_PERIPHB_VSECTION
/* Get the offset into the 1MB section containing the register */
uintptr_t sectoffset = vregaddr & 0x000fffff;
/* Return that offset into the virtual peripheral A base address */
return SAM_PERIPHB_PSECTION | sectoffset;
#else
/* 1-to-1 mapping */
return vregaddr;
#endif
}
/****************************************************************************
* Name: sysc_physregaddr
*
* Description:
* Give the virtual address of a system controller register, return the
* physical address of the register
*
****************************************************************************/
static uintptr_t sysc_physregaddr(uintptr_t vregaddr)
{
#if SAM_SYSC_PSECTION != SAM_SYSC_VSECTION
/* Get the offset into the 1MB section containing the register */
uintptr_t sectoffset = vregaddr & 0x000fffff;
/* Return that offset into the virtual peripheral A base address */
return SAM_SYSC_PSECTION | sectoffset;
#else
/* 1-to-1 mapping */
return vregaddr;
#endif
}
/****************************************************************************
* Name: isram_physregaddr
*
* Description:
* Give the virtual address of an internal SRAM memory location, return the
* physical address of that location
*
****************************************************************************/
static uintptr_t isram_physregaddr(uintptr_t vregaddr)
{
#if SAM_ISRAM_PSECTION != SAM_ISRAM_VSECTION
/* Get the offset into the 1MB section containing the register */
uintptr_t sectoffset = vregaddr & 0x000fffff;
/* Return that offset into the virtual peripheral A base address */
return SAM_ISRAM_PSECTION | sectoffset;
#else
/* 1-to-1 mapping */
return vregaddr;
#endif
}
/****************************************************************************
* Name: sdram_physregaddr
*
* Description:
* Give the virtual address of an external SDRAM memory location, return
* the physical address of that location
*
****************************************************************************/
#ifdef CONFIG_SAMA5_DDRCS
static uintptr_t sdram_physregaddr(uintptr_t vregaddr)
{
#if SAM_DDRCS_PSECTION != SAM_DDRCS_VSECTION
/* Get the offset into the 1MB section containing the register */
uintptr_t sectoffset = vregaddr & 0x000fffff;
/* Return that offset into the virtual peripheral A base address */
return SAM_DDRCS_PSECTION | sectoffset;
#else
/* 1-to-1 mapping */
return vregaddr;
#endif
}
#endif
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: sam_physregaddr
*
* Description:
* Give the virtual address of a register, return the physical address of
* the register
*
****************************************************************************/
uintptr_t sam_physregaddr(uintptr_t vregaddr)
{
/* Check for a peripheral A register */
if (vregaddr >= SAM_PERIPHA_VSECTION &&
vregaddr < (SAM_PERIPHA_VSECTION + SAM_PERIPHA_SIZE))
{
return peripha_physregaddr(vregaddr);
}
/* Check for a peripheral A register */
else if (vregaddr >= SAM_PERIPHB_VSECTION &&
vregaddr < (SAM_PERIPHB_VSECTION + SAM_PERIPHB_SIZE))
{
return periphb_physregaddr(vregaddr);
}
/* Check for a system controller register */
else if (vregaddr >= SAM_SYSC_VSECTION &&
vregaddr < (SAM_SYSC_VSECTION + SAM_SYSC_SIZE))
{
return sysc_physregaddr(vregaddr);
}
/* We will not get here unless we are called with an invalid register
* address
*/
DEBUGPANIC();
return vregaddr;
}
/****************************************************************************
* Name: sam_physramaddr
*
* Description:
* Give the virtual address of a RAM memory location, return the physical
* address of that location.
*
****************************************************************************/
uintptr_t sam_physramaddr(uintptr_t vregaddr)
{
/* Check for internal SRAM. We we assume that ISRAM0 and ISRAM1 are
* contiguous.
*/
if (vregaddr >= SAM_ISRAM_VSECTION &&
vregaddr < (SAM_ISRAM_VSECTION + SAM_ISRAM_SIZE))
{
return isram_physregaddr(vregaddr);
}
#ifdef CONFIG_SAMA5_DDRCS
/* Check for external SDRAM */
else if (vregaddr >= SAM_DDRCS_VSECTION &&
vregaddr < (SAM_DDRCS_VSECTION + SAMA5_DDRCS_SIZE))
{
return sdram_physregaddr(vregaddr);
}
#endif
/* We will not get here unless we are called with an invalid or
* unsupported RAM address
*/
DEBUGPANIC();
return vregaddr;
}

View File

@ -0,0 +1,104 @@
/****************************************************************************
* arch/arm/src/sama5/sam_memories.h
*
* Copyright (C) 2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS 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.
*
****************************************************************************/
#ifndef __ARCH_ARM_SRC_SAMA5_SAM_MEMORIES_H
#define __ARCH_ARM_SRC_SAMA5_SAM_MEMORIES_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Public Types
****************************************************************************/
/****************************************************************************
* Inline Functions
****************************************************************************/
#ifndef __ASSEMBLY__
/****************************************************************************
* Public Data
****************************************************************************/
#undef EXTERN
#if defined(__cplusplus)
#define EXTERN extern "C"
extern "C"
{
#else
#define EXTERN extern
#endif
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
/****************************************************************************
* Name: sam_physregaddr
*
* Description:
* Give the virtual address of a register, return the physical address of
* the register
*
****************************************************************************/
uintptr_t sam_physregaddr(uintptr_t vregaddr);
/****************************************************************************
* Name: sam_physramaddr
*
* Description:
* Give the virtual address of a RAM memory location, return the physical
* address of that location.
*
****************************************************************************/
uintptr_t sam_physramaddr(uintptr_t vregaddr);
#undef EXTERN
#if defined(__cplusplus)
}
#endif
#endif /* __ASSEMBLY__ */
#endif /* __ARCH_ARM_SRC_SAMA5_SAM_MEMORIES_H */

View File

@ -66,8 +66,9 @@
#include "chip.h"
#include "sam_pio.h"
#include "sam_dmac.h"
#include "sam_spi.h"
#include "sam_memories.h"
#include "sam_periphclks.h"
#include "sam_spi.h"
#include "chip/sam_pmc.h"
#include "chip/sam_spi.h"
#include "chip/sam_pinmap.h"
@ -272,7 +273,7 @@ static void spi_dma_sampledone(struct sam_spics_s *spics);
static void spi_rxcallback(DMA_HANDLE handle, void *arg, int result);
static void spi_txcallback(DMA_HANDLE handle, void *arg, int result);
static uint32_t spi_physregaddr(struct sam_spics_s *spics,
static inline uintptr_t spi_physregaddr(struct sam_spics_s *spics,
unsigned int offset);
#endif
@ -849,44 +850,11 @@ static void spi_txcallback(DMA_HANDLE handle, void *arg, int result)
****************************************************************************/
#ifdef CONFIG_SAMA5_SPI_DMA
static uint32_t spi_physregaddr(struct sam_spics_s *spics,
unsigned int offset)
static inline uintptr_t spi_physregaddr(struct sam_spics_s *spics,
unsigned int offset)
{
struct sam_spidev_s *spi = spi_device(spics);
/* Get the offset into the 1MB section containing the SPI registers */
uint32_t pbase = spi->base & 0x000fffff;
#ifdef CONFIG_SAMA5_SPI0
/* Add in the physical base for SPI0
*
* We only have to check if this is SPI0 if SPI1 is enabled.
*/
#if defined(CONFIG_SAMA5_SPI1)
if (spics->spino == 0)
#endif
{
pbase |= SAM_PERIPHA_PSECTION;
}
#if defined(CONFIG_SAMA5_SPI1)
else
#endif
#endif
#ifdef CONFIG_SAMA5_SPI1
/* Add in the physical base for SPI1
*
* If we get here, we con't have to check anything.
*/
{
pbase |= SAM_PERIPHB_PSECTION;
}
#endif
return pbase + offset;
return sam_physregaddr(spi->base + offset);
}
#endif
@ -1425,6 +1393,7 @@ static void spi_exchange(struct spi_dev_s *dev, const void *txbuffer,
uint32_t txdummy;
uint32_t rxdummy;
uint32_t paddr;
uint32_t maddr;
int ret;
/* If we cannot do DMA -OR- if this is a small SPI transfer, then let
@ -1522,7 +1491,9 @@ static void spi_exchange(struct spi_dev_s *dev, const void *txbuffer,
/* Configure the exchange transfers */
paddr = spi_physregaddr(spics, SAM_SPI_RDR_OFFSET);
ret = sam_dmarxsetup(spics->rxdma, paddr, (uint32_t)rxbuffer, nwords);
maddr = sam_physramaddr((uintptr_t)rxbuffer);
ret = sam_dmarxsetup(spics->rxdma, paddr, maddr, nwords);
if (ret < 0)
{
dmadbg("ERROR: sam_dmarxsetup failed: %d\n", ret);
@ -1532,7 +1503,9 @@ static void spi_exchange(struct spi_dev_s *dev, const void *txbuffer,
spi_rxdma_sample(spics, DMA_AFTER_SETUP);
paddr = spi_physregaddr(spics, SAM_SPI_TDR_OFFSET);
ret = sam_dmatxsetup(spics->txdma, paddr, (uint32_t)txbuffer, nwords);
maddr = sam_physramaddr((uintptr_t)txbuffer);
ret = sam_dmatxsetup(spics->txdma, paddr, maddr, nwords);
if (ret < 0)
{
dmadbg("ERROR: sam_dmatxsetup failed: %d\n", ret);