SAMA5: More MMU-related changes to properly initialize SDRAM

This commit is contained in:
Gregory Nutt 2013-08-02 11:11:57 -06:00
parent 894618f894
commit b00d72a7f2
8 changed files with 553 additions and 149 deletions

View File

@ -0,0 +1,205 @@
/****************************************************************************
* arch/arm/src/armv7-a/arm_mmu.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 "cache.h"
#include "mmu.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Private Data
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: mmu_l1_setentry
*
* Description:
* Set a one level 1 translation table entry. Only a single L1 page table
* is supported.
*
* Input Paramters:
* paddr - The physical address to be mapped. Must be aligned to a 1MB
* address boundary
* vaddr - The virtual address to be mapped. Must be aligned to a 1MB
* address boundary
* mmuflags - The MMU flags to use in the mapping.
*
****************************************************************************/
#ifndef CONFIG_ARCH_ROMPGTABLE
void mmu_l1_setentry(uint32_t paddr, uint32_t vaddr, uint32_t mmuflags)
{
uint32_t *l1table = (uint32_t*)PGTABLE_BASE_VADDR;
uint32_t index = vaddr >> 20;
/* Save the page table entry */
l1table[index] = (paddr | mmuflags);
/* Flush the data cache entry. Make sure that the modified contents
* of the page table are flushed into physical memory.
*/
cp15_clean_dcache_bymva((uint32_t)&l1table[index]);
/* Invalidate the TLB cache associated with virtual address range */
mmu_invalidate_region(vaddr, 1024*1024);
}
#endif
/****************************************************************************
* Name: mmu_l2_setentry
*
* Description:
* Set one small (4096B) entry in a level2 translation table.
*
* Input Parameters:
* l2vaddr - the virtual address of the beginning of the L2 translation
* table.
* paddr - The physical address to be mapped. Must be aligned to a 4KB
* address boundary
* vaddr - The virtual address to be mapped. Must be aligned to a 4KB
* address boundary
* mmuflags - The MMU flags to use in the mapping.
*
****************************************************************************/
#ifndef CONFIG_ARCH_ROMPGTABLE
void mmu_l2_setentry(uint32_t l2vaddr, uint32_t paddr, uint32_t vaddr,
uint32_t mmuflags)
{
uint32_t *l2table = (uint32_t*)l2vaddr;
uint32_t index;
/* The table divides a 1Mb address space up into 256 entries, each
* corresponding to 4Kb of address space. The page table index is
* related to the offset from the beginning of 1Mb region.
*/
index = (vaddr & 0x000ff000) >> 12;
/* Save the table entry */
l2table[index] = (paddr | mmuflags);
/* Flush the data cache entry. Make sure that the modified contents
* of the page table are flushed into physical memory.
*/
cp15_clean_dcache_bymva((uint32_t)&l2table[index]);
/* Invalidate the TLB cache associated with virtual address range */
cp15_invalidate_tlb_bymva(vaddr);
}
#endif
/****************************************************************************
* Name: mmu_l2_map_region
*
* Description:
* Set multiple level 1 translation table entries in order to map a
* region of memory.
*
* Input Parameters:
* mapping - Describes the mapping to be performed.
*
****************************************************************************/
#ifndef CONFIG_ARCH_ROMPGTABLE
void mmu_l2_map_region(const struct section_mapping_s *mapping)
{
uint32_t paddr = mapping->physbase;
uint32_t vaddr = mapping->virtbase;
uint32_t mmuflags = mapping->mmuflags;
int i;
/* Loop, writting each mapping into the L1 page table */
for (i = 0; i < mapping->nsections; i++)
{
mmu_l1_setentry(paddr, vaddr, mmuflags);
paddr += SECTION_SIZE;
vaddr += SECTION_SIZE;
}
}
#endif
/****************************************************************************
* Name: mmu_invalidate_region
*
* Description:
* Invalidate TLBs for a range of addresses (all 4KB aligned).
*
* Input Parameters:
* vaddr - The beginning of the region to invalidate.
* size - The size of the region in bytes to be invalidated.
*
****************************************************************************/
#ifndef CONFIG_ARCH_ROMPGTABLE
void mmu_invalidate_region(uint32_t vstart, size_t size)
{
uint32_t vaddr = vstart & 0xfffff000;
uint32_t vend = vaddr + size;
/* Loop, writting each mapping into the L1 page table */
while (vaddr < vend)
{
cp15_invalidate_tlb_bymva(vaddr);
vaddr += 4096;
}
}
#endif

View File

