forked from xuos/xiuos
add part of bsp for sabre lite board
This commit is contained in:
@@ -118,12 +118,12 @@ static int32_t FreeHwIrq(uint32_t irq_num)
|
||||
*
|
||||
* @return 0 on success; -1 on failure
|
||||
*/
|
||||
static int32_t EnableHwIrq(uint32_t irq_num)
|
||||
static int32_t EnableHwIrq(uint32_t irq_num, uint32_t cpu_id)
|
||||
{
|
||||
if (irq_num >= ARCH_MAX_IRQ_NUM )
|
||||
return -1;
|
||||
|
||||
return ArchEnableHwIrq(irq_num);
|
||||
return ArchEnableHwIrq(irq_num, cpu_id);
|
||||
}
|
||||
/**
|
||||
* This function will disable a irq.
|
||||
@@ -133,12 +133,12 @@ static int32_t EnableHwIrq(uint32_t irq_num)
|
||||
* @return 0 on success; -1 on failure
|
||||
*/
|
||||
|
||||
static int32_t DisableHwIrq(uint32_t irq_num)
|
||||
static int32_t DisableHwIrq(uint32_t irq_num, uint32_t cpu_id)
|
||||
{
|
||||
if (irq_num >= ARCH_MAX_IRQ_NUM )
|
||||
return -1;
|
||||
|
||||
return ArchDisableHwIrq(irq_num);
|
||||
return ArchDisableHwIrq(irq_num, cpu_id);
|
||||
}
|
||||
|
||||
/* called from arch-specific ISR wrapper */
|
||||
|
||||
@@ -55,8 +55,8 @@ struct IsrDone
|
||||
bool (*isInIsr)();
|
||||
int32_t (*registerIrq)(uint32_t irq_num, IsrHandlerType handler, void *arg);
|
||||
int32_t (*freeIrq)(uint32_t irq_num);
|
||||
int32_t (*enableIrq)(uint32_t irq_num);
|
||||
int32_t (*disableIrq)(uint32_t irq_num);
|
||||
int32_t (*enableIrq)(uint32_t irq_num, uint32_t cpu_id);
|
||||
int32_t (*disableIrq)(uint32_t irq_num, uint32_t cpu_id);
|
||||
void (*handleIrq)(uint32_t irq_num);
|
||||
uint16_t (*getCounter)() ;
|
||||
void (*incCounter)();
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
SRC_FILES := boot.S cache.S exception.S cortexA9.S gic.c interrupt.c
|
||||
SRC_FILES := boot.S cache.S exception.S cortexA9.S gic.c interrupt.c mmu.c ccm_pll.c
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
||||
|
||||
@@ -19,8 +19,8 @@
|
||||
|
||||
#define ARCH_MAX_IRQ_NUM PLATFORM_MAX_IRQ_NR
|
||||
|
||||
int32_t ArchEnableHwIrq(uint32_t irq_num);
|
||||
int32_t ArchDisableHwIrq(uint32_t irq_num);
|
||||
int32_t ArchEnableHwIrq(uint32_t irq_num, uint32_t cpu_id);
|
||||
int32_t ArchDisableHwIrq(uint32_t irq_num, uint32_t cpu_id);
|
||||
|
||||
//! @brief
|
||||
typedef enum {
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright (c) 2012, Freescale Semiconductor, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o 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.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. 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 HOLDER 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.
|
||||
*/
|
||||
|
||||
//! @addtogroup cortexa9
|
||||
//! @{
|
||||
|
||||
/*!
|
||||
* @file arm_cp_registers.h
|
||||
* @brief Definitions for ARM coprocessor registers.
|
||||
*/
|
||||
|
||||
#ifndef __ARM_CP_REGISTERS_H__
|
||||
#define __ARM_CP_REGISTERS_H__
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Definitions
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//! @name ACTLR
|
||||
//@{
|
||||
#define BM_ACTLR_SMP (1 << 6)
|
||||
//@}
|
||||
|
||||
//! @name DFSR
|
||||
//@{
|
||||
#define BM_DFSR_WNR (1 << 11) //!< Write not Read bit. 0=read, 1=write.
|
||||
#define BM_DFSR_FS4 (0x400) //!< Fault status bit 4..
|
||||
#define BP_DFSR_FS4 (10) //!< Bit position for FS[4].
|
||||
#define BM_DFSR_FS (0xf) //!< Fault status bits [3:0].
|
||||
//@}
|
||||
|
||||
//! @name SCTLR
|
||||
//@{
|
||||
#define BM_SCTLR_TE (1 << 30) //!< Thumb exception enable.
|
||||
#define BM_SCTLR_AFE (1 << 29) //!< Access flag enable.
|
||||
#define BM_SCTLR_TRE (1 << 28) //!< TEX remap enable.
|
||||
#define BM_SCTLR_NMFI (1 << 27) //!< Non-maskable FIQ support.
|
||||
#define BM_SCTLR_EE (1 << 25) //!< Exception endianess.
|
||||
#define BM_SCTLR_VE (1 << 24) //!< Interrupt vectors enable.
|
||||
#define BM_SCTLR_FI (1 << 21) //!< Fast interrupt configurable enable.
|
||||
#define BM_SCTLR_RR (1 << 14) //!< Round Robin
|
||||
#define BM_SCTLR_V (1 << 13) //!< Vectors
|
||||
#define BM_SCTLR_I (1 << 12) //!< Instruction cache enable
|
||||
#define BM_SCTLR_Z (1 << 11) //!< Branch prediction enable
|
||||
#define BM_SCTLR_SW (1 << 10) //!< SWP and SWPB enable
|
||||
#define BM_SCTLR_CP15BEN (1 << 5) //!< CP15 barrier enable
|
||||
#define BM_SCTLR_C (1 << 2) //!< Data cache enable
|
||||
#define BM_SCTLR_A (1 << 1) //!< Alignment check enable
|
||||
#define BM_SCTLR_M (1 << 0) //!< MMU enable
|
||||
//@}
|
||||
|
||||
//! @}
|
||||
|
||||
#endif // __ARM_CP_REGISTERS_H__
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// EOF
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
.section ".startup","ax"
|
||||
.globl _reset
|
||||
|
||||
.extern init
|
||||
_reset:
|
||||
|
||||
/* set the cpu to SVC32 mode and disable interrupt */
|
||||
@@ -22,6 +22,11 @@ _reset:
|
||||
|
||||
ldr r0, =stack_top
|
||||
|
||||
@ get cpu id, and subtract the offset from the stacks base address
|
||||
mrc p15,0,r2,c0,c0,5 @ read multiprocessor affinity register
|
||||
and r2, r2, #3 @ mask off, leaving CPU ID field
|
||||
mov r5, r2 @ save cpu id for later
|
||||
|
||||
@ Set the startup stack for svc
|
||||
mov sp, r0
|
||||
|
||||
@@ -86,7 +91,7 @@ ctor_loop:
|
||||
b ctor_loop
|
||||
ctor_end:
|
||||
|
||||
bl start_kernel
|
||||
bl init
|
||||
|
||||
_loop_here:
|
||||
b _loop_here
|
||||
442
Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/ccm_pll.c
Executable file
442
Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/ccm_pll.c
Executable file
@@ -0,0 +1,442 @@
|
||||
/*
|
||||
* Copyright (c) 2011-2012, Freescale Semiconductor, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o 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.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. 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 HOLDER 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.
|
||||
*/
|
||||
|
||||
#include "sdk.h"
|
||||
#include "registers/regsccm.h"
|
||||
#include "registers/regsccmanalog.h"
|
||||
#include "registers/regsgpc.h"
|
||||
#include "registers/regsiomuxc.h"
|
||||
#include "registers/regsuart.h"
|
||||
#include "registers/regsssi.h"
|
||||
#include "registers/regsepit.h"
|
||||
#include "registers/regsgpt.h"
|
||||
#include "registers/regsi2c.h"
|
||||
#include "registers/regsspdif.h"
|
||||
#include "registers/regsspba.h"
|
||||
#include "registers/regssdmaarm.h"
|
||||
#include "registers/regsecspi.h"
|
||||
|
||||
#if defined(CHIP_MX6DQ)
|
||||
#include "registers/regssata.h"
|
||||
#endif
|
||||
|
||||
#if !defined(CHIP_MX6SL)
|
||||
#include "registers/regsgpmi.h"
|
||||
#include "registers/regsesai.h"
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Variables
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
const uint32_t PLL1_OUTPUT = 792000000;
|
||||
const uint32_t PLL2_OUTPUT[] = { 528000000, 396000000, 352000000, 198000000, 594000000 };
|
||||
const uint32_t PLL3_OUTPUT[] = { 480000000, 720000000, 540000000, 508235294, 454736842 };
|
||||
const uint32_t PLL4_OUTPUT = 650000000;
|
||||
const uint32_t PLL5_OUTPUT = 650000000;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Code
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void ccm_init(void)
|
||||
{
|
||||
// ETHNET
|
||||
HW_CCM_ANALOG_PLL_ENET_CLR(BM_CCM_ANALOG_PLL_ENET_POWERDOWN);
|
||||
HW_CCM_ANALOG_PLL_ENET_SET(BM_CCM_ANALOG_PLL_ENET_ENABLE);
|
||||
HW_CCM_ANALOG_PLL_ENET_CLR(BM_CCM_ANALOG_PLL_ENET_BYPASS);
|
||||
#if !defined (CHIP_MX6SL)
|
||||
HW_CCM_ANALOG_PLL_ENET.B.DIV_SELECT = 0x3;
|
||||
#else
|
||||
HW_CCM_ANALOG_PLL_ENET.B.DIV_SELECT = 0x1;
|
||||
#endif
|
||||
|
||||
// Ungate clocks that are not enabled in a driver - need to be updated
|
||||
HW_CCM_CCGR0_WR(0xffffffff);
|
||||
HW_CCM_CCGR1_WR(0xFFCF0FFF); // EPIT, ESAI, GPT enabled by driver
|
||||
HW_CCM_CCGR2_WR(0xFFFFF03F); // I2C enabled by driver
|
||||
HW_CCM_CCGR3_WR(0xffffffff);
|
||||
HW_CCM_CCGR4_WR(0x00FFFF03); // GPMI, Perfmon enabled by driver
|
||||
HW_CCM_CCGR5_WR(0xF0FFFFCF); // UART, SATA enabled by driver
|
||||
HW_CCM_CCGR6_WR(0xffffffff);
|
||||
|
||||
/*
|
||||
* Keep default settings at reset.
|
||||
* pre_periph_clk_sel is by default at 0, so the selected output
|
||||
* of PLL2 is the main output at 528MHz.
|
||||
* => by default, ahb_podf divides by 4 => AHB_CLK@132MHz.
|
||||
* => by default, ipg_podf divides by 2 => IPG_CLK@66MHz.
|
||||
*/
|
||||
HW_CCM_CBCDR.U = BF_CCM_CBCDR_AHB_PODF(3)
|
||||
#if !defined (CHIP_MX6SL)
|
||||
| BF_CCM_CBCDR_AXI_PODF(1)
|
||||
#endif
|
||||
| BF_CCM_CBCDR_IPG_PODF(1);
|
||||
|
||||
/*
|
||||
* UART clock tree: PLL3 (480MHz) div-by-6: 80MHz
|
||||
* 80MHz uart_clk_podf (div-by-1) = 80MHz (UART module clock input)
|
||||
*/
|
||||
// writel(readl(CCM_CSCDR1) & 0x0000003F, CCM_CSCDR1);
|
||||
// HW_CCM_CSCDR1.U =
|
||||
|
||||
/* Mask all interrupt sources that could wake up the processor when in
|
||||
a low power mode. A source is individually masked/unmasked when the
|
||||
interrupt is enabled/disabled by the GIC/interrupt driver. */
|
||||
HW_GPC_IMR1_WR(0xFFFFFFFF);
|
||||
HW_GPC_IMR2_WR(0xFFFFFFFF);
|
||||
HW_GPC_IMR3_WR(0xFFFFFFFF);
|
||||
HW_GPC_IMR4_WR(0xFFFFFFFF);
|
||||
}
|
||||
|
||||
uint32_t get_main_clock(main_clocks_t clock)
|
||||
{
|
||||
uint32_t ret_val = 0;
|
||||
uint32_t pre_periph_clk_sel = HW_CCM_CBCMR.B.PRE_PERIPH_CLK_SEL;
|
||||
|
||||
switch (clock) {
|
||||
case CPU_CLK:
|
||||
ret_val = PLL1_OUTPUT;
|
||||
break;
|
||||
#if !defined (CHIP_MX6SL)
|
||||
case AXI_CLK:
|
||||
ret_val = PLL2_OUTPUT[pre_periph_clk_sel] / (HW_CCM_CBCDR.B.AXI_PODF + 1);
|
||||
break;
|
||||
case MMDC_CH0_AXI_CLK:
|
||||
ret_val = PLL2_OUTPUT[pre_periph_clk_sel] / (HW_CCM_CBCDR.B.MMDC_CH0_AXI_PODF + 1);
|
||||
break;
|
||||
#endif
|
||||
case AHB_CLK:
|
||||
ret_val = PLL2_OUTPUT[pre_periph_clk_sel] / (HW_CCM_CBCDR.B.AHB_PODF + 1);
|
||||
break;
|
||||
case IPG_CLK:
|
||||
ret_val =
|
||||
PLL2_OUTPUT[pre_periph_clk_sel] / (HW_CCM_CBCDR.B.AHB_PODF +
|
||||
1) / (HW_CCM_CBCDR.B.IPG_PODF + 1);
|
||||
break;
|
||||
case IPG_PER_CLK:
|
||||
ret_val =
|
||||
PLL2_OUTPUT[pre_periph_clk_sel] / (HW_CCM_CBCDR.B.AHB_PODF +
|
||||
1) / (HW_CCM_CBCDR.B.IPG_PODF +
|
||||
1) / (HW_CCM_CSCMR1.B.PERCLK_PODF + 1);
|
||||
break;
|
||||
#if !defined (CHIP_MX6SL)
|
||||
case MMDC_CH1_AXI_CLK:
|
||||
ret_val = PLL2_OUTPUT[pre_periph_clk_sel] / (HW_CCM_CBCDR.B.MMDC_CH1_AXI_PODF + 1);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
uint32_t get_peri_clock(peri_clocks_t clock)
|
||||
{
|
||||
uint32_t ret_val = 0;
|
||||
|
||||
switch (clock)
|
||||
{
|
||||
case UART1_MODULE_CLK:
|
||||
case UART2_MODULE_CLK:
|
||||
case UART3_MODULE_CLK:
|
||||
case UART4_MODULE_CLK:
|
||||
// UART source clock is a fixed PLL3 / 6
|
||||
ret_val = PLL3_OUTPUT[0] / 6 / (HW_CCM_CSCDR1.B.UART_CLK_PODF + 1);
|
||||
break;
|
||||
|
||||
// eCSPI clock:
|
||||
// PLL3(480) -> /8 -> CSCDR2[ECSPI_CLK_PODF]
|
||||
case SPI_CLK:
|
||||
ret_val = PLL3_OUTPUT[0] / 8 / (HW_CCM_CSCDR2.B.ECSPI_CLK_PODF + 1);
|
||||
break;
|
||||
|
||||
#if !defined (CHIP_MX6SL)
|
||||
case RAWNAND_CLK:
|
||||
ret_val =
|
||||
PLL3_OUTPUT[0] / (HW_CCM_CS2CDR.B.ENFC_CLK_PRED + 1) / (HW_CCM_CS2CDR.B.ENFC_CLK_PODF +
|
||||
1);
|
||||
break;
|
||||
|
||||
case CAN_CLK:
|
||||
// For i.mx6dq/sdl CAN source clock is a fixed PLL3 / 8
|
||||
ret_val = PLL3_OUTPUT[0] / 8 / (HW_CCM_CSCMR2.B.CAN_CLK_PODF + 1);
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Set/unset clock gating for a peripheral.
|
||||
* @param ccm_ccgrx Address of the clock gating register: CCM_CCGR1,...
|
||||
* @param cgx_offset Offset of the clock gating field: CG(x).
|
||||
* @param gating_mode Clock gating mode: CLOCK_ON or CLOCK_OFF.
|
||||
*/
|
||||
void ccm_ccgr_config(uint32_t ccm_ccgrx, uint32_t cgx_offset, uint32_t gating_mode)
|
||||
{
|
||||
if (gating_mode == CLOCK_ON)
|
||||
{
|
||||
*(volatile uint32_t *)(ccm_ccgrx) |= cgx_offset;
|
||||
}
|
||||
else
|
||||
{
|
||||
*(volatile uint32_t *)(ccm_ccgrx) &= ~cgx_offset;
|
||||
}
|
||||
}
|
||||
|
||||
void clock_gating_config(uint32_t base_address, uint32_t gating_mode)
|
||||
{
|
||||
uint32_t ccm_ccgrx = 0;
|
||||
uint32_t cgx_offset = 0;
|
||||
|
||||
switch (base_address)
|
||||
{
|
||||
case REGS_UART1_BASE:
|
||||
case REGS_UART2_BASE:
|
||||
case REGS_UART3_BASE:
|
||||
case REGS_UART4_BASE:
|
||||
case REGS_UART5_BASE:
|
||||
ccm_ccgrx = HW_CCM_CCGR5_ADDR;
|
||||
cgx_offset = CG(13) | CG(12);
|
||||
break;
|
||||
case REGS_SSI3_BASE:
|
||||
ccm_ccgrx = HW_CCM_CCGR5_ADDR;
|
||||
cgx_offset = CG(11);
|
||||
break;
|
||||
case REGS_SSI2_BASE:
|
||||
ccm_ccgrx = HW_CCM_CCGR5_ADDR;
|
||||
cgx_offset = CG(10);
|
||||
break;
|
||||
case REGS_SSI1_BASE:
|
||||
ccm_ccgrx = HW_CCM_CCGR5_ADDR;
|
||||
cgx_offset = CG(9);
|
||||
break;
|
||||
case REGS_SPDIF_BASE:
|
||||
ccm_ccgrx = HW_CCM_CCGR5_ADDR;
|
||||
cgx_offset = CG(7);
|
||||
break;
|
||||
case REGS_SPBA_BASE:
|
||||
ccm_ccgrx = HW_CCM_CCGR5_ADDR;
|
||||
cgx_offset = CG(6);
|
||||
break;
|
||||
case REGS_SDMAARM_BASE:
|
||||
ccm_ccgrx = HW_CCM_CCGR5_ADDR;
|
||||
cgx_offset = CG(3);
|
||||
break;
|
||||
#if CHIP_MX6DQ
|
||||
case REGS_SATA_BASE:
|
||||
ccm_ccgrx = HW_CCM_CCGR5_ADDR;
|
||||
cgx_offset = CG(2);
|
||||
break;
|
||||
#endif // CHIP_MX6DQ
|
||||
case REGS_EPIT1_BASE:
|
||||
ccm_ccgrx = HW_CCM_CCGR1_ADDR;
|
||||
cgx_offset = CG(6);
|
||||
break;
|
||||
case REGS_EPIT2_BASE:
|
||||
ccm_ccgrx = HW_CCM_CCGR1_ADDR;
|
||||
cgx_offset = CG(7);
|
||||
break;
|
||||
case REGS_GPT_BASE:
|
||||
ccm_ccgrx = HW_CCM_CCGR1_ADDR;
|
||||
cgx_offset = CG(10);
|
||||
break;
|
||||
case REGS_I2C1_BASE:
|
||||
ccm_ccgrx = HW_CCM_CCGR2_ADDR;
|
||||
cgx_offset = CG(3);
|
||||
break;
|
||||
case REGS_I2C2_BASE:
|
||||
ccm_ccgrx = HW_CCM_CCGR2_ADDR;
|
||||
cgx_offset = CG(4);
|
||||
break;
|
||||
case REGS_I2C3_BASE:
|
||||
ccm_ccgrx = HW_CCM_CCGR2_ADDR;
|
||||
cgx_offset = CG(5);
|
||||
break;
|
||||
case REGS_ECSPI1_BASE:
|
||||
ccm_ccgrx = HW_CCM_CCGR1_ADDR;
|
||||
cgx_offset = CG(0);
|
||||
break;
|
||||
case REGS_ECSPI2_BASE:
|
||||
ccm_ccgrx = HW_CCM_CCGR1_ADDR;
|
||||
cgx_offset = CG(1);
|
||||
break;
|
||||
case REGS_ECSPI3_BASE:
|
||||
ccm_ccgrx = HW_CCM_CCGR1_ADDR;
|
||||
cgx_offset = CG(2);
|
||||
break;
|
||||
case REGS_ECSPI4_BASE:
|
||||
ccm_ccgrx = HW_CCM_CCGR1_ADDR;
|
||||
cgx_offset = CG(3);
|
||||
break;
|
||||
#if CHIP_MX6DQ
|
||||
case REGS_ECSPI5_BASE:
|
||||
ccm_ccgrx = HW_CCM_CCGR1_ADDR;
|
||||
cgx_offset = CG(4);
|
||||
break;
|
||||
#endif // CHIP_MX6DQ
|
||||
#if !defined (CHIP_MX6SL)
|
||||
case REGS_GPMI_BASE:
|
||||
ccm_ccgrx = HW_CCM_CCGR4_ADDR;
|
||||
cgx_offset = CG(15) | CG(14) | CG(13) | CG(12);
|
||||
break;
|
||||
case REGS_ESAI_BASE:
|
||||
ccm_ccgrx = HW_CCM_CCGR1_ADDR;
|
||||
cgx_offset = CG(8);
|
||||
break;
|
||||
case CAAM_BASE_ADDR:
|
||||
ccm_ccgrx = HW_CCM_CCGR0_ADDR;
|
||||
cgx_offset = CG(6) | CG(5) | CG(4);
|
||||
break;
|
||||
#endif // !defined (CHIP_MX6SL)
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// apply changes only if a valid address was found
|
||||
if (ccm_ccgrx != 0)
|
||||
{
|
||||
ccm_ccgr_config(ccm_ccgrx, cgx_offset, gating_mode);
|
||||
}
|
||||
}
|
||||
|
||||
void ccm_set_lpm_wakeup_source(uint32_t irq_id, bool doEnable)
|
||||
{
|
||||
uint32_t reg_offset = 0;
|
||||
uint32_t bit_offset = 0;
|
||||
uint32_t gpc_imr = 0;
|
||||
|
||||
// calculate the offset of the register handling that interrupt ID
|
||||
// ID starts at 32, so for instance ID=89 is handled by IMR2 because
|
||||
// the integer part of the division is reg_offset = 2
|
||||
reg_offset = (irq_id / 32);
|
||||
// and the rest of the previous division is used to calculate the bit
|
||||
// offset in the register, so for ID=89 this is bit_offset = 25
|
||||
bit_offset = irq_id - 32 * reg_offset;
|
||||
|
||||
// get the current value of the corresponding GPC_IMRx register
|
||||
gpc_imr = readl(HW_GPC_IMR1_ADDR + (reg_offset - 1) * 4);
|
||||
|
||||
if (doEnable) {
|
||||
// clear the corresponding bit to unmask the interrupt source
|
||||
gpc_imr &= ~(1 << bit_offset);
|
||||
// write the new mask
|
||||
writel(gpc_imr, HW_GPC_IMR1_ADDR + (reg_offset - 1) * 4);
|
||||
} else {
|
||||
// set the corresponding bit to mask the interrupt source
|
||||
gpc_imr |= (1 << bit_offset);
|
||||
// write the new mask
|
||||
writel(gpc_imr, HW_GPC_IMR1_ADDR + (reg_offset - 1) * 4);
|
||||
}
|
||||
}
|
||||
|
||||
void ccm_enter_low_power(lp_modes_t lp_mode)
|
||||
{
|
||||
uint32_t ccm_clpcr = 0;
|
||||
|
||||
// if MMDC channel 1 is not used, the handshake must be masked
|
||||
// set disable core clock in wait - set disable oscillator in stop
|
||||
ccm_clpcr =
|
||||
#if !defined (CHIP_MX6SL)
|
||||
BM_CCM_CLPCR_BYPASS_MMDC_CH1_LPM_HS |
|
||||
#endif
|
||||
BM_CCM_CLPCR_SBYOS | BM_CCM_CLPCR_ARM_CLK_DIS_ON_LPM | lp_mode;
|
||||
|
||||
if (lp_mode == STOP_MODE) {
|
||||
// enable peripherals well-biased
|
||||
ccm_clpcr |= BM_CCM_CLPCR_WB_PER_AT_LPM;
|
||||
}
|
||||
|
||||
HW_CCM_CLPCR_WR(ccm_clpcr);
|
||||
|
||||
__asm(
|
||||
// data synchronization barrier (caches, TLB maintenance, ...)
|
||||
"dsb;"
|
||||
// wait for interrupt instruction
|
||||
"wfi;"
|
||||
// instruction synchronization barrier (flush the pipe-line)
|
||||
"isb;");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
#if !defined (CHIP_MX6SL)
|
||||
/*!
|
||||
* @brief Configure ipu 1 and 2 hsp clk to default 264MHz
|
||||
*
|
||||
* ipu_hsp_clk is derived from mmdc_ch0 divided by 2.
|
||||
*/
|
||||
void ipu_hsp_clk_config(void)
|
||||
{
|
||||
// clk_sel from mmdc_ch0, podf=1
|
||||
HW_CCM_CSCDR3_WR(BF_CCM_CSCDR3_IPU1_HSP_CLK_SEL(0)
|
||||
| BF_CCM_CSCDR3_IPU1_HSP_PODF(1)
|
||||
#if CHIP_MX6DQ
|
||||
| BF_CCM_CSCDR3_IPU2_HSP_CLK_SEL(0)
|
||||
| BF_CCM_CSCDR3_IPU2_HSP_PODF(1)
|
||||
#endif // CHIP_MX6DQ
|
||||
);
|
||||
}
|
||||
|
||||
void gpu_clock_config(void)
|
||||
{
|
||||
HW_CCM_ANALOG_PLL_VIDEO_NUM_WR(0xFF0D6C3);
|
||||
HW_CCM_ANALOG_PLL_VIDEO_WR(BF_CCM_ANALOG_PLL_VIDEO_DIV_SELECT(2) |
|
||||
BF_CCM_ANALOG_PLL_VIDEO_ENABLE(1) |
|
||||
BF_CCM_ANALOG_PLL_VIDEO_BYPASS(1));
|
||||
while (!HW_CCM_ANALOG_PLL_VIDEO.B.LOCK) ; //waiting for PLL lock
|
||||
BF_CLR(CCM_ANALOG_PLL_VIDEO, BYPASS);
|
||||
|
||||
//ldb_di0_clk select PLL5
|
||||
HW_CCM_CS2CDR.B.LDB_DI0_CLK_SEL = 0; // PLL5
|
||||
|
||||
HW_IOMUXC_GPR3.B.LVDS1_MUX_CTL = 0; // LVDS1 source is IPU1 DI0 port
|
||||
HW_IOMUXC_GPR3.B.LVDS0_MUX_CTL = 2; // LVDS0 source is IPU2 DI0 port
|
||||
|
||||
HW_CCM_CHSCCDR.B.IPU1_DI0_CLK_SEL = 3; // derive clock from ldb_di0_clk
|
||||
HW_CCM_CSCMR2_SET(BM_CCM_CSCMR2_LDB_DI0_IPU_DIV | BM_CCM_CSCMR2_LDB_DI1_IPU_DIV); // ldb_di0 divided by 3.5
|
||||
|
||||
#if CHIP_MX6DQ
|
||||
HW_CCM_CSCDR2.B.IPU2_DI0_CLK_SEL = 3; // derive clock from ldb_di0_clk
|
||||
HW_CCM_CSCDR2.B.IPU2_DI1_CLK_SEL = 3; // derive clock from 352M PFD
|
||||
#endif // CHIP_MX6DQ
|
||||
}
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// End of file
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
* Copyright (c) 2012, Freescale Semiconductor, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o 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.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. 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 HOLDER 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 _CCM_PLL_H_
|
||||
#define _CCM_PLL_H_
|
||||
|
||||
#include "sdk_types.h"
|
||||
|
||||
//! @addtogroup diag_clocks
|
||||
//! @{
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Definitions
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define CLK_SRC_32K 32768
|
||||
|
||||
//! @brief Create a clock gate bit mask value.
|
||||
//! @param x 0..15, for CG0 to CG15
|
||||
#define CG(x) (3 << (x*2))
|
||||
|
||||
//! @brief Constants for CCM CCGR register fields.
|
||||
enum _clock_gate_constants
|
||||
{
|
||||
CLOCK_ON = 0x3, //!< Clock always on in both run and stop modes.
|
||||
CLOCK_ON_RUN = 0x1, //!< Clock on only in run mode.
|
||||
CLOCK_OFF = 0x0 //!< Clocked gated off.
|
||||
};
|
||||
|
||||
//! @brief Low power mdoes.
|
||||
typedef enum _lp_modes {
|
||||
RUN_MODE,
|
||||
WAIT_MODE,
|
||||
STOP_MODE,
|
||||
} lp_modes_t;
|
||||
|
||||
//! @brief Main clock sources.
|
||||
typedef enum _main_clocks {
|
||||
CPU_CLK,
|
||||
AXI_CLK,
|
||||
MMDC_CH0_AXI_CLK,
|
||||
AHB_CLK,
|
||||
IPG_CLK,
|
||||
IPG_PER_CLK,
|
||||
MMDC_CH1_AXI_CLK,
|
||||
} main_clocks_t;
|
||||
|
||||
//! @brief Peripheral clocks.
|
||||
typedef enum _peri_clocks {
|
||||
UART1_MODULE_CLK,
|
||||
UART2_MODULE_CLK,
|
||||
UART3_MODULE_CLK,
|
||||
UART4_MODULE_CLK,
|
||||
SSI1_BAUD,
|
||||
SSI2_BAUD,
|
||||
CSI_BAUD,
|
||||
MSTICK1_CLK,
|
||||
MSTICK2_CLK,
|
||||
RAWNAND_CLK,
|
||||
USB_CLK,
|
||||
VPU_CLK,
|
||||
SPI_CLK,
|
||||
CAN_CLK
|
||||
} peri_clocks_t;
|
||||
|
||||
//! @brief Available PLLs.
|
||||
typedef enum plls {
|
||||
PLL1,
|
||||
PLL2,
|
||||
PLL3,
|
||||
PLL4,
|
||||
PLL5,
|
||||
} plls_t;
|
||||
|
||||
extern const uint32_t PLL1_OUTPUT;
|
||||
extern const uint32_t PLL2_OUTPUT[];
|
||||
extern const uint32_t PLL3_OUTPUT[];
|
||||
extern const uint32_t PLL4_OUTPUT;
|
||||
extern const uint32_t PLL5_OUTPUT;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// API
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
//! @brief Set/unset clock gating for a peripheral.
|
||||
//! @param base_address configure clock gating for that module from the base address.
|
||||
//! @param gating_mode clock gating mode: CLOCK_ON or CLOCK_OFF.
|
||||
void clock_gating_config(uint32_t base_address, uint32_t gating_mode);
|
||||
|
||||
//! @brief Returns the frequency of a clock in megahertz.
|
||||
uint32_t get_main_clock(main_clocks_t clk);
|
||||
|
||||
//! @brief Returns the frequency of a clock in megahertz.
|
||||
uint32_t get_peri_clock(peri_clocks_t clk);
|
||||
|
||||
//! @brief Inits clock sources.
|
||||
void ccm_init(void);
|
||||
|
||||
//! @brief Prepare and enter in a low power mode.
|
||||
//! @param lp_mode low power mode : WAIT_MODE or STOP_MODE.
|
||||
void ccm_enter_low_power(lp_modes_t lp_mode);
|
||||
|
||||
//! @brief Mask/unmask an interrupt source that can wake up the processor when in a
|
||||
//! low power mode.
|
||||
//!
|
||||
//! @param irq_id ID of the interrupt to mask/unmask.
|
||||
//! @param doEnable Pass true to unmask the source ID.
|
||||
void ccm_set_lpm_wakeup_source(uint32_t irq_id, bool doEnable);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
//! @}
|
||||
|
||||
#endif
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// EOF
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -27,19 +27,19 @@ void EnableLocalInterrupt(unsigned long level)
|
||||
return;
|
||||
}
|
||||
|
||||
int32_t ArchEnableHwIrq(uint32_t irq_num)
|
||||
int32_t ArchEnableHwIrq(uint32_t irq_num, uint32_t cpu_id)
|
||||
{
|
||||
// gic_set_irq_priority(irq_num, priority);
|
||||
gic_set_irq_security(irq_num, false); // set IRQ as non-secure
|
||||
// gic_set_cpu_target(irq_num, CPU_0, true);
|
||||
gic_set_cpu_target(irq_num, cpu_id, true);
|
||||
gic_enable_irq(irq_num, true);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t ArchDisableHwIrq(uint32_t irq_num)
|
||||
int32_t ArchDisableHwIrq(uint32_t irq_num, uint32_t cpu_id)
|
||||
{
|
||||
gic_enable_irq(irq_num, false);
|
||||
// gic_set_cpu_target(irq_num, CPU_0, false);
|
||||
gic_set_cpu_target(irq_num, cpu_id, false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
285
Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/mmu.c
Normal file
285
Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/mmu.c
Normal file
@@ -0,0 +1,285 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2012, Freescale Semiconductor, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o 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.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. 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 HOLDER 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.
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @file mmu.c
|
||||
* @brief System memory arangement.
|
||||
*/
|
||||
#include "cortex_a9.h"
|
||||
#include "mmu.h"
|
||||
#include "arm_cp_registers.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Definitions
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//! @brief Size in bytes of the first-level page table.
|
||||
#define MMU_L1_PAGE_TABLE_SIZE (16 * 1024)
|
||||
|
||||
//! @brief First-level 1MB section descriptor entry.
|
||||
typedef union mmu_l1_section {
|
||||
uint32_t u;
|
||||
struct {
|
||||
uint32_t id:2; //!< ID
|
||||
uint32_t b:1; //!< Bufferable
|
||||
uint32_t c:1; //!< Cacheable
|
||||
uint32_t xn:1; //!< Execute-not
|
||||
uint32_t domain:4; //!< Domain
|
||||
uint32_t _impl_defined:1; //!< Implementation defined, should be zero.
|
||||
uint32_t ap1_0:2; //!< Access permissions AP[1:0]
|
||||
uint32_t tex:3; //!< TEX remap
|
||||
uint32_t ap2:1; //!< Access permissions AP[2]
|
||||
uint32_t s:1; //!< Shareable
|
||||
uint32_t ng:1; //!< Not-global
|
||||
uint32_t _zero:1; //!< Should be zero.
|
||||
uint32_t ns:1; //!< Non-secure
|
||||
uint32_t address:12; //!< Physical base address
|
||||
};
|
||||
} mmu_l1_section_t;
|
||||
|
||||
enum {
|
||||
kMMU_L1_Section_ID = 2, //!< ID value for a 1MB section first-level entry.
|
||||
kMMU_L1_Section_Address_Shift = 20 //!< Bit offset of the physical base address field.
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Externs
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
extern char __l1_page_table_start;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Code
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void mmu_enable()
|
||||
{
|
||||
// invalidate all tlb
|
||||
arm_unified_tlb_invalidate();
|
||||
|
||||
// read SCTLR
|
||||
uint32_t sctlr;
|
||||
_ARM_MRC(15, 0, sctlr, 1, 0, 0);
|
||||
|
||||
// set MMU enable bit
|
||||
sctlr |= BM_SCTLR_M;
|
||||
|
||||
// write modified SCTLR
|
||||
_ARM_MCR(15, 0, sctlr, 1, 0, 0);
|
||||
}
|
||||
|
||||
void mmu_disable()
|
||||
{
|
||||
// read current SCTLR
|
||||
uint32_t sctlr;
|
||||
_ARM_MRC(15, 0, sctlr, 1, 0, 0);
|
||||
|
||||
// clear MMU enable bit
|
||||
sctlr &=~ BM_SCTLR_M;
|
||||
|
||||
// write modified SCTLR
|
||||
_ARM_MCR(15, 0, sctlr, 1, 0, 0);
|
||||
}
|
||||
|
||||
void mmu_init()
|
||||
{
|
||||
// Get the L1 page table base address.
|
||||
uint32_t * table = (uint32_t *)&__l1_page_table_start;
|
||||
uint32_t share_attr = kShareable;
|
||||
|
||||
// write table address to TTBR0
|
||||
_ARM_MCR(15, 0, table, 2, 0, 0);
|
||||
|
||||
// set Client mode for all Domains
|
||||
uint32_t dacr = 0x55555555;
|
||||
_ARM_MCR(15, 0, dacr, 3, 0, 0); // MCR p15, 0, <Rd>, c3, c0, 0 ; Write DACR
|
||||
|
||||
// Clear the L1 table.
|
||||
bzero(table, MMU_L1_PAGE_TABLE_SIZE);
|
||||
|
||||
// Create default mappings.
|
||||
mmu_map_l1_range(0x00000000, 0x00000000, 0x00900000, kStronglyOrdered, kShareable, kRWAccess); // ROM and peripherals
|
||||
mmu_map_l1_range(0x00900000, 0x00900000, 0x00100000, kStronglyOrdered, kShareable, kRWAccess); // OCRAM
|
||||
mmu_map_l1_range(0x00a00000, 0x00a00000, 0x0f600000, kStronglyOrdered, kShareable, kRWAccess); // More peripherals
|
||||
|
||||
// Check whether SMP is enabled. If it is not, then we don't want to make SDRAM shareable.
|
||||
uint32_t actlr = 0x0;
|
||||
_ARM_MRC(15, 0, actlr, 1, 0, 1);
|
||||
if (actlr & BM_ACTLR_SMP)
|
||||
{
|
||||
share_attr = kShareable;
|
||||
}
|
||||
else
|
||||
{
|
||||
share_attr = kNonshareable;
|
||||
}
|
||||
|
||||
#if defined(CHIP_MX6DQ) || defined(CHIP_MX6SDL)
|
||||
mmu_map_l1_range(0x10000000, 0x10000000, 0x80000000, kOuterInner_WB_WA, share_attr, kRWAccess); // 2GB DDR
|
||||
#elif defined(CHIP_MX6SL)
|
||||
mmu_map_l1_range(0x80000000, 0x80000000, 0x40000000, kOuterInner_WB_WA, share_attr, kRWAccess); // 1GB DDR
|
||||
#else
|
||||
#error Unknown chip type!
|
||||
#endif
|
||||
}
|
||||
|
||||
void mmu_map_l1_range(uint32_t pa, uint32_t va, uint32_t length, mmu_memory_type_t memoryType, mmu_shareability_t isShareable, mmu_access_t access)
|
||||
{
|
||||
register mmu_l1_section_t entry;
|
||||
entry.u = 0;
|
||||
|
||||
// Set constant attributes.
|
||||
entry.id = kMMU_L1_Section_ID;
|
||||
entry.xn = 0; // Allow execution
|
||||
entry.domain = 0; // Domain 0
|
||||
entry.ng = 0; // Global
|
||||
entry.ns = 0; // Secure
|
||||
|
||||
// Set attributes based on the selected memory type.
|
||||
switch (memoryType)
|
||||
{
|
||||
case kStronglyOrdered:
|
||||
entry.c = 0;
|
||||
entry.b = 0;
|
||||
entry.tex = 0;
|
||||
entry.s = 1; // Ignored
|
||||
break;
|
||||
case kDevice:
|
||||
if (isShareable)
|
||||
{
|
||||
entry.c = 0;
|
||||
entry.b = 1;
|
||||
entry.tex = 0;
|
||||
entry.s = 1; // Ignored
|
||||
}
|
||||
else
|
||||
{
|
||||
entry.c = 0;
|
||||
entry.b = 0;
|
||||
entry.tex = 2;
|
||||
entry.s = 0; // Ignored
|
||||
}
|
||||
break;
|
||||
case kOuterInner_WB_WA:
|
||||
entry.c = 1;
|
||||
entry.b = 1;
|
||||
entry.tex = 1;
|
||||
entry.s = isShareable;
|
||||
break;
|
||||
case kOuterInner_WT:
|
||||
entry.c = 1;
|
||||
entry.b = 0;
|
||||
entry.tex = 0;
|
||||
entry.s = isShareable;
|
||||
break;
|
||||
case kNoncacheable:
|
||||
entry.c = 0;
|
||||
entry.b = 0;
|
||||
entry.tex = 1;
|
||||
entry.s = isShareable;
|
||||
break;
|
||||
}
|
||||
|
||||
// Set attributes from specified access mode.
|
||||
switch (access)
|
||||
{
|
||||
case kNoAccess:
|
||||
entry.ap2 = 0;
|
||||
entry.ap1_0 = 0;
|
||||
break;
|
||||
case kROAccess:
|
||||
entry.ap2 = 1;
|
||||
entry.ap1_0 = 3;
|
||||
break;
|
||||
case kRWAccess:
|
||||
entry.ap2 = 0;
|
||||
entry.ap1_0 = 3;
|
||||
break;
|
||||
}
|
||||
|
||||
// Get the L1 page table base address.
|
||||
uint32_t * table = (uint32_t *)&__l1_page_table_start;
|
||||
|
||||
// Convert addresses to 12-bit bases.
|
||||
uint32_t vbase = va >> kMMU_L1_Section_Address_Shift;
|
||||
uint32_t pbase = pa >> kMMU_L1_Section_Address_Shift;
|
||||
uint32_t entries = length >> kMMU_L1_Section_Address_Shift;
|
||||
|
||||
// Fill in L1 page table entries.
|
||||
for (; entries > 0; ++pbase, ++vbase, --entries)
|
||||
{
|
||||
entry.address = pbase;
|
||||
table[vbase] = entry.u;
|
||||
}
|
||||
|
||||
// Invalidate TLB
|
||||
arm_unified_tlb_invalidate();
|
||||
}
|
||||
|
||||
bool mmu_virtual_to_physical(uint32_t virtualAddress, uint32_t * physicalAddress)
|
||||
{
|
||||
uint32_t pa = 0;
|
||||
|
||||
// VA to PA translation with privileged read permission check
|
||||
_ARM_MCR(15, 0, virtualAddress & 0xfffffc00, 7, 8, 0);
|
||||
|
||||
// Read PA register
|
||||
_ARM_MRC(15, 0, pa, 7, 4, 0);
|
||||
|
||||
// First bit of returned value is Result of conversion (0 is successful translation)
|
||||
if (pa & 1)
|
||||
{
|
||||
// We can try write permission also
|
||||
// VA to PA translation with privileged write permission check
|
||||
_ARM_MCR(15, 0, virtualAddress & 0xfffffc00, 7, 8, 1);
|
||||
|
||||
// Read PA register
|
||||
_ARM_MRC(15, 0, pa, 7, 4, 0);
|
||||
|
||||
// First bit of returned value is Result of conversion (0 is successful translation)
|
||||
if (pa & 1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (physicalAddress)
|
||||
{
|
||||
// complete address returning base + offset
|
||||
pa = (pa & 0xfffff000) | (virtualAddress & 0x00000fff);
|
||||
*physicalAddress = pa;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// EOF
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
157
Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/mmu.h
Normal file
157
Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/mmu.h
Normal file
@@ -0,0 +1,157 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2012, Freescale Semiconductor, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o 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.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. 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 HOLDER 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.
|
||||
*/
|
||||
|
||||
//! @addtogroup diag_mmu
|
||||
//! @{
|
||||
|
||||
/*!
|
||||
* @file mmu.h
|
||||
* @brief System memory arrangement.
|
||||
*/
|
||||
|
||||
#ifndef _MMU_H_
|
||||
#define _MMU_H_
|
||||
|
||||
#include "sdk.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Definitions
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//! @brief Memory region attributes.
|
||||
typedef enum _mmu_memory_type
|
||||
{
|
||||
kStronglyOrdered,
|
||||
kDevice,
|
||||
kOuterInner_WB_WA,
|
||||
kOuterInner_WT,
|
||||
kNoncacheable,
|
||||
} mmu_memory_type_t;
|
||||
|
||||
//! @brief Memory region shareability options.
|
||||
typedef enum _mmu_shareability
|
||||
{
|
||||
kShareable = 1,
|
||||
kNonshareable = 0
|
||||
} mmu_shareability_t;
|
||||
|
||||
//! @brief Access permissions for a memory region.
|
||||
typedef enum _mmu_access
|
||||
{
|
||||
kNoAccess,
|
||||
kROAccess,
|
||||
kRWAccess
|
||||
} mmu_access_t;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Prototypes
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*!
|
||||
* @brief Enable the MMU.
|
||||
*
|
||||
* The L1 page tables and MMU settings must have already been configured by
|
||||
* calling mmu_init() before the MMU is enabled.
|
||||
*/
|
||||
void mmu_enable();
|
||||
|
||||
/*!
|
||||
* @brief Disable the MMU.
|
||||
*/
|
||||
void mmu_disable();
|
||||
|
||||
/*!
|
||||
* @brief Set up the default first-level page table.
|
||||
*
|
||||
* Initializes the L1 page table with the following regions:
|
||||
* - 0x00000000...0x00900000 : ROM and peripherals, strongly-ordered
|
||||
* - 0x00900000...0x00a00000 : OCRAM, strongly-ordered
|
||||
* - For MX6DQ or MX6SDL: 0x10000000...0x90000000 : DDR, normal, outer inner, write-back, write-allocate
|
||||
* - For MX6SL: 0x80000000...0xc0000000 : DDR, normal, outer inner, write-back, write-allocate
|
||||
*
|
||||
* If the CPU is participating in SMP, then the DDR regions are made shareable. Otherwise they
|
||||
* are marked as non-shareable.
|
||||
*
|
||||
* The TTBR0 register is set to the base of the L1 table.
|
||||
*
|
||||
* All memory domains are configured to allow client access. However, note that only domain 0 is
|
||||
* used by mmu_map_l1_range().
|
||||
*/
|
||||
void mmu_init();
|
||||
|
||||
/*!
|
||||
* @brief Maps a range of memory in the first-level page table.
|
||||
*
|
||||
* Entries in the first-level page table are filled in for the range of virtual addresses
|
||||
* starting at @a va and continuing for @a length bytes. These virtual addreses are mapped
|
||||
* to the physical addresses starting at @a pa and continuing for @a length bytes. All table
|
||||
* entries for the range of mapped memory have the same attributes, which are selected with
|
||||
* the @a memoryType, @a isShareable, and @a access parameters.
|
||||
*
|
||||
* @param pa The base physical address of the range to which the virtual address will be mapped.
|
||||
* @param va The base virtual address of the range.
|
||||
* @param length The size of the range to be mapped, in bytes. This value must be divisible by 1MB.
|
||||
* @param memoryType The type of the memory region. This controls caching, buffering, ordering of
|
||||
* memory accesses, and other attributes of the region.
|
||||
* @param isShareable The shareability of the physical memory. Ignored for strongly-ordered memory.
|
||||
* @param access Access permissions.
|
||||
*/
|
||||
void mmu_map_l1_range(uint32_t pa, uint32_t va, uint32_t length, mmu_memory_type_t memoryType, mmu_shareability_t isShareable, mmu_access_t access);
|
||||
|
||||
/*!
|
||||
* @brief Convert virtual address to physical.
|
||||
*
|
||||
* First attempts a priviledged read translation for the current security mode. If that fails,
|
||||
* a priviledged write translation, also for the current security mode, is attempted. If this
|
||||
* second attempt at translation fails, then false will be returned.
|
||||
*
|
||||
* @param virtualAddress Virtual address to convert to a physical address.
|
||||
* @param[out] physicalAddress This parameter is filled in with the physical address corresponding
|
||||
* to the virtual address passed in @a virtualAddress.
|
||||
* @retval true The address returned through @a physicalAddress is valid.
|
||||
* @retval false The conversion failed for some reason.
|
||||
*/
|
||||
bool mmu_virtual_to_physical(uint32_t virtualAddress, uint32_t * physicalAddress);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
//! @}
|
||||
|
||||
#endif // _MMU_H_
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// EOF
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Reference in New Issue
Block a user