@ -147,14 +147,14 @@
#define CP15_DCCIMVAC(r) _CP15(0, r, c7, c14, 1)
#define CP15_DCCISW(r) _CP15(0, r, c7, c14, 2)
#define CP15_TLBIALLIS(r) _CP15(0, r, c8, c3, 0) /* TLB maintenance operations */
#define CP15_TLBIMVAIS(r) _CP15(0, r, c8, c3, 1)
#define CP15_TLBIASIDIS(r) _CP15(0, r, c8, c3, 2)
#define CP15_TLBIMVAAIS(r) _CP15(0, r, c8, c3, 3)
#define CP15_TLBIALL(r,c) _CP15(0, r, c8, c, 0) /* CRm = c5, c6, or c7 */
#define CP15_TLBIMVA(r,c) _CP15(0, r, c8, c, 1) /* CRm = c5, c6, or c7 */
#define CP15_TLBIASID(r,c) _CP15(0, r, c8, c, 2) /* CRm = c5, c6, or c7 */
#define CP15_TLBIMVAA(r,c) _CP15(0, r, c8, c, 3) /* CRm = c5, c6, or c7 */
#define CP15_TLBIALLIS(r) _CP15(0, r, c8, c3, 0) /* Invalidate entire unified TLB Inner Shareable */
#define CP15_TLBIMVAIS(r) _CP15(0, r, c8, c3, 1) /* Invalidate unified TLB entry by MVA and ASID, Inner Shareable */
#define CP15_TLBIASIDIS(r) _CP15(0, r, c8, c3, 2) /* Invalidate unified TLB by ASID match Inner Shareable */
#define CP15_TLBIMVAAIS(r) _CP15(0, r, c8, c3, 3) /* Invalidate unified TLB entry by MVA all ASID Inner Shareable */
#define CP15_TLBIALL(r,c) _CP15(0, r, c8, c, 0) /* Invalidate entire instruction TLB. CRm = c5, c6, or c7 */
#define CP15_TLBIMVA(r,c) _CP15(0, r, c8, c, 1) /* Invalidate instruction TLB entry by MVA and ASID. CRm = c5, c6, or c7 */
#define CP15_TLBIASID(r,c) _CP15(0, r, c8, c, 2) /* Invalidate data TLB by ASID match. CRm = c5, c6, or c7 */
#define CP15_TLBIMVAA(r,c) _CP15(0, r, c8, c, 3) /* Invalidate unified TLB entry by MVA and ASID. CRm = c5, c6, or c7 */
#define CP15_MCR(r) _CP15(0, r, c9, c12, 0) /* Performance Monitor Control Register */
#define CP15_PMCNTENSET(r) _CP15(0, r, c9, c12, 1) /* Count Enable Set Register */

View File

@ -49,6 +49,14 @@
* Included Files
************************************************************************************/
#include <nuttx/config.h>
#ifndef __ASSEMBLY__
# include <sys/types.h>
# include <stdint.h>
# include "chip.h"
#endif /* __ASSEMBLY__ */
/************************************************************************************
* Pre-processor Definitions
************************************************************************************/
@ -490,7 +498,7 @@
* NMRR[23:22] = 0b11, Region is Write-Back, no Write-Allocate
*/
#define PMD_STRONGLY_ORDER (0)
#define PMD_STRONGLY_ORDERED (0)
#define PMD_DEVICE (PMD_SECT_B)
#define PMD_WRITE_THROUGH (PMD_SECT_C)
#define PMD_WRITE_BACK (PMD_SECT_B | PMD_SECT_C)
@ -511,6 +519,9 @@
PMD_SECT_DOM(0))
#define MMU_IOFLAGS (PMD_TYPE_SECT | PMD_SECT_AP_RW1 | PMD_DEVICE | \
PMD_SECT_DOM(0) | PMD_SECT_XN)
#define MMU_STRONGLY_ORDERED (PMD_TYPE_SECT | PMD_SECT_AP_RW1 | \
PMD_STRONGLY_ORDERED | PMD_SECT_DOM(0) | \
PMD_SECT_XN)
#define MMU_L1_VECTORFLAGS (PMD_TYPE_PTE | PMD_PTE_PXN | PMD_PTE_DOM(0))
#define MMU_L2_VECTORFLAGS (PTE_TYPE_SMALL | PTE_WRITE_THROUGH | PTE_AP_RW1)
@ -787,6 +798,26 @@
#endif /* CONFIG_PAGING */
/************************************************************************************
* Public Types
************************************************************************************/
#ifndef __ASSEMBLY__
/* struct section_mapping_s describes the L1 mapping of a large region of memory
* consisting of one or more 1MB sections (nsections).
*
* All addresses must be aligned to 1MB address boundaries.
*/
struct section_mapping_s
{
uint32_t physbase; /* Physical address of the region to be mapped */
uint32_t virtbase; /* Virtual address of the region to be mapped */
uint32_t mmuflags; /* MMU settings for the region (e.g., cache-able) */
uint32_t nsections; /* Number of mappings in the region */
};
#endif
/************************************************************************************
* Assemby Macros
************************************************************************************/
@ -814,7 +845,12 @@
* Name: cp15_invalidate_tlbs
*
* Description:
* Invalidate TLBs
* Invalidate entire unified TLB
*
* The Invalidate entire TLB operations invalidate all unlocked entries in the
* TLB. The operation ignores the value in the register Rt specified by the MCR
* instruction that performs the operation. Software does not have to write a
* value to the register before issuing the MCR instruction.
*
* Inputs:
* None
@ -825,6 +861,24 @@
mcr p15, 0, \scratch, c8, c7, 0 /* TLBIALL */
.endm
/************************************************************************************
* Name: cp15_invalidate_tlb_bymva
*
* Description:
* Invalidate unified TLB entry by MVA all ASID Inner Shareable
*
* Inputs:
* vaddr - The virtual address to be invalidated
*
************************************************************************************/
.macro cp15_invalidate_tlb_bymva, vaddr
dsb
mcr p15, 0, \vaddr, c8, c3, 3 /* TLBIMVAAIS */
dsb
isb
.endm
/************************************************************************************
* Name: cp15_wrdacr
*
@ -1060,7 +1114,12 @@ static inline void cp15_disable_mmu(void)
* Name: cp15_invalidate_tlbs
*
* Description:
* Invalidate TLBs
* Invalidate entire unified TLB
*
* The Invalidate entire TLB operations invalidate all unlocked entries in the
* TLB. The operation ignores the value in the register Rt specified by the MCR
* instruction that performs the operation. Software does not have to write a
* value to the register before issuing the MCR instruction.
*
* Inputs:
* None
@ -1078,6 +1137,31 @@ static inline void cp15_invalidate_tlbs(void)
);
}
/************************************************************************************
* Name: cp15_invalidate_tlb_bymva
*
* Description:
* Invalidate unified TLB entry by MVA all ASID Inner Shareable
*
* Inputs:
* vaddr - The virtual address to be invalidated
*
************************************************************************************/
static inline void cp15_invalidate_tlb_bymva(uint32_t vaddr)
{
__asm__ __volatile__
(
"\tdsb\n"
"\tmcr p15, 0, %0, c8, c3, 3\n" /* TLBIMVAAIS */
"\tdsb\n"
"\tisb\n"
:
: "r" (vaddr)
: "r1", "memory"
);
}
/************************************************************************************
* Name: cp15_wrdacr
*
@ -1144,6 +1228,61 @@ static inline void cp14_wrttb(unsigned int ttb)
);
}
/*************************************************************************************
* Name: mmu_l1_getentry
*
* Description:
* Given a virtual address, return the valule of the corresponding L1 table entry.
*
* Input Paramters:
* vaddr - The virtual address to be mapped.
*
************************************************************************************/
#ifndef CONFIG_ARCH_ROMPGTABLE
static inline uint32_t mmu_l1_getentry(uint32_t vaddr)
{
uint32_t *l1table = (uint32_t*)PGTABLE_BASE_VADDR;
uint32_t index = vaddr >> 20;
/* Return the address of the page table entry */
return l1table[index];
}
#endif
/*************************************************************************************
* Name: mmu_l2_getentry
*
* Description:
* Given a address of the beginning of an L2 page table and a virtual address,
* return the varlue of the corresponding L2 page table entry.
*
* Input Paramters:
* l2vaddr - The virtual address of the beginning of the L2 page table
* vaddr - The virtual address to be mapped.
*
************************************************************************************/
#ifndef CONFIG_ARCH_ROMPGTABLE
static inline uint32_t mmu_l2_getentry(uint32_t l2vaddr, uint32_t vaddr)
{
uint32_t *l2table = (uint32_t*)l2vaddr;
uint32_t index;
/* The table divides a 1Mb address space up into 256 entries, each
* corresponding to 4Kb of address space. The page table index is
* related to the offset from the beginning of 1Mb region.
*/
index = (vaddr & 0x000ff000) >> 12;
/* Return the address of the page table entry */
return l2table[index];
}
#endif
#endif /* __ASSEMBLY__ */
/************************************************************************************
@ -1162,6 +1301,58 @@ extern "C" {
#define EXTERN extern
#endif
/************************************************************************************
* Name: mmu_l1_setentry
*
* Description:
* Set a one level 1 translation table entry. Only a single L1 page table is
* supported.
*
* Input Paramters:
* paddr - The physical address to be mapped. Must be aligned to a 1MB address
* boundary
* vaddr - The virtual address to be mapped. Must be aligned to a 1MB address
* boundary
* mmuflags - The MMU flags to use in the mapping.
*
************************************************************************************/
#ifndef CONFIG_ARCH_ROMPGTABLE
void mmu_l1_setentry(uint32_t paddr, uint32_t vaddr, uint32_t mmuflags);
#endif
/************************************************************************************
* Name: mmu_l2_map_region
*
* Description:
* Set multiple level 1 translation table entries in order to map a region of
* memory.
*
* Input Parameters:
* mapping - Describes the mapping to be performed.
*
************************************************************************************/
#ifndef CONFIG_ARCH_ROMPGTABLE
void mmu_l2_map_region(const struct section_mapping_s *mapping);
#endif
/****************************************************************************
* Name: mmu_invalidate_region
*
* Description:
* Invalidate TLBs for a range of addresses (all 4KB aligned).
*
* Input Parameters:
* vaddr - The beginning of the region to invalidate.
* size - The size of the region in bytes to be invalidated.
*
****************************************************************************/
#ifndef CONFIG_ARCH_ROMPGTABLE
void mmu_invalidate_region(uint32_t vstart, size_t size);
#endif
#undef EXTERN
#ifdef __cplusplus
}

View File

@ -44,7 +44,7 @@ config SAMA5_WDT
default n
config SAMA5_HSMC
bool "Multi-bit ECC Interrupt (HSMC)"
bool "Static Memory Controller (HSMC)"
default n
config SAMA5_SMD
@ -241,6 +241,7 @@ menu "External Memory Configuration"
config SAMA5_DDRCS
bool "External DDR-SDRAM Memory"
default n
depends on SAMA5_MPDDRC
---help---
Build in support for DDR-SDRAM memory resources.
@ -270,6 +271,7 @@ endif # SAMA5_DDRCS
config SAMA5_EBICS0
bool "External CS0 Memory"
default n
depends on SAMA5_HSMC
---help---
Build in support for memory resources in the chip select 0 (CS0)
memory region.
@ -318,6 +320,7 @@ endif # SAMA5_EBICS0
config SAMA5_EBICS1
bool "External CS1 Memory"
default n
depends on SAMA5_HSMC
---help---
Build in support for memory resources in the chip select 1 (CS1)
memory region.
@ -365,6 +368,7 @@ endif # SAMA5_EBICS1
config SAMA5_EBICS2
bool "External CS2 Memory"
depends on SAMA5_HSMC
default n
---help---
Build in support for memory resources in the chip select 2 (CS2)
@ -414,6 +418,7 @@ endif # SAMA5_EBICS2
config SAMA5_EBICS3
bool "External CS3 Memory"
default n
depends on SAMA5_HSMC
---help---
Build in support for memory resources in the chip select 3 (CS3)
memory region.

View File

@ -62,7 +62,7 @@ CMN_CSRCS += up_mdelay.c up_udelay.c
CMN_CSRCS += up_modifyreg8.c up_modifyreg16.c up_modifyreg32.c
CMN_CSRCS += arm_assert.c arm_blocktask.c arm_copyfullstate.c arm_dataabort.c
CMN_CSRCS += arm_doirq.c arm_initialstate.c arm_prefetchabort.c
CMN_CSRCS += arm_doirq.c arm_initialstate.c arm_mmu.c arm_prefetchabort.c
CMN_CSRCS += arm_releasepending.c arm_reprioritizertr.c
CMN_CSRCS += arm_schedulesigaction.c arm_sigdeliver.c arm_syscall.c
CMN_CSRCS += arm_unblocktask.c arm_undefinedinsn.c

View File

@ -46,6 +46,13 @@
/************************************************************************************
* Pre-processor Definitions
************************************************************************************/
/* Decimal configuration values may exceed 2Gb and, hence, overflow to negative
* values unless we force them to unsigned long:
*/
#define __CONCAT(a,b) a ## b
#define MKULONG(a) __CONCAT(a,ul)
/* Overview:
*
* SAMA5 Physical (unmapped) Memory Map
@ -189,6 +196,14 @@
#define SAM_PERIPHB_SIZE (272*1024) /* 0xf8000000-0xf8043fff: Internal Peripherals */
#define SAM_SYSC_SIZE (1*1024*1024) /* 0xfff00000-0x0ffffedf: Internal Peripherals */
/* Force configured sizes that might exceed 2GB to be unsigned long */
#define SAMA5_EBICS0_SIZE MKULONG(CONFIG_SAMA5_EBICS0_SIZE)
#define SAMA5_DDRCS_SIZE MKULONG(CONFIG_SAMA5_DDRCS_SIZE)
#define SAMA5_EBICS1_SIZE MKULONG(CONFIG_SAMA5_EBICS1_SIZE)
#define SAMA5_EBICS2_SIZE MKULONG(CONFIG_SAMA5_EBICS2_SIZE)
#define SAMA5_EBICS3_SIZE MKULONG(CONFIG_SAMA5_EBICS3_SIZE)
/* Convert size in bytes to number of sections (in Mb). */
#define _NSECTIONS(b) (((b)+0x000fffff) >> 20)
@ -212,11 +227,11 @@
#define SAM_AXIMX_NSECTIONS _NSECTIONS(SAM_AXIMX_SIZE)
#define SAM_DAP_NSECTIONS _NSECTIONS(SAM_DAP_SIZE)
#define SAM_EBICS0_NSECTIONS _NSECTIONS(CONFIG_SAMA5_EBICS0_SIZE)
#define SAM_DDRCS_NSECTIONS _NSECTIONS(CONFIG_SAMA5_DDRCS_SIZE)
#define SAM_EBICS1_NSECTIONS _NSECTIONS(CONFIG_SAMA5_EBICS1_SIZE)
#define SAM_EBICS2_NSECTIONS _NSECTIONS(CONFIG_SAMA5_EBICS2_SIZE)
#define SAM_EBICS3_NSECTIONS _NSECTIONS(CONFIG_SAMA5_EBICS3_SIZE)
#define SAM_EBICS0_NSECTIONS _NSECTIONS(SAMA5_EBICS0_SIZE)
#define SAM_DDRCS_NSECTIONS _NSECTIONS(SAMA5_DDRCS_SIZE)
#define SAM_EBICS1_NSECTIONS _NSECTIONS(SAMA5_EBICS1_SIZE)
#define SAM_EBICS2_NSECTIONS _NSECTIONS(SAMA5_EBICS2_SIZE)
#define SAM_EBICS3_NSECTIONS _NSECTIONS(SAMA5_EBICS3_SIZE)
#define SAM_NFCCR_NSECTIONS _NSECTIONS(SAM_NFCCR_SIZE)
#define SAM_PERIPHA_NSECTIONS _NSECTIONS(SAM_PERIPHA_SIZE)

View File

@ -45,6 +45,7 @@
#include <debug.h>
#include <nuttx/arch.h>
#include <nuttx/kmalloc.h>
#include <nuttx/userspace.h>
#include <arch/board/board.h>
@ -242,11 +243,11 @@ void up_addregion(void)
size_t size;
#ifdef CONFIG_SAMA5_ISRAM_HEAP
#if defined(CONFIG_NUTTX_KERNEL) && defined(CONFIG_MM_KERNEL_HEAP)
size = SAM_ISRAM0_SIZE + SAM_ISRAM1_SIZE;
#if defined(CONFIG_NUTTX_KERNEL) && defined(CONFIG_MM_KERNEL_HEAP)
/* Allow user-mode access to the ISRAM heap */
size = SAM_ISRAM0_SIZE + SAM_ISRAM1_SIZE;
sam_uheap((uintptr_t)SAM_ISRAM0_VADDR, size);
#endif
@ -261,10 +262,11 @@ void up_addregion(void)
#ifdef CONFIG_SAMA5_DDRCS_HEAP
if (nregions > 0)
{
size = SAMA5_DDRCS_SIZE;
#if defined(CONFIG_NUTTX_KERNEL) && defined(CONFIG_MM_KERNEL_HEAP)
/* Allow user-mode access to the ISRAM heap */
size = CONFIG_SAMA5_DDRCS_SIZE;
sam_uheap((uintptr_t)SAM_DDRCS_VSECTION, size);
#endif
@ -285,10 +287,11 @@ void up_addregion(void)
#ifdef SAMA5_EBICS0_HEAP
if (nregions > 0)
{
size = SAMA5_EBICS0_SIZE;
#if defined(CONFIG_NUTTX_KERNEL) && defined(CONFIG_MM_KERNEL_HEAP)
/* Allow user-mode access to the ISRAM heap */
size = CONFIG_SAMA5_EBICS0_SIZE;
sam_uheap((uintptr_t)SAM_EBICS0_VSECTION, size);
#endif
@ -309,10 +312,11 @@ void up_addregion(void)
#ifdef SAMA5_EBICS1_HEAP
if (nregions > 0)
{
size = SAMA5_EBICS1_SIZE;
#if defined(CONFIG_NUTTX_KERNEL) && defined(CONFIG_MM_KERNEL_HEAP)
/* Allow user-mode access to the ISRAM heap */
size = CONFIG_SAMA5_EBICS1_SIZE;
sam_uheap((uintptr_t)SAM_EBICS1_VSECTION, size);
#endif
@ -333,10 +337,11 @@ void up_addregion(void)
#ifdef SAMA5_EBICS2_HEAP
if (nregions > 0)
{
size = SAMA5_EBICS2_SIZE;
#if defined(CONFIG_NUTTX_KERNEL) && defined(CONFIG_MM_KERNEL_HEAP)
/* Allow user-mode access to the ISRAM heap */
size = CONFIG_SAMA5_EBICS2_SIZE;
sam_uheap((uintptr_t)SAM_EBICS2_VSECTION, size);
#endif
@ -357,10 +362,11 @@ void up_addregion(void)
#ifdef SAMA5_EBICS3_HEAP
if (nregions > 0)
{
size = SAMA5_EBICS3_SIZE;
#if defined(CONFIG_NUTTX_KERNEL) && defined(CONFIG_MM_KERNEL_HEAP)
/* Allow user-mode access to the ISRAM heap */
size = CONFIG_SAMA5_EBICS3_SIZE;
sam_uheap((uintptr_t)SAM_EBICS3_VSECTION, size);
#endif

View File

@ -51,7 +51,6 @@
#include "chip.h"
#include "arm.h"
#include "mmu.h"
#include "cache.h"
#include "fpu.h"
#include "up_internal.h"
#include "up_arch.h"
@ -89,14 +88,6 @@
* Private Types
****************************************************************************/
struct section_mapping_s
{
uint32_t physbase; /* Physical address of the region to be mapped */
uint32_t virtbase; /* Virtual address of the region to be mapped */
uint32_t mmuflags; /* MMU settings for the region (e.g., cache-able) */
uint32_t nsections; /* Number of mappings in the region */
};
/****************************************************************************
* Public Variables
****************************************************************************/
@ -142,140 +133,128 @@ static const struct section_mapping_s section_mapping[] =
*/
#if defined(CONFIG_ARCH_LOWVECTORS) && !defined(CONFIG_SAMA5_BOOT_ISRAM)
{ CONFIG_FLASH_VSTART, 0x00000000, MMU_ROMFLAGS, 1},
{ CONFIG_FLASH_VSTART, 0x00000000,
MMU_ROMFLAGS, 1 },
#else
{ SAM_BOOTMEM_PSECTION, SAM_BOOTMEM_VSECTION,
SAM_BOOTMEM_MMUFLAGS, SAM_BOOTMEM_NSECTIONS},
{ SAM_BOOTMEM_PSECTION, SAM_BOOTMEM_VSECTION,
SAM_BOOTMEM_MMUFLAGS, SAM_BOOTMEM_NSECTIONS },
#endif
{ SAM_ROM_PSECTION, SAM_ROM_VSECTION,
SAM_ROM_MMUFLAGS, SAM_ROM_NSECTIONS},
{ SAM_NFCSRAM_PSECTION, SAM_NFCSRAM_VSECTION,
SAM_NFCSRAM_MMUFLAGS, SAM_NFCSRAM_NSECTIONS},
{ SAM_ROM_PSECTION, SAM_ROM_VSECTION,
SAM_ROM_MMUFLAGS, SAM_ROM_NSECTIONS },
{ SAM_NFCSRAM_PSECTION, SAM_NFCSRAM_VSECTION,
SAM_NFCSRAM_MMUFLAGS, SAM_NFCSRAM_NSECTIONS },
#ifndef CONFIG_PAGING /* Internal SRAM is already fully mapped */
{ SAM_ISRAM_PSECTION, SAM_ISRAM_VSECTION,
SAM_ISRAM_MMUFLAGS, SAM_ISRAM_NSECTIONS},
{ SAM_ISRAM_PSECTION, SAM_ISRAM_VSECTION,
SAM_ISRAM_MMUFLAGS, SAM_ISRAM_NSECTIONS },
#endif
{ SAM_SMD_PSECTION, SAM_SMD_VSECTION,
SAM_SMD_MMUFLAGS, SAM_SMD_NSECTIONS},
{ SAM_SMD_PSECTION, SAM_SMD_VSECTION,
SAM_SMD_MMUFLAGS, SAM_SMD_NSECTIONS },
{ SAM_UDPHSRAM_PSECTION, SAM_UDPHSRAM_VSECTION,
SAM_UDPHSRAM_MMUFLAGS, SAM_UDPHSRAM_NSECTIONS},
{ SAM_UHPOHCI_PSECTION, SAM_UHPOHCI_VSECTION,
SAM_UHPOHCI_MMUFLAGS, SAM_UHPOHCI_NSECTIONS},
{ SAM_UHPEHCI_PSECTION, SAM_UHPEHCI_VSECTION,
SAM_UHPEHCI_MMUFLAGS, SAM_UHPEHCI_NSECTIONS},
{ SAM_AXIMX_PSECTION, SAM_AXIMX_VSECTION,
SAM_AXIMX_MMUFLAGS, SAM_AXIMX_NSECTIONS},
{ SAM_DAP_PSECTION, SAM_DAP_VSECTION,
SAM_DAP_MMUFLAGS, SAM_DAP_NSECTIONS},
SAM_UDPHSRAM_MMUFLAGS, SAM_UDPHSRAM_NSECTIONS },
{ SAM_UHPOHCI_PSECTION, SAM_UHPOHCI_VSECTION,
SAM_UHPOHCI_MMUFLAGS, SAM_UHPOHCI_NSECTIONS },
{ SAM_UHPEHCI_PSECTION, SAM_UHPEHCI_VSECTION,
SAM_UHPEHCI_MMUFLAGS, SAM_UHPEHCI_NSECTIONS },
{ SAM_AXIMX_PSECTION, SAM_AXIMX_VSECTION,
SAM_AXIMX_MMUFLAGS, SAM_AXIMX_NSECTIONS },
{ SAM_DAP_PSECTION, SAM_DAP_VSECTION,
SAM_DAP_MMUFLAGS, SAM_DAP_NSECTIONS },
/* SAMA5 External Memories */
/* SAMA5 CS0 External Memories */
#ifdef CONFIG_SAMA5_EBICS0
{ SAM_EBICS0_PSECTION, SAM_EBICS0_VSECTION,
SAM_EBICS0_MMUFLAGS, SAM_EBICS0_NSECTIONS},
SAM_EBICS0_MMUFLAGS, SAM_EBICS0_NSECTIONS },
#endif
/* SAMA5 External SDRAM Memory. The SDRAM is not usable until it has been
* initialized. If we are running out of SDRAM now, we can assume that some
* second level boot loader has properly configured SRAM for us. In that
* case, we set the the MMU flags for the final, fully cache-able state.
*
* If we are running from ISRAM or NOR flash, then we will need to configure
* the SDRAM ourselves. In this case, we set the MMU flags to the strongly
* ordered, non-cacheable state. We need this direct access to SDRAM in
* order to configure it. Once SDRAM has been initialized, it will be re-
* configured in its final state.
*/
#ifdef CONFIG_SAMA5_DDRCS
{ SAM_DDRCS_PSECTION, SAM_DDRCS_VSECTION,
SAM_DDRCS_MMUFLAGS, SAM_DDRCS_NSECTIONS},
#ifdef CONFIG_SAMA5_BOOT_SDRAM
{ SAM_DDRCS_PSECTION, SAM_DDRCS_VSECTION,
MMU_STRONGLY_ORDERED, SAM_DDRCS_NSECTIONS },
#else
{ SAM_DDRCS_PSECTION, SAM_DDRCS_VSECTION,
SAM_DDRCS_MMUFLAGS, SAM_DDRCS_NSECTIONS },
#endif
#endif
/* SAMA5 CS1-3 External Memories */
#ifdef CONFIG_SAMA5_EBICS1
{ SAM_EBICS1_PSECTION, SAM_EBICS1_VSECTION,
SAM_EBICS1_MMUFLAGS, SAM_EBICS1_NSECTIONS},
{ SAM_EBICS1_PSECTION, SAM_EBICS1_VSECTION,
SAM_EBICS1_MMUFLAGS, SAM_EBICS1_NSECTIONS },
#endif
#ifdef CONFIG_SAMA5_EBICS2
{ SAM_EBICS2_PSECTION, SAM_EBICS2_VSECTION,
SAM_EBICS2_MMUFLAGS, SAM_EBICS2_NSECTIONS},
{ SAM_EBICS2_PSECTION, SAM_EBICS2_VSECTION,
SAM_EBICS2_MMUFLAGS, SAM_EBICS2_NSECTIONS },
#endif
#ifdef CONFIG_SAMA5_EBICS3
{ SAM_EBICS3_PSECTION, SAM_EBICS3_VSECTION,
SAM_EBICS3_MMUFLAGS, SAM_EBICS3_NSECTIONS},
{ SAM_EBICS3_PSECTION, SAM_EBICS3_VSECTION,
SAM_EBICS3_MMUFLAGS, SAM_EBICS3_NSECTIONS },
#endif
#ifdef CONFIG_SAMA5_NFCCR
{ SAM_NFCCR_PSECTION, SAM_NFCCR_VSECTION,
SAM_NFCCR_MMUFLAGS, SAM_NFCCR_NSECTIONS},
{ SAM_NFCCR_PSECTION, SAM_NFCCR_VSECTION,
SAM_NFCCR_MMUFLAGS, SAM_NFCCR_NSECTIONS },
#endif
/* SAMA5 Internal Peripherals */
{ SAM_PERIPHA_PSECTION, SAM_PERIPHA_VSECTION,
SAM_PERIPHA_MMUFLAGS, SAM_PERIPHA_NSECTIONS},
SAM_PERIPHA_MMUFLAGS, SAM_PERIPHA_NSECTIONS },
{ SAM_PERIPHB_PSECTION, SAM_PERIPHB_VSECTION,
SAM_PERIPHB_MMUFLAGS, SAM_PERIPHB_NSECTIONS},
{ SAM_SYSC_PSECTION, SAM_SYSC_VSECTION,
SAM_SYSC_MMUFLAGS, SAM_SYSC_NSECTIONS},
SAM_PERIPHB_MMUFLAGS, SAM_PERIPHB_NSECTIONS },
{ SAM_SYSC_PSECTION, SAM_SYSC_VSECTION,
SAM_SYSC_MMUFLAGS, SAM_SYSC_NSECTIONS },
};
#define NMAPPINGS (sizeof(section_mapping) / sizeof(struct section_mapping_s))
#endif
/* SAMA5 External SDRAM Memory. Final configuration. The SDRAM was
* configured in a temporary state to support low-level ininitialization.
* After the SDRAM has been fully initialized, this structure is used to
* set the SDRM in its final, fully cache-able state.
*/
#if defined(CONFIG_SAMA5_DDRCS) && !defined(CONFIG_SAMA5_BOOT_SDRAM)
static const struct section_mapping_s operational_mapping =
{
SAM_DDRCS_PSECTION, SAM_DDRCS_VSECTION,
SAM_DDRCS_MMUFLAGS, SAM_DDRCS_NSECTIONS
};
#endif
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: sam_setl1entry
*
* Description:
* Set a level 1 translation table entry.
*
****************************************************************************/
#ifndef CONFIG_ARCH_ROMPGTABLE
static inline void sam_setl1entry(uint32_t paddr, uint32_t vaddr,
uint32_t mmuflags)
{
uint32_t *pgtable = (uint32_t*)PGTABLE_BASE_VADDR;
uint32_t index = vaddr >> 20;
/* Save the page table entry */
pgtable[index] = (paddr | mmuflags);
}
#endif
/****************************************************************************
* Name: sam_setl2smallentry
****************************************************************************/
static inline void sam_setl2smallentry(uint32_t ctabvaddr, uint32_t paddr,
uint32_t vaddr, uint32_t mmuflags)
{
uint32_t *ctable = (uint32_t*)ctabvaddr;
uint32_t index;
/* The table divides a 1Mb address space up into 256 entries, each
* corresponding to 4Kb of address space. The page table index is
* related to the offset from the beginning of 1Mb region.
*/
index = (vaddr & 0x000ff000) >> 12;
/* Save the table entry */
ctable[index] = (paddr | mmuflags);
}
/****************************************************************************
* Name: sam_setupmappings
*
* Description
* Map all of the memory regions defined in section_mapping[]
*
****************************************************************************/
#ifndef CONFIG_ARCH_ROMPGTABLE
static void sam_setupmappings(void)
static inline void sam_setupmappings(void)
{
int i, j;
int i;
for (i = 0; i < NMAPPINGS; i++)
{
uint32_t sect_paddr = section_mapping[i].physbase;
uint32_t sect_vaddr = section_mapping[i].virtbase;
uint32_t mmuflags = section_mapping[i].mmuflags;
for (j = 0; j < section_mapping[i].nsections; j++)
{
sam_setl1entry(sect_paddr, sect_vaddr, mmuflags);
sect_paddr += SECTION_SIZE;
sect_vaddr += SECTION_SIZE;
}
mmu_l2_map_region(&section_mapping[i]);
}
}
#endif
@ -290,16 +269,17 @@ static void sam_setupmappings(void)
#if !defined(CONFIG_ARCH_ROMPGTABLE) && defined(CONFIG_ARCH_LOWVECTORS) && \
defined(CONFIG_PAGING)
static void sam_vectorpermissions(uint32_t mmuflags)
static void sam_vectorpermissions(uint32_t mmuflags)
{
/* The PTE for the beginning of ISRAM is at the base of the L2 page table */
uint32_t *ptr = (uint32_t*)PG_L2_VECT_VADDR;
uint32_t pte;
uint32_t pte = mmu_l2_getentry(PG_L2_VECT_VADDR, 0);
/* The pte might be zero the first time this function is called. */
/* String the MMU flags from the page table entry.
*
* The pte might be zero the first time this function is called.
*/
pte = *ptr;
if (pte == 0)
{
pte = PG_VECT_PBASE;
@ -309,13 +289,9 @@ static void sam_vectorpermissions(uint32_t mmuflags)
pte &= PG_L1_PADDRMASK;
}
/* Update the MMU flags and save */
/* Update the page table entry with the MMU flags and save */
*ptr = pte | mmuflags;
/* Invalid the TLB for this address */
tlb_invalidate_single(PG_L2_VECT_VADDR);
mmu_l2_setentry(PG_L2_VECT_VADDR, pte, 0, mmuflags);
}
#endif
@ -352,17 +328,17 @@ static void sam_vectormapping(void)
while (vector_paddr < end_paddr)
{
sam_setl2smallentry(VECTOR_L2_VBASE, vector_paddr, vector_vaddr,
MMU_L2_VECTORFLAGS);
mmu_l2_setentry(VECTOR_L2_VBASE, vector_paddr, vector_vaddr,
MMU_L2_VECTORFLAGS);
vector_paddr += 4096;
vector_vaddr += 4096;
}
/* Now set the level 1 descriptor to refer to the level 2 page table. */
sam_setl1entry(VECTOR_L2_PBASE & PMD_PTE_PADDR_MASK,
SAM_VECTOR_VADDR & PMD_PTE_PADDR_MASK,
MMU_L1_VECTORFLAGS);
mmu_l1_setentry(VECTOR_L2_PBASE & PMD_PTE_PADDR_MASK,
SAM_VECTOR_VADDR & PMD_PTE_PADDR_MASK,
MMU_L1_VECTORFLAGS);
}
#else
/* No vector remap */
@ -527,13 +503,6 @@ void up_boot(void)
sam_vectormapping();
/* The SRAM address hold the the page table is probably buffered. Make sure
* that the modified contents of the page table are flushed into physical
* memory.
*/
cp15_clean_dcache(PGTABLE_BASE_VADDR, PGTABLE_BASE_VADDR + PGTABLE_SIZE);
#endif /* CONFIG_ARCH_ROMPGTABLE */
/* Setup up vector block. _vector_start and _vector_end are exported from
@ -578,7 +547,20 @@ void up_boot(void)
sam_userspace();
#endif
/* Perform board-specific initialization */
/* Perform board-specific initialization, This must include:
*
* - Initialization of board-specific memory resources (e.g., SDRAM)
* - Configuration of board specific resources (GPIOs, LEDs, etc).
*/
sam_boardinitialize();
/* SDRAM was configured in a temporary state to support low-level
* ininitialization. Now that the SDRAM has been fully initialized,
* we can reconfigure the SDRAM in its final, fully cache-able state.
*/
#if defined(CONFIG_SAMA5_DDRCS) && !defined(CONFIG_SAMA5_BOOT_SDRAM)
mmu_l2_map_region(&operational_mapping);
#endif
}