Support XiZi_AIoT

This commit is contained in:
TXuian 2024-01-31 10:30:34 +08:00
parent f6cf46027d
commit 494312183b
351 changed files with 46408 additions and 450091 deletions

View File

@ -2,7 +2,7 @@
# Automatically generated file; DO NOT EDIT.
# XiZi_AIoT Project Configuration
#
CONFIG_BOARD_IMX6Q_SABRELITE_EVB=y
CONFIG_BOARD_IMX6Q_SABRELITE=y
CONFIG_ARCH_ARM=y
#

View File

@ -9,7 +9,7 @@ emulator_support +=
support := $(riscv_support) $(arm_support) $(emulator_support)
SRC_DIR :=
export BOARD ?=imx6q-sabrelite
export BOARD ?= imx6q-sabrelite
# This is the environment variable for kconfig-mconf
export KCONFIG_CONFIG ?= .config
@ -19,7 +19,6 @@ $(warning "This is what we support:")
$(warning "RISCV EVB: $(riscv_support)")
$(warning "ARM EVB: $(arm_support)")
$(warning "EMULATORS: $(emulator_support)")
# $(warning "$(support)")
$(error "break" )
endif
@ -32,20 +31,18 @@ MAKEFILES =$(KERNEL_ROOT)/.config
export BSP_ROOT ?= $(KERNEL_ROOT)/services/boards/$(BOARD)
export UBIQUITOUS_ROOT ?= ..
include services/boards/$(BOARD)/config.mk
export BSP_BUILD_DIR := boards/$(BOARD)
include $(KERNEL_ROOT)/hardkernel/arch/arm/armv7-a/cortex-a9/preboot_for_nxp_imx6q_sabrelite/config.mk
export BSP_BUILD_DIR := $(KERNEL_ROOT)
export HOSTTOOLS_DIR ?= $(KERNEL_ROOT)/services/tools/hosttools
export CONFIG2H_EXE ?= $(HOSTTOOLS_DIR)/xsconfig.sh
export CPPPATHS
export SRC_APP_DIR := ../../APP_Framework
export SRC_KERNEL_DIR := hardkernel services softkernel support testing
# export SRC_DIR:= $(SRC_APP_DIR) $(SRC_KERNEL_DIR)
export SRC_DIR:= $(SRC_KERNEL_DIR)
export SRC_KERNEL_DIR := hardkernel kernel_actracer services softkernel testing
export SRC_DIR := $(SRC_KERNEL_DIR)
export LIBCC
export MUSL_DIR := $(KERNEL_ROOT)/services/lib/musllib
PART:=
PART :=
all:
ifeq ($(CONFIG_COMPILER_APP)_$(CONFIG_COMPILER_KERNEL),y_)
@ -78,15 +75,6 @@ COMPILE_ALL:
@$(MAKE) -C build TARGET=XiZi-$(BOARD).elf LINK_FLAGS=LFLAGS
@rm build/Makefile build/make.obj
COMPILE_MUSL:
@for dir in $(MUSL_DIR);do \
$(MAKE) -C $$dir COMPILE_TYPE=$@ CONFIG_RESOURCES_LWIP=n; \
done
@cp link_libc.mk build/Makefile
@$(MAKE) -C build TARGET=libmusl.a LINK_FLAGS=LFLAGS
@cp build/libmusl.a $(KERNEL_ROOT)/lib/musllib/libmusl.a
@rm build/Makefile build/make.obj
COMPILE_KERNEL:
@for dir in $(SRC_KERNEL_DIR);do \
$(MAKE) -C $$dir; \
@ -135,6 +123,12 @@ clean:
@echo Clean target and build_dir
@rm -rf build
@rm -rf temp.txt
@rm -rf services/boards/imx6q-sabrelite/*.o
@rm -rf services/boards/imx6q-sabrelite/*.asm
@rm -rf services/boards/imx6q-sabrelite/bin
@rm -rf services/tools/mkfs/mkfs
@rm -rf services/boards/imx6q-sabrelite/fs.img
@rm -rf services/boards/imx6q-sabrelite/user.map
distclean:
@echo Clean all configuration

File diff suppressed because it is too large Load Diff

View File

@ -1,20 +1,8 @@
ifeq ($(COMPILE_TYPE), COMPILE_MUSL)
SRC_DIR_TEMP := $(MUSL_DIR)
else ifeq ($(COMPILE_TYPE), COMPILE_LWIP)
SRC_DIR_TEMP := $(LWIP_DIR)
else
SRC_DIR_TEMP := $(SRC_DIR)
endif
SRC_DIR :=
MUSL_DIR :=
LWIP_DIR :=
ifeq ($(USE_APP_INCLUDEPATH), y)
include $(KERNEL_ROOT)/path_app.mk
else
include $(KERNEL_ROOT)/path_kernel.mk
endif
include $(KERNEL_ROOT)/path_kernel.mk
export CPPPATHS := $(KERNELPATHS)
CUR_DIR :=$(shell pwd)
@ -27,9 +15,8 @@ CFLAGS += $(DEFINES)
AFLAGS += $(DEFINES)
CXXFLAGS += $(DEFINES)
BUILD_DIR := $(KERNEL_ROOT)/build
APP_DIR := Ubiquitous/XiZi
APP_DIR := Ubiquitous/XiZi_AIoT
.PHONY:COMPILER
COMPILER:
@if [ "${SRC_DIR_TEMP}" != "" ]; then \
@ -39,23 +26,22 @@ COMPILER:
fi
@/bin/echo -n $(OBJS) " " >> $(KERNEL_ROOT)/build/make.obj
################################################
define add_c_file
$(eval COBJ := $(1:%.c=%.o)) \
$(eval COBJ := $(notdir $(1:%.c=%.o))) \
$(eval COBJ := $(subst $(subst $(APP_DIR),,$(KERNEL_ROOT)),,$(COBJ))) \
$(eval LOCALC := $(addprefix $(BUILD_DIR)/,$(COBJ))) \
$(eval OBJS += $(LOCALC)) \
$(if $(strip $(LOCALC)),$(eval $(LOCALC): $(1)
@if [ ! -d $$(@D) ]; then mkdir -p $$(@D); fi
@echo cc $$<
@echo cc $$<
@/bin/echo -n $(dir $(LOCALC)) >>$(KERNEL_ROOT)/build/make.dep
@($(CROSS_COMPILE)gcc -MM $$(CFLAGS) -c $$<) >>$(KERNEL_ROOT)/build/make.dep
@$(CROSS_COMPILE)gcc $$(CFLAGS) -c $$< -o $$@))
endef
define add_cpp_file
$(eval COBJ := $(1:%.cpp=%.o)) \
$(eval COBJ := $(notdir $(1:%.cpp=%.o))) \
$(eval COBJ := $(subst $(subst $(APP_DIR),,$(KERNEL_ROOT)),,$(COBJ))) \
$(eval LOCALCPP := $(addprefix $(BUILD_DIR)/,$(COBJ))) \
$(eval OBJS += $(LOCALCPP)) \
@ -68,7 +54,7 @@ $(if $(strip $(LOCALCPP)),$(eval $(LOCALCPP): $(1)
endef
define add_cc_file
$(eval COBJ := $(1:%.cc=%.o)) \
$(eval COBJ := $(notdir $(1:%.cc=%.o))) \
$(eval COBJ := $(subst $(subst $(APP_DIR),,$(KERNEL_ROOT)),,$(COBJ))) \
$(eval LOCALCPP := $(addprefix $(BUILD_DIR)/,$(COBJ))) \
$(eval OBJS += $(LOCALCPP)) \
@ -81,7 +67,7 @@ $(if $(strip $(LOCALCPP)),$(eval $(LOCALCPP): $(1)
endef
define add_S_file
$(eval SOBJ := $(1:%.S=%.o)) \
$(eval SOBJ := $(notdir $(1:%.S=%.o))) \
$(eval SOBJ := $(subst $(subst $(APP_DIR),,$(KERNEL_ROOT)),,$(SOBJ))) \
$(eval LOCALS := $(addprefix $(BUILD_DIR)/,$(SOBJ))) \
$(eval OBJS += $(LOCALS)) \
@ -94,7 +80,7 @@ $(if $(strip $(LOCALS)),$(eval $(LOCALS): $(1)
endef
define add_a_file
$(eval SOBJ := $(1:%.a=%.a)) \
$(eval SOBJ := $(notdir $(1:%.a=%.a))) \
$(eval SOBJ := $(subst $(subst $(APP_DIR),,$(KERNEL_ROOT)),,$(SOBJ))) \
$(eval LOCALA := $(addprefix $(BUILD_DIR)/,$(SOBJ))) \
$(eval OBJS += $(LOCALA)) \

View File

@ -1,3 +1,4 @@
SRC_DIR := arch abstraction
SRC_DIR := arch clock mmu intr uart cache
SRC_FILES := hardkernel_init.c
include $(KERNEL_ROOT)/compiler.mk

View File

@ -1,3 +0,0 @@
SRC_FILES := cache.c isr.c abstraction_mmu.c
include $(KERNEL_ROOT)/compiler.mk

View File

@ -1,206 +0,0 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file: abstraction_mmu.c
* @brief: the general management of system mmu
* @version: 3.0
* @author: AIIT XUOS Lab
* @date: 2023/4/27
*
*/
#include <abstraction_mmu.h>
AbstractionMmu abstraction_mmu;
volatile uint32_t global_L1_pte_table[4096];
/**
* @description: write cmd to CP15 register
* @param reg_type - CP15 register type
* @param val - ops val pointer
* @return
*/
static void MmuCp15Write(uint8_t reg_type, uint32_t *val)
{
uint32_t write_val = *val;
switch (reg_type) {
case AM_MMU_CP15_TTBCR:
TTBCR_W(write_val);
AM_ISB;
case AM_MMU_CP15_TTBR0:
TTBR0_W(write_val);
AM_ISB;
default:
break;
}
}
/**
* @description: read CP15 register from mmu
* @param reg_type - CP15 register type
* @param val - ops val pointer
* @return
*/
static void MmuCp15Read(uint8_t reg_type, uint32_t *val)
{
uint32_t read_val = 0;
switch (reg_type) {
case AM_MMU_CP15_TTBCR:
TTBCR_R(read_val);
case AM_MMU_CP15_TTBR0:
TTBR0_R(read_val);
default:
break;
}
*val = read_val;
}
/**
* @description: write or read CP15 register to set mmu
* @param ops_type - CP15 write or read
* @param reg_type - CP15 register type
* @param val - ops val pointer
* @return
*/
static void MmuRegOps(uint8_t ops_type, uint8_t reg_type, uint32_t *val)
{
switch (ops_type) {
case AM_MMU_CP15_WRITE:
MmuCp15Write(reg_type, val);
case AM_MMU_CP15_READ:
MmuCp15Read(reg_type, val);
default:
break;
}
}
/**
* @description: Init abstraction_mmu function
* @param mmu - abstraction mmu pointer
* @param ttb_base - ttb base pointer
* @return success : 0 error : -1
*/
static int _AbstractionMmuInit(AbstractionMmu *mmu, uint32_t *ttb_base)
{
mmu_init();
return 0;
}
/**
* @description: map L1 or L2 page table section
* @param mmu - abstraction mmu pointer
* @param section_size - section size
* @return success : 0 error : -1
*/
static int _AbstractionMmuSectionMap(AbstractionMmu *mmu, uint32_t section_size)
{
uint32_t vaddr_length = mmu->vaddr_end - mmu->vaddr_start + 1;
mmu_map_l1_range(mmu->paddr_start, mmu->vaddr_start, vaddr_length,
mmu->mmu_memory_type, mmu->mmu_shareability, mmu->mmu_access);
mmu->mmu_status = 1;
return 0;
}
/**
* @description: unmap L1 or L2 page table section
* @param mmu - abstraction mmu pointer
* @param vaddr_start - virtual address start
* @param vaddr_size - virtual address size
* @return success : 0 error : -1
*/
static int _AbstractionMmuSectionUnmap(AbstractionMmu *mmu, uint32_t vaddr_start, uint32_t vaddr_size)
{
uint32_t *l1_umap_ventry = mmu->ttb_vbase + (vaddr_start >> AM_MMU_L1_SECTION_SHIFT);
uint32_t vaddr_end = vaddr_start + vaddr_size - 1;
uint32_t umap_count = (vaddr_end >> AM_MMU_L1_SECTION_SHIFT) - (vaddr_start >> AM_MMU_L1_SECTION_SHIFT) + 1;
while (umap_count) {
AM_DMB;
*l1_umap_ventry = 0;
AM_DSB;
umap_count--;
l1_umap_ventry += (1 << AM_MMU_L1_SECTION_SHIFT);//1MB section
}
AM_DSB;
CLEARTLB(0);//clear TLB data and configure
AM_DSB;
AM_ISB;
mmu->mmu_status = 0;
return 0;
}
/**
* @description: switch ttb base by re-write ttbr register
* @param mmu - abstraction mmu pointer
* @return success : 0 error : -1
*/
static int _AbstractionMmuTtbSwitch(AbstractionMmu *mmu)
{
uint32_t ttbr, ttbcr;
MmuRegOps(AM_MMU_CP15_READ, AM_MMU_CP15_TTBCR, &ttbcr);
/* Set TTBR0 with inner/outer write back write allocate and not shareable, [4:3]=01, [1]=0, [6,0]=01 */
ttbr = ((mmu->ttb_pbase & 0xFFFFC000UL) | 0x9UL);
/* enable TTBR0 */
ttbcr = 0;
AM_DSB;
MmuRegOps(AM_MMU_CP15_WRITE, AM_MMU_CP15_TTBR0, &ttbr);
MmuRegOps(AM_MMU_CP15_WRITE, AM_MMU_CP15_TTBCR, &ttbcr);
return 0;
}
/**
* @description: get physical address transformed from virtual address
* @param mmu - abstraction mmu pointer
* @param vaddr - virtual address pointer
* @param paddr - physical address pointer
* @return success : 0 error : -1
*/
static int _AbstracktonMmuTransform(AbstractionMmu *mmu, uint32_t *vaddr, uint32_t *paddr)
{
uint32_t virtualAddress = *vaddr;
if (mmu->mmu_status) {
mmu_virtual_to_physical(virtualAddress, paddr);
}
return 0;
}
static struct AbstractionMmuDone mmu_done = {
.AbstractionMmuInit = _AbstractionMmuInit,
.AbstractionMmuSectionMap = _AbstractionMmuSectionMap,
.AbstractionMmuSectionUnmap = _AbstractionMmuSectionUnmap,
.AbstractionMmuTtbSwitch = _AbstractionMmuTtbSwitch,
.AbstracktonMmuTransform = _AbstracktonMmuTransform,
};
/**
* @description: init abstraciton mmu info when system start
* @return success : 0 error : -1
*/
int SysInitAbstractionMmu(void)
{
abstraction_mmu.mmu_done = &mmu_done;
}

View File

@ -1,114 +0,0 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file: mmu.h
* @brief: the general management of system mmu
* @version: 3.0
* @author: AIIT XUOS Lab
* @date: 2023/5/24
*
*/
#include <stdint.h>
#include <mmu.h>
#define ARCH_ARM
#ifdef ARCH_ARM
/* ARM System Registers */
#define AM_DSB __asm__ volatile("dsb" ::: "memory")
#define AM_DMB __asm__ volatile("dmb" ::: "memory")
#define AM_ISB __asm__ volatile("isb" ::: "memory")
#define AM_WFI __asm__ volatile("wfi" ::: "memory")
#define AM_BARRIER __asm__ volatile("":::"memory")
#define AM_WFE __asm__ volatile("wfe" ::: "memory")
#define AM_SEV __asm__ volatile("sev" ::: "memory")
#define TTBR0_R(val) __asm__ volatile("mrc p15, 0, %0, c2, c0, 0" : "=r"(val))
#define TTBR0_W(val) __asm__ volatile("mcr p15, 0, %0, c2, c0, 0" ::"r"(val))
#define TTBCR_R(val) __asm__ volatile("mrc p15, 0, %0, c2, c0, 2" : "=r"(val))
#define TTBCR_W(val) __asm__ volatile("mcr p15, 0, %0, c2, c0, 2" ::"r"(val))
#define CLEARTLB(val) __asm__ volatile("mcr p15, 0, %0, c8, c7, 0" ::"r"(val))
#endif
#define AM_MMU_L1_PAGE_TABLE_SIZE (4 * 4096)
#define AM_MMU_L1_SECTION_SHIFT 20
typedef enum
{
AM_MMU_CP15_WRITE = 0,
AM_MMU_CP15_READ,
}MmuCP15OpsType;
typedef enum
{
AM_MMU_CP15_TTBCR = 0,
AM_MMU_CP15_TTBR0,
AM_MMU_CP15_CLEARTLB,
}MmuCP15RegType;
typedef enum
{
AM_StronglyOrdered = 0,
AM_Device,
AM_OuterInner_WB_WA,
AM_OuterInner_WT,
AM_Noncacheable,
}MmuMemoryType;
typedef enum
{
AM_Noaccess = 0,
AM_Read_Write,
AM_Read,
}MmuAccess;
typedef enum
{
AM_Shareable = 1,
AM_Nonshareable = 0
}MmuShareability;
struct AbstractionMmuDone
{
int (*AbstractionMmuInit)(AbstractionMmu *mmu, uint32_t *ttb_base);
int (*AbstractionMmuSectionMap)(AbstractionMmu *mmu, uint32_t section_size);
int (*AbstractionMmuSectionUnmap)(AbstractionMmu *mmu, uint32_t vaddr_start, uint32_t vaddr_size);
int (*AbstractionMmuTtbSwitch)(AbstractionMmu *mmu);
int (*AbstracktonMmuTransform)(AbstractionMmu *mmu, uint32_t *vaddr, uint32_t *paddr);
};
typedef struct
{
uint32_t ttb_vbase;
uint32_t ttb_pbase;
uint32_t vaddr_start;
uint32_t vaddr_end;
uint32_t paddr_start;
uint32_t paddr_end;
uint32_t vpaddr_offset;
uint32_t pte_attr;
uint32_t mmu_status;
MmuMemoryType mmu_memory_type;
MmuAccess mmu_access;
MmuShareability mmu_shareability;
struct AbstractionMmuDone *mmu_done;
int lock;
int link_list;
}AbstractionMmu;

View File

@ -1,35 +0,0 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file: cache.c
* @brief: the general management of system cache
* @version: 3.0
* @author: AIIT XUOS Lab
* @date: 2023/4/27
*
*/
void InvalidInsCache()
{
PlatInvalidInsCache();
}
void InvalidDataCache(unsigned long start, unsigned long end)
{
PlatInvalidDateCache(start, end);
}
void CleanDataCache(unsigned long start, unsigned long end)
{
PlatCleanDateCache(start, end);
}

View File

@ -1,215 +0,0 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file: isr.c
* @brief: the general management of system isr
* @version: 1.0
* @author: AIIT XUOS Lab
* @date: 2020/3/15
*
*/
#include <string.h>
#include "isr.h"
struct InterruptServiceRoutines isrManager = {0} ;
#ifdef ARCH_SMP
extern int GetCpuId(void);
#endif
/**
* This functionwill get the isr nest level.
*
* @return isr nest level
*/
static uint16_t GetIsrCounter()
{
uint16_t ret = 0;
#ifdef ARCH_SMP
ret = isrManager.isr_count[GetCpuId()];
#else
ret = isrManager.isr_count;
#endif
return ret;
}
static void IncIsrCounter()
{
#ifdef ARCH_SMP
isrManager.isr_count[GetCpuId()] ++ ;
#else
isrManager.isr_count ++;
#endif
return ;
}
static void DecIsrCounter()
{
#ifdef ARCH_SMP
isrManager.isr_count[GetCpuId()] -- ;
#else
isrManager.isr_count --;
#endif
return ;
}
bool IsInIsr()
{
#ifdef ARCH_SMP
return ( isrManager.isr_count[GetCpuId()] != 0 ? TRUE : FALSE ) ;
#else
return ( isrManager.isr_count != 0 ? TRUE : FALSE ) ;
#endif
}
/**
* This function will register a new irq.
*
* @param irq_num the number of the irq
* @param handler the callback of the interrupt
* @param arg param of thge callback
*
* @return 0 on success; -1 on failure
*/
static int32_t RegisterHwIrq(uint32_t irq_num, IsrHandlerType handler, void *arg)
{
if (irq_num >= ARCH_MAX_IRQ_NUM )
return -1;
struct IrqDesc *desc = &isrManager.irq_table[irq_num];
desc->handler = handler;
desc->param = arg;
return 0;
}
/**
* This function will free a irq.
*
* @param irq_num the number of the irq
*
* @return 0 on success; -1 on failure
*/
static int32_t FreeHwIrq(uint32_t irq_num)
{
if (irq_num >= ARCH_MAX_IRQ_NUM )
return -1;
memset(&isrManager.irq_table[irq_num], 0, sizeof(struct IrqDesc));
return 0;
}
/**
* This function will enable a irq.
*
* @param irq_num the number of the irq
*
* @return 0 on success; -1 on failure
*/
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, cpu_id);
}
/**
* This function will disable a irq.
*
* @param irq_num the number of the irq
*
* @return 0 on success; -1 on failure
*/
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, cpu_id);
}
/* called from arch-specific ISR wrapper */
static void IsrCommon(uint32_t irq_num)
{
struct IrqDesc *desc = &isrManager.irq_table[irq_num];
if (desc->handler == NULL) {
// SYS_KDEBUG_LOG(KDBG_IRQ, ("Spurious interrupt: IRQ No. %d\n", irq_num));
while (1) {}
}
desc->handler(irq_num, desc->param);
}
static void SetIsrSwitchTrigerFlag()
{
#ifdef ARCH_SMP
isrManager.isr_switch_trigger_flag[GetCpuId()] = 1;
#else
isrManager.isr_switch_trigger_flag = 1;
#endif
}
static void ClearIsrSwitchTrigerFlag()
{
#ifdef ARCH_SMP
isrManager.isr_switch_trigger_flag[GetCpuId()] = 0;
#else
isrManager.isr_switch_trigger_flag = 0;
#endif
}
static uint8_t GetIsrSwitchTrigerFlag()
{
#ifdef ARCH_SMP
return isrManager.isr_switch_trigger_flag[GetCpuId()];
#else
return isrManager.isr_switch_trigger_flag ;
#endif
}
struct IsrDone isrDone = {
IsInIsr,
RegisterHwIrq ,
FreeHwIrq,
EnableHwIrq,
DisableHwIrq,
IsrCommon,
GetIsrCounter,
IncIsrCounter,
DecIsrCounter,
GetIsrSwitchTrigerFlag,
SetIsrSwitchTrigerFlag,
ClearIsrSwitchTrigerFlag
};
void SysInitIsrManager()
{
extern int __isrtbl_idx_start;
extern int __isrtbl_start;
extern int __isrtbl_end;
memset(&isrManager,0,sizeof(struct InterruptServiceRoutines));
isrManager.done = &isrDone;
uint32_t *index = (uint32_t *)&__isrtbl_idx_start;
struct IrqDesc *desc = (struct IrqDesc *)&__isrtbl_start;
while (desc != (struct IrqDesc *)&__isrtbl_end)
isrManager.irq_table[*index++] = *desc++;
}

View File

@ -1,98 +0,0 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file: isr.h
* @brief: function declaration and structure defintion of isr
* @version: 1.0
* @author: AIIT XUOS Lab
* @date: 2020/3/10
*
*/
#ifndef __ISR_H__
#define __ISR_H__
#include <stdint.h>
#include <arch_interrupt.h>
#ifdef __cplusplus
extern "C" {
#endif
#define DECLARE_HW_IRQ(_irq_num, _handler, _arg) \
const uint32_t __irq_desc_idx_##_handler SECTION(".isrtbl.idx") = _irq_num + ARCH_IRQ_NUM_OFFSET ; \
const struct IrqDesc __irq_desc_##_handler SECTION(".isrtbl") = { \
.handler = _handler, \
.param = _arg, \
}
typedef void (*IsrHandlerType)(int vector, void *param);
struct IrqDesc
{
IsrHandlerType handler;
void *param;
#ifdef CONFIG_INTERRUPT_INFO
char name[NAME_NUM_MAX];
uint32_t counter;
#endif
};
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, 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)();
void (*decCounter)();
uint8_t (*getSwitchTrigerFlag)();
void (*setSwitchTrigerFlag)();
void (*clearSwitchTrigerFlag)();
};
struct InterruptServiceRoutines {
#ifdef ARCH_SMP
volatile uint16_t isr_count[CPU_NUMBERS];
volatile uint8_t isr_switch_trigger_flag[CPU_NUMBERS];
#else
volatile uint16_t isr_count ;
volatile uint8_t isr_switch_trigger_flag;
#endif
struct IrqDesc irq_table[ARCH_MAX_IRQ_NUM];
struct IsrDone *done;
};
extern struct InterruptServiceRoutines isrManager ;
uint32_t DisableLocalInterrupt();
void EnableLocalInterrupt(unsigned long level);
#define DISABLE_INTERRUPT DisableLocalInterrupt
#define ENABLE_INTERRUPT EnableLocalInterrupt
void SysInitIsrManager();
void InitHwinterrupt(void);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,3 +1,3 @@
SRC_DIR := $(ARCH)
SRC_DIR := arm
include $(KERNEL_ROOT)/compiler.mk

View File

@ -1,4 +1,4 @@
# The following three platforms support compatiable instructions.
SRC_DIR := $(ARCH_ARMV)
SRC_DIR := armv7-a
include $(KERNEL_ROOT)/compiler.mk

View File

@ -1,8 +1,4 @@
# The following three platforms support compatiable instructions.
ifeq ($(CONFIG_BOARD_IMX6Q_SABRELITE_EVB),y)
SRC_DIR := cortex-a9
endif
include $(KERNEL_ROOT)/compiler.mk

View File

@ -1,87 +0,0 @@
.equ Mode_USR, 0x10
.equ Mode_FIQ, 0x11
.equ Mode_IRQ, 0x12
.equ Mode_SVC, 0x13
.equ Mode_ABT, 0x17
.equ Mode_UND, 0x1B
.equ Mode_SYS, 0x1F
.equ I_Bit, 0x80 @ when I bit is set, IRQ is disabled
.equ F_Bit, 0x40 @ when F bit is set, FIQ is disabled
.equ STACK_SIZE, 0x00000100
.globl _start
_start:
/* set the cpu to SVC32 mode and disable interrupt */
mrs r0, cpsr
bic r0, r0, #0x1f
orr r0, r0, #0x13
msr cpsr_c, r0
mrc p15, 0, r0, c1, c0, 0
bic r0, #(1 << 12) /* i cache */
bic r0, #(1 << 2) /* d cache */
bic r0, #(1 << 0) /* mmu */
mcr p15, 0, r0, c1, c0, 0
ldr r0, =stack_top
@ Set the startup stack for svc
mov sp, r0
@ Enter Undefined Instruction Mode and set its Stack Pointer
msr cpsr_c, #Mode_UND|I_Bit|F_Bit
mov sp, r0
sub r0, r0, #STACK_SIZE
@ Enter Abort Mode and set its Stack Pointer
msr cpsr_c, #Mode_ABT|I_Bit|F_Bit
mov sp, r0
sub r0, r0, #STACK_SIZE
@ Enter FIQ Mode and set its Stack Pointer
msr cpsr_c, #Mode_FIQ|I_Bit|F_Bit
mov sp, r0
sub r0, r0, #STACK_SIZE
@ Enter IRQ Mode and set its Stack Pointer
msr cpsr_c, #Mode_IRQ|I_Bit|F_Bit
mov sp, r0
sub r0, r0, #STACK_SIZE
/* come back to SVC mode */
msr cpsr_c, #Mode_SVC|I_Bit|F_Bit
/* clear .bss */
mov r0, #0 /* get a zero */
ldr r1,=BSS_START /* bss start */
ldr r2,=BSS_END /* bss end */
bss_loop:
cmp r1,r2 /* check if data to clear */
strlo r0,[r1],#4 /* clear 4 bytes */
blo bss_loop /* loop until done */
/* call C++ constructors of global objects */
ldr r0, =__ctors_start__
ldr r1, =__ctors_end__
bss_end:
ctor_loop:
cmp r0, r1
beq ctor_end
ldr r2, [r0], #4
stmfd sp!, {r0-r1}
mov lr, pc
bx r2
ldmfd sp!, {r0-r1}
b ctor_loop
ctor_end:
bl start_kernel
_loop_here:
b _loop_here

View File

@ -1,66 +0,0 @@
.section .vectors, "ax"
.code 32
.globl ExceptionVectors
ExceptionVectors:
ldr pc, _ResetException
ldr pc, _UndefInstrException
ldr pc, _SwiException
ldr pc, _PrefetchAbortException
ldr pc, _DataAbortAbortException
ldr pc, _ResvException
ldr pc, _IrqException
ldr pc, _FiqException
.globl Reset_Handler
.globl UndefInstrExceptionHandle
.globl SwiExceptionHandle
.globl PrefetchAbortExceptionHandle
.globl DataAbortExceptionHandle
.globl ResvExceptionHandle
.globl ExceptionIsrEntry
.globl FiqExceptionHandle
_ResetException:
.word Reset_Handler
_UndefInstrException:
.word UndefInstrExceptionHandle
_SwiException:
.word SwiExceptionHandle
_PrefetchAbortException:
.word PrefetchAbortExceptionHandle
_DataAbortAbortException:
.word DataAbortExceptionHandle
_ResvException:
.word ResvExceptionHandle
_IrqException:
.word ExceptionIsrEntry
_FiqException:
.word FiqExceptionHandle
.globl _start
Reset_Handler:
b _start
UndefInstrExceptionHandle:
b UndefInstrIsrEntry
SwiExceptionHandle:
b SvcIsrEntry
PrefetchAbortExceptionHandle:
b PrefetchAbortIsrEntry
DataAbortExceptionHandle:
b UndefInstrIsrEntry
ResvExceptionHandle:
b DataAbortIsrEntry
ExceptionIsrEntry:
stmfd sp!, {r0-r12,lr}
bl IsrEntry
FiqExceptionHandle:
b FiqIsrEntry

View File

@ -1,3 +1,4 @@
SRC_FILES := boot.S cache.S exception.S cortexA9.S gic.c interrupt.c mmu.c ccm_pll.c
SRC_DIR := preboot_for_nxp_imx6q_sabrelite
SRC_FILES := boot.S context_switch.S core.c
include $(KERNEL_ROOT)/compiler.mk

View File

@ -1,54 +0,0 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#ifndef ARCH_INTERRUPT_H__
#define ARCH_INTERRUPT_H__
#include <stdint.h>
#include <board.h>
#include "gic.h"
#define ARCH_MAX_IRQ_NUM PLATFORM_MAX_IRQ_NR
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 {
CPU_0,
CPU_1,
CPU_2,
CPU_3,
} cpuid_e;
struct ExceptionStackRegister
{
uint32_t r0;
uint32_t r1;
uint32_t r2;
uint32_t r3;
uint32_t r4;
uint32_t r5;
uint32_t r6;
uint32_t r7;
uint32_t r8;
uint32_t r9;
uint32_t r10;
uint32_t r11;
uint32_t r12;
uint32_t r13_sp;
uint32_t r14_lr;
uint32_t r15_pc;
uint32_t cpsr;
};
#endif

View File

@ -1,85 +0,0 @@
/*
* 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
////////////////////////////////////////////////////////////////////////////////

View File

@ -1,97 +1,109 @@
#include <asm_defines.h>
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
.global ExceptionVectors
/**
* @file start_boot.S
* @brief boot function
* @version 3.0
* @author AIIT XUOS Lab
* @date 2023.08.15
*/
.section ".startup","ax"
.globl _reset
.extern init
_reset:
/*************************************************
File name: start_boot.S
Description: cortex-a9 start boot function
Others:
History:
1. Date: 2023-08-28
Author: AIIT XUOS Lab
Modification:
1. first version
*************************************************/
#include "core.h"
/* set the cpu to SVC32 mode and disable interrupt */
mrs r0, cpsr
bic r0, r0, #0x1f
orr r0, r0, #0x13
msr cpsr_c, r0
.global _boot_start
.global CpuInitCrit
/* disable i/d cache mmu*/
mrc p15, 0, r0, c1, c0, 0
bic r0, #(1 << 12) /* i cache */
bic r0, #(1 << 2) /* d cache */
bic r0, #(1 << 0) /* mmu */
mcr p15, 0, r0, c1, c0, 0
.global primary_cpu_init
_boot_start:
@ save r0 for cores 1-3, r0 arg field passed by ROM
@ r0 is a function pointer for secondary cpus
mov r4, r0
mrs r0, cpsr /*Enter SVC mode*/
bic r0, r0, #0x1f
orr r0, r0, #0xd3
msr cpsr, r0
bl CpuInitCrit
/* set NSACR, both Secure and Non-secure access are allowed to NEON */
MRC p15, 0, r0, c1, c1, 2
ORR r0, r0, #(0x3<<10) @ enable fpu/neon
MCR p15, 0, r0, c1, c1, 2
/* Set the CPACR for access to CP10 and CP11*/
LDR r0, =0xF00000
MCR p15, 0, r0, c1, c0, 2
/* Set the FPEXC EN bit to enable the FPU */
MOV r3, #0x40000000
@VMSR FPEXC, r3
MCR p10, 7, r3, c8, c0, 0
mrc p15, 0, r0, c1, c0, 0
bic r0, r0, #(0x1<<1) @clear A bit of SCTLR
mcr p15, 0, r0, c1, c0, 0
@ clear some registers
mov r11, #0
mov r12, #0
mov lr, #0
ldr r0, =stack_top
ldr r0, =stacks_top @ symbol defined in linker file
mov r1, #MODE_STACK_SIZE
@ 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
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
mul r3, r2, r1
sub r0, r0, r3
msr CPSR_c, #ARM_MODE_SVC | I_BIT | F_BIT
mov sp, r0
sub r0, r0, r1
@ check cpu id - cpu0 is primary cpu
cmp r5, #0
beq primary_cpu_init
bx r4 @ for secondary cpus, jump to argument function pointer passed in by ROM
@ control should not return from the secondary cpu entry point
b .
@ Set the startup stack for svc
mov sp, r0
@ Enter Undefined Instruction Mode and set its Stack Pointer
msr cpsr_c, #MODE_UND|I_BIT|F_BIT
mov sp, r0
sub r0, r0, #EXCEPTION_STACK_SIZE
@ Enter Abort Mode and set its Stack Pointer
msr cpsr_c, #MODE_ABT|I_BIT|F_BIT
mov sp, r0
sub r0, r0, #EXCEPTION_STACK_SIZE
@ Enter FIQ Mode and set its Stack Pointer
msr cpsr_c, #MODE_FIQ|I_BIT|F_BIT
mov sp, r0
sub r0, r0, #EXCEPTION_STACK_SIZE
@ Enter IRQ Mode and set its Stack Pointer
msr cpsr_c, #MODE_IRQ|I_BIT|F_BIT
mov sp, r0
sub r0, r0, #EXCEPTION_STACK_SIZE
/* come back to SVC mode */
msr cpsr_c, #MODE_SVC|I_BIT|F_BIT
/*
* copy the vector table into the RAM vectors
* this assumes that the RAM vectors size is divisible by 3 words (12 bytes)
*/
ldr r1,=__ram_vectors_start
ldr r2,=__ram_vectors_end
ldr r3,=ExceptionVectors
1: cmp r1,r2
ldmlt r3!,{r4,r5,r6}
stmlt r1!,{r4,r5,r6}
primary_cpu_init:
/* init .bss */
/* clear the .bss section (zero init) */
ldr r1, =boot_start_addr
ldr r2, =boot_end_addr
mov r3, #0
1: cmp r1, r2
stmltia r1!, {r3}
blt 1b
@ branch to c library entry point
mov r0, #0 @ argc
mov r1, #0 @ argv
mov r2, #0 @ env
bl bootmain
/* clear .bss */
mov r0, #0 /* get a zero */
ldr r1,=__bss_start /* bss start */
ldr r2,=__bss_end /* bss end */
bss_loop:
cmp r1,r2 /* check if data to clear */
strlo r0,[r1],#4 /* clear 4 bytes */
blo bss_loop /* loop until done */
/* call C++ constructors of global objects */
ldr r0, =__ctors_start__
ldr r1, =__ctors_end__
bss_end:
ctor_loop:
cmp r0, r1
beq ctor_end
ldr r2, [r0], #4
stmfd sp!, {r0-r1}
mov lr, pc
bx r2
ldmfd sp!, {r0-r1}
b ctor_loop
ctor_end:
bl init
_loop_here:
b _loop_here
.end

View File

@ -1,442 +0,0 @@
/*
* 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
////////////////////////////////////////////////////////////////////////////////

View File

@ -0,0 +1,44 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
.global context_switch
context_switch:
# store original context to stack
str lr, [r13, #-4]!
str r12, [r13, #-4]!
str r11, [r13, #-4]!
str r10, [r13, #-4]!
str r9, [r13, #-4]!
str r8, [r13, #-4]!
str r7, [r13, #-4]!
str r6, [r13, #-4]!
str r5, [r13, #-4]!
str r4, [r13, #-4]!
# switch the stack
str r13, [r0] // save current sp to the old PCB (**old)
mov r13, r1 // load the next stack
# restore context from stack
ldr r4, [r13], #4
ldr r5, [r13], #4
ldr r6, [r13], #4
ldr r7, [r13], #4
ldr r8, [r13], #4
ldr r9, [r13], #4
ldr r10, [r13], #4
ldr r11, [r13], #4
ldr r12, [r13], #4
ldr lr, [r13], #4
# return to the caller
bx lr

View File

@ -0,0 +1,80 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file core.c
* @brief spl boot function
* @version 3.0
* @author AIIT XUOS Lab
* @date 2023.09.07
*/
/*************************************************
File name: core.c
Description: cortex-a9 core function, include cpu registers operationscore boot
Others:
History:
1. Date: 2023-08-28
Author: AIIT XUOS Lab
Modification:
1. first version
*************************************************/
/*********cortex-a9 general register************
Applications level view System level view
| User | Syetem | Hyp | Svc | Abort | Undefined | IRQ | FIQ
r0 r0 r0 r0 r0 r0 r0 r0 r0
r1 r1 r1 r1 r1 r1 r1 r1 r1
r2 r2 r2 r2 r2 r2 r2 r2 r2
r3 r3 r3 r3 r3 r3 r3 r3 r3
r4 r4 r4 r4 r4 r4 r4 r4 r4
r5 r5 r5 r5 r5 r5 r5 r5 r5
r6 r6 r6 r6 r6 r6 r6 r6 r6
r7 r7 r7 r7 r7 r7 r7 r7 r7
r8 r8 r8 r8 r8 r8 r8 r8 r8_fiq
r9 r9 r9 r9 r9 r9 r9 r9 r9_fiq
r10 r10 r10 r10 r10 r10 r10 r10 r10_fiq
r11 r11 r11 r11 r11 r11 r11 r11 r11_fiq
r12 r12 r12 r12 r12 r12 r12 r12 r12_fiq
SP SP SP SP_hyp SP_svc SP_abt SP_und SP_irq SP_fiq
LR LR LR LR LR_svc LR_abt LR_und LR_irq LR_fiq
PC PC PC PC PC PC PC PC PC
APSR CPSR CPSR CPSR CPSR CPSR CPSR CPSR CPSR
SPSR_hyp SPSR_svc SPSR_abt SPSR_und SPSR_irq SPSR_fiq
ELR_hyp
************************************************/
/*********cortex-a9 CP15 register***************
CRn / opc1 / CRm / opc2 / description
c0 0,1,2 c0-c7 0,1,2,3,4,5,6,7 ID寄存器相关操作
c1 0,4 c0,c1 0,1,2,3,4,5,6,7 SCTLR系统控制寄存器等
c2 0,4 c0,c1 0,1,2 TTBR0TTBR1TTBCR寄存器
c3 0 c0 0 DACR域控制寄存器
c5 0,4 c0,c1 0,1 DFSR数据异常状态寄存器IFSR指令异常状态寄存器
c6 0,4 c0 0,2,4 DFAR数据异常地址寄存器IFAR指令异常地址寄存器
c7 0,4 c0,c1,c4,c5,c6,c8,c10,c11,c14 0,1,2,3,4,5,6,7 cache操作相关寄存器
c8 0,4 c3,c5,c6,c7 0,1,2,3 TLB操作相关寄存器
c9 0,1,2,3,4,5,6,7 c12,c13,c14 0,1,2,3,4,5,6,7
c10 0,1,2,3,4,5,6,7 c0,c2 0,1,2,3,4,5,6,7 TLB权限控制寄存器
c11 0,1,2,3,4,5,6,7 c0,c1,c2,c3,c4,c5,c6,c7,c7,c15 0,1,2,3,4,5,6,7 TCM的DMA控制寄存器
c12 0,4 c0,c1 0,1
c13 0,4 c0 0,1,2,3,4 ID保存寄存器
c14 0,1,2,3,4,5,6,7 c0-c15 0,1,2,3,4,5,6,7
c15 0,1,2,3,4,5,6,7 c0-c15 0,1,2,3,4,5,6,7 (svc mode only)
MRC p15, opc1, r0, CRn, CRm, opc2 -------- CP15内寄存器CRn的值读到指定通用寄存器r0中
MCR p15, opc1, r0, CRn, CRm, opc2 -------- r0的值写到CP15内寄存器CRn中
************************************************/
#include "core.h"

View File

@ -0,0 +1,196 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file core.h
* @brief cortex-a9 core function
* @version 3.0
* @author AIIT XUOS Lab
* @date 2023.11.20
*/
/*************************************************
File name: core.h
Description: cortex-a9 core function
Others:
History:
1. Date: 2023-11-20
Author: AIIT XUOS Lab
Modification:
1. first version
*************************************************/
#pragma once
// Interrupt control bits
#define NO_INT 0xc0 // disable IRQ.
#define DIS_INT 0x80 // disable both IRQ and FIQ.
//! @name CPSR fields
//@{
#define CPSR_N (1 << 31) //!< Negative
#define CPSR_Z (1 << 30) //!< Zero
#define CPSR_C (1 << 29) //!< Carry
#define CPSR_V (1 << 28) //!< Overflow
#define CPSR_Q (1 << 27) //!< Saturation
#define CPSR_E (1 << 9) //!< Endianness
#define CPSR_A (1 << 8) //!< Async abort mask
#define CPSR_I (1 << 7) //!< IRQ mask
#define CPSR_F (1 << 6) //!< FIQ mask
#define CPSR_T (1 << 5) //!< Thumb mode
#define CPSR_MODE (0x1f) //!< Current processor mode
//@}
#define MODE_STACK_SIZE 0x4000
//! @name Interrupt enable bits in CPSR
//@{
#define I_BIT 0x80 //!< When I bit is set, IRQ is disabled
#define F_BIT 0x40 //!< When F bit is set, FIQ is disabled
//@}
// ARM modes.
#define ARM_CPSR_MODE_MASK 0x1f
#define ARM_MODE_USR 0x10
#define ARM_MODE_FIQ 0x11
#define ARM_MODE_IRQ 0x12
#define ARM_MODE_SVC 0x13
#define ARM_MODE_ABT 0x17
#define ARM_MODE_UND 0x1b
#define ARM_MODE_SYS 0x1f
#ifndef __ASSEMBLER__
#include <stdint.h>
#include <string.h>
#include "cortex_a9.h"
#define NR_CPU 4
__attribute__((always_inline)) static inline uint32_t user_mode()
{
uint32_t val;
__asm__ __volatile__(
"mrs %0, cpsr"
: "=r"(val)
:
:);
val &= ~DIS_INT;
val &= ~ARM_CPSR_MODE_MASK;
val |= ARM_MODE_USR;
return val;
}
struct context {
uint32_t r4;
uint32_t r5;
uint32_t r6;
uint32_t r7;
uint32_t r8;
uint32_t r9;
uint32_t r10;
uint32_t r11;
uint32_t r12;
uint32_t lr;
};
/// @brief init task context, set return address to trap return
/// @param
extern void trap_return(void);
__attribute__((__always_inline__)) static inline void arch_init_context(struct context* ctx)
{
memset(ctx, 0, sizeof(*ctx));
ctx->lr = (uint32_t)(trap_return);
}
struct trapframe {
uint32_t sp_usr;
uint32_t lr_usr;
uint32_t lr_svc;
uint32_t spsr;
uint32_t r0;
uint32_t r1;
uint32_t r2;
uint32_t r3;
uint32_t r4;
uint32_t r5;
uint32_t r6;
uint32_t r7;
uint32_t r8;
uint32_t r9;
uint32_t r10;
uint32_t r11;
uint32_t r12;
uint32_t pc;
};
/// @brief init task trapframe (*especially the user mode cpsr)
/// @param tf
/// @param sp
/// @param pc
__attribute__((__always_inline__)) static inline void arch_init_trapframe(struct trapframe* tf, uintptr_t sp, uintptr_t pc)
{
memset(tf, 0, sizeof(*tf));
tf->spsr = user_mode();
tf->sp_usr = sp;
tf->lr_svc = 0;
tf->lr_usr = 0;
tf->pc = pc;
}
/// @brief set pc and sp to trapframe
/// @param tf
/// @param sp
/// @param pc
__attribute__((__always_inline__)) static inline void arch_trapframe_set_sp_pc(struct trapframe* tf, uintptr_t sp, uintptr_t pc)
{
tf->sp_usr = sp;
tf->pc = pc;
}
/// @brief set params of main(int argc, char** argv) to trapframe (argc, argv)
/// @param tf
/// @param argc
/// @param argv
__attribute__((__always_inline__)) static inline void arch_set_main_params(struct trapframe* tf, int argc, uintptr_t argv)
{
tf->r0 = (uint32_t)argc;
tf->r1 = (uint32_t)argv;
}
/// @brief retrieve params to trapframe (up to max number of 6) and pass it to syscall()
/// @param sys_num
/// @param param1
/// @param param2
/// @param param3
/// @param param4
/// @param param5
/// @return
extern int syscall(int sys_num, uintptr_t param1, uintptr_t param2, uintptr_t param3, uintptr_t param4);
__attribute__((__always_inline__)) static inline int arch_syscall(struct trapframe* tf, int* syscall_num)
{
// call syscall
*syscall_num = tf->r0;
return syscall(*syscall_num, tf->r1, tf->r2, tf->r3, tf->r4);
}
/// @brief set return reg to trapframe
/// @param tf
/// @param ret
__attribute__((__always_inline__)) static inline void arch_set_return(struct trapframe* tf, int ret)
{
tf->r0 = (uint32_t)ret;
}
#endif

View File

@ -1,145 +0,0 @@
#include <asm_defines.h>
.section .text.vectors, "ax"
.code 32
.globl ExceptionVectors
ExceptionVectors:
ldr pc, _ResetException
ldr pc, _UndefInstrException
ldr pc, _SwiException
ldr pc, _PrefetchAbortException
ldr pc, _DataAbortAbortException
ldr pc, _ResvException
ldr pc, _IrqException
ldr pc, _FiqException
.globl _reset
.globl UndefInstrExceptionHandle
.globl SwiExceptionHandle
.globl PrefetchAbortExceptionHandle
.globl DataAbortExceptionHandle
.globl ResvExceptionHandle
.globl ExceptionIsrEntry
.globl FiqExceptionHandle
_ResetException:
.word _reset
_UndefInstrException:
.word UndefInstrExceptionHandle
_SwiException:
.word SwiExceptionHandle
_PrefetchAbortException:
.word PrefetchAbortExceptionHandle
_DataAbortAbortException:
.word DataAbortExceptionHandle
_ResvException:
.word ResvExceptionHandle
_IrqException:
.word ExceptionIsrEntry
_FiqException:
.word FiqExceptionHandle
.word 0 // extra word in RAM vectors
.macro push_svc_reg
sub sp, sp, #17 * 4 @/* Sizeof(struct rt_hw_exp_stack) */
stmia sp, {r0 - r12} @/* Calling r0-r12 */
mov r0, sp
mrs r6, spsr @/* Save CPSR */
str lr, [r0, #15*4] @/* Push PC */
str r6, [r0, #16*4] @/* Push CPSR */
cps #MODE_SVC
str sp, [r0, #13*4] @/* Save calling SP */
str lr, [r0, #14*4] @/* Save calling PC */
.endm
.align 5
.globl UndefInstrExceptionHandle
UndefInstrExceptionHandle:
1:
b 1b
.align 5
.globl SwiExceptionHandle
SwiExceptionHandle:
push_svc_reg
bl DoSvcCallProcess
b .
.align 5
.globl PrefetchAbortExceptionHandle
PrefetchAbortExceptionHandle:
1:
b 1b
.align 5
.globl DataAbortExceptionHandle
DataAbortExceptionHandle:
1:
b 1b
.align 5
.globl ResvExceptionHandle
ResvExceptionHandle:
1:
b 1b
.section .text.isr, "ax"
.align 5
.globl ExceptionIsrEntry
ExceptionIsrEntry:
stmfd sp!, {r0-r12,lr}
bl DoIrqProcess
@ ldr r0, =rt_thread_switch_interrupt_flag
@ ldr r1, [r0]
@ cmp r1, #1
@ beq rt_hw_context_switch_interrupt_do
ldmfd sp!, {r0-r12,lr}
subs pc, lr, #4
@ rt_hw_context_switch_interrupt_do:
@ mov r1, #0 @ clear flag
@ str r1, [r0]
@ mov r1, sp @ r1 point to {r0-r3} in stack
@ add sp, sp, #4*4
@ ldmfd sp!, {r4-r12,lr}@ reload saved registers
@ mrs r0, spsr @ get cpsr of interrupt thread
@ sub r2, lr, #4 @ save old task's pc to r2
@ @ Switch to SVC mode with no interrupt. If the usr mode guest is
@ @ interrupted, this will just switch to the stack of kernel space.
@ @ save the registers in kernel space won't trigger data abort.
@ msr cpsr_c, #I_Bit|F_Bit|Mode_SVC
@ stmfd sp!, {r2} @ push old task's pc
@ stmfd sp!, {r4-r12,lr}@ push old task's lr,r12-r4
@ ldmfd r1, {r1-r4} @ restore r0-r3 of the interrupt thread
@ stmfd sp!, {r1-r4} @ push old task's r0-r3
@ stmfd sp!, {r0} @ push old task's cpsr
@ ldr r4, =rt_interrupt_from_thread
@ ldr r5, [r4]
@ str sp, [r5] @ store sp in preempted tasks's TCB
@ ldr r6, =rt_interrupt_to_thread
@ ldr r6, [r6]
@ ldr sp, [r6] @ get new task's stack pointer
@ ldmfd sp!, {r4} @ pop new task's cpsr to spsr
@ msr spsr_cxsf, r4
@ ldmfd sp!, {r0-r12,lr,pc}^ @ pop new task's r0-r12,lr & pc, copy spsr to cpsr
.align 5
.globl FiqExceptionHandle
FiqExceptionHandle:
1:
b 1b

View File

@ -1,111 +0,0 @@
// extern void _svcall(uintptr_t* contex);
#include <stdint.h>
#include <stddef.h>
#include <isr.h>
uint32_t DisableLocalInterrupt(void)
{
uint32_t intSave;
__asm__ __volatile__(
"mrs %0, cpsr \n"
"cpsid if "
: "=r"(intSave)
:
: "memory");
return intSave;
}
void EnableLocalInterrupt(unsigned long level)
{
uint32_t intSave;
__asm__ __volatile__(
"mrs %0, cpsr \n"
"cpsie if "
: "=r"(intSave)
:
: "memory");
return;
}
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_id, true);
gic_enable_irq(irq_num, true);
return 0;
}
int32_t ArchDisableHwIrq(uint32_t irq_num, uint32_t cpu_id)
{
gic_enable_irq(irq_num, false);
gic_set_cpu_target(irq_num, cpu_id, false);
return 0;
}
extern void KTaskOsAssignAfterIrq(void *context);
void IsrEntry(uint32_t irq_num)
{
isrManager.done->incCounter();
isrManager.done->handleIrq(irq_num);
// KTaskOsAssignAfterIrq(NULL);
isrManager.done->decCounter();
}
/**
* this function will show registers of CPU
*
* @param regs the registers point
*/
void PrintStackFrame(struct ExceptionStackRegister *regs)
{
// KPrintf("Execption:\n");
// KPrintf("r0: 0x%08x\n", regs->r0);
// KPrintf("r1: 0x%08x\n", regs->r1);
// KPrintf("r2: 0x%08x\n", regs->r2);
// KPrintf("r3: 0x%08x\n", regs->r3);
// KPrintf("r4: 0x%08x\n", regs->r4);
// KPrintf("r5: 0x%08x\n", regs->r5);
// KPrintf("r6: 0x%08x\n", regs->r6);
// KPrintf("r7: 0x%08x\n", regs->r7);
// KPrintf("r8: 0x%08x\n", regs->r8);
// KPrintf("r9: 0x%08x\n", regs->r9);
// KPrintf("r10: 0x%08x\n", regs->r10);
// KPrintf("r11: 0x%08x\n", regs->r11);
// KPrintf("r12: 0x%08x\n", regs->r12);
// KPrintf("r13_sp: 0x%08x\n", regs->r13_sp);
// KPrintf("r14_lr: 0x%08x\n", regs->r14_lr);
// KPrintf("r15_pc: 0x%08x\n", regs->r15_pc);
// KPrintf("cpsr: 0x%08x\n", regs->cpsr);
}
void DoSvcCallProcess(struct ExceptionStackRegister *regs)
{
}
void DoIrqProcess(void)
{
uint32_t iar = gic_read_irq_ack();
uint32_t irq_num = iar & 0x3ff;
if(irq_num >= ARCH_MAX_IRQ_NUM)
{
gic_write_end_of_irq(irq_num);
return;
}
IsrEntry(irq_num);
gic_write_end_of_irq(irq_num);
}
// uintptr_t *Svcall(unsigned int ipsr, uintptr_t* contex )
// {
// #ifdef TASK_ISOLATION
// _svcall(contex);
// #endif
// return contex;
// }

View File

@ -1,285 +0,0 @@
/*
* 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
////////////////////////////////////////////////////////////////////////////////

View File

@ -1,157 +0,0 @@
/*
* 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
////////////////////////////////////////////////////////////////////////////////

View File

@ -0,0 +1,3 @@
SRC_FILES := ivt.c dcd.c imx6q_lowlevel_init.S cortexA9.S
include $(KERNEL_ROOT)/compiler.mk

View File

@ -1,8 +1,9 @@
export CROSS_COMPILE ?=/usr/bin/arm-none-eabi-
export CROSS_COMPILE ?= arm-none-eabi-
export DEVICE = -march=armv7-a -mtune=cortex-a9 -mfpu=vfpv3-d16 -ftree-vectorize -ffast-math -mfloat-abi=softfp
export CFLAGS := $(DEVICE) -Wall -O0 -g -gdwarf-2
export AFLAGS := -c $(DEVICE) -x assembler-with-cpp -D__ASSEMBLY__ -gdwarf-2
export LFLAGS := $(DEVICE) -Wl,--gc-sections,-Map=XiZi-imx6q-sabrelite.map,-cref,-u,ExceptionVectors -T $(BSP_ROOT)/link.lds
# export LFLAGS := $(DEVICE) -Wl,-Map=XiZi-imx6q-sabrelite.map,-cref,-u,_boot_start -T $(KERNEL_ROOT)/hardkernel/arch/arm/armv7-a/cortex-a9/preboot_for_nxp_imx6q_sabrelite/nxp_imx6q_sabrelite.lds
export LFLAGS := $(DEVICE) --specs=nosys.specs -Wl,-Map=XiZi-imx6q-sabrelite.map,-cref,-u,_boot_start -T $(KERNEL_ROOT)/hardkernel/arch/arm/armv7-a/cortex-a9/preboot_for_nxp_imx6q_sabrelite/nxp_imx6q_sabrelite.lds
export CXXFLAGS :=
ifeq ($(CONFIG_LIB_MUSLLIB), y)
@ -11,10 +12,6 @@ export LIBCC := -lgcc
export LINK_MUSLLIB := $(KERNEL_ROOT)/lib/musllib/libmusl.a
endif
# ifeq ($(CONFIG_RESOURCES_LWIP), y)
# export LINK_LWIP := $(KERNEL_ROOT)/resources/ethernet/LwIP/liblwip.a
# endif
export DEFINES := -DHAVE_CCONFIG_H -DCHIP_MX6DQ
export USING_NEWLIB =1

View File

@ -119,6 +119,7 @@ get_arm_private_peripheral_base:
@ Get base address of private perpherial space
mrc p15, 4, r0, c15, c0, 0 @ Read periph base address
@ mov r0, #0x00A00000
bx lr
.endfunc @get_arm_private_peripheral_base()@
@ -201,7 +202,8 @@ arm_branch_target_cache_invalidate_is:
.func scu_enable
scu_enable:
mrc p15, 4, r0, c15, c0, 0 @ Read periph base address
@ mrc p15, 4, r0, c15, c0, 0 @ Read periph base address
mov r0, #0x00A00000
ldr r1, [r0, #0x0] @ Read the SCU Control Register
orr r1, r1, #0x1 @ Set bit 0 (The Enable bit)
@ -255,7 +257,8 @@ scu_leave_smp:
.func scu_get_cpus_in_smp
scu_get_cpus_in_smp:
mrc p15, 4, r0, c15, c0, 0 @ Read periph base address
@ mrc p15, 4, r0, c15, c0, 0 @ Read periph base address
mov r0, #0x00A00000
ldr r0, [r0, #0x004] @ Read SCU Configuration register
mov r0, r0, lsr #4 @ Bits 7:4 gives the cores in SMP mode, shift then mask

View File

@ -0,0 +1,191 @@
/*
* Copyright (c) 2010-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 dcd.c
* @brief device configuration data function for imx6q
* @version 3.0
* @author AIIT XUOS Lab
* @date 2023.08.25
*/
/*************************************************
File name: dcd.c
Description: imx6q device configuration data
Others:
History:
1. Date: 2023-08-28
Author: AIIT XUOS Lab
Modification:
1. first version
*************************************************/
#include <hab_defines.h>
#include <soc_memory_map.h>
#include <iomux_register.h>
#include <registers.h>
//! @brief dcd data, list of (register, value) pairs to initialize ddr
uint8_t input_dcd[] __attribute__ ((section (".dcd_data")))= {
/*Use default DDR frequency: 528MHz*/
/* configure the IOMUX for the DDR3 interface */
//DATA STROBE:
DCD_DATA(IOMUXC_SW_PAD_CTL_GRP_DDRMODE_CTL, 0x00020000),
DCD_DATA(IOMUXC_SW_PAD_CTL_PAD_DRAM_SDQS0, 0x00000030),
DCD_DATA(IOMUXC_SW_PAD_CTL_PAD_DRAM_SDQS1, 0x00000030),
DCD_DATA(IOMUXC_SW_PAD_CTL_PAD_DRAM_SDQS2, 0x00000030),
DCD_DATA(IOMUXC_SW_PAD_CTL_PAD_DRAM_SDQS3, 0x00000030),
DCD_DATA(IOMUXC_SW_PAD_CTL_PAD_DRAM_SDQS4, 0x00000030),
DCD_DATA(IOMUXC_SW_PAD_CTL_PAD_DRAM_SDQS5, 0x00000030),
DCD_DATA(IOMUXC_SW_PAD_CTL_PAD_DRAM_SDQS6, 0x00000030),
DCD_DATA(IOMUXC_SW_PAD_CTL_PAD_DRAM_SDQS7, 0x00000030),
//DATA
DCD_DATA(IOMUXC_SW_PAD_CTL_GRP_DDRMODE, 0x00020000),
DCD_DATA(IOMUXC_SW_PAD_CTL_GRP_B0DS, 0x00000030),
DCD_DATA(IOMUXC_SW_PAD_CTL_GRP_B1DS, 0x00000030),
DCD_DATA(IOMUXC_SW_PAD_CTL_GRP_B2DS, 0x00000030),
DCD_DATA(IOMUXC_SW_PAD_CTL_GRP_B3DS, 0x00000030),
DCD_DATA(IOMUXC_SW_PAD_CTL_GRP_B4DS, 0x00000030),
DCD_DATA(IOMUXC_SW_PAD_CTL_GRP_B5DS, 0x00000030),
DCD_DATA(IOMUXC_SW_PAD_CTL_GRP_B6DS, 0x00000030),
DCD_DATA(IOMUXC_SW_PAD_CTL_GRP_B7DS, 0x00000030),
DCD_DATA(IOMUXC_SW_PAD_CTL_PAD_DRAM_DQM0, 0x00020030),
DCD_DATA(IOMUXC_SW_PAD_CTL_PAD_DRAM_DQM1, 0x00020030),
DCD_DATA(IOMUXC_SW_PAD_CTL_PAD_DRAM_DQM2, 0x00020030),
DCD_DATA(IOMUXC_SW_PAD_CTL_PAD_DRAM_DQM3, 0x00020030),
DCD_DATA(IOMUXC_SW_PAD_CTL_PAD_DRAM_DQM4, 0x00020030),
DCD_DATA(IOMUXC_SW_PAD_CTL_PAD_DRAM_DQM5, 0x00020030),
DCD_DATA(IOMUXC_SW_PAD_CTL_PAD_DRAM_DQM6, 0x00020030),
DCD_DATA(IOMUXC_SW_PAD_CTL_PAD_DRAM_DQM7, 0x00020030),
//ADDRESS:
DCD_DATA(IOMUXC_SW_PAD_CTL_PAD_DRAM_CAS, 0x00020030),
DCD_DATA(IOMUXC_SW_PAD_CTL_PAD_DRAM_RAS, 0x00020030),
DCD_DATA(IOMUXC_SW_PAD_CTL_GRP_ADDDS, 0x00000030),
//CLOCK:
DCD_DATA(IOMUXC_SW_PAD_CTL_PAD_DRAM_SDCLK_0, 0x00020030),
DCD_DATA(IOMUXC_SW_PAD_CTL_PAD_DRAM_SDCLK_1, 0x00020030),
//CONTROL:
DCD_DATA(IOMUXC_SW_PAD_CTL_PAD_DRAM_RESET, 0x00020030),
DCD_DATA(IOMUXC_SW_PAD_CTL_PAD_DRAM_SDCKE0, 0x00003000),
DCD_DATA(IOMUXC_SW_PAD_CTL_PAD_DRAM_SDCKE1, 0x00003000),
DCD_DATA(IOMUXC_SW_PAD_CTL_PAD_DRAM_SDBA2, 0x00000000),
DCD_DATA(IOMUXC_SW_PAD_CTL_PAD_DRAM_SDODT0, 0x00003030),
DCD_DATA(IOMUXC_SW_PAD_CTL_PAD_DRAM_SDODT1, 0x00003030),
DCD_DATA(IOMUXC_SW_PAD_CTL_GRP_CTLDS, 0x00000030),
//DDR IO TYPE:
DCD_DATA(IOMUXC_SW_PAD_CTL_GRP_DDR_TYPE, 0x000c0000),
DCD_DATA(IOMUXC_SW_PAD_CTL_GRP_DDRPKE, 0x00000000),
//read data bit delay: (3 is the reccommended default value)
DCD_DATA(MMDC_P0_BASE_ADDR + MPRDDQBY0DL_OFFSET, 0x33333333),
DCD_DATA(MMDC_P0_BASE_ADDR + MPRDDQBY1DL_OFFSET, 0x33333333),
DCD_DATA(MMDC_P0_BASE_ADDR + MPRDDQBY2DL_OFFSET, 0x33333333),
DCD_DATA(MMDC_P0_BASE_ADDR + MPRDDQBY3DL_OFFSET, 0x33333333),
DCD_DATA(MMDC_P1_BASE_ADDR + MPRDDQBY0DL_OFFSET, 0x33333333),
DCD_DATA(MMDC_P1_BASE_ADDR + MPRDDQBY1DL_OFFSET, 0x33333333),
DCD_DATA(MMDC_P1_BASE_ADDR + MPRDDQBY2DL_OFFSET, 0x33333333),
DCD_DATA(MMDC_P1_BASE_ADDR + MPRDDQBY3DL_OFFSET, 0x33333333),
// reset the MMDC and disable the chip selects.
DCD_DATA(MMDC_P0_BASE_ADDR + MDMISC_OFFSET, 0x00081740),
/* configure the MMDC */
//DDR3, 528MHz, 64-bit mode, only MMDC0 is initiated:
DCD_DATA(MMDC_P0_BASE_ADDR + MDSCR_OFFSET, 0x00008000),
DCD_DATA(MMDC_P0_BASE_ADDR + MDCFG0_OFFSET, 0x555A7975),
DCD_DATA(MMDC_P0_BASE_ADDR + MDCFG1_OFFSET, 0xFF538E64),
DCD_DATA(MMDC_P0_BASE_ADDR + MDCFG2_OFFSET, 0x01FF00DB),
DCD_DATA(MMDC_P0_BASE_ADDR + MDRWD_OFFSET, 0x000026D2),
DCD_DATA(MMDC_P0_BASE_ADDR + MDOR_OFFSET, 0x005B0E21),
DCD_DATA(MMDC_P0_BASE_ADDR + MDOTC_OFFSET, 0x09444040),
DCD_DATA(MMDC_P0_BASE_ADDR + MDPDC_OFFSET, 0x00025576),
DCD_DATA(MMDC_P0_BASE_ADDR + MDASP_OFFSET, 0x00000027),
DCD_DATA(MMDC_P0_BASE_ADDR + MDCTL_OFFSET, 0x831A0000),
/* Initialize 2GB DDR3 - Micron MT41J128M */
//MR2:
DCD_DATA(MMDC_P0_BASE_ADDR + MDSCR_OFFSET, 0x04088032),
DCD_DATA(MMDC_P0_BASE_ADDR + MDSCR_OFFSET, 0x0408803A),
//MR3:
DCD_DATA(MMDC_P0_BASE_ADDR + MDSCR_OFFSET, 0x00008033),
DCD_DATA(MMDC_P0_BASE_ADDR + MDSCR_OFFSET, 0x0000803B),
//MR1:
DCD_DATA(MMDC_P0_BASE_ADDR + MDSCR_OFFSET, 0x00428031),
DCD_DATA(MMDC_P0_BASE_ADDR + MDSCR_OFFSET, 0x00428039),
//MR0:
DCD_DATA(MMDC_P0_BASE_ADDR + MDSCR_OFFSET, 0x09408030),
DCD_DATA(MMDC_P0_BASE_ADDR + MDSCR_OFFSET, 0x09408038),
//DDR device ZQ calibration:
DCD_DATA(MMDC_P0_BASE_ADDR + MDSCR_OFFSET, 0x04008040),
DCD_DATA(MMDC_P0_BASE_ADDR + MDSCR_OFFSET, 0x04008048),
/* DDR3 calibrations */
//ZQ:
DCD_DATA(MMDC_P0_BASE_ADDR + MPZQHWCTRL_OFFSET, 0xA1380003),
DCD_DATA(MMDC_P1_BASE_ADDR + MPZQHWCTRL_OFFSET, 0xA1380003),
//final DDR setup, before operation start:
DCD_DATA(MMDC_P0_BASE_ADDR + MDREF_OFFSET, 0x00005800),
DCD_DATA(MMDC_P0_BASE_ADDR + MPODTCTRL_OFFSET, 0x00000007),
DCD_DATA(MMDC_P1_BASE_ADDR + MPODTCTRL_OFFSET, 0x00000007),
//Read DQS Gating calibration:
DCD_DATA(MMDC_P0_BASE_ADDR + MPDGCTRL0_OFFSET, 0x42720306),
DCD_DATA(MMDC_P0_BASE_ADDR + MPDGCTRL1_OFFSET, 0x026F0266),
DCD_DATA(MMDC_P1_BASE_ADDR + MPDGCTRL0_OFFSET, 0x4273030A),
DCD_DATA(MMDC_P1_BASE_ADDR + MPDGCTRL1_OFFSET, 0x02740240),
//Read calibration:
DCD_DATA(MMDC_P0_BASE_ADDR + MPRDDLCTL_OFFSET, 0x45393B3E),
DCD_DATA(MMDC_P1_BASE_ADDR + MPRDDLCTL_OFFSET, 0x403A3747),
//Write calibration:
DCD_DATA(MMDC_P0_BASE_ADDR + MPWRDLCTL_OFFSET, 0x40434541),
DCD_DATA(MMDC_P1_BASE_ADDR + MPWRDLCTL_OFFSET, 0x473E4A3B),
//write leveling:
DCD_DATA(MMDC_P0_BASE_ADDR + MPWLDECTRL0_OFFSET, 0x0011000E),
DCD_DATA(MMDC_P0_BASE_ADDR + MPWLDECTRL1_OFFSET, 0x000E001B),
DCD_DATA(MMDC_P1_BASE_ADDR + MPWLDECTRL0_OFFSET, 0x00190015),
DCD_DATA(MMDC_P1_BASE_ADDR + MPWLDECTRL1_OFFSET, 0x00070018),
//complete calibrations by forcing measurement
DCD_DATA(MMDC_P0_BASE_ADDR + MPMUR0_OFFSET, 0x00000800),
DCD_DATA(MMDC_P1_BASE_ADDR + MPMUR0_OFFSET, 0x00000800),
/* Initialize 2GB DDR3 - Micron MT41J128M */
DCD_DATA(MMDC_P0_BASE_ADDR + MDSCR_OFFSET, 0x00000000),
//final DDR setup, before operation start:
DCD_DATA(MMDC_P0_BASE_ADDR + MAPSR_OFFSET, 0x00011006),
};
//! @brief HAB command write data header, with tag,
//! size of dcd data with hdr,
//! parameter field (size of register value and flag)
uint8_t input_dcd_wrt_cmd[] __attribute__ ((section (".dcd_wrt_cmd")))= {
HAB_CMD_WRT_DAT,
EXPAND_UINT16(sizeof(input_dcd) + HDR_BYTES),
WRT_DAT_PAR(0, HAB_DATA_WIDTH_WORD) //!< flag 0, width 4
};
//! @brief HAB dcd header with dcd tag, size of entire dcd and version.
uint8_t input_dcd_hdr[] __attribute__ ((section (".dcd_hdr")))= {
HAB_TAG_DCD,
EXPAND_UINT16(sizeof(input_dcd) + sizeof(input_dcd_wrt_cmd) + HDR_BYTES),
HAB_VER(4,0)
};

View File

@ -0,0 +1,211 @@
/*
* Copyright (C) 2011 Freescale Semiconductor, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
/**
* @file imx6q_lowlevel_init.S
* @brief support imx6q lowlevel init function
* @version 3.0
* @author AIIT XUOS Lab
* @date 2023.08.15
*/
/*************************************************
File name: imx6q_lowlevel_init.S
Description: imx6q board init function, , reference from board/freescale/mx6q_sabrelite/lowlevel_init.S
Others:
History:
1. Date: 2023-08-28
Author: AIIT XUOS Lab
Modification:
1. first version
*************************************************/
#include <soc_memory_map.h>
.global CpuInitCrit
CpuInitCrit:
/*
* Invalidate L1 I/D
*/
mov r0, #0 @ set up for MCR
mcr p15, 0, r0, c8, c7, 0 @ invalidate TLBs
mcr p15, 0, r0, c7, c5, 0 @ invalidate icache
/*
* disable MMU stuff and caches
*/
mrc p15, 0, r0, c1, c0, 0
bic r0, r0, #0x00002000 @ clear bits 13 (--V-)
bic r0, r0, #0x00000007 @ clear bits 2:0 (-CAM)
orr r0, r0, #0x00000002 @ set bit 1 (--A-) Align
orr r0, r0, #0x00000800 @ set bit 12 (Z---) BTB
mcr p15, 0, r0, c1, c0, 0
/*
* Jump to board specific initialization...
* The Mask ROM will have already initialized
* basic memory. Go here to bump up clock rate and handle
* wake up conditions.
*/
mov ip, lr @ persevere link reg across call
bl lowlevel_init @ go setup pll,mux,memory
mov lr, ip @ restore link
mov pc, lr @ back to my caller
/*
Disable L2Cache because ROM turn it on when uboot use plug-in.
If L2Cache is on default, there are cache coherence problem if kernel have
not config L2Cache.
*/
.macro init_l2cc
ldr r1, =0xa02000
ldr r0, =0x0
str r0, [r1, #0x100]
.endm /* init_l2cc */
/* invalidate the D-CACHE */
.macro inv_dcache
mov r0,#0
mcr p15,2,r0,c0,c0,0 /* cache size selection register, select dcache */
mrc p15,1,r0,c0,c0,0 /* cache size ID register */
mov r0,r0,ASR #13
ldr r3,=0xfff
and r0,r0,r3
cmp r0,#0x7f
moveq r6,#0x1000
beq size_done
cmp r0,#0xff
moveq r6,#0x2000
movne r6,#0x4000
size_done:
mov r2,#0
mov r3,#0x40000000
mov r4,#0x80000000
mov r5,#0xc0000000
d_inv_loop:
mcr p15,0,r2,c7,c6,2 /* invalidate dcache by set / way */
mcr p15,0,r3,c7,c6,2 /* invalidate dcache by set / way */
mcr p15,0,r4,c7,c6,2 /* invalidate dcache by set / way */
mcr p15,0,r5,c7,c6,2 /* invalidate dcache by set / way */
add r2,r2,#0x20
add r3,r3,#0x20
add r4,r4,#0x20
add r5,r5,#0x20
cmp r2,r6
bne d_inv_loop
.endm
/* AIPS setup - Only setup MPROTx registers.
* The PACR default values are good.*/
.macro init_aips
/*
* Set all MPROTx to be non-bufferable, trusted for R/W,
* not forced to user-mode.
*/
ldr r0, =AIPS1_ON_BASE_ADDR
ldr r1, =0x77777777
str r1, [r0, #0x0]
str r1, [r0, #0x4]
ldr r1, =0x0
str r1, [r0, #0x40]
str r1, [r0, #0x44]
str r1, [r0, #0x48]
str r1, [r0, #0x4C]
str r1, [r0, #0x50]
ldr r0, =AIPS2_ON_BASE_ADDR
ldr r1, =0x77777777
str r1, [r0, #0x0]
str r1, [r0, #0x4]
ldr r1, =0x0
str r1, [r0, #0x40]
str r1, [r0, #0x44]
str r1, [r0, #0x48]
str r1, [r0, #0x4C]
str r1, [r0, #0x50]
.endm /* init_aips */
.macro setup_pll pll, freq
.endm
.macro init_clock
/* PLL1, PLL2, and PLL3 are enabled by ROM */
#ifdef CONFIG_PLL3
/* enable PLL3 for UART */
ldr r0, ANATOP_BASE_ADDR_W
/* power up PLL */
ldr r1, [r0, #ANATOP_USB1]
orr r1, r1, #0x1000
str r1, [r0, #ANATOP_USB1]
/* enable PLL */
ldr r1, [r0, #ANATOP_USB1]
orr r1, r1, #0x2000
str r1, [r0, #ANATOP_USB1]
/* wait PLL lock */
100:
ldr r1, [r0, #ANATOP_USB1]
mov r1, r1, lsr #31
cmp r1, #0x1
bne 100b
/* clear bypass bit */
ldr r1, [r0, #ANATOP_USB1]
and r1, r1, #0xfffeffff
str r1, [r0, #ANATOP_USB1]
#endif
/* Restore the default values in the Gate registers */
ldr r1, =0xFFFFFFFF
ldr r0, CCM_BASE_ADDR_W
str r1, [r0, #CLKCTL_CCGR0]
str r1, [r0, #CLKCTL_CCGR1]
str r1, [r0, #CLKCTL_CCGR2]
str r1, [r0, #CLKCTL_CCGR3]
str r1, [r0, #CLKCTL_CCGR4]
str r1, [r0, #CLKCTL_CCGR5]
str r1, [r0, #CLKCTL_CCGR6]
str r1, [r0, #CLKCTL_CCGR7]
.endm
.section ".text.init", "x"
.globl lowlevel_init
lowlevel_init:
inv_dcache
init_l2cc
init_aips
init_clock
mov pc, lr
/* Board level setting value */
ANATOP_BASE_ADDR_W: .word ANATOP_BASE_ADDR
CCM_BASE_ADDR_W: .word CCM_BASE_ADDR

View File

@ -43,18 +43,22 @@
//! @name Instruction macros
//@{
#define _ARM_NOP() asm volatile ("nop\n\t")
#define _ARM_WFI() asm volatile ("wfi\n\t")
#define _ARM_WFE() asm volatile ("wfe\n\t")
#define _ARM_SEV() asm volatile ("sev\n\t")
#define _ARM_DSB() asm volatile ("dsb\n\t")
#define _ARM_ISB() asm volatile ("isb\n\t")
#define NOP() __asm__ volatile("nop\n\t")
#define WFI() __asm__ volatile("wfi\n\t")
#define WFE() __asm__ volatile("wfe\n\t")
#define SEV() __asm__ volatile("sev\n\t")
#define DMB() __asm__ volatile("dmb\n\t")
#define DSB() __asm__ volatile("dsb\n\t")
#define ISB() __asm__ volatile("isb\n\t")
#define _ARM_MRC(coproc, opcode1, Rt, CRn, CRm, opcode2) \
asm volatile ("mrc p" #coproc ", " #opcode1 ", %[output], c" #CRn ", c" #CRm ", " #opcode2 "\n" : [output] "=r" (Rt))
#define _ARM_MCR(coproc, opcode1, Rt, CRn, CRm, opcode2) \
asm volatile ("mcr p" #coproc ", " #opcode1 ", %[input], c" #CRn ", c" #CRm ", " #opcode2 "\n" :: [input] "r" (Rt))
#define _ARM_MRC(coproc, opcode1, Rt, CRn, CRm, opcode2) \
asm volatile("mrc p" #coproc ", " #opcode1 ", %[output], c" #CRn ", c" #CRm ", " #opcode2 "\n" : [output] "=r"(Rt))
#define _ARM_MCR(coproc, opcode1, Rt, CRn, CRm, opcode2) \
asm volatile("mcr p" #coproc ", " #opcode1 ", %[input], c" #CRn ", c" #CRm ", " #opcode2 "\n" ::[input] "r"(Rt))
#define WriteReg(value, address) (*(volatile unsigned int*)(address) = (value))
#define ReadReg(address) (*(volatile unsigned int*)(address))
//@}
////////////////////////////////////////////////////////////////////////////////
@ -80,12 +84,11 @@ void enable_neon_fpu(void);
void disable_strict_align_check(void);
//! @brief Get base address of private perpherial space.
//!
//!
//! @return The address of the ARM CPU's private peripherals.
uint32_t get_arm_private_peripheral_base(void);
// uint32_t get_arm_private_peripheral_base(void);
//@}
//! @name Data cache operations
//@{

View File

@ -0,0 +1,653 @@
/*
* 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.
*/
// File: iomux_register.h
#ifndef _IOMUX_REGISTER_H_
#define _IOMUX_REGISTER_H_
//
// IOMUXC_GPR*
//
// #define IOMUXC_GPR0 0x020E0000
// #define IOMUXC_GPR1 0x020E0004
// #define IOMUXC_GPR2 0x020E0008
// #define IOMUXC_GPR3 0x020E000C
// #define IOMUXC_GPR4 0x020E0010
// #define IOMUXC_GPR5 0x020E0014
// #define IOMUXC_GPR6 0x020E0018
// #define IOMUXC_GPR7 0x020E001C
// #define IOMUXC_GPR8 0x020E0020
// #define IOMUXC_GPR9 0x020E0024
// #define IOMUXC_GPR10 0x020E0028
// #define IOMUXC_GPR11 0x020E002C
// #define IOMUXC_GPR12 0x020E0030
// #define IOMUXC_GPR13 0x020E0034
// //
// // IOMUXC_OBSERVE_MUX_*
// //
// #define IOMUXC_OBSERVE_MUX_0 0x020E0038
// #define IOMUXC_OBSERVE_MUX_1 0x020E003C
// #define IOMUXC_OBSERVE_MUX_2 0x020E0040
// #define IOMUXC_OBSERVE_MUX_3 0x020E0044
// #define IOMUXC_OBSERVE_MUX_4 0x020E0048
// //
// // IOMUXC_SW_MUX_CTL_PAD_*
// //
// #define IOMUXC_SW_MUX_CTL_PAD_SD2_DAT1 0x020E004C
// #define IOMUXC_SW_MUX_CTL_PAD_SD2_DAT2 0x020E0050
// #define IOMUXC_SW_MUX_CTL_PAD_SD2_DAT0 0x020E0054
// #define IOMUXC_SW_MUX_CTL_PAD_RGMII_TXC 0x020E0058
// #define IOMUXC_SW_MUX_CTL_PAD_RGMII_TD0 0x020E005C
// #define IOMUXC_SW_MUX_CTL_PAD_RGMII_TD1 0x020E0060
// #define IOMUXC_SW_MUX_CTL_PAD_RGMII_TD2 0x020E0064
// #define IOMUXC_SW_MUX_CTL_PAD_RGMII_TD3 0x020E0068
// #define IOMUXC_SW_MUX_CTL_PAD_RGMII_RX_CTL 0x020E006C
// #define IOMUXC_SW_MUX_CTL_PAD_RGMII_RD0 0x020E0070
// #define IOMUXC_SW_MUX_CTL_PAD_RGMII_TX_CTL 0x020E0074
// #define IOMUXC_SW_MUX_CTL_PAD_RGMII_RD1 0x020E0078
// #define IOMUXC_SW_MUX_CTL_PAD_RGMII_RD2 0x020E007C
// #define IOMUXC_SW_MUX_CTL_PAD_RGMII_RD3 0x020E0080
// #define IOMUXC_SW_MUX_CTL_PAD_RGMII_RXC 0x020E0084
// #define IOMUXC_SW_MUX_CTL_PAD_EIM_A25 0x020E0088
// #define IOMUXC_SW_MUX_CTL_PAD_EIM_EB2 0x020E008C
// #define IOMUXC_SW_MUX_CTL_PAD_EIM_D16 0x020E0090
// #define IOMUXC_SW_MUX_CTL_PAD_EIM_D17 0x020E0094
// #define IOMUXC_SW_MUX_CTL_PAD_EIM_D18 0x020E0098
// #define IOMUXC_SW_MUX_CTL_PAD_EIM_D19 0x020E009C
// #define IOMUXC_SW_MUX_CTL_PAD_EIM_D20 0x020E00A0
// #define IOMUXC_SW_MUX_CTL_PAD_EIM_D21 0x020E00A4
// #define IOMUXC_SW_MUX_CTL_PAD_EIM_D22 0x020E00A8
// #define IOMUXC_SW_MUX_CTL_PAD_EIM_D23 0x020E00AC
// #define IOMUXC_SW_MUX_CTL_PAD_EIM_EB3 0x020E00B0
// #define IOMUXC_SW_MUX_CTL_PAD_EIM_D24 0x020E00B4
// #define IOMUXC_SW_MUX_CTL_PAD_EIM_D25 0x020E00B8
// #define IOMUXC_SW_MUX_CTL_PAD_EIM_D26 0x020E00BC
// #define IOMUXC_SW_MUX_CTL_PAD_EIM_D27 0x020E00C0
// #define IOMUXC_SW_MUX_CTL_PAD_EIM_D28 0x020E00C4
// #define IOMUXC_SW_MUX_CTL_PAD_EIM_D29 0x020E00C8
// #define IOMUXC_SW_MUX_CTL_PAD_EIM_D30 0x020E00CC
// #define IOMUXC_SW_MUX_CTL_PAD_EIM_D31 0x020E00D0
// #define IOMUXC_SW_MUX_CTL_PAD_EIM_A24 0x020E00D4
// #define IOMUXC_SW_MUX_CTL_PAD_EIM_A23 0x020E00D8
// #define IOMUXC_SW_MUX_CTL_PAD_EIM_A22 0x020E00DC
// #define IOMUXC_SW_MUX_CTL_PAD_EIM_A21 0x020E00E0
// #define IOMUXC_SW_MUX_CTL_PAD_EIM_A20 0x020E00E4
// #define IOMUXC_SW_MUX_CTL_PAD_EIM_A19 0x020E00E8
// #define IOMUXC_SW_MUX_CTL_PAD_EIM_A18 0x020E00EC
// #define IOMUXC_SW_MUX_CTL_PAD_EIM_A17 0x020E00F0
// #define IOMUXC_SW_MUX_CTL_PAD_EIM_A16 0x020E00F4
// #define IOMUXC_SW_MUX_CTL_PAD_EIM_CS0 0x020E00F8
// #define IOMUXC_SW_MUX_CTL_PAD_EIM_CS1 0x020E00FC
// #define IOMUXC_SW_MUX_CTL_PAD_EIM_OE 0x020E0100
// #define IOMUXC_SW_MUX_CTL_PAD_EIM_RW 0x020E0104
// #define IOMUXC_SW_MUX_CTL_PAD_EIM_LBA 0x020E0108
// #define IOMUXC_SW_MUX_CTL_PAD_EIM_EB0 0x020E010C
// #define IOMUXC_SW_MUX_CTL_PAD_EIM_EB1 0x020E0110
// #define IOMUXC_SW_MUX_CTL_PAD_EIM_DA0 0x020E0114
// #define IOMUXC_SW_MUX_CTL_PAD_EIM_DA1 0x020E0118
// #define IOMUXC_SW_MUX_CTL_PAD_EIM_DA2 0x020E011C
// #define IOMUXC_SW_MUX_CTL_PAD_EIM_DA3 0x020E0120
// #define IOMUXC_SW_MUX_CTL_PAD_EIM_DA4 0x020E0124
// #define IOMUXC_SW_MUX_CTL_PAD_EIM_DA5 0x020E0128
// #define IOMUXC_SW_MUX_CTL_PAD_EIM_DA6 0x020E012C
// #define IOMUXC_SW_MUX_CTL_PAD_EIM_DA7 0x020E0130
// #define IOMUXC_SW_MUX_CTL_PAD_EIM_DA8 0x020E0134
// #define IOMUXC_SW_MUX_CTL_PAD_EIM_DA9 0x020E0138
// #define IOMUXC_SW_MUX_CTL_PAD_EIM_DA10 0x020E013C
// #define IOMUXC_SW_MUX_CTL_PAD_EIM_DA11 0x020E0140
// #define IOMUXC_SW_MUX_CTL_PAD_EIM_DA12 0x020E0144
// #define IOMUXC_SW_MUX_CTL_PAD_EIM_DA13 0x020E0148
// #define IOMUXC_SW_MUX_CTL_PAD_EIM_DA14 0x020E014C
// #define IOMUXC_SW_MUX_CTL_PAD_EIM_DA15 0x020E0150
// #define IOMUXC_SW_MUX_CTL_PAD_EIM_WAIT 0x020E0154
// #define IOMUXC_SW_MUX_CTL_PAD_EIM_BCLK 0x020E0158
// #define IOMUXC_SW_MUX_CTL_PAD_DI0_DISP_CLK 0x020E015C
// #define IOMUXC_SW_MUX_CTL_PAD_DI0_PIN15 0x020E0160
// #define IOMUXC_SW_MUX_CTL_PAD_DI0_PIN2 0x020E0164
// #define IOMUXC_SW_MUX_CTL_PAD_DI0_PIN3 0x020E0168
// #define IOMUXC_SW_MUX_CTL_PAD_DI0_PIN4 0x020E016C
// #define IOMUXC_SW_MUX_CTL_PAD_DISP0_DAT0 0x020E0170
// #define IOMUXC_SW_MUX_CTL_PAD_DISP0_DAT1 0x020E0174
// #define IOMUXC_SW_MUX_CTL_PAD_DISP0_DAT2 0x020E0178
// #define IOMUXC_SW_MUX_CTL_PAD_DISP0_DAT3 0x020E017C
// #define IOMUXC_SW_MUX_CTL_PAD_DISP0_DAT4 0x020E0180
// #define IOMUXC_SW_MUX_CTL_PAD_DISP0_DAT5 0x020E0184
// #define IOMUXC_SW_MUX_CTL_PAD_DISP0_DAT6 0x020E0188
// #define IOMUXC_SW_MUX_CTL_PAD_DISP0_DAT7 0x020E018C
// #define IOMUXC_SW_MUX_CTL_PAD_DISP0_DAT8 0x020E0190
// #define IOMUXC_SW_MUX_CTL_PAD_DISP0_DAT9 0x020E0194
// #define IOMUXC_SW_MUX_CTL_PAD_DISP0_DAT10 0x020E0198
// #define IOMUXC_SW_MUX_CTL_PAD_DISP0_DAT11 0x020E019C
// #define IOMUXC_SW_MUX_CTL_PAD_DISP0_DAT12 0x020E01A0
// #define IOMUXC_SW_MUX_CTL_PAD_DISP0_DAT13 0x020E01A4
// #define IOMUXC_SW_MUX_CTL_PAD_DISP0_DAT14 0x020E01A8
// #define IOMUXC_SW_MUX_CTL_PAD_DISP0_DAT15 0x020E01AC
// #define IOMUXC_SW_MUX_CTL_PAD_DISP0_DAT16 0x020E01B0
// #define IOMUXC_SW_MUX_CTL_PAD_DISP0_DAT17 0x020E01B4
// #define IOMUXC_SW_MUX_CTL_PAD_DISP0_DAT18 0x020E01B8
// #define IOMUXC_SW_MUX_CTL_PAD_DISP0_DAT19 0x020E01BC
// #define IOMUXC_SW_MUX_CTL_PAD_DISP0_DAT20 0x020E01C0
// #define IOMUXC_SW_MUX_CTL_PAD_DISP0_DAT21 0x020E01C4
// #define IOMUXC_SW_MUX_CTL_PAD_DISP0_DAT22 0x020E01C8
// #define IOMUXC_SW_MUX_CTL_PAD_DISP0_DAT23 0x020E01CC
// #define IOMUXC_SW_MUX_CTL_PAD_ENET_MDIO 0x020E01D0
// #define IOMUXC_SW_MUX_CTL_PAD_ENET_REF_CLK 0x020E01D4
// #define IOMUXC_SW_MUX_CTL_PAD_ENET_RX_ER 0x020E01D8
// #define IOMUXC_SW_MUX_CTL_PAD_ENET_CRS_DV 0x020E01DC
// #define IOMUXC_SW_MUX_CTL_PAD_ENET_RXD1 0x020E01E0
// #define IOMUXC_SW_MUX_CTL_PAD_ENET_RXD0 0x020E01E4
// #define IOMUXC_SW_MUX_CTL_PAD_ENET_TX_EN 0x020E01E8
// #define IOMUXC_SW_MUX_CTL_PAD_ENET_TXD1 0x020E01EC
// #define IOMUXC_SW_MUX_CTL_PAD_ENET_TXD0 0x020E01F0
// #define IOMUXC_SW_MUX_CTL_PAD_ENET_MDC 0x020E01F4
// #define IOMUXC_SW_MUX_CTL_PAD_KEY_COL0 0x020E01F8
// #define IOMUXC_SW_MUX_CTL_PAD_KEY_ROW0 0x020E01FC
// #define IOMUXC_SW_MUX_CTL_PAD_KEY_COL1 0x020E0200
// #define IOMUXC_SW_MUX_CTL_PAD_KEY_ROW1 0x020E0204
// #define IOMUXC_SW_MUX_CTL_PAD_KEY_COL2 0x020E0208
// #define IOMUXC_SW_MUX_CTL_PAD_KEY_ROW2 0x020E020C
// #define IOMUXC_SW_MUX_CTL_PAD_KEY_COL3 0x020E0210
// #define IOMUXC_SW_MUX_CTL_PAD_KEY_ROW3 0x020E0214
// #define IOMUXC_SW_MUX_CTL_PAD_KEY_COL4 0x020E0218
// #define IOMUXC_SW_MUX_CTL_PAD_KEY_ROW4 0x020E021C
// #define IOMUXC_SW_MUX_CTL_PAD_GPIO_0 0x020E0220
// #define IOMUXC_SW_MUX_CTL_PAD_GPIO_1 0x020E0224
// #define IOMUXC_SW_MUX_CTL_PAD_GPIO_9 0x020E0228
// #define IOMUXC_SW_MUX_CTL_PAD_GPIO_3 0x020E022C
// #define IOMUXC_SW_MUX_CTL_PAD_GPIO_6 0x020E0230
// #define IOMUXC_SW_MUX_CTL_PAD_GPIO_2 0x020E0234
// #define IOMUXC_SW_MUX_CTL_PAD_GPIO_4 0x020E0238
// #define IOMUXC_SW_MUX_CTL_PAD_GPIO_5 0x020E023C
// #define IOMUXC_SW_MUX_CTL_PAD_GPIO_7 0x020E0240
// #define IOMUXC_SW_MUX_CTL_PAD_GPIO_8 0x020E0244
// #define IOMUXC_SW_MUX_CTL_PAD_GPIO_16 0x020E0248
// #define IOMUXC_SW_MUX_CTL_PAD_GPIO_17 0x020E024C
// #define IOMUXC_SW_MUX_CTL_PAD_GPIO_18 0x020E0250
// #define IOMUXC_SW_MUX_CTL_PAD_GPIO_19 0x020E0254
// #define IOMUXC_SW_MUX_CTL_PAD_CSI0_PIXCLK 0x020E0258
// #define IOMUXC_SW_MUX_CTL_PAD_CSI0_MCLK 0x020E025C
// #define IOMUXC_SW_MUX_CTL_PAD_CSI0_DATA_EN 0x020E0260
// #define IOMUXC_SW_MUX_CTL_PAD_CSI0_VSYNC 0x020E0264
// #define IOMUXC_SW_MUX_CTL_PAD_CSI0_DAT4 0x020E0268
// #define IOMUXC_SW_MUX_CTL_PAD_CSI0_DAT5 0x020E026C
// #define IOMUXC_SW_MUX_CTL_PAD_CSI0_DAT6 0x020E0270
// #define IOMUXC_SW_MUX_CTL_PAD_CSI0_DAT7 0x020E0274
// #define IOMUXC_SW_MUX_CTL_PAD_CSI0_DAT8 0x020E0278
// #define IOMUXC_SW_MUX_CTL_PAD_CSI0_DAT9 0x020E027C
// #define IOMUXC_SW_MUX_CTL_PAD_CSI0_DAT10 0x020E0280
// #define IOMUXC_SW_MUX_CTL_PAD_CSI0_DAT11 0x020E0284
// #define IOMUXC_SW_MUX_CTL_PAD_CSI0_DAT12 0x020E0288
// #define IOMUXC_SW_MUX_CTL_PAD_CSI0_DAT13 0x020E028C
// #define IOMUXC_SW_MUX_CTL_PAD_CSI0_DAT14 0x020E0290
// #define IOMUXC_SW_MUX_CTL_PAD_CSI0_DAT15 0x020E0294
// #define IOMUXC_SW_MUX_CTL_PAD_CSI0_DAT16 0x020E0298
// #define IOMUXC_SW_MUX_CTL_PAD_CSI0_DAT17 0x020E029C
// #define IOMUXC_SW_MUX_CTL_PAD_CSI0_DAT18 0x020E02A0
// #define IOMUXC_SW_MUX_CTL_PAD_CSI0_DAT19 0x020E02A4
// #define IOMUXC_SW_MUX_CTL_PAD_SD3_DAT7 0x020E02A8
// #define IOMUXC_SW_MUX_CTL_PAD_SD3_DAT6 0x020E02AC
// #define IOMUXC_SW_MUX_CTL_PAD_SD3_DAT5 0x020E02B0
// #define IOMUXC_SW_MUX_CTL_PAD_SD3_DAT4 0x020E02B4
// #define IOMUXC_SW_MUX_CTL_PAD_SD3_CMD 0x020E02B8
// #define IOMUXC_SW_MUX_CTL_PAD_SD3_CLK 0x020E02BC
// #define IOMUXC_SW_MUX_CTL_PAD_SD3_DAT0 0x020E02C0
// #define IOMUXC_SW_MUX_CTL_PAD_SD3_DAT1 0x020E02C4
// #define IOMUXC_SW_MUX_CTL_PAD_SD3_DAT2 0x020E02C8
// #define IOMUXC_SW_MUX_CTL_PAD_SD3_DAT3 0x020E02CC
// #define IOMUXC_SW_MUX_CTL_PAD_SD3_RST 0x020E02D0
// #define IOMUXC_SW_MUX_CTL_PAD_NANDF_CLE 0x020E02D4
// #define IOMUXC_SW_MUX_CTL_PAD_NANDF_ALE 0x020E02D8
// #define IOMUXC_SW_MUX_CTL_PAD_NANDF_WP_B 0x020E02DC
// #define IOMUXC_SW_MUX_CTL_PAD_NANDF_RB0 0x020E02E0
// #define IOMUXC_SW_MUX_CTL_PAD_NANDF_CS0 0x020E02E4
// #define IOMUXC_SW_MUX_CTL_PAD_NANDF_CS1 0x020E02E8
// #define IOMUXC_SW_MUX_CTL_PAD_NANDF_CS2 0x020E02EC
// #define IOMUXC_SW_MUX_CTL_PAD_NANDF_CS3 0x020E02F0
// #define IOMUXC_SW_MUX_CTL_PAD_SD4_CMD 0x020E02F4
// #define IOMUXC_SW_MUX_CTL_PAD_SD4_CLK 0x020E02F8
// #define IOMUXC_SW_MUX_CTL_PAD_NANDF_D0 0x020E02FC
// #define IOMUXC_SW_MUX_CTL_PAD_NANDF_D1 0x020E0300
// #define IOMUXC_SW_MUX_CTL_PAD_NANDF_D2 0x020E0304
// #define IOMUXC_SW_MUX_CTL_PAD_NANDF_D3 0x020E0308
// #define IOMUXC_SW_MUX_CTL_PAD_NANDF_D4 0x020E030C
// #define IOMUXC_SW_MUX_CTL_PAD_NANDF_D5 0x020E0310
// #define IOMUXC_SW_MUX_CTL_PAD_NANDF_D6 0x020E0314
// #define IOMUXC_SW_MUX_CTL_PAD_NANDF_D7 0x020E0318
// #define IOMUXC_SW_MUX_CTL_PAD_SD4_DAT0 0x020E031C
// #define IOMUXC_SW_MUX_CTL_PAD_SD4_DAT1 0x020E0320
// #define IOMUXC_SW_MUX_CTL_PAD_SD4_DAT2 0x020E0324
// #define IOMUXC_SW_MUX_CTL_PAD_SD4_DAT3 0x020E0328
// #define IOMUXC_SW_MUX_CTL_PAD_SD4_DAT4 0x020E032C
// #define IOMUXC_SW_MUX_CTL_PAD_SD4_DAT5 0x020E0330
// #define IOMUXC_SW_MUX_CTL_PAD_SD4_DAT6 0x020E0334
// #define IOMUXC_SW_MUX_CTL_PAD_SD4_DAT7 0x020E0338
// #define IOMUXC_SW_MUX_CTL_PAD_SD1_DAT1 0x020E033C
// #define IOMUXC_SW_MUX_CTL_PAD_SD1_DAT0 0x020E0340
// #define IOMUXC_SW_MUX_CTL_PAD_SD1_DAT3 0x020E0344
// #define IOMUXC_SW_MUX_CTL_PAD_SD1_CMD 0x020E0348
// #define IOMUXC_SW_MUX_CTL_PAD_SD1_DAT2 0x020E034C
// #define IOMUXC_SW_MUX_CTL_PAD_SD1_CLK 0x020E0350
// #define IOMUXC_SW_MUX_CTL_PAD_SD2_CLK 0x020E0354
// #define IOMUXC_SW_MUX_CTL_PAD_SD2_CMD 0x020E0358
// #define IOMUXC_SW_MUX_CTL_PAD_SD2_DAT3 0x020E035C
// //
// // IOMUXC_SW_PAD_CTL_PAD_*
// // IOMUXC_SW_PAD_CTL_GRP_*
// //
// #define IOMUXC_SW_PAD_CTL_PAD_SD2_DAT1 0x020E0360
// #define IOMUXC_SW_PAD_CTL_PAD_SD2_DAT2 0x020E0364
// #define IOMUXC_SW_PAD_CTL_PAD_SD2_DAT0 0x020E0368
// #define IOMUXC_SW_PAD_CTL_PAD_RGMII_TXC 0x020E036C
// #define IOMUXC_SW_PAD_CTL_PAD_RGMII_TD0 0x020E0370
// #define IOMUXC_SW_PAD_CTL_PAD_RGMII_TD1 0x020E0374
// #define IOMUXC_SW_PAD_CTL_PAD_RGMII_TD2 0x020E0378
// #define IOMUXC_SW_PAD_CTL_PAD_RGMII_TD3 0x020E037C
// #define IOMUXC_SW_PAD_CTL_PAD_RGMII_RX_CTL 0x020E0380
// #define IOMUXC_SW_PAD_CTL_PAD_RGMII_RD0 0x020E0384
// #define IOMUXC_SW_PAD_CTL_PAD_RGMII_TX_CTL 0x020E0388
// #define IOMUXC_SW_PAD_CTL_PAD_RGMII_RD1 0x020E038C
// #define IOMUXC_SW_PAD_CTL_PAD_RGMII_RD2 0x020E0390
// #define IOMUXC_SW_PAD_CTL_PAD_RGMII_RD3 0x020E0394
// #define IOMUXC_SW_PAD_CTL_PAD_RGMII_RXC 0x020E0398
// #define IOMUXC_SW_PAD_CTL_PAD_EIM_A25 0x020E039C
// #define IOMUXC_SW_PAD_CTL_PAD_EIM_EB2 0x020E03A0
// #define IOMUXC_SW_PAD_CTL_PAD_EIM_D16 0x020E03A4
// #define IOMUXC_SW_PAD_CTL_PAD_EIM_D17 0x020E03A8
// #define IOMUXC_SW_PAD_CTL_PAD_EIM_D18 0x020E03AC
// #define IOMUXC_SW_PAD_CTL_PAD_EIM_D19 0x020E03B0
// #define IOMUXC_SW_PAD_CTL_PAD_EIM_D20 0x020E03B4
// #define IOMUXC_SW_PAD_CTL_PAD_EIM_D21 0x020E03B8
// #define IOMUXC_SW_PAD_CTL_PAD_EIM_D22 0x020E03BC
// #define IOMUXC_SW_PAD_CTL_PAD_EIM_D23 0x020E03C0
// #define IOMUXC_SW_PAD_CTL_PAD_EIM_EB3 0x020E03C4
// #define IOMUXC_SW_PAD_CTL_PAD_EIM_D24 0x020E03C8
// #define IOMUXC_SW_PAD_CTL_PAD_EIM_D25 0x020E03CC
// #define IOMUXC_SW_PAD_CTL_PAD_EIM_D26 0x020E03D0
// #define IOMUXC_SW_PAD_CTL_PAD_EIM_D27 0x020E03D4
// #define IOMUXC_SW_PAD_CTL_PAD_EIM_D28 0x020E03D8
// #define IOMUXC_SW_PAD_CTL_PAD_EIM_D29 0x020E03DC
// #define IOMUXC_SW_PAD_CTL_PAD_EIM_D30 0x020E03E0
// #define IOMUXC_SW_PAD_CTL_PAD_EIM_D31 0x020E03E4
// #define IOMUXC_SW_PAD_CTL_PAD_EIM_A24 0x020E03E8
// #define IOMUXC_SW_PAD_CTL_PAD_EIM_A23 0x020E03EC
// #define IOMUXC_SW_PAD_CTL_PAD_EIM_A22 0x020E03F0
// #define IOMUXC_SW_PAD_CTL_PAD_EIM_A21 0x020E03F4
// #define IOMUXC_SW_PAD_CTL_PAD_EIM_A20 0x020E03F8
// #define IOMUXC_SW_PAD_CTL_PAD_EIM_A19 0x020E03FC
// #define IOMUXC_SW_PAD_CTL_PAD_EIM_A18 0x020E0400
// #define IOMUXC_SW_PAD_CTL_PAD_EIM_A17 0x020E0404
// #define IOMUXC_SW_PAD_CTL_PAD_EIM_A16 0x020E0408
// #define IOMUXC_SW_PAD_CTL_PAD_EIM_CS0 0x020E040C
// #define IOMUXC_SW_PAD_CTL_PAD_EIM_CS1 0x020E0410
// #define IOMUXC_SW_PAD_CTL_PAD_EIM_OE 0x020E0414
// #define IOMUXC_SW_PAD_CTL_PAD_EIM_RW 0x020E0418
// #define IOMUXC_SW_PAD_CTL_PAD_EIM_LBA 0x020E041C
// #define IOMUXC_SW_PAD_CTL_PAD_EIM_EB0 0x020E0420
// #define IOMUXC_SW_PAD_CTL_PAD_EIM_EB1 0x020E0424
// #define IOMUXC_SW_PAD_CTL_PAD_EIM_DA0 0x020E0428
// #define IOMUXC_SW_PAD_CTL_PAD_EIM_DA1 0x020E042C
// #define IOMUXC_SW_PAD_CTL_PAD_EIM_DA2 0x020E0430
// #define IOMUXC_SW_PAD_CTL_PAD_EIM_DA3 0x020E0434
// #define IOMUXC_SW_PAD_CTL_PAD_EIM_DA4 0x020E0438
// #define IOMUXC_SW_PAD_CTL_PAD_EIM_DA5 0x020E043C
// #define IOMUXC_SW_PAD_CTL_PAD_EIM_DA6 0x020E0440
// #define IOMUXC_SW_PAD_CTL_PAD_EIM_DA7 0x020E0444
// #define IOMUXC_SW_PAD_CTL_PAD_EIM_DA8 0x020E0448
// #define IOMUXC_SW_PAD_CTL_PAD_EIM_DA9 0x020E044C
// #define IOMUXC_SW_PAD_CTL_PAD_EIM_DA10 0x020E0450
// #define IOMUXC_SW_PAD_CTL_PAD_EIM_DA11 0x020E0454
// #define IOMUXC_SW_PAD_CTL_PAD_EIM_DA12 0x020E0458
// #define IOMUXC_SW_PAD_CTL_PAD_EIM_DA13 0x020E045C
// #define IOMUXC_SW_PAD_CTL_PAD_EIM_DA14 0x020E0460
// #define IOMUXC_SW_PAD_CTL_PAD_EIM_DA15 0x020E0464
// #define IOMUXC_SW_PAD_CTL_PAD_EIM_WAIT 0x020E0468
// #define IOMUXC_SW_PAD_CTL_PAD_EIM_BCLK 0x020E046C
// #define IOMUXC_SW_PAD_CTL_PAD_DI0_DISP_CLK 0x020E0470
// #define IOMUXC_SW_PAD_CTL_PAD_DI0_PIN15 0x020E0474
// #define IOMUXC_SW_PAD_CTL_PAD_DI0_PIN2 0x020E0478
// #define IOMUXC_SW_PAD_CTL_PAD_DI0_PIN3 0x020E047C
// #define IOMUXC_SW_PAD_CTL_PAD_DI0_PIN4 0x020E0480
// #define IOMUXC_SW_PAD_CTL_PAD_DISP0_DAT0 0x020E0484
// #define IOMUXC_SW_PAD_CTL_PAD_DISP0_DAT1 0x020E0488
// #define IOMUXC_SW_PAD_CTL_PAD_DISP0_DAT2 0x020E048C
// #define IOMUXC_SW_PAD_CTL_PAD_DISP0_DAT3 0x020E0490
// #define IOMUXC_SW_PAD_CTL_PAD_DISP0_DAT4 0x020E0494
// #define IOMUXC_SW_PAD_CTL_PAD_DISP0_DAT5 0x020E0498
// #define IOMUXC_SW_PAD_CTL_PAD_DISP0_DAT6 0x020E049C
// #define IOMUXC_SW_PAD_CTL_PAD_DISP0_DAT7 0x020E04A0
// #define IOMUXC_SW_PAD_CTL_PAD_DISP0_DAT8 0x020E04A4
// #define IOMUXC_SW_PAD_CTL_PAD_DISP0_DAT9 0x020E04A8
// #define IOMUXC_SW_PAD_CTL_PAD_DISP0_DAT10 0x020E04AC
// #define IOMUXC_SW_PAD_CTL_PAD_DISP0_DAT11 0x020E04B0
// #define IOMUXC_SW_PAD_CTL_PAD_DISP0_DAT12 0x020E04B4
// #define IOMUXC_SW_PAD_CTL_PAD_DISP0_DAT13 0x020E04B8
// #define IOMUXC_SW_PAD_CTL_PAD_DISP0_DAT14 0x020E04BC
// #define IOMUXC_SW_PAD_CTL_PAD_DISP0_DAT15 0x020E04C0
// #define IOMUXC_SW_PAD_CTL_PAD_DISP0_DAT16 0x020E04C4
// #define IOMUXC_SW_PAD_CTL_PAD_DISP0_DAT17 0x020E04C8
// #define IOMUXC_SW_PAD_CTL_PAD_DISP0_DAT18 0x020E04CC
// #define IOMUXC_SW_PAD_CTL_PAD_DISP0_DAT19 0x020E04D0
// #define IOMUXC_SW_PAD_CTL_PAD_DISP0_DAT20 0x020E04D4
// #define IOMUXC_SW_PAD_CTL_PAD_DISP0_DAT21 0x020E04D8
// #define IOMUXC_SW_PAD_CTL_PAD_DISP0_DAT22 0x020E04DC
// #define IOMUXC_SW_PAD_CTL_PAD_DISP0_DAT23 0x020E04E0
// #define IOMUXC_SW_PAD_CTL_PAD_ENET_MDIO 0x020E04E4
// #define IOMUXC_SW_PAD_CTL_PAD_ENET_REF_CLK 0x020E04E8
// #define IOMUXC_SW_PAD_CTL_PAD_ENET_RX_ER 0x020E04EC
// #define IOMUXC_SW_PAD_CTL_PAD_ENET_CRS_DV 0x020E04F0
// #define IOMUXC_SW_PAD_CTL_PAD_ENET_RXD1 0x020E04F4
// #define IOMUXC_SW_PAD_CTL_PAD_ENET_RXD0 0x020E04F8
// #define IOMUXC_SW_PAD_CTL_PAD_ENET_TX_EN 0x020E04FC
// #define IOMUXC_SW_PAD_CTL_PAD_ENET_TXD1 0x020E0500
// #define IOMUXC_SW_PAD_CTL_PAD_ENET_TXD0 0x020E0504
// #define IOMUXC_SW_PAD_CTL_PAD_ENET_MDC 0x020E0508
#define IOMUXC_SW_PAD_CTL_PAD_DRAM_SDQS5 0x020E050C
#define IOMUXC_SW_PAD_CTL_PAD_DRAM_DQM5 0x020E0510
#define IOMUXC_SW_PAD_CTL_PAD_DRAM_DQM4 0x020E0514
#define IOMUXC_SW_PAD_CTL_PAD_DRAM_SDQS4 0x020E0518
#define IOMUXC_SW_PAD_CTL_PAD_DRAM_SDQS3 0x020E051C
#define IOMUXC_SW_PAD_CTL_PAD_DRAM_DQM3 0x020E0520
#define IOMUXC_SW_PAD_CTL_PAD_DRAM_SDQS2 0x020E0524
#define IOMUXC_SW_PAD_CTL_PAD_DRAM_DQM2 0x020E0528
#define IOMUXC_SW_PAD_CTL_PAD_DRAM_A0 0x020E052C
#define IOMUXC_SW_PAD_CTL_PAD_DRAM_A1 0x020E0530
#define IOMUXC_SW_PAD_CTL_PAD_DRAM_A2 0x020E0534
#define IOMUXC_SW_PAD_CTL_PAD_DRAM_A3 0x020E0538
#define IOMUXC_SW_PAD_CTL_PAD_DRAM_A4 0x020E053C
#define IOMUXC_SW_PAD_CTL_PAD_DRAM_A5 0x020E0540
#define IOMUXC_SW_PAD_CTL_PAD_DRAM_A6 0x020E0544
#define IOMUXC_SW_PAD_CTL_PAD_DRAM_A7 0x020E0548
#define IOMUXC_SW_PAD_CTL_PAD_DRAM_A8 0x020E054C
#define IOMUXC_SW_PAD_CTL_PAD_DRAM_A9 0x020E0550
#define IOMUXC_SW_PAD_CTL_PAD_DRAM_A10 0x020E0554
#define IOMUXC_SW_PAD_CTL_PAD_DRAM_A11 0x020E0558
#define IOMUXC_SW_PAD_CTL_PAD_DRAM_A12 0x020E055C
#define IOMUXC_SW_PAD_CTL_PAD_DRAM_A13 0x020E0560
#define IOMUXC_SW_PAD_CTL_PAD_DRAM_A14 0x020E0564
#define IOMUXC_SW_PAD_CTL_PAD_DRAM_A15 0x020E0568
#define IOMUXC_SW_PAD_CTL_PAD_DRAM_CAS 0x020E056C
#define IOMUXC_SW_PAD_CTL_PAD_DRAM_CS0 0x020E0570
#define IOMUXC_SW_PAD_CTL_PAD_DRAM_CS1 0x020E0574
#define IOMUXC_SW_PAD_CTL_PAD_DRAM_RAS 0x020E0578
#define IOMUXC_SW_PAD_CTL_PAD_DRAM_RESET 0x020E057C
#define IOMUXC_SW_PAD_CTL_PAD_DRAM_SDBA0 0x020E0580
#define IOMUXC_SW_PAD_CTL_PAD_DRAM_SDBA1 0x020E0584
#define IOMUXC_SW_PAD_CTL_PAD_DRAM_SDCLK_0 0x020E0588
#define IOMUXC_SW_PAD_CTL_PAD_DRAM_SDBA2 0x020E058C
#define IOMUXC_SW_PAD_CTL_PAD_DRAM_SDCKE0 0x020E0590
#define IOMUXC_SW_PAD_CTL_PAD_DRAM_SDCLK_1 0x020E0594
#define IOMUXC_SW_PAD_CTL_PAD_DRAM_SDCKE1 0x020E0598
#define IOMUXC_SW_PAD_CTL_PAD_DRAM_SDODT0 0x020E059C
#define IOMUXC_SW_PAD_CTL_PAD_DRAM_SDODT1 0x020E05A0
#define IOMUXC_SW_PAD_CTL_PAD_DRAM_SDWE 0x020E05A4
#define IOMUXC_SW_PAD_CTL_PAD_DRAM_SDQS0 0x020E05A8
#define IOMUXC_SW_PAD_CTL_PAD_DRAM_DQM0 0x020E05AC
#define IOMUXC_SW_PAD_CTL_PAD_DRAM_SDQS1 0x020E05B0
#define IOMUXC_SW_PAD_CTL_PAD_DRAM_DQM1 0x020E05B4
#define IOMUXC_SW_PAD_CTL_PAD_DRAM_SDQS6 0x020E05B8
#define IOMUXC_SW_PAD_CTL_PAD_DRAM_DQM6 0x020E05BC
#define IOMUXC_SW_PAD_CTL_PAD_DRAM_SDQS7 0x020E05C0
#define IOMUXC_SW_PAD_CTL_PAD_DRAM_DQM7 0x020E05C4
// #define IOMUXC_SW_PAD_CTL_PAD_KEY_COL0 0x020E05C8
// #define IOMUXC_SW_PAD_CTL_PAD_KEY_ROW0 0x020E05CC
// #define IOMUXC_SW_PAD_CTL_PAD_KEY_COL1 0x020E05D0
// #define IOMUXC_SW_PAD_CTL_PAD_KEY_ROW1 0x020E05D4
// #define IOMUXC_SW_PAD_CTL_PAD_KEY_COL2 0x020E05D8
// #define IOMUXC_SW_PAD_CTL_PAD_KEY_ROW2 0x020E05DC
// #define IOMUXC_SW_PAD_CTL_PAD_KEY_COL3 0x020E05E0
// #define IOMUXC_SW_PAD_CTL_PAD_KEY_ROW3 0x020E05E4
// #define IOMUXC_SW_PAD_CTL_PAD_KEY_COL4 0x020E05E8
// #define IOMUXC_SW_PAD_CTL_PAD_KEY_ROW4 0x020E05EC
// #define IOMUXC_SW_PAD_CTL_PAD_GPIO_0 0x020E05F0
// #define IOMUXC_SW_PAD_CTL_PAD_GPIO_1 0x020E05F4
// #define IOMUXC_SW_PAD_CTL_PAD_GPIO_9 0x020E05F8
// #define IOMUXC_SW_PAD_CTL_PAD_GPIO_3 0x020E05FC
// #define IOMUXC_SW_PAD_CTL_PAD_GPIO_6 0x020E0600
// #define IOMUXC_SW_PAD_CTL_PAD_GPIO_2 0x020E0604
// #define IOMUXC_SW_PAD_CTL_PAD_GPIO_4 0x020E0608
// #define IOMUXC_SW_PAD_CTL_PAD_GPIO_5 0x020E060C
// #define IOMUXC_SW_PAD_CTL_PAD_GPIO_7 0x020E0610
// #define IOMUXC_SW_PAD_CTL_PAD_GPIO_8 0x020E0614
// #define IOMUXC_SW_PAD_CTL_PAD_GPIO_16 0x020E0618
// #define IOMUXC_SW_PAD_CTL_PAD_GPIO_17 0x020E061C
// #define IOMUXC_SW_PAD_CTL_PAD_GPIO_18 0x020E0620
// #define IOMUXC_SW_PAD_CTL_PAD_GPIO_19 0x020E0624
// #define IOMUXC_SW_PAD_CTL_PAD_CSI0_PIXCLK 0x020E0628
// #define IOMUXC_SW_PAD_CTL_PAD_CSI0_MCLK 0x020E062C
// #define IOMUXC_SW_PAD_CTL_PAD_CSI0_DATA_EN 0x020E0630
// #define IOMUXC_SW_PAD_CTL_PAD_CSI0_VSYNC 0x020E0634
// #define IOMUXC_SW_PAD_CTL_PAD_CSI0_DAT4 0x020E0638
// #define IOMUXC_SW_PAD_CTL_PAD_CSI0_DAT5 0x020E063C
// #define IOMUXC_SW_PAD_CTL_PAD_CSI0_DAT6 0x020E0640
// #define IOMUXC_SW_PAD_CTL_PAD_CSI0_DAT7 0x020E0644
// #define IOMUXC_SW_PAD_CTL_PAD_CSI0_DAT8 0x020E0648
// #define IOMUXC_SW_PAD_CTL_PAD_CSI0_DAT9 0x020E064C
// #define IOMUXC_SW_PAD_CTL_PAD_CSI0_DAT10 0x020E0650
// #define IOMUXC_SW_PAD_CTL_PAD_CSI0_DAT11 0x020E0654
// #define IOMUXC_SW_PAD_CTL_PAD_CSI0_DAT12 0x020E0658
// #define IOMUXC_SW_PAD_CTL_PAD_CSI0_DAT13 0x020E065C
// #define IOMUXC_SW_PAD_CTL_PAD_CSI0_DAT14 0x020E0660
// #define IOMUXC_SW_PAD_CTL_PAD_CSI0_DAT15 0x020E0664
// #define IOMUXC_SW_PAD_CTL_PAD_CSI0_DAT16 0x020E0668
// #define IOMUXC_SW_PAD_CTL_PAD_CSI0_DAT17 0x020E066C
// #define IOMUXC_SW_PAD_CTL_PAD_CSI0_DAT18 0x020E0670
// #define IOMUXC_SW_PAD_CTL_PAD_CSI0_DAT19 0x020E0674
// #define IOMUXC_SW_PAD_CTL_PAD_JTAG_TMS 0x020E0678
// #define IOMUXC_SW_PAD_CTL_PAD_JTAG_MOD 0x020E067C
// #define IOMUXC_SW_PAD_CTL_PAD_JTAG_TRSTB 0x020E0680
// #define IOMUXC_SW_PAD_CTL_PAD_JTAG_TDI 0x020E0684
// #define IOMUXC_SW_PAD_CTL_PAD_JTAG_TCK 0x020E0688
// #define IOMUXC_SW_PAD_CTL_PAD_JTAG_TDO 0x020E068C
// #define IOMUXC_SW_PAD_CTL_PAD_SD3_DAT7 0x020E0690
// #define IOMUXC_SW_PAD_CTL_PAD_SD3_DAT6 0x020E0694
// #define IOMUXC_SW_PAD_CTL_PAD_SD3_DAT5 0x020E0698
// #define IOMUXC_SW_PAD_CTL_PAD_SD3_DAT4 0x020E069C
// #define IOMUXC_SW_PAD_CTL_PAD_SD3_CMD 0x020E06A0
// #define IOMUXC_SW_PAD_CTL_PAD_SD3_CLK 0x020E06A4
// #define IOMUXC_SW_PAD_CTL_PAD_SD3_DAT0 0x020E06A8
// #define IOMUXC_SW_PAD_CTL_PAD_SD3_DAT1 0x020E06AC
// #define IOMUXC_SW_PAD_CTL_PAD_SD3_DAT2 0x020E06B0
// #define IOMUXC_SW_PAD_CTL_PAD_SD3_DAT3 0x020E06B4
// #define IOMUXC_SW_PAD_CTL_PAD_SD3_RST 0x020E06B8
// #define IOMUXC_SW_PAD_CTL_PAD_NANDF_CLE 0x020E06BC
// #define IOMUXC_SW_PAD_CTL_PAD_NANDF_ALE 0x020E06C0
// #define IOMUXC_SW_PAD_CTL_PAD_NANDF_WP_B 0x020E06C4
// #define IOMUXC_SW_PAD_CTL_PAD_NANDF_RB0 0x020E06C8
// #define IOMUXC_SW_PAD_CTL_PAD_NANDF_CS0 0x020E06CC
// #define IOMUXC_SW_PAD_CTL_PAD_NANDF_CS1 0x020E06D0
// #define IOMUXC_SW_PAD_CTL_PAD_NANDF_CS2 0x020E06D4
// #define IOMUXC_SW_PAD_CTL_PAD_NANDF_CS3 0x020E06D8
// #define IOMUXC_SW_PAD_CTL_PAD_SD4_CMD 0x020E06DC
// #define IOMUXC_SW_PAD_CTL_PAD_SD4_CLK 0x020E06E0
// #define IOMUXC_SW_PAD_CTL_PAD_NANDF_D0 0x020E06E4
// #define IOMUXC_SW_PAD_CTL_PAD_NANDF_D1 0x020E06E8
// #define IOMUXC_SW_PAD_CTL_PAD_NANDF_D2 0x020E06EC
// #define IOMUXC_SW_PAD_CTL_PAD_NANDF_D3 0x020E06F0
// #define IOMUXC_SW_PAD_CTL_PAD_NANDF_D4 0x020E06F4
// #define IOMUXC_SW_PAD_CTL_PAD_NANDF_D5 0x020E06F8
// #define IOMUXC_SW_PAD_CTL_PAD_NANDF_D6 0x020E06FC
// #define IOMUXC_SW_PAD_CTL_PAD_NANDF_D7 0x020E0700
// #define IOMUXC_SW_PAD_CTL_PAD_SD4_DAT0 0x020E0704
// #define IOMUXC_SW_PAD_CTL_PAD_SD4_DAT1 0x020E0708
// #define IOMUXC_SW_PAD_CTL_PAD_SD4_DAT2 0x020E070C
// #define IOMUXC_SW_PAD_CTL_PAD_SD4_DAT3 0x020E0710
// #define IOMUXC_SW_PAD_CTL_PAD_SD4_DAT4 0x020E0714
// #define IOMUXC_SW_PAD_CTL_PAD_SD4_DAT5 0x020E0718
// #define IOMUXC_SW_PAD_CTL_PAD_SD4_DAT6 0x020E071C
// #define IOMUXC_SW_PAD_CTL_PAD_SD4_DAT7 0x020E0720
// #define IOMUXC_SW_PAD_CTL_PAD_SD1_DAT1 0x020E0724
// #define IOMUXC_SW_PAD_CTL_PAD_SD1_DAT0 0x020E0728
// #define IOMUXC_SW_PAD_CTL_PAD_SD1_DAT3 0x020E072C
// #define IOMUXC_SW_PAD_CTL_PAD_SD1_CMD 0x020E0730
// #define IOMUXC_SW_PAD_CTL_PAD_SD1_DAT2 0x020E0734
// #define IOMUXC_SW_PAD_CTL_PAD_SD1_CLK 0x020E0738
// #define IOMUXC_SW_PAD_CTL_PAD_SD2_CLK 0x020E073C
// #define IOMUXC_SW_PAD_CTL_PAD_SD2_CMD 0x020E0740
// #define IOMUXC_SW_PAD_CTL_PAD_SD2_DAT3 0x020E0744
#define IOMUXC_SW_PAD_CTL_GRP_B7DS 0x020E0748
#define IOMUXC_SW_PAD_CTL_GRP_ADDDS 0x020E074C
#define IOMUXC_SW_PAD_CTL_GRP_DDRMODE_CTL 0x020E0750
#define IOMUXC_SW_PAD_CTL_GRP_TERM_CTL0 0x020E0754
#define IOMUXC_SW_PAD_CTL_GRP_DDRPKE 0x020E0758
#define IOMUXC_SW_PAD_CTL_GRP_TERM_CTL1 0x020E075C
#define IOMUXC_SW_PAD_CTL_GRP_TERM_CTL2 0x020E0760
#define IOMUXC_SW_PAD_CTL_GRP_TERM_CTL3 0x020E0764
#define IOMUXC_SW_PAD_CTL_GRP_DDRPK 0x020E0768
#define IOMUXC_SW_PAD_CTL_GRP_TERM_CTL4 0x020E076C
#define IOMUXC_SW_PAD_CTL_GRP_DDRHYS 0x020E0770
#define IOMUXC_SW_PAD_CTL_GRP_DDRMODE 0x020E0774
#define IOMUXC_SW_PAD_CTL_GRP_TERM_CTL5 0x020E0778
#define IOMUXC_SW_PAD_CTL_GRP_TERM_CTL6 0x020E077C
#define IOMUXC_SW_PAD_CTL_GRP_TERM_CTL7 0x020E0780
#define IOMUXC_SW_PAD_CTL_GRP_B0DS 0x020E0784
#define IOMUXC_SW_PAD_CTL_GRP_B1DS 0x020E0788
#define IOMUXC_SW_PAD_CTL_GRP_CTLDS 0x020E078C
#define IOMUXC_SW_PAD_CTL_GRP_DDR_TYPE_RGMII 0x020E0790
#define IOMUXC_SW_PAD_CTL_GRP_B2DS 0x020E0794
#define IOMUXC_SW_PAD_CTL_GRP_DDR_TYPE 0x020E0798
#define IOMUXC_SW_PAD_CTL_GRP_B3DS 0x020E079C
#define IOMUXC_SW_PAD_CTL_GRP_B4DS 0x020E07A0
#define IOMUXC_SW_PAD_CTL_GRP_B5DS 0x020E07A4
#define IOMUXC_SW_PAD_CTL_GRP_B6DS 0x020E07A8
// #define IOMUXC_SW_PAD_CTL_GRP_RGMII_TERM 0x020E07AC
// //
// // IOMUXC_*_SELECT_INPUT
// //
// #define IOMUXC_ASRC_ASRCK_CLOCK_6_SELECT_INPUT 0x020E07B0
// #define IOMUXC_AUDMUX_P4_INPUT_DA_AMX_SELECT_INPUT 0x020E07B4
// #define IOMUXC_AUDMUX_P4_INPUT_DB_AMX_SELECT_INPUT 0x020E07B8
// #define IOMUXC_AUDMUX_P4_INPUT_RXCLK_AMX_SELECT_INPUT 0x020E07BC
// #define IOMUXC_AUDMUX_P4_INPUT_RXFS_AMX_SELECT_INPUT 0x020E07C0
// #define IOMUXC_AUDMUX_P4_INPUT_TXCLK_AMX_SELECT_INPUT 0x020E07C4
// #define IOMUXC_AUDMUX_P4_INPUT_TXFS_AMX_SELECT_INPUT 0x020E07C8
// #define IOMUXC_AUDMUX_P5_INPUT_DA_AMX_SELECT_INPUT 0x020E07CC
// #define IOMUXC_AUDMUX_P5_INPUT_DB_AMX_SELECT_INPUT 0x020E07D0
// #define IOMUXC_AUDMUX_P5_INPUT_RXCLK_AMX_SELECT_INPUT 0x020E07D4
// #define IOMUXC_AUDMUX_P5_INPUT_RXFS_AMX_SELECT_INPUT 0x020E07D8
// #define IOMUXC_AUDMUX_P5_INPUT_TXCLK_AMX_SELECT_INPUT 0x020E07DC
// #define IOMUXC_AUDMUX_P5_INPUT_TXFS_AMX_SELECT_INPUT 0x020E07E0
// #define IOMUXC_CAN1_IPP_IND_CANRX_SELECT_INPUT 0x020E07E4
// #define IOMUXC_CAN2_IPP_IND_CANRX_SELECT_INPUT 0x020E07E8
// #define IOMUXC_CCM_IPP_DI1_CLK_SELECT_INPUT 0x020E07EC
// #define IOMUXC_CCM_PMIC_VFUNCIONAL_READY_SELECT_INPUT 0x020E07F0
// #define IOMUXC_ECSPI1_IPP_CSPI_CLK_IN_SELECT_INPUT 0x020E07F4
// #define IOMUXC_ECSPI1_IPP_IND_MISO_SELECT_INPUT 0x020E07F8
// #define IOMUXC_ECSPI1_IPP_IND_MOSI_SELECT_INPUT 0x020E07FC
// #define IOMUXC_ECSPI1_IPP_IND_SS_B_0_SELECT_INPUT 0x020E0800
// #define IOMUXC_ECSPI1_IPP_IND_SS_B_1_SELECT_INPUT 0x020E0804
// #define IOMUXC_ECSPI1_IPP_IND_SS_B_2_SELECT_INPUT 0x020E0808
// #define IOMUXC_ECSPI1_IPP_IND_SS_B_3_SELECT_INPUT 0x020E080C
// #define IOMUXC_ECSPI2_IPP_CSPI_CLK_IN_SELECT_INPUT 0x020E0810
// #define IOMUXC_ECSPI2_IPP_IND_MISO_SELECT_INPUT 0x020E0814
// #define IOMUXC_ECSPI2_IPP_IND_MOSI_SELECT_INPUT 0x020E0818
// #define IOMUXC_ECSPI2_IPP_IND_SS_B_0_SELECT_INPUT 0x020E081C
// #define IOMUXC_ECSPI2_IPP_IND_SS_B_1_SELECT_INPUT 0x020E0820
// #define IOMUXC_ECSPI4_IPP_IND_SS_B_0_SELECT_INPUT 0x020E0824
// #define IOMUXC_ECSPI5_IPP_CSPI_CLK_IN_SELECT_INPUT 0x020E0828
// #define IOMUXC_ECSPI5_IPP_IND_MISO_SELECT_INPUT 0x020E082C
// #define IOMUXC_ECSPI5_IPP_IND_MOSI_SELECT_INPUT 0x020E0830
// #define IOMUXC_ECSPI5_IPP_IND_SS_B_0_SELECT_INPUT 0x020E0834
// #define IOMUXC_ECSPI5_IPP_IND_SS_B_1_SELECT_INPUT 0x020E0838
// #define IOMUXC_ENET_IPG_CLK_RMII_SELECT_INPUT 0x020E083C
// #define IOMUXC_ENET_IPP_IND_MAC0_MDIO_SELECT_INPUT 0x020E0840
// #define IOMUXC_ENET_IPP_IND_MAC0_RXCLK_SELECT_INPUT 0x020E0844
// #define IOMUXC_ENET_IPP_IND_MAC0_RXDATA_0_SELECT_INPUT 0x020E0848
// #define IOMUXC_ENET_IPP_IND_MAC0_RXDATA_1_SELECT_INPUT 0x020E084C
// #define IOMUXC_ENET_IPP_IND_MAC0_RXDATA_2_SELECT_INPUT 0x020E0850
// #define IOMUXC_ENET_IPP_IND_MAC0_RXDATA_3_SELECT_INPUT 0x020E0854
// #define IOMUXC_ENET_IPP_IND_MAC0_RXEN_SELECT_INPUT 0x020E0858
// #define IOMUXC_ESAI_IPP_IND_FSR_SELECT_INPUT 0x020E085C
// #define IOMUXC_ESAI_IPP_IND_FST_SELECT_INPUT 0x020E0860
// #define IOMUXC_ESAI_IPP_IND_HCKR_SELECT_INPUT 0x020E0864
// #define IOMUXC_ESAI_IPP_IND_HCKT_SELECT_INPUT 0x020E0868
// #define IOMUXC_ESAI_IPP_IND_SCKR_SELECT_INPUT 0x020E086C
// #define IOMUXC_ESAI_IPP_IND_SCKT_SELECT_INPUT 0x020E0870
// #define IOMUXC_ESAI_IPP_IND_SDO0_SELECT_INPUT 0x020E0874
// #define IOMUXC_ESAI_IPP_IND_SDO1_SELECT_INPUT 0x020E0878
// #define IOMUXC_ESAI_IPP_IND_SDO2_SDI3_SELECT_INPUT 0x020E087C
// #define IOMUXC_ESAI_IPP_IND_SDO3_SDI2_SELECT_INPUT 0x020E0880
// #define IOMUXC_ESAI_IPP_IND_SDO4_SDI1_SELECT_INPUT 0x020E0884
// #define IOMUXC_ESAI_IPP_IND_SDO5_SDI0_SELECT_INPUT 0x020E0888
// #define IOMUXC_HDMI_TX_ICECIN_SELECT_INPUT 0x020E088C
// #define IOMUXC_HDMI_TX_II2C_MSTH13TDDC_SCLIN_SELECT_INPUT 0x020E0890
// #define IOMUXC_HDMI_TX_II2C_MSTH13TDDC_SDAIN_SELECT_INPUT 0x020E0894
// #define IOMUXC_I2C1_IPP_SCL_IN_SELECT_INPUT 0x020E0898
// #define IOMUXC_I2C1_IPP_SDA_IN_SELECT_INPUT 0x020E089C
// #define IOMUXC_I2C2_IPP_SCL_IN_SELECT_INPUT 0x020E08A0
// #define IOMUXC_I2C2_IPP_SDA_IN_SELECT_INPUT 0x020E08A4
// #define IOMUXC_I2C3_IPP_SCL_IN_SELECT_INPUT 0x020E08A8
// #define IOMUXC_I2C3_IPP_SDA_IN_SELECT_INPUT 0x020E08AC
// #define IOMUXC_IPU2_IPP_IND_SENS1_DATA_10_SELECT_INPUT 0x020E08B0
// #define IOMUXC_IPU2_IPP_IND_SENS1_DATA_11_SELECT_INPUT 0x020E08B4
// #define IOMUXC_IPU2_IPP_IND_SENS1_DATA_12_SELECT_INPUT 0x020E08B8
// #define IOMUXC_IPU2_IPP_IND_SENS1_DATA_13_SELECT_INPUT 0x020E08BC
// #define IOMUXC_IPU2_IPP_IND_SENS1_DATA_14_SELECT_INPUT 0x020E08C0
// #define IOMUXC_IPU2_IPP_IND_SENS1_DATA_15_SELECT_INPUT 0x020E08C4
// #define IOMUXC_IPU2_IPP_IND_SENS1_DATA_16_SELECT_INPUT 0x020E08C8
// #define IOMUXC_IPU2_IPP_IND_SENS1_DATA_17_SELECT_INPUT 0x020E08CC
// #define IOMUXC_IPU2_IPP_IND_SENS1_DATA_18_SELECT_INPUT 0x020E08D0
// #define IOMUXC_IPU2_IPP_IND_SENS1_DATA_19_SELECT_INPUT 0x020E08D4
// #define IOMUXC_IPU2_IPP_IND_SENS1_DATA_EN_SELECT_INPUT 0x020E08D8
// #define IOMUXC_IPU2_IPP_IND_SENS1_HSYNC_SELECT_INPUT 0x020E08DC
// #define IOMUXC_IPU2_IPP_IND_SENS1_PIX_CLK_SELECT_INPUT 0x020E08E0
// #define IOMUXC_IPU2_IPP_IND_SENS1_VSYNC_SELECT_INPUT 0x020E08E4
// #define IOMUXC_KPP_IPP_IND_COL_5_SELECT_INPUT 0x020E08E8
// #define IOMUXC_KPP_IPP_IND_COL_6_SELECT_INPUT 0x020E08EC
// #define IOMUXC_KPP_IPP_IND_COL_7_SELECT_INPUT 0x020E08F0
// #define IOMUXC_KPP_IPP_IND_ROW_5_SELECT_INPUT 0x020E08F4
// #define IOMUXC_KPP_IPP_IND_ROW_6_SELECT_INPUT 0x020E08F8
// #define IOMUXC_KPP_IPP_IND_ROW_7_SELECT_INPUT 0x020E08FC
// #define IOMUXC_MLB_MLB_CLK_IN_SELECT_INPUT 0x020E0900
// #define IOMUXC_MLB_MLB_DATA_IN_SELECT_INPUT 0x020E0904
// #define IOMUXC_MLB_MLB_SIG_IN_SELECT_INPUT 0x020E0908
// #define IOMUXC_SDMA_EVENTS_14_SELECT_INPUT 0x020E090C
// #define IOMUXC_SDMA_EVENTS_15_SELECT_INPUT 0x020E0910
// #define IOMUXC_SPDIF_SPDIF_IN1_SELECT_INPUT 0x020E0914
// #define IOMUXC_SPDIF_TX_CLK2_SELECT_INPUT 0x020E0918
// #define IOMUXC_UART1_IPP_UART_RTS_B_SELECT_INPUT 0x020E091C
// #define IOMUXC_UART1_IPP_UART_RXD_MUX_SELECT_INPUT 0x020E0920
// #define IOMUXC_UART2_IPP_UART_RTS_B_SELECT_INPUT 0x020E0924
// #define IOMUXC_UART2_IPP_UART_RXD_MUX_SELECT_INPUT 0x020E0928
// #define IOMUXC_UART3_IPP_UART_RTS_B_SELECT_INPUT 0x020E092C
// #define IOMUXC_UART3_IPP_UART_RXD_MUX_SELECT_INPUT 0x020E0930
// #define IOMUXC_UART4_IPP_UART_RTS_B_SELECT_INPUT 0x020E0934
// #define IOMUXC_UART4_IPP_UART_RXD_MUX_SELECT_INPUT 0x020E0938
// #define IOMUXC_UART5_IPP_UART_RTS_B_SELECT_INPUT 0x020E093C
// #define IOMUXC_UART5_IPP_UART_RXD_MUX_SELECT_INPUT 0x020E0940
// #define IOMUXC_USBOH3_IPP_IND_OTG_OC_SELECT_INPUT 0x020E0944
// #define IOMUXC_USBOH3_IPP_IND_UH1_OC_SELECT_INPUT 0x020E0948
// #define IOMUXC_USDHC1_IPP_WP_ON_SELECT_INPUT 0x020E094C
#endif // _IOMUX_REGISTER_H_

View File

@ -27,7 +27,7 @@
* (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 "registers/regs.h"
#include "regs.h"
//#################################################
//#
@ -35,7 +35,7 @@
//# This file lists instances offset memory location
//#
//#################################################
/*
//#########################################
//# ARM PLATFORM INTERNALS - SCU REGISTERS
//#########################################
@ -2344,7 +2344,7 @@
//#########################################
//# MMDC registers
//#########################################
*/
//DDR LOGIC
#define MDCTL_OFFSET 0x00
#define MDPDC_OFFSET 0x04
@ -2435,6 +2435,7 @@
#define MPDCCR_OFFSET PHY_BASE_ADDR + 0xC0
#define MPBC_OFFSET PHY_BASE_ADDR + 0xC4
/*
//#########################################
//# WEIM registers
//#########################################
@ -3457,4 +3458,4 @@
#define MIPI_HW_HSI_RX_FIFO_STAT 0x214
#define MIPI_HW_HSI_DLL_CTRL 0x220
#define MIPI_HW_HSI_DLL_STAT 0x224
*/

View File

@ -53,7 +53,7 @@ typedef unsigned int reg32_t;
//
// macros for single instance registers
//
/*
#define BF_SET(reg, field) HW_##reg##_SET(BM_##reg##_##field)
#define BF_CLR(reg, field) HW_##reg##_CLR(BM_##reg##_##field)
#define BF_TOG(reg, field) HW_##reg##_TOG(BM_##reg##_##field)
@ -473,7 +473,7 @@ typedef unsigned int reg32_t;
BF_##reg##_##f6(v6) | \
BF_##reg##_##f7(v7) | \
BF_##reg##_##f8(v8))))
*/
#endif // _REGS_H
////////////////////////////////////////////////////////////////////////////////

View File

@ -0,0 +1,831 @@
/*
* Copyright (C) 2011-2012 Freescale Semiconductor, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/**
* @file soc_memory_map.h
* @brief support imx6q soc memory map define, reference from u-boot-2009-08/include/asm-arm/arch-mx6/mx6.h
* @version 3.0
* @author AIIT XUOS Lab
* @date 2023.09.08
*/
#ifndef SOC_MEMORY_MAP_H
#define SOC_MEMORY_MAP_H
// clang-format off
/*
* Some of i.MX 6 Series SoC registers are associated with four addresses
* used for different operations - read/write, set, clear and toggle bits.
*
* Some of registers do not implement such feature and, thus, should be
* accessed/manipulated via single address in common way.
*/
#define REG_RD(base, reg) \
(*(volatile unsigned int *)((base) + (reg)))
#define REG_WR(base, reg, value) \
((*(volatile unsigned int *)((base) + (reg))) = (value))
#define REG_SET(base, reg, value) \
((*(volatile unsigned int *)((base) + (reg ## _SET))) = (value))
#define REG_CLR(base, reg, value) \
((*(volatile unsigned int *)((base) + (reg ## _CLR))) = (value))
#define REG_TOG(base, reg, value) \
((*(volatile unsigned int *)((base) + (reg ## _TOG))) = (value))
#define REG_RD_ADDR(addr) \
(*(volatile unsigned int *)((addr)))
#define REG_WR_ADDR(addr, value) \
((*(volatile unsigned int *)((addr))) = (value))
#define REG_SET_ADDR(addr, value) \
((*(volatile unsigned int *)((addr) + 0x4)) = (value))
#define REG_CLR_ADDR(addr, value) \
((*(volatile unsigned int *)((addr) + 0x8)) = (value))
#define REG_TOG_ADDR(addr, value) \
((*(volatile unsigned int *)((addr) + 0xc)) = (value))
#define __REG(x) (*((volatile u32 *)(x)))
#define __REG16(x) (*((volatile u16 *)(x)))
#define __REG8(x) (*((volatile u8 *)(x)))
/*
*ROM address which denotes silicon rev
*/
#define ROM_SI_REV 0x48
/*!
* @file arch-mxc/mx6.h
* @brief This file contains register definitions.
*
* @ingroup MSL_MX6
*/
/*
* IPU
*/
#define IPU_CTRL_BASE_ADDR 0x02400000
/*!
* Register an interrupt handler for the SMN as well as the SCC. In some
* implementations, the SMN is not connected at all, and in others, it is
* on the same interrupt line as the SCM. Comment this line out accordingly
*/
#define USE_SMN_INTERRUPT
/*!
* This option is used to set or clear the RXDMUXSEL bit in control reg 3.
* Certain platforms need this bit to be set in order to receive Irda data.
*/
#define MXC_UART_IR_RXDMUX 0x0004
/*!
* This option is used to set or clear the RXDMUXSEL bit in control reg 3.
* Certain platforms need this bit to be set in order to receive UART data.
*/
#define MXC_UART_RXDMUX 0x0004
/*!
* This option is used to set or clear the dspdma bit in the SDMA config
* register.
*/
#define MXC_DMA_REQ_DSPDMA 0
/*!
* Define this option to specify we are using the newer SDMA module.
*/
#define MXC_DMA_REQ_V2
/*!
* The maximum frequency that the pixel clock can be at so as to
* activate DVFS-PER.
*/
#define DVFS_MAX_PIX_CLK 54000000
/*!
* The Low 32 bits of CPU Serial Number Fuse Index
*/
#define CPU_UID_LOW_FUSE_INDEX 1
/*!
* The High 32 bits of CPU Serial Number Fuse Index
*/
#define CPU_UID_HIGH_FUSE_INDEX 2
// /* IROM
// */
// #define IROM_BASE_ADDR 0x0
// #define IROM_SIZE SZ_64K
// /* CPU Memory Map */
// #ifdef CONFIG_MX6SL
// #define MMDC0_ARB_BASE_ADDR 0x80000000
// #define MMDC0_ARB_END_ADDR 0xFFFFFFFF
// #define MMDC1_ARB_BASE_ADDR 0xC0000000
// #define MMDC1_ARB_END_ADDR 0xFFFFFFFF
// #else
// #define MMDC0_ARB_BASE_ADDR 0x10000000
// #define MMDC0_ARB_END_ADDR 0x7FFFFFFF
// #define MMDC1_ARB_BASE_ADDR 0x80000000
// #define MMDC1_ARB_END_ADDR 0xFFFFFFFF
// #endif
// #define OCRAM_ARB_BASE_ADDR 0x00900000
// #define OCRAM_ARB_END_ADDR 0x009FFFFF
// #define IRAM_BASE_ADDR OCRAM_ARB_BASE_ADDR
// #define PCIE_ARB_BASE_ADDR 0x01000000
// #define PCIE_ARB_END_ADDR 0x01FFFFFF
// /* Blocks connected via pl301periph */
// #define ROMCP_ARB_BASE_ADDR 0x00000000
// #define ROMCP_ARB_END_ADDR 0x00017FFF
// #define BOOT_ROM_BASE_ADDR ROMCP_ARB_BASE_ADDR
// #ifdef CONFIG_MX6SL
// #define GPU_2D_ARB_BASE_ADDR 0x02200000
// #define GPU_2D_ARB_END_ADDR 0x02203FFF
// #define OPENVG_ARB_BASE_ADDR 0x02204000
// #define OPENVG_ARB_END_ADDR 0x02207FFF
// #else
// #define CAAM_ARB_BASE_ADDR 0x00100000
// #define CAAM_ARB_END_ADDR 0x00103FFF
// #define APBH_DMA_ARB_BASE_ADDR 0x00110000
// #define APBH_DMA_ARB_END_ADDR 0x00117FFF
// #define HDMI_ARB_BASE_ADDR 0x00120000
// #define HDMI_ARB_END_ADDR 0x00128FFF
// #define GPU_3D_ARB_BASE_ADDR 0x00130000
// #define GPU_3D_ARB_END_ADDR 0x00133FFF
// #define GPU_2D_ARB_BASE_ADDR 0x00134000
// #define GPU_2D_ARB_END_ADDR 0x00137FFF
// #define DTCP_ARB_BASE_ADDR 0x00138000
// #define DTCP_ARB_END_ADDR 0x0013BFFF
// #define GPU_MEM_BASE_ADDR GPU_3D_ARB_BASE_ADDR
// #endif
// /* GPV - PL301 configuration ports */
// #define GPV0_BASE_ADDR 0x00B00000
// #define GPV1_BASE_ADDR 0x00C00000
// #ifdef CONFIG_MX6SL
// #define GPV2_BASE_ADDR 0x00D00000
// #else
// #define GPV2_BASE_ADDR 0x00200000
// #define GPV3_BASE_ADDR 0x00300000
// #define GPV4_BASE_ADDR 0x00800000
// #endif
#define AIPS1_ARB_BASE_ADDR 0x02000000
#define AIPS1_ARB_END_ADDR 0x020FFFFF
#define AIPS2_ARB_BASE_ADDR 0x02100000
#define AIPS2_ARB_END_ADDR 0x021FFFFF
// #define SATA_ARB_BASE_ADDR 0x02200000
// #define SATA_ARB_END_ADDR 0x02203FFF
// #define OPENVG_ARB_BASE_ADDR 0x02204000
// #define OPENVG_ARB_END_ADDR 0x02207FFF
// #define HSI_ARB_BASE_ADDR 0x02208000
// #define HSI_ARB_END_ADDR 0x0220BFFF
// #define IPU1_ARB_BASE_ADDR 0x02400000
// #define IPU1_ARB_END_ADDR 0x027FFFFF
// #define IPU2_ARB_BASE_ADDR 0x02800000
// #define IPU2_ARB_END_ADDR 0x02BFFFFF
// #define WEIM_ARB_BASE_ADDR 0x08000000
// #define WEIM_ARB_END_ADDR 0x0FFFFFFF
// /* Legacy Defines */
// #define CSD0_DDR_BASE_ADDR MMDC0_ARB_BASE_ADDR
// #define CSD1_DDR_BASE_ADDR MMDC1_ARB_BASE_ADDR
// #define CS0_BASE_ADDR WEIM_ARB_BASE_ADDR
// #define NAND_FLASH_BASE_ADDR APBH_DMA_ARB_BASE_ADDR
// #define ABPHDMA_BASE_ADDR APBH_DMA_ARB_BASE_ADDR
// #define GPMI_BASE_ADDR (APBH_DMA_ARB_BASE_ADDR + 0x02000)
// #define BCH_BASE_ADDR (APBH_DMA_ARB_BASE_ADDR + 0x04000)
/* Defines for Blocks connected via AIPS (SkyBlue) */
#define ATZ1_BASE_ADDR AIPS1_ARB_BASE_ADDR
#define ATZ2_BASE_ADDR AIPS2_ARB_BASE_ADDR
// /* slots 0,7 of SDMA reserved, therefore left unused in IPMUX3 */
// #define SPDIF_BASE_ADDR (ATZ1_BASE_ADDR + 0x04000)
// #define ECSPI1_BASE_ADDR (ATZ1_BASE_ADDR + 0x08000)
// #define ECSPI2_BASE_ADDR (ATZ1_BASE_ADDR + 0x0C000)
// #define ECSPI3_BASE_ADDR (ATZ1_BASE_ADDR + 0x10000)
// #define ECSPI4_BASE_ADDR (ATZ1_BASE_ADDR + 0x14000)
// #ifdef CONFIG_MX6SL
// #define UART5_IPS_BASE_ADDR (ATZ1_BASE_ADDR + 0x18000)
// #define UART1_IPS_BASE_ADDR (ATZ1_BASE_ADDR + 0x20000)
// #define UART2_IPS_BASE_ADDR (ATZ1_BASE_ADDR + 0x24000)
// #define SSI1_IPS_BASE_ADDR (ATZ1_BASE_ADDR + 0x28000)
// #define SSI2_IPS_BASE_ADDR (ATZ1_BASE_ADDR + 0x2C000)
// #define SSI3_IPS_BASE_ADDR (ATZ1_BASE_ADDR + 0x30000)
// #define UART3_IPS_BASE_ADDR (ATZ1_BASE_ADDR + 0x34000)
// #define UART4_IPS_BASE_ADDR (ATZ1_BASE_ADDR + 0x38000)
// #else
// #define ECSPI5_BASE_ADDR (ATZ1_BASE_ADDR + 0x18000)
// #define UART1_BASE_ADDR (ATZ1_BASE_ADDR + 0x20000)
// #define ESAI1_BASE_ADDR (ATZ1_BASE_ADDR + 0x24000)
// #define SSI1_BASE_ADDR (ATZ1_BASE_ADDR + 0x28000)
// #define SSI2_BASE_ADDR (ATZ1_BASE_ADDR + 0x2C000)
// #define SSI3_BASE_ADDR (ATZ1_BASE_ADDR + 0x30000)
// #define ASRC_BASE_ADDR (ATZ1_BASE_ADDR + 0x34000)
// #endif
// #define SPBA_BASE_ADDR (ATZ1_BASE_ADDR + 0x3C000)
// #define VPU_BASE_ADDR (ATZ1_BASE_ADDR + 0x40000)
// /* ATZ#1- On Platform */
#define AIPS1_ON_BASE_ADDR (ATZ1_BASE_ADDR + 0x7C000)
/* ATZ#1- Off Platform */
#define AIPS1_OFF_BASE_ADDR (ATZ1_BASE_ADDR + 0x80000)
// #define PWM1_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x0000)
// #define PWM2_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x4000)
// #define PWM3_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x8000)
// #define PWM4_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0xC000)
// #ifdef CONFIG_MX6SL
// #define DBGMON_IPS_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x10000)
// #define QOSC_IPS_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x14000)
// #else
// #define CAN1_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x10000)
// #define CAN2_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x14000)
// #endif
#define GPT_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x18000)
// #define GPIO1_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x1C000)
// #define GPIO2_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x20000)
// #define GPIO3_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x24000)
// #define GPIO4_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x28000)
// #define GPIO5_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x2C000)
// #define GPIO6_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x30000)
// #define GPIO7_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x34000)
// #define KPP_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x38000)
// #define WDOG1_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x3C000)
// #define WDOG2_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x40000)
#define CCM_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x44000)
#define ANATOP_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x48000)
// #define USB_PHY0_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x49000)
// #define USB_PHY1_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x4A000)
// #define SNVS_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x4C000)
// #define EPIT1_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x50000)
// #define EPIT2_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x54000)
// #define SRC_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x58000)
// #define GPC_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x5C000)
#define IOMUXC_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x60000)
// #ifdef CONFIG_MX6SL
// #define CSI_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x64000)
// #define SIPIX_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x68000)
// #define SDMA_PORT_HOST_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x6C000)
// #else
// #define DCIC1_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x64000)
// #define DCIC2_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x68000)
// #define DMA_REQ_PORT_HOST_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x6C000)
// #endif
// #define EPXP_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x70000)
// #define EPDC_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x74000)
// #define ELCDIF_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x78000)
// #define DCP_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x7C000)
/* ATZ#2- On Platform */
#define AIPS2_ON_BASE_ADDR (ATZ2_BASE_ADDR + 0x7C000)
/* ATZ#2- Off Platform */
#define AIPS2_OFF_BASE_ADDR (ATZ2_BASE_ADDR + 0x80000)
// /* ATZ#2 - Global enable (0) */
// #define CAAM_BASE_ADDR (ATZ2_BASE_ADDR)
// #define ARM_BASE_ADDR (ATZ2_BASE_ADDR + 0x40000)
// #ifdef CONFIG_MX6SL
// #define USBO2H_PL301_IPS_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x0000)
// #define USBO2H_USB_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x4000)
// #else
// #define USBOH3_PL301_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x0000)
// #define USBOH3_USB_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x4000)
// #endif
// #define ENET_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x8000)
// /* Frank Li Need IC confirm OTG base address*/
// #ifdef CONFIG_MX6SL
// #define OTG_BASE_ADDR USBO2H_USB_BASE_ADDR
// #define MSHC_IPS_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0xC000)
// #else
// #define OTG_BASE_ADDR USBOH3_USB_BASE_ADDR
// #define MLB_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0xC000)
// #endif
// #define USDHC1_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x10000)
// #define USDHC2_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x14000)
// #define USDHC3_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x18000)
// #define USDHC4_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x1C000)
// #define I2C1_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x20000)
// #define I2C2_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x24000)
// #define I2C3_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x28000)
// #define ROMCP_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x2C000)
#define MMDC_P0_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x30000)
#ifdef CONFIG_MX6SL
#define RNGB_IPS_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x34000)
#else
#define MMDC_P1_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x34000)
#endif
// #define WEIM_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x38000)
// #define OCOTP_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x3C000)
// #define CSU_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x40000)
// #define IP2APB_PERFMON1_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x44000)
// #define IP2APB_PERFMON2_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x48000)
// #define IP2APB_PERFMON3_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x4C000)
// #define IP2APB_TZASC1_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x50000)
// #define IP2APB_TZASC2_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x54000)
// #define AUDMUX_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x58000)
// #define MIPI_CSI2_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x5C000)
// #define MIPI_DSI_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x60000)
// #define VDOA_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x64000)
// #define UART2_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x68000)
// #define UART3_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x6C000)
// #define UART4_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x70000)
// #define UART5_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x74000)
// #define IP2APB_USBPHY1_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x78000)
// #define IP2APB_USBPHY2_BASE_ADDR (AIPS2_OFF_BASE_ADDR + 0x7C000)
// /* Cortex-A9 MPCore private memory region */
// #define ARM_PERIPHBASE 0x00A00000
// #define SCU_BASE_ADDR (ARM_PERIPHBASE)
// #define IC_INTERFACES_BASE_ADDR (ARM_PERIPHBASE + 0x0100)
// #define GLOBAL_TIMER_BASE_ADDR (ARM_PERIPHBASE + 0x0200)
// #define PRIVATE_TIMERS_WD_BASE_ADDR (ARM_PERIPHBASE + 0x0600)
// #define IC_DISTRIBUTOR_BASE_ADDR (ARM_PERIPHBASE + 0x1000)
// /*!
// * Defines for modules using static and dynamic DMA channels
// */
// #define MXC_DMA_CHANNEL_IRAM 30
// #define MXC_DMA_CHANNEL_SPDIF_TX MXC_DMA_DYNAMIC_CHANNEL
// #define MXC_DMA_CHANNEL_SPDIF_RX MXC_DMA_DYNAMIC_CHANNEL
// #define MXC_DMA_CHANNEL_UART1_RX MXC_DMA_DYNAMIC_CHANNEL
// #define MXC_DMA_CHANNEL_UART1_TX MXC_DMA_DYNAMIC_CHANNEL
// #define MXC_DMA_CHANNEL_UART2_RX MXC_DMA_DYNAMIC_CHANNEL
// #define MXC_DMA_CHANNEL_UART2_TX MXC_DMA_DYNAMIC_CHANNEL
// #define MXC_DMA_CHANNEL_UART3_RX MXC_DMA_DYNAMIC_CHANNEL
// #define MXC_DMA_CHANNEL_UART3_TX MXC_DMA_DYNAMIC_CHANNEL
// #define MXC_DMA_CHANNEL_UART4_RX MXC_DMA_DYNAMIC_CHANNEL
// #define MXC_DMA_CHANNEL_UART4_TX MXC_DMA_DYNAMIC_CHANNEL
// #define MXC_DMA_CHANNEL_UART5_RX MXC_DMA_DYNAMIC_CHANNEL
// #define MXC_DMA_CHANNEL_UART5_TX MXC_DMA_DYNAMIC_CHANNEL
// #define MXC_DMA_CHANNEL_MMC1 MXC_DMA_DYNAMIC_CHANNEL
// #define MXC_DMA_CHANNEL_MMC2 MXC_DMA_DYNAMIC_CHANNEL
// #define MXC_DMA_CHANNEL_SSI1_RX MXC_DMA_DYNAMIC_CHANNEL
// #define MXC_DMA_CHANNEL_SSI1_TX MXC_DMA_DYNAMIC_CHANNEL
// #define MXC_DMA_CHANNEL_SSI2_RX MXC_DMA_DYNAMIC_CHANNEL
// #ifdef CONFIG_DMA_REQ_IRAM
// #define MXC_DMA_CHANNEL_SSI2_TX (MXC_DMA_CHANNEL_IRAM + 1)
// #else /*CONFIG_DMA_REQ_IRAM */
// #define MXC_DMA_CHANNEL_SSI2_TX MXC_DMA_DYNAMIC_CHANNEL
// #endif /*CONFIG_DMA_REQ_IRAM */
// #define MXC_DMA_CHANNEL_SSI3_RX MXC_DMA_DYNAMIC_CHANNEL
// #define MXC_DMA_CHANNEL_SSI3_TX MXC_DMA_DYNAMIC_CHANNEL
// #define MXC_DMA_CHANNEL_CSPI1_RX MXC_DMA_DYNAMIC_CHANNEL
// #define MXC_DMA_CHANNEL_CSPI1_TX MXC_DMA_DYNAMIC_CHANNEL
// #define MXC_DMA_CHANNEL_CSPI2_RX MXC_DMA_DYNAMIC_CHANNEL
// #define MXC_DMA_CHANNEL_CSPI2_TX MXC_DMA_DYNAMIC_CHANNEL
// #define MXC_DMA_CHANNEL_CSPI3_RX MXC_DMA_DYNAMIC_CHANNEL
// #define MXC_DMA_CHANNEL_CSPI3_TX MXC_DMA_DYNAMIC_CHANNEL
// #define MXC_DMA_CHANNEL_ATA_RX MXC_DMA_DYNAMIC_CHANNEL
// #define MXC_DMA_CHANNEL_ATA_TX MXC_DMA_DYNAMIC_CHANNEL
// #define MXC_DMA_CHANNEL_MEMORY MXC_DMA_DYNAMIC_CHANNEL
// #define MXC_DMA_CHANNEL_ASRCA_RX MXC_DMA_DYNAMIC_CHANNEL
// #define MXC_DMA_CHANNEL_ASRCA_TX MXC_DMA_DYNAMIC_CHANNEL
// #define MXC_DMA_CHANNEL_ASRCB_RX MXC_DMA_DYNAMIC_CHANNEL
// #define MXC_DMA_CHANNEL_ASRCB_TX MXC_DMA_DYNAMIC_CHANNEL
// #define MXC_DMA_CHANNEL_ASRCC_RX MXC_DMA_DYNAMIC_CHANNEL
// #define MXC_DMA_CHANNEL_ASRCC_TX MXC_DMA_DYNAMIC_CHANNEL
// #define MXC_DMA_CHANNEL_ESAI_RX MXC_DMA_DYNAMIC_CHANNEL
// #define MXC_DMA_CHANNEL_ESAI_TX MXC_DMA_DYNAMIC_CHANNEL
// #define MXC_DMA_CHANNEL_ASRCA_ESAI MXC_DMA_DYNAMIC_CHANNEL
// #define MXC_DMA_CHANNEL_ASRCB_ESAI MXC_DMA_DYNAMIC_CHANNEL
// #define MXC_DMA_CHANNEL_ASRCC_ESAI MXC_DMA_DYNAMIC_CHANNEL
// #define MXC_DMA_CHANNEL_ASRCA_SSI1_TX0 MXC_DMA_DYNAMIC_CHANNEL
// #define MXC_DMA_CHANNEL_ASRCA_SSI1_TX1 MXC_DMA_DYNAMIC_CHANNEL
// #define MXC_DMA_CHANNEL_ASRCA_SSI2_TX0 MXC_DMA_DYNAMIC_CHANNEL
// #define MXC_DMA_CHANNEL_ASRCA_SSI2_TX1 MXC_DMA_DYNAMIC_CHANNEL
// #define MXC_DMA_CHANNEL_ASRCB_SSI1_TX0 MXC_DMA_DYNAMIC_CHANNEL
// #define MXC_DMA_CHANNEL_ASRCB_SSI1_TX1 MXC_DMA_DYNAMIC_CHANNEL
// #define MXC_DMA_CHANNEL_ASRCB_SSI2_TX0 MXC_DMA_DYNAMIC_CHANNEL
// #define MXC_DMA_CHANNEL_ASRCB_SSI2_TX1 MXC_DMA_DYNAMIC_CHANNEL
// /* define virtual address */
// #define PERIPBASE_VIRT 0xF0000000
// #define AIPS1_BASE_ADDR_VIRT (PERIPBASE_VIRT + AIPS1_ARB_BASE_ADDR)
// #define AIPS2_BASE_ADDR_VIRT (PERIPBASE_VIRT + AIPS2_ARB_BASE_ADDR)
// #define ARM_PERIPHBASE_VIRT (PERIPBASE_VIRT + ARM_PERIPHBASE)
// #define AIPS1_SIZE SZ_1M
// #define AIPS2_SIZE SZ_1M
// #define ARM_PERIPHBASE_SIZE SZ_8K
// #define MX6_IO_ADDRESS(x) ((x) - PERIPBASE_VIRT)
/*!
* This macro defines the physical to virtual address mapping for all the
* peripheral modules. It is used by passing in the physical address as x
* and returning the virtual address. If the physical address is not mapped,
* it returns 0xDEADBEEF
*/
#define IO_ADDRESS(x) \
(void __force __iomem *) \
(((((x) >= (unsigned long)AIPS1_ARB_BASE_ADDR) && \
((x) <= (unsigned long)AIPS2_ARB_END_ADDR)) || \
((x) >= (unsigned long)ARM_PERIPHBASE && \
((x) <= (unsigned long)(ARM_PERIPHBASE + ARM_PERIPHBASE)))) ? \
MX6_IO_ADDRESS(x) : 0xDEADBEEF)
// /*
// * DMA request assignments
// */
// #define DMA_REQ_VPU 0
// #define DMA_REQ_GPC 1
// #define DMA_REQ_IPU1 2
// #define DMA_REQ_EXT_DMA_REQ_0 2
// #define DMA_REQ_CSPI1_RX 3
// #define DMA_REQ_I2C3_A 3
// #define DMA_REQ_CSPI1_TX 4
// #define DMA_REQ_I2C2_A 4
// #define DMA_REQ_CSPI2_RX 5
// #define DMA_REQ_I2C1_A 5
// #define DMA_REQ_CSPI2_TX 6
// #define DMA_REQ_CSPI3_RX 7
// #define DMA_REQ_CSPI3_TX 8
// #define DMA_REQ_CSPI4_RX 9
// #define DMA_REQ_EPIT2 9
// #define DMA_REQ_CSPI4_TX 10
// #define DMA_REQ_I2C1_B 10
// #define DMA_REQ_CSPI5_RX 11
// #define DMA_REQ_CSPI5_TX 12
// #define DMA_REQ_GPT 13
// #define DMA_REQ_SPDIF_RX 14
// #define DMA_REQ_EXT_DMA_REQ_1 14
// #define DMA_REQ_SPDIF_TX 15
// #define DMA_REQ_EPIT1 16
// #define DMA_REQ_ASRC_RX1 17
// #define DMA_REQ_ASRC_RX2 18
// #define DMA_REQ_ASRC_RX3 19
// #define DMA_REQ_ASRC_TX1 20
// #define DMA_REQ_ASRC_TX2 21
// #define DMA_REQ_ASRC_TX3 22
// #define DMA_REQ_ESAI_RX 23
// #define DMA_REQ_I2C3_B 23
// #define DMA_REQ_ESAI_TX 24
// #define DMA_REQ_UART1_RX 25
// #define DMA_REQ_UART1_TX 26
// #define DMA_REQ_UART2_RX 27
// #define DMA_REQ_UART2_TX 28
// #define DMA_REQ_UART3_RX 29
// #define DMA_REQ_UART3_TX 30
// #define DMA_REQ_UART4_RX 31
// #define DMA_REQ_UART4_TX 32
// #define DMA_REQ_UART5_RX 33
// #define DMA_REQ_UART5_TX 34
// #define DMA_REQ_SSI1_RX1 35
// #define DMA_REQ_SSI1_TX1 36
// #define DMA_REQ_SSI1_RX0 37
// #define DMA_REQ_SSI1_TX0 38
// #define DMA_REQ_SSI2_RX1 39
// #define DMA_REQ_SSI2_TX1 40
// #define DMA_REQ_SSI2_RX0 41
// #define DMA_REQ_SSI2_TX0 42
// #define DMA_REQ_SSI3_RX1 43
// #define DMA_REQ_SSI3_TX1 44
// #define DMA_REQ_SSI3_RX0 45
// #define DMA_REQ_SSI3_TX0 46
// #define DMA_REQ_DTCP 47
// /*
// * Interrupt numbers
// */
// #define MXC_INT_GPR 32
// #define MXC_INT_CHEETAH_CSYSPWRUPREQ 33
// #define MXC_INT_SDMA 34
// #ifndef CONFIG_MX6SL
// #define MXC_INT_VPU_JPG 35
// #define MXC_INT_INTERRUPT_36_NUM 36
// #define MXC_INT_IPU1_ERR 37
// #define MXC_INT_IPU1_FUNC 38
// #define MXC_INT_IPU2_ERR 39
// #define MXC_INT_IPU2_FUNC 40
// #define MXC_INT_GPU3D_IRQ 41
// #else
// #define MXC_INT_MSHC 35
// #define MXC_INT_SNVS_PMIC_OFF 36
// #define MXC_INT_RNGB 37
// #define MXC_INT_SPDC 38
// #define MXC_INT_CSI 39
// #endif
// #define MXC_INT_GPU2D_IRQ 42
// #define MXC_INT_OPENVG_XAQ2 43
// #define MXC_INT_VPU_IPI 44
// #define MXC_INT_APBHDMA_DMA 45
// #define MXC_INT_WEIM 46
// #define MXC_INT_RAWNAND_BCH 47
// #define MXC_INT_RAWNAND_GPMI 48
// #define MXC_INT_DTCP 49
// #define MXC_INT_VDOA 50
// #define MXC_INT_SNVS 51
// #define MXC_INT_SNVS_SEC 52
// #define MXC_INT_CSU 53
// #define MXC_INT_USDHC1 54
// #define MXC_INT_USDHC2 55
// #define MXC_INT_USDHC3 56
// #define MXC_INT_USDHC4 57
// #define MXC_INT_UART1_ANDED 58
// #define MXC_INT_UART2_ANDED 59
// #define MXC_INT_UART3_ANDED 60
// #define MXC_INT_UART4_ANDED 61
// #define MXC_INT_UART5_ANDED 62
// #define MXC_INT_ECSPI1 63
// #define MXC_INT_ECSPI2 64
// #define MXC_INT_ECSPI3 65
// #define MXC_INT_ECSPI4 66
// #define MXC_INT_ECSPI5 67
// #define MXC_INT_I2C1 68
// #define MXC_INT_I2C2 69
// #define MXC_INT_I2C3 70
// #ifdef CONFIG_MX6Q
// #define MXC_INT_SATA 71
// #define MXC_INT_USBOH3_UH1 72
// #define MXC_INT_USBOH3_UH2 73
// #define MXC_INT_USBOH3_UH3 74
// #define MXC_INT_USBOH3_UOTG 75
// #else
// #define MXC_INT_LCDIF 71
// #define MXC_INT_USBO2H_UH1 72
// #define MXC_INT_USBO2H_UH2 73
// #define MXC_INT_USBO2H_UH3 74
// #define MXC_INT_USBO2H_UOTG 75
// #endif
// #define MXC_INT_ANATOP_UTMI0 76
// #define MXC_INT_ANATOP_UTMI1 77
// #define MXC_INT_SSI1 78
// #define MXC_INT_SSI2 79
// #define MXC_INT_SSI3 80
// #define MXC_INT_ANATOP_TEMPSNSR 81
// #define MXC_INT_ASRC 82
// #define MXC_INT_ESAI 83
// #define MXC_INT_SPDIF 84
// #define MXC_INT_MLB 85
// #define MXC_INT_ANATOP_ANA1 86
// #define MXC_INT_GPT 87
// #define MXC_INT_EPIT1 88
// #define MXC_INT_EPIT2 89
// #define MXC_INT_GPIO1_INT7_NUM 90
// #define MXC_INT_GPIO1_INT6_NUM 91
// #define MXC_INT_GPIO1_INT5_NUM 92
// #define MXC_INT_GPIO1_INT4_NUM 93
// #define MXC_INT_GPIO1_INT3_NUM 94
// #define MXC_INT_GPIO1_INT2_NUM 95
// #define MXC_INT_GPIO1_INT1_NUM 96
// #define MXC_INT_GPIO1_INT0_NUM 97
// #define MXC_INT_GPIO1_INT15_0_NUM 98
// #define MXC_INT_GPIO1_INT31_16_NUM 99
// #define MXC_INT_GPIO2_INT15_0_NUM 100
// #define MXC_INT_GPIO2_INT31_16_NUM 101
// #define MXC_INT_GPIO3_INT15_0_NUM 102
// #define MXC_INT_GPIO3_INT31_16_NUM 103
// #define MXC_INT_GPIO4_INT15_0_NUM 104
// #define MXC_INT_GPIO4_INT31_16_NUM 105
// #define MXC_INT_GPIO5_INT15_0_NUM 106
// #define MXC_INT_GPIO5_INT31_16_NUM 107
// #define MXC_INT_GPIO6_INT15_0_NUM 108
// #define MXC_INT_GPIO6_INT31_16_NUM 109
// #define MXC_INT_GPIO7_INT15_0_NUM 110
// #define MXC_INT_GPIO7_INT31_16_NUM 111
// #define MXC_INT_WDOG1 112
// #define MXC_INT_WDOG2 113
// #define MXC_INT_KPP 114
// #define MXC_INT_PWM1 115
// #define MXC_INT_PWM2 116
// #define MXC_INT_PWM3 117
// #define MXC_INT_PWM4 118
// #define MXC_INT_CCM_INT1_NUM 119
// #define MXC_INT_CCM_INT2_NUM 120
// #define MXC_INT_GPC_INT1_NUM 121
// #define MXC_INT_GPC_INT2_NUM 122
// #define MXC_INT_SRC 123
// #define MXC_INT_CHEETAH_L2 124
// #define MXC_INT_CHEETAH_PARITY 125
// #define MXC_INT_CHEETAH_PERFORM 126
// #define MXC_INT_CHEETAH_TRIGGER 127
// #define MXC_INT_SRC_CPU_WDOG 128
// #ifndef CONFIG_MX6SL
// #define MXC_INT_INTERRUPT_129_NUM 129
// #define MXC_INT_INTERRUPT_130_NUM 130
// #define MXC_INT_INTERRUPT_13 131
// #define MXC_INT_CSI_INTR1 132
// #define MXC_INT_CSI_INTR2 133
// #define MXC_INT_DSI 134
// #define MXC_INT_HSI 135
// #else
// #define MXC_INT_EPDC 129
// #define MXC_INT_PXP 130
// #define MXC_INT_DCP_GP 131
// #define MXC_INT_DCP_CH0 132
// #define MXC_INT_DCP_SEC 133
// #endif
// #define MXC_INT_SJC 136
// #ifndef CONFIG_MX6SL
// #define MXC_INT_CAAM_INT0_NUM 137
// #define MXC_INT_CAAM_INT1_NUM 138
// #define MXC_INT_INTERRUPT_139_NUM 139
// #define MXC_INT_TZASC1 140
// #define MXC_INT_TZASC2 141
// #define MXC_INT_CAN1 142
// #define MXC_INT_CAN2 143
// #define MXC_INT_PERFMON1 144
// #define MXC_INT_PERFMON2 145
// #define MXC_INT_PERFMON3 146
// #define MXC_INT_HDMI_TX 147
// #define MXC_INT_HDMI_TX_WAKEUP 148
// #define MXC_INT_MLB_AHB0 149
// #define MXC_INT_ENET1 150
// #define MXC_INT_ENET2 151
// #define MXC_INT_PCIE_0 152
// #define MXC_INT_PCIE_1 153
// #define MXC_INT_PCIE_2 154
// #define MXC_INT_PCIE_3 155
// #define MXC_INT_DCIC1 156
// #define MXC_INT_DCIC2 157
// #define MXC_INT_MLB_AHB1 158
// #else
// #define MXC_INT_TZASC1 140
// #define MXC_INT_FEC 146
// #endif
// #define MXC_INT_ANATOP_ANA2 159
// /* gpio and gpio based interrupt handling */
// #define GPIO_DR 0x00
// #define GPIO_GDIR 0x04
// #define GPIO_PSR 0x08
// #define GPIO_ICR1 0x0C
// #define GPIO_ICR2 0x10
// #define GPIO_IMR 0x14
// #define GPIO_ISR 0x18
// #define GPIO_INT_LOW_LEV 0x0
// #define GPIO_INT_HIGH_LEV 0x1
// #define GPIO_INT_RISE_EDGE 0x2
// #define GPIO_INT_FALL_EDGE 0x3
// #define GPIO_INT_NONE 0x4
#define CLKCTL_CCR 0x00
#define CLKCTL_CCDR 0x04
#define CLKCTL_CSR 0x08
#define CLKCTL_CCSR 0x0C
#define CLKCTL_CACRR 0x10
#define CLKCTL_CBCDR 0x14
#define CLKCTL_CBCMR 0x18
#define CLKCTL_CSCMR1 0x1C
#define CLKCTL_CSCMR2 0x20
#define CLKCTL_CSCDR1 0x24
#define CLKCTL_CS1CDR 0x28
#define CLKCTL_CS2CDR 0x2C
#define CLKCTL_CDCDR 0x30
#define CLKCTL_CHSCCDR 0x34
#define CLKCTL_CSCDR2 0x38
#define CLKCTL_CSCDR3 0x3C
#define CLKCTL_CSCDR4 0x40
#define CLKCTL_CWDR 0x44
#define CLKCTL_CDHIPR 0x48
#define CLKCTL_CDCR 0x4C
#define CLKCTL_CTOR 0x50
#define CLKCTL_CLPCR 0x54
#define CLKCTL_CISR 0x58
#define CLKCTL_CIMR 0x5C
#define CLKCTL_CCOSR 0x60
#define CLKCTL_CGPR 0x64
#define CLKCTL_CCGR0 0x68
#define CLKCTL_CCGR1 0x6C
#define CLKCTL_CCGR2 0x70
#define CLKCTL_CCGR3 0x74
#define CLKCTL_CCGR4 0x78
#define CLKCTL_CCGR5 0x7C
#define CLKCTL_CCGR6 0x80
#define CLKCTL_CCGR7 0x84
#define CLKCTL_CMEOR 0x88
// #define ANATOP_USB1 0x10
// #define ANATOP_USB2 0x20
// #define ANATOP_PLL_VIDEO 0xA0
// #define CHIP_TYPE_DQ 0x63000
// #define CHIP_TYPE_DL 0x61000
// #define CHIP_TYPE_SOLO 0x61000
// #define CHIP_TYPE_SOLOLITE 0x60000
// #define CHIP_REV_1_0 0x10
// #define CHIP_REV_2_0 0x20
// #define CHIP_REV_2_1 0x21
// #define CHIP_REV_UNKNOWN 0xff
// #define BOARD_REV_1 0x000
// #define BOARD_REV_2 0x100
// #define BOARD_REV_3 0x200
// #define BOARD_REV_4 0x300
// #define BOARD_REV_5 0x400
// #define PLATFORM_ICGC 0x14
// #define SRC_GPR9 0x40
// #define SRC_GPR10 0x44
// //#define SNVS_LPGPR 0x68
/* Get Board ID */
#define board_is_rev(system_rev, rev) (((system_rev & 0x0F00) == rev) ? 1 : 0)
#define chip_is_type(system_rev, rev) \
(((system_rev & 0xFF000) == rev) ? 1 : 0)
// #define mx6_board_is_unknown() board_is_rev(fsl_system_rev, BOARD_REV_1)
// #define mx6_board_is_reva() board_is_rev(fsl_system_rev, BOARD_REV_2)
// #define mx6_board_is_revb() board_is_rev(fsl_system_rev, BOARD_REV_3)
// #define mx6_board_is_revc() board_is_rev(fsl_system_rev, BOARD_REV_4)
// #define mx6_chip_is_dq() chip_is_type(fsl_system_rev, CHIP_TYPE_DQ)
// #define mx6_chip_is_dl() chip_is_type(fsl_system_rev, CHIP_TYPE_DL)
// #define mx6_chip_is_solo() chip_is_type(fsl_system_rev, CHIP_TYPE_SOLO)
// #define mx6_chip_is_sololite() chip_is_type(fsl_system_rev, CHIP_TYPE_SOLOLITE)
// #define mx6_chip_dq_name "i.MX6Q"
// #define mx6_chip_dl_solo_name "i.MX6DL/Solo"
// #define mx6_chip_sololite_name "i.MX6SoloLite"
#define mx6_chip_name() (mx6_chip_is_dq() ? mx6_chip_dq_name : \
((mx6_chip_is_dl() | mx6_chip_is_solo()) ? mx6_chip_dl_solo_name : \
(mx6_chip_is_sololite() ? mx6_chip_sololite_name : "unknown-chip")))
#define mx6_board_rev_name() (mx6_board_is_reva() ? "RevA" : \
(mx6_board_is_revb() ? "RevB" : \
(mx6_board_is_revc() ? "RevC" : "unknown-board")))
// clang-format on
#ifndef __ASSEMBLER__
enum boot_device {
WEIM_NOR_BOOT,
ONE_NAND_BOOT,
PATA_BOOT,
SATA_BOOT,
I2C_BOOT,
SPI_NOR_BOOT,
SD_BOOT,
MMC_BOOT,
NAND_BOOT,
UNKNOWN_BOOT,
BOOT_DEV_NUM = UNKNOWN_BOOT,
};
enum mxc_clock {
MXC_ARM_CLK = 0,
MXC_PER_CLK,
MXC_AHB_CLK,
MXC_IPG_CLK,
MXC_IPG_PERCLK,
MXC_UART_CLK,
MXC_CSPI_CLK,
MXC_AXI_CLK,
MXC_EMI_SLOW_CLK,
MXC_DDR_CLK,
MXC_ESDHC_CLK,
MXC_ESDHC2_CLK,
MXC_ESDHC3_CLK,
MXC_ESDHC4_CLK,
MXC_SATA_CLK,
MXC_NFC_CLK,
MXC_GPMI_CLK,
MXC_BCH_CLK,
};
enum mxc_peri_clocks {
MXC_UART1_BAUD,
MXC_UART2_BAUD,
MXC_UART3_BAUD,
MXC_SSI1_BAUD,
MXC_SSI2_BAUD,
MXC_CSI_BAUD,
MXC_MSTICK1_CLK,
MXC_MSTICK2_CLK,
MXC_SPI1_CLK,
MXC_SPI2_CLK,
};
extern unsigned int fsl_system_rev;
extern unsigned int mxc_get_clock(enum mxc_clock clk);
extern unsigned int get_board_rev(void);
extern int is_soc_rev(int rev);
extern enum boot_device get_boot_device(void);
extern void fsl_set_system_rev(void);
#endif /* __ASSEMBLER__*/
#endif /* __ASM_ARCH_MXC_MX6_H__ */

View File

@ -28,9 +28,28 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* @file ivt.c
* @brief image vector table configuration for imx6q
* @version 3.0
* @author AIIT XUOS Lab
* @date 2023.08.25
*/
/*************************************************
File name: ivt.c
Description: imx6q image vector table
Others:
History:
1. Date: 2023-08-28
Author: AIIT XUOS Lab
Modification:
1. first version
*************************************************/
#include <hab_defines.h>
extern unsigned * _start_image_add;
extern unsigned * _start_image_addr;
extern unsigned * __start_boot_data;
extern unsigned * _image_size;
@ -38,9 +57,9 @@ extern unsigned * __hab_data;
extern uint8_t input_dcd_hdr[];
extern void _reset(void);
extern void _boot_start(void);
struct hab_ivt input_ivt __attribute__ ((section (".ivt"))) ={
struct hab_ivt input_ivt __attribute__((section(".ivt"))) = {
/** @ref hdr word with tag #HAB_TAG_IVT, length and HAB version fields
* (see @ref data)
*/
@ -48,7 +67,7 @@ struct hab_ivt input_ivt __attribute__ ((section (".ivt"))) ={
/** Absolute address of the first instruction to execute from the
* image
*/
(hab_image_entry_f)_reset,
(hab_image_entry_f)_boot_start,
/** Reserved in this version of HAB: should be NULL. */
NULL,
@ -59,10 +78,11 @@ struct hab_ivt input_ivt __attribute__ ((section (".ivt"))) ={
*/
&__start_boot_data,
/** Absolute address of the IVT.*/
(const void*) (&input_ivt),
(const void*)(&input_ivt),
/** Absolute address of the image CSF.*/
(const void*) &__hab_data,
//(const void*) &__hab_data,
0,
/** Reserved in this version of HAB: should be zero. */
0
@ -75,7 +95,7 @@ typedef struct {
} boot_data_t;
boot_data_t bd __attribute__ ((section (".boot_data"))) ={
(uint32_t) &_start_image_add,
(uint32_t) &_start_image_addr,
(uint32_t) &_image_size,
0,
};

View File

@ -0,0 +1,194 @@
/*
* Copyright (c) 2010-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 OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* @file nxp_imx6q_sabrelite.lds
* @brief nxp imx6q sabrelite lds function
* @version 3.0
* @author AIIT XUOS Lab
* @date 2023.08.25
*/
OUTPUT_FORMAT("elf32-littlearm") /*binary file format*/
OUTPUT_ARCH(arm) /*arch target*/
ENTRY(_vector_jumper) /*entry address pointer*/
/* mx6dq has 256kB of OCRAM
* +-------------------+ 0x0093FFFF
* | RAM Vector |
* +-------------------+ 0x0093FFB8
* | Stack |
* | 8KB |
* +-------------------+ 0x0093E000
* | MMU Table |
* | 24KB |
* +-------------------+ 0x00938000
* | |
* | Free Area |
* | 195KB |
* | |
* +-------------------+ 0x00907400
* | DCD Table |
* | 1KB |
* +-------------------+ 0x00907000
* | Reserved |
* | 28KB |
* +-------------------+ 0x00900000
*/
/*
#define OCRAM_ORG 0x00907400
#define OCRAM_FREE_SIZE 196K*/
/*
* External DDR CHIP_MX6DQ/CHIP_MX6SDL start 0x10000000, CHIP_MX6SL start 0x80000000
*/
/*
#define DDR_ORG 0x10000000
#define DDR_LEN 2048M*/
BOOT_STACK_SIZE = 0x4000;
RAM_VECTORS_SIZE = 72;
/* Specify the memory areas */
MEMORY
{
ocram (rwx) : ORIGIN = 0x00900000, LENGTH = 256K
ddr3 (rwx) : ORIGIN = 0x10000000, LENGTH = 1024M
virt_ddr3 (WRX) : ORIGIN = 0x90010000, LENGTH = 1024M
}
SECTIONS
{
. = ORIGIN(ddr3);
. = ALIGN(4);
_start_image_addr = .;
.ivt :
{
. = . + 0x400;
KEEP(*(.ivt))
} > ddr3
.boot_data :
{
__start_boot_data = .;
KEEP(*(.boot_data))
} > ddr3
/* aligned to ease the hexdump read of generated binary */
.dcd_hdr : ALIGN(16)
{
KEEP(*(.dcd_hdr))
} > ddr3
.dcd_wrt_cmd :
{
KEEP(*(.dcd_wrt_cmd))
} > ddr3
.dcd_data :
{
KEEP(*(.dcd_data))
} > ddr3
.start_sec : {
. = ALIGN(0x1000);
/* read only area. */
boot.o(.text)
imx6q_lowlevel_init.o(.text .text.*)
bootmmu.o(.text .text.*)
boot.o(.rodata .rodata.*)
imx6q_lowlevel_init.o(.rodata .rodata.*)
bootmmu.o(.rodata .rodata.*)
/* already initialized to zero. */
boot.o(.data .data.*)
imx6q_lowlevel_init.o(.data .data.*)
bootmmu.o(.data .data.*)
/* initialization start checkpoint. */
PROVIDE(boot_start_addr = .);
boot.o(.bss .bss.* COMMON)
imx6q_lowlevel_init.o(.bss .bss.* COMMON)
bootmmu.o(.bss .bss.* COMMON)
/* stack for booting code. */
. = ALIGN(0x1000);
PROVIDE(stacks_start = .);
. += BOOT_STACK_SIZE;
PROVIDE(stacks_end = .);
PROVIDE(stacks_top = .);
/* initialization end checkpoint. */
PROVIDE(boot_end_addr = .);
} > ddr3
/* Other Kernel code is placed over 0x80000000 + 128KB. */
.text : AT(0x10010000) {
*(.vectors)
. = ALIGN(0x1000);
*(.text .text.* .gnu.linkonce.t.*)
} > virt_ddr3
. = ALIGN(0x1000);
/* Other Kernel code text checkpoint. */
PROVIDE(kern_text = .);
.data : {
*(.data .data.*)
/* user app */
. = ALIGN(0x1000);
PROVIDE(_binary_fs_img_start = .);
*(.rawdata_fs_img*)
PROVIDE(_binary_fs_img_end = .);
PROVIDE(_binary_init_start = .);
*(.rawdata_init*)
PROVIDE(_binary_init_end = .);
PROVIDE(_binary_default_fs_start = .);
*(.rawdata_memfs*)
PROVIDE(_binary_default_fs_end = .);
} > virt_ddr3
PROVIDE(kernel_data_begin = .);
_image_size = . - 0x90000000;
.bss : {
PROVIDE(__bss_start__ = .);
*(.bss .bss.* COMMON)
PROVIDE(__bss_end__ = .);
} > virt_ddr3
. = ALIGN(0x1000);
PROVIDE(kernel_data_end = .);
}

View File

@ -0,0 +1,3 @@
SRC_DIR := arm
include $(KERNEL_ROOT)/compiler.mk

View File

@ -0,0 +1,3 @@
SRC_DIR := cortex-a9
include $(KERNEL_ROOT)/compiler.mk

View File

@ -0,0 +1,3 @@
SRC_FILES := l1_cache.c
include $(KERNEL_ROOT)/compiler.mk

View File

@ -0,0 +1,317 @@
/*
* 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.
*/
/**
* @file: l1_cache.c
* @brief: the general management of L1 cache
* @version: 3.0
* @author: AIIT XUOS Lab
* @date: 2023/11/6
*
*/
/*************************************************
File name: l1_cache.c
Description: the general management of L1 cache
Others:
History:
1. Date: 2023-04-27
Author: AIIT XUOS Lab
Modification:
1implement the l1 cache operations
*************************************************/
#include "l1_cache.h"
void InvalidateL1Dcache(uintptr_t start, uintptr_t end)
{
uintptr_t length = end - start;
void* addr = (void*)start;
uint32_t va;
uint32_t csidr = 0, line_size = 0;
// get the cache line size
_ARM_MRC(15, 1, csidr, 0, 0, 0);
line_size = 1 << ((csidr & 0x7) + 4);
// align the address with line
const void * end_addr = (const void *)((uint32_t)addr + length);
do
{
// Clean data cache line to PoC (Point of Coherence) by va.
va = (uint32_t) ((uint32_t)addr & (~(line_size - 1))); //addr & va_VIRTUAL_ADDRESS_MASK
_ARM_MCR(15, 0, va, 7, 6, 1);
// increment addres to next line and decrement lenght
addr = (void*)((uint32_t)addr + line_size);
} while (addr < end_addr);
// All Cache, Branch predictor and TLB maintenance operations before followed instruction complete
DSB();
}
void InvalidateL1DcacheAll(void)
{
uint32_t csid; // Cache Size ID
uint32_t wayset; // wayset parameter
int num_sets; // number of sets
int num_ways; // number of ways
_ARM_MRC(15, 1, csid, 0, 0, 0); // Read Cache Size ID
// Fill number of sets and number of ways from csid register This walues are decremented by 1
num_ways = (csid >> 0x03) & 0x3FFu; //((csid& csid_ASSOCIATIVITY_MASK) >> csid_ASSOCIATIVITY_SHIFT)
// Invalidation all lines (all Sets in all ways)
while (num_ways >= 0) {
num_sets = (csid >> 0x0D) & 0x7FFFu; //((csid & csid_NUMSETS_MASK) >> csid_NUMSETS_SHIFT)
while (num_sets >= 0) {
wayset = (num_sets << 5u) | (num_ways << 30u); //(num_sets << SETWAY_SET_SHIFT) | (num_sets << 3SETWAY_WAY_SHIFT)
// invalidate line if we know set and way
_ARM_MCR(15, 0, wayset, 7, 6, 2);
num_sets--;
}
num_ways--;
}
// All Cache, Branch predictor and TLB maintenance operations before followed instruction complete
DSB();
}
void CleanL1Dcache(uintptr_t start, uintptr_t end)
{
void* addr = (void*)start;
uintptr_t length = end - start;
uint32_t va;
uint32_t csidr = 0, line_size = 0;
const void * end_addr = (const void *)((uint32_t)addr + length);
// get the cache line size
_ARM_MRC(15, 1, csidr, 0, 0, 0);
line_size = 1 << ((csidr & 0x7) + 4);
do
{
// Clean data cache line to PoC (Point of Coherence) by va.
va = (uint32_t) ((uint32_t)addr & (~(line_size - 1))); //addr & va_VIRTUAL_ADDRESS_MASK
_ARM_MCR(15, 0, va, 7, 10, 1);
// increment addres to next line and decrement lenght
addr = (void*)((uint32_t)addr + line_size);
} while (addr < end_addr);
// All Cache, Branch predictor and TLB maintenance operations before followed instruction complete
DSB();
}
void CleanL1DcacheAll(void)
{
uint32_t csid; // Cache Size ID
uint32_t wayset; // wayset parameter
int num_sets; // number of sets
int num_ways; // number of ways
_ARM_MRC(15, 1, csid, 0, 0, 0); // Read Cache Size ID
// Fill number of sets and number of ways from csid register This walues are decremented by 1
num_ways = (csid >> 0x03) & 0x3FFu; //((csid& csid_ASSOCIATIVITY_MASK) >> csid_ASSOCIATIVITY_SHIFT`)
while (num_ways >= 0) {
num_sets = (csid >> 0x0D) & 0x7FFFu; //((csid & csid_NUMSETS_MASK) >> csid_NUMSETS_SHIFT )
while (num_sets >= 0) {
wayset = (num_sets << 5u) | (num_ways << 30u); //(num_sets << SETWAY_SET_SHIFT) | (num_ways << 3SETWAY_WAY_SHIFT)
// FLUSH (clean) line if we know set and way
_ARM_MCR(15, 0, wayset, 7, 10, 2);
num_sets--;
}
num_ways--;
}
// All Cache, Branch predictor and TLB maintenance operations before followed instruction complete
DSB();
}
void FlushL1Dcache(uintptr_t start, uintptr_t end)
{
void* addr = (void*)start;
// size_t length=end-start;
uint32_t va;
uint32_t csidr = 0, line_size = 0;
const void * end_addr = (const void *)((uint32_t)end);
// get the cache line size
_ARM_MRC(15, 1, csidr, 0, 0, 0);
line_size = 1 << ((csidr & 0x7) + 4);
do
{
// Clean data cache line to PoC (Point of Coherence) by va.
va = (uint32_t) ((uint32_t)addr & (~(line_size - 1))); //addr & va_VIRTUAL_ADDRESS_MASK
_ARM_MCR(15, 0, va, 7, 14, 1);
// increment addres to next line and decrement lenght
addr = (void*)((uint32_t)addr + line_size);
} while (addr < end_addr);
// All Cache, Branch predictor and TLB maintenance operations before followed instruction complete
DSB();
}
void FlushL1DcacheAll(void)
{
uint32_t csid; // Cache Size ID
uint32_t wayset; // wayset parameter
int num_sets; // number of sets
int num_ways; // number of ways
_ARM_MRC(15, 1, csid, 0, 0, 0); // Read Cache Size ID
// Fill number of sets and number of ways from csid register This walues are decremented by 1
num_ways = (csid >> 0x03) & 0x3FFu; //((csid& csid_ASSOCIATIVITY_MASK) >> csid_ASSOCIATIVITY_SHIFT`)
while (num_ways >= 0) {
num_sets = (csid >> 0x0D) & 0x7FFFu; //((csid & csid_NUMSETS_MASK) >> csid_NUMSETS_SHIFT )
while (num_sets >= 0) {
wayset = (num_sets << 5u) | (num_ways << 30u); //(num_sets << SETWAY_SET_SHIFT) | (num_ways << 3SETWAY_WAY_SHIFT)
// FLUSH (clean) line if we know set and way
_ARM_MCR(15, 0, wayset, 7, 14, 2);
num_sets--;
}
num_ways--;
}
// All Cache, Branch predictor and TLB maintenance operations before followed instruction complete
DSB();
}
void InvalidateL1IcacheAll()
{
uint32_t SBZ = 0x0u;
_ARM_MCR(15, 0, SBZ, 7, 5, 0);
// synchronize context on this processor
ISB();
}
void InvalidateL1Icache(uintptr_t start, uintptr_t end)
{
void* addr = (void*)start;
uint32_t va;
uint32_t csidr = 0, line_size = 0;
const void * end_addr = (const void *)((uint32_t)end);
// get the cache line size
_ARM_MRC(15, 1, csidr, 0, 0, 0);
line_size = 1 << ((csidr & 0x7) + 4);
do
{
// Clean data cache line to PoC (Point of Coherence) by va.
va = (uint32_t) ((uint32_t)addr & (~(line_size - 1))); //addr & va_VIRTUAL_ADDRESS_MASK
_ARM_MCR(15, 0, va, 7, 5, 1);
// increment addres to next line and decrement lenght
addr = (void*)((uint32_t)addr + line_size);
} while (addr < end_addr);
// synchronize context on this processor
ISB();
}
void EnableL1Icache(void)
{
uint32_t sctlr ;// System Control Register
// read sctlr
_ARM_MRC(15, 0, sctlr, 1, 0, 0);
// ignore the operation if I is enabled already
if(!(sctlr & BM_SCTLR_I))
{
// set I bit (instruction caching enable)
sctlr |= BM_SCTLR_I;
// write modified sctlr
_ARM_MCR(15, 0, sctlr, 1, 0, 0);
// synchronize context on this processor
ISB();
}
}
void DisableL1Icache()
{
uint32_t sctlr ;// System Control Register
// read sctlr
_ARM_MRC(15, 0, sctlr, 1, 0, 0);
// Clear I bit (instruction caching enable)
sctlr &= ~BM_SCTLR_I;
// write modified sctlr
_ARM_MCR(15, 0, sctlr, 1, 0, 0);
// synchronize context on this processor
ISB();
}
void EnableL1Dcache()
{
uint32_t sctlr; // System Control Register
// read sctlr
_ARM_MRC(15, 0, sctlr, 1, 0, 0);
if (!(sctlr & BM_SCTLR_C))
{
// set C bit (data caching enable)
sctlr |= BM_SCTLR_C;
// write modified sctlr
_ARM_MCR(15, 0, sctlr, 1, 0, 0);
// All Cache, Branch predictor and TLB maintenance operations before followed instruction complete
DSB();
}
}
void DisableL1Dcache()
{
uint32_t sctlr; // System Control Register
// read sctlr
_ARM_MRC(15, 0, sctlr, 1, 0, 0);
// set C bit (data caching enable)
sctlr &= ~BM_SCTLR_C;
// write modified sctlr
_ARM_MCR(15, 0, sctlr, 1, 0, 0);
// All Cache, Branch predictor and TLB maintenance operations before followed instruction complete
DSB();
}

View File

@ -0,0 +1,80 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file: l1_cache.h
* @brief: the general management of L1 cache
* @version: 3.0
* @author: AIIT XUOS Lab
* @date: 2023/4/27
*
*/
/*************************************************
File name: l1_cache.h
Description: the general management of L1 cache
Others:
History:
1. Date: 2023-04-27
Author: AIIT XUOS Lab
Modification:
1define the l1 cache operations
*************************************************/
#include "core.h"
#include <stdint.h>
/*
* L1 Cache Registers:
*
* Register: DCIMVAC - Invalidate data cache line by VA to PoC.
*
* Register: DCISW - Invalidate data cache line by Set/Way.
*
* Register: DCCMVAC - Clean data cache line to PoC by VA.
*
* Register: DCCSW - Clean data cache line by Set/Way.
*
* Register: DCCMVAU - Clean data or unified cache line by VA to PoU.
*
* Register: DCCIMVAC - Clean and invalidate data cache line by VA to PoC.
*
* Register: DCCISW - Clean and invalidate data cache line by Set/Way.
*/
#define BM_SCTLR_I (1 << 12) //!< Instruction cache enable
#define BM_SCTLR_C (1 << 2) //!< Data cache enable
void InvalidateL1Dcache(uintptr_t start, uintptr_t end);
void InvalidateL1DcacheAll(void);
void CleanL1Dcache(uintptr_t start, uintptr_t end);
void CleanL1DcacheAll(void);
void FlushL1Dcache(uintptr_t start, uintptr_t end);
void FlushL1DcacheAll(void);
void InvalidateL1IcacheAll(void);
void InvalidateL1Icache(uintptr_t start, uintptr_t end);
void EnableL1Icache(void);
void DisableL1Icache();
void EnableL1Dcache();
void DisableL1Dcache();

View File

@ -0,0 +1,3 @@
SRC_DIR := pl310
include $(KERNEL_ROOT)/compiler.mk

View File

@ -0,0 +1,3 @@
SRC_FILES := l2_cache.c
include $(KERNEL_ROOT)/compiler.mk

View File

@ -0,0 +1,702 @@
/****************************************************************************
* arch/arm/src/armv7-a/arm_l2cc_pl310.c
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/* Reference: "CoreLink<6E> Level 2 Cache Controller L2C-310", Revision r3p2,
* Technical Reference Manual, ARM DDI 0246F (ID011711), ARM
*
* NOTE: This logic is incompatible with older versions of the PL310!
*/
/**
* @file l2_cache.c
* @brief the general management of L2 cache
* @version 3.0
* @author AIIT XUOS Lab
* @date 2023/08/10
*/
/*************************************************
File name: l2_cache.c
Description: the general management of L2 cache
Others:
History:
1. Date: 2023-04-27
Author: AIIT XUOS Lab
Modification:
1support xiuos cache interface
*************************************************/
#include "l2_cache.h"
#include "core.h"
#include "l2cc_pl310.h"
#define CONFIG_ARMV7A_ASSOCIATIVITY_16WAY
#define CONFIG_ARMV7A_WAYSIZE_16KB
#define read32(a) (*(volatile uint32_t*)(a))
#define write32(v, a) (*(volatile uint32_t*)(a) = (v))
#define PANIC() panic()
#define ASSERT(f) do { if (!(f)) PANIC(); } while (0)
#define VERIFY(f) do { if ((f) < 0) PANIC(); } while (0)
#ifdef CONFIG_DEBUG_ASSERTIONS
# define DEBUGPANIC() PANIC()
# define DEBUGASSERT(f) ASSERT(f)
# define DEBUGVERIFY(f) VERIFY(f)
#else
# define DEBUGPANIC()
# define DEBUGASSERT(f) ((void)(1 || (f)))
# define DEBUGVERIFY(f) ((void)(f))
#endif
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* Configuration ************************************************************/
/* Number of ways depends on ARM configuration */
#if defined(CONFIG_ARMV7A_ASSOCIATIVITY_8WAY)
# define PL310_NWAYS 8
# define PL310_WAY_MASK 0x000000ff
#elif defined(CONFIG_ARMV7A_ASSOCIATIVITY_16WAY)
# define PL310_NWAYS 16
# define PL310_WAY_MASK 0x0000ffff
#else
# error "Number of ways not selected"
#endif
/* The size of one depends on ARM configuration */
#if defined(CONFIG_ARMV7A_WAYSIZE_16KB)
# define PL310_WAYSIZE (16 * 1024)
#elif defined(CONFIG_ARMV7A_WAYSIZE_32KB)
# define PL310_WAYSIZE (32 * 1024)
#elif defined(CONFIG_ARMV7A_WAYSIZE_64KB)
# define PL310_WAYSIZE (64 * 1024)
#elif defined(CONFIG_ARMV7A_WAYSIZE_128KB)
# define PL310_WAYSIZE (128 * 1024)
#elif defined(CONFIG_ARMV7A_WAYSIZE_256KB)
# define PL310_WAYSIZE (256 * 1024)
#elif defined(CONFIG_ARMV7A_WAYSIZE_512KB)
# define PL310_WAYSIZE (512 * 1024)
#else
# error "Way size not selected"
#endif
/* The size of the cache is then the product of the number of ways times
* the size of each way.
*/
#define PL310_CACHE_SIZE (PL310_NWAYS * PL310_WAYSIZE)
/* Use for aligning addresses to a cache line boundary */
#define PL310_CACHE_LINE_MASK (PL310_CACHE_LINE_SIZE - 1)
/* Configurable options
*
* REVISIT: Currently there are not configuration options. All values
* are just set to the default.
*/
/* Bit 0: Full line zero enable
*
* Default: 0=Full line of write zero behavior disabled
*/
#define L2CC_ACR_FLZE_CONFIG (0) /* 0=Full line of write zero behavior disabled */
/* Bit 10: High Priority for SO and Dev Reads Enable
*
* Default: 0=Strongly Ordered and Device reads have lower priority than
* cacheable accesses
*/
#define L2CC_ACR_HPSO_CONFIG (0) /* 0=Have lower priority than cache */
/* Bit 11: Store Buffer Device Limitation Enable
*
* Default: 0=Store buffer device limitation disabled
*/
#define L2CC_ACR_SBDLE_CONFIG (0) /* 0=Store buffer device limitation disabled */
/* Bit 12: Exclusive Cache Configuration
*
* Default: 0=Disabled
*/
#define L2CC_ACR_EXCC_CONFIG (0) /* 0=Disabled */
/* Bit 13: Shared Attribute Invalidate Enable
*
* Default: 0=Shared invalidate behavior disabled
*/
#define L2CC_ACR_SAIE_CONFIG (0) /* 0=Shared invalidate behavior disabled */
/* Bit 20: Event Monitor Bus Enable
*
* Default: 0=Disabled
*/
#define L2CC_ACR_EMBEN_CONFIG (0) /* 0=Disabled */
/* Bit 21: Parity Enable
*
* Default: 0=Disabled
*/
#define L2CC_ACR_PEN_CONFIG (0) /* 0=Disabled */
/* Bit 22: Shared Attribute Override Enable
*
* Default: 0=Treats shared accesses as specified in the TRM
*/
#define L2CC_ACR_SAOEN_CONFIG (0) /* 0=As specified in the TRM */
/* Bits 23-24: Force Write Allocate
*
* Default: 0=Use AWCACHE attributes for WA
*/
#define L2CC_ACR_FWA_CONFIG L2CC_ACR_FWA_AWCACHE /* Use AWCACHE attributes for WA */
/* Bit 25: Cache Replacement Policy
*
* Default: 1=Round robin replacement policy
*/
#define L2CC_ACR_CRPOL_CONFIG L2CC_ACR_CRPOL /* 1=Round robin replacement policy */
/* Bit 26: Non-Secure Lockdown Enable
*
* Default: 0=Lockdown registers cannot be modified using non-secure accesses
*/
#define L2CC_ACR_NSLEN_CONFIG (0) /* 0=Secure access only */
/* Bit 27: Non-Secure Interrupt Access Control
*
* Default: 0=Interrupt Clear and Mask can only be modified or read with
* secure accesses
*/
#define L2CC_ACR_NSIAC_CONFIG (0) /* 0=Secure access only */
/* Bit 28: Data Prefetch Enable
*
* Default: 0=Data prefetching disabled
*/
#define L2CC_ACR_DPEN_CONFIG (0) /* 0=Data prefetching disabled */
/* Bit 29: Instruction Prefetch Enable
*
* Default: 0=Instruction prefetching disabled
*/
#define L2CC_ACR_IPEN_CONFIG (0) /* 0=Instruction prefetching disabled */
/* Bit 30: Early BRESP enable
*
* Default: 0=Early BRESP disabled
*/
#define L2CC_ACR_EBRESP_CONFIG (0) /* 0=Early BRESP disabled */
#define L2CC_ACR_CONFIG \
(L2CC_ACR_FLZE_CONFIG | L2CC_ACR_HPSO_CONFIG | L2CC_ACR_SBDLE_CONFIG | \
L2CC_ACR_EXCC_CONFIG | L2CC_ACR_SAIE_CONFIG | L2CC_ACR_EMBEN_CONFIG | \
L2CC_ACR_PEN_CONFIG | L2CC_ACR_SAOEN_CONFIG | L2CC_ACR_FWA_CONFIG | \
L2CC_ACR_CRPOL_CONFIG | L2CC_ACR_NSLEN_CONFIG | L2CC_ACR_NSIAC_CONFIG | \
L2CC_ACR_DPEN_CONFIG | L2CC_ACR_IPEN_CONFIG | L2CC_ACR_EBRESP_CONFIG)
#define L2CC_ACR_ALLCONFIGS (0x7f303c01)
#define L2CC_ACR_CONFIGMASK (L2CC_ACR_SBZ | L2CC_ACR_ALLCONFIGS)
/* Filter end address */
#define CONFIG_PL310_FLEND (CONFIG_PL310_FLSTRT + CONFIG_PL310_FLSIZE)
/* Block size. Used to break up long operations so that interrupts are not
* disabled for a long time.
*/
#define PL310_GULP_SIZE 4096
/* Misc commoly defined and re-defined things */
#ifndef MIN
# define MIN(a,b) (((a) < (b)) ? (a) : (b))
#endif
#ifndef MAX
# define MAX(a,b) (((a) > (b)) ? (a) : (b))
#endif
#ifndef OK
# define OK 0
#endif
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: pl310_flush_all
*
* Description:
* Flush all ways using the Clean Invalidate Way Register (CIWR).
*
****************************************************************************/
void pl310_flush_all(void)
{
DSB();
/* Flush all ways by writing the set of ways to be cleaned to the Clean
* Invalidate Way Register (CIWR).
*/
write32(PL310_WAY_MASK, L2CC_CIWR);
/* Wait for cache operation by way to complete */
while ((read32(L2CC_CIWR) & PL310_WAY_MASK) != 0)
;
/* Drain the STB. Operation complete when all buffers, LRB, LFB, STB, and
* EB, are empty.
*/
write32(0, L2CC_CSR);
DSB();
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: arm_l2ccinitialize
*
* Description:
* One time configuration of the L2 cache. The L2 cache will be enabled
* upon return.
*
****************************************************************************/
void arm_l2ccinitialize(void)
{
uint32_t regval;
int i;
#if defined(CONFIG_ARMV7A_ASSOCIATIVITY_8WAY)
DEBUGASSERT((read32(L2CC_ACR) & L2CC_ACR_ASS) == 0);
#elif defined(CONFIG_ARMV7A_ASSOCIATIVITY_16WAY)
DEBUGASSERT((read32(L2CC_ACR) & L2CC_ACR_ASS) == L2CC_ACR_ASS);
#else
# error No associativity selected
#endif
#if defined(CONFIG_ARMV7A_WAYSIZE_16KB)
DEBUGASSERT((read32(L2CC_ACR) & L2CC_ACR_WAYSIZE_MASK) == L2CC_ACR_WAYSIZE_16KB);
#elif defined(CONFIG_ARMV7A_WAYSIZE_32KB)
DEBUGASSERT((read32(L2CC_ACR) & L2CC_ACR_WAYSIZE_MASK) == L2CC_ACR_WAYSIZE_32KB);
#elif defined(CONFIG_ARMV7A_WAYSIZE_64KB)
DEBUGASSERT((read32(L2CC_ACR) & L2CC_ACR_WAYSIZE_MASK) == L2CC_ACR_WAYSIZE_64KB);
#elif defined(CONFIG_ARMV7A_WAYSIZE_128KB)
DEBUGASSERT((read32(L2CC_ACR) & L2CC_ACR_WAYSIZE_MASK) == L2CC_ACR_WAYSIZE_128KB);
#elif defined(CONFIG_ARMV7A_WAYSIZE_256KB)
DEBUGASSERT((read32(L2CC_ACR) & L2CC_ACR_WAYSIZE_MASK) == L2CC_ACR_WAYSIZE_256KB);
#elif defined(CONFIG_ARMV7A_WAYSIZE_512KB)
DEBUGASSERT((read32(L2CC_ACR) & L2CC_ACR_WAYSIZE_MASK) == L2CC_ACR_WAYSIZE_512KB);
#else
# error No way size selected
#endif
if ((read32(L2CC_CR) & L2CC_CR_L2CEN) == 0) {
#if defined(CONFIG_PL310_TRCR_TSETLAT) && defined(CONFIG_PL310_TRCR_TRDLAT) && defined(CONFIG_PL310_TRCR_TWRLAT)
/* Configure Tag RAM control */
regval = ((CONFIG_PL310_TRCR_TSETLAT - 1) << L2CC_TRCR_TSETLAT_SHIFT)((CONFIG_PL310_TRCR_TRDLAT - 1) << L2CC_TRCR_TRDLAT_SHIFT) | ((CONFIG_PL310_TRCR_TWRLAT - 1) << L2CC_TRCR_TWRLAT_SHIFT);
write32(regval, L2CC_TRCR);
#endif
#if defined(CONFIG_PL310_DRCR_DSETLAT) && defined(CONFIG_PL310_DRCR_DRDLAT) && defined(CONFIG_PL310_DRCR_DWRLAT)
/* Configure Data RAM control */
regval = ((CONFIG_PL310_DRCR_DSETLAT - 1) << L2CC_DRCR_DSETLAT_SHIFT) | ((CONFIG_PL310_DRCR_DRDLAT - 1) << L2CC_DRCR_DRDLAT_SHIFT) | ((CONFIG_PL310_DRCR_DWRLAT - 1) << L2CC_DRCR_DWRLAT_SHIFT);
write32(regval, L2CC_DRCR);
#endif
#ifdef PL310_ADDRESS_FILTERING
#if defined(CONFIG_PL310_FLSTRT) && defined(CONFIG_PL310_FLSIZE)
/* Configure the address filter */
regval = (CONFIG_PL310_FLEND + ~L2CC_FLEND_MASK) & L2CC_FLEND_MASK;
write32(regval, L2CC_FLEND);
regval = (CONFIG_PL310_FLSTRT & L2CC_FLSTRT_MASK) | L2CC_FLSTRT_ENABLE;
write32(regval | L2X0_ADDR_FILTER_EN, L2CC_FLSTRT);
#endif
#endif
/* Make sure that the memory is not locked down */
for (i = 0; i < PL310_NLOCKREGS; i++) {
write32(0, L2CC_DLKR(i));
write32(0, L2CC_ILKR(i));
}
/* Configure the cache properties */
regval = read32(L2CC_ACR);
regval &= ~L2CC_ACR_CONFIGMASK;
regval |= L2CC_ACR_CONFIG;
write32(regval, L2CC_ACR);
/* Invalidate and enable the cache */
InvalidateL2CacheAll();
write32(L2CC_CR_L2CEN, L2CC_CR);
}
}
/****************************************************************************
* Name: l2cc_enable
*
* Description:
* Re-enable the L2CC-P310 L2 cache by setting the enable bit in the
* Control Register (CR)
*
****************************************************************************/
void EnableL2Cache(void)
{
InvalidateL2CacheAll();
write32(L2CC_CR_L2CEN, L2CC_CR);
}
/****************************************************************************
* Name: l2cc_disable
*
* Description:
* Disable the L2CC-P310 L2 cache by clearing the Control Register (CR)
*
*
****************************************************************************/
void DisableL2Cache(void)
{
write32(0, L2CC_CR);
DSB();
}
/****************************************************************************
* Name: l2cc_sync
*
* Description:
* Drain the STB. Operation complete when all buffers, LRB, LFB, STB, and
* EB, are empty.
*
****************************************************************************/
void SyncL2Cache(void)
{
write32(0, L2CC_CSR);
}
/****************************************************************************
* Name: l2cc_invalidate_all
*
* Description:
* Invalidate all ways using the Invalidate Way Register (IWR).
*
****************************************************************************/
void InvalidateL2CacheAll(void)
{
uint32_t regval;
/* Invalidate all ways */
/* Disable the L2 cache while we invalidate it */
regval = read32(L2CC_CR);
DisableL2Cache();
/* Invalidate all ways by writing the bit mask of ways to be invalidated
* the Invalidate Way Register (IWR).
*/
write32(PL310_WAY_MASK, L2CC_IWR);
while ((read32(L2CC_IWR) & PL310_WAY_MASK) != 0)
;
/* Drain the STB. Operation complete when all buffers, LRB, LFB, STB, and
* EB, are empty.
*/
write32(0, L2CC_CSR);
/* Then re-enable the L2 cache if it was enabled before */
write32(regval, L2CC_CR);
}
/****************************************************************************
* Name: l2cc_invalidate
*
* Description:
* Invalidate a range of addresses by writing to the Invalidate Physical
* Address Line Register (IPALR) repeatedly.
*
****************************************************************************/
void InvalidateL2Cache(uintptr_t startaddr, uintptr_t endaddr)
{
uintptr_t invalsize;
uintptr_t gulpend;
/* Check if the start address is aligned with a cacheline */
if ((startaddr & PL310_CACHE_LINE_MASK) != 0) {
/* No.. align down and flush the cache line by writing the address to
* the Clean Invalidate Physical Address Line Register (CIPALR).
*/
startaddr &= ~PL310_CACHE_LINE_MASK;
write32(startaddr, L2CC_CIPALR);
/* Then start invalidating at the next cache line */
startaddr += PL310_CACHE_LINE_SIZE;
}
/* Check if the end address is aligned with a cache line */
if ((endaddr & PL310_CACHE_LINE_MASK) != 0) {
/* No.. align down and flush cache line by writing the address to
* the Clean Invalidate Physical Address Line Register (CIPALR).
*/
endaddr &= ~PL310_CACHE_LINE_MASK;
write32(endaddr, L2CC_CIPALR);
}
/* Loop, invalidated the address range by cache line. Interrupts are re-
* enabled momentarily every PL310_GULP_SIZE bytes.
*/
while (startaddr < endaddr) {
/* Get the size of the next gulp of cache lines to invalidate. We do
* this in small chunks so that we do not have to keep interrupts
* disabled throughout the whole flush.
*/
invalsize = endaddr - startaddr;
gulpend = startaddr + MIN(invalsize, PL310_GULP_SIZE);
/* Disable interrupts and invalidate the gulp */
while (startaddr < gulpend) {
/* Invalidate the cache line by writing the address to the
* Invalidate Physical Address Line Register (IPALR).
*/
write32(startaddr, L2CC_IPALR);
/* Start of the next cache line */
startaddr += PL310_CACHE_LINE_SIZE;
}
/* Enable interrupts momentarily */
}
/* Drain the STB. Operation complete when all buffers, LRB, LFB, STB, and
* EB, are empty.
*/
write32(0, L2CC_CSR);
}
/****************************************************************************
* Name: l2cc_clean_all
*
* Description:
* Clean all ways by using the Clean Ways Register (CWR).
*
****************************************************************************/
void CleanL2CacheAll(void)
{
write32(PL310_WAY_MASK, L2CC_CWR);
/* Wait for cache operation by way to complete */
while ((read32(L2CC_CWR) & PL310_WAY_MASK) != 0)
;
/* Drain the STB. Operation complete when all buffers, LRB, LFB, STB, and
* EB, are empty.
*/
write32(0, L2CC_CSR);
}
/****************************************************************************
* Name: l2cc_clean
*
* Description:
* Clean the cache line over a range of addresses uing the Clean Physical
* Address Line Register (CPALR) repeatedly.
*
****************************************************************************/
void CleanL2Cache(uintptr_t startaddr, uintptr_t endaddr)
{
uintptr_t cleansize;
uintptr_t gulpend;
/* If the range of addresses to clean is as large or larger the L2 cache,
* then just clean the whole thing.
*/
cleansize = endaddr - startaddr;
if (cleansize >= PL310_CACHE_SIZE) {
CleanL2CacheAll();
return;
}
/* Align the starting address to a cache line boundary */
startaddr &= ~PL310_CACHE_LINE_MASK;
/* Clean the L2 cache by cache line, enabling interrupts momentarily
* every PL310_GULP_SIZE bytes.
*/
while (startaddr < endaddr) {
/* Get the size of the next gulp of cache lines to flush. We do
* this in small chunks so that we do not have to keep interrupts
* disabled throughout the whole flush.
*/
cleansize = endaddr - startaddr;
gulpend = startaddr + MIN(cleansize, PL310_GULP_SIZE);
/* Disable interrupts and clean the gulp */
while (startaddr < gulpend) {
/* Clean the cache line by writing the address to the Clean
* Physical Address Line Register (CPALR).
*/
write32(startaddr, L2CC_CPALR);
/* Start of the next cache line */
startaddr += PL310_CACHE_LINE_SIZE;
}
/* Enable interrupts momentarily */
}
/* Drain the STB. Operation complete when all buffers, LRB, LFB, STB, and
* EB, are empty.
*/
write32(0, L2CC_CSR);
}
/****************************************************************************
* Name: l2cc_flush_all
*
* Description:
* Flush all ways using the Clean Invalidate Way Register (CIWR).
*
****************************************************************************/
void FlushL2CacheAll(void)
{
/* Flush all ways using the Clean Invalidate Way Register (CIWR). */
pl310_flush_all();
}
/****************************************************************************
* Name: l2cc_flush
*
* Description:
* Flush a range of address by using the Clean Invalidate Physical Address
* Line Register (CIPALR) repeatedly.
*
****************************************************************************/
void FlushL2Cache(uint32_t startaddr, uint32_t endaddr)
{
uintptr_t flushsize;
uintptr_t gulpend;
/* If the range of addresses to flush is as large or larger the L2 cache,
* then just flush the whole thing.
*/
flushsize = endaddr - startaddr;
if (flushsize >= PL310_CACHE_SIZE)
{
pl310_flush_all();
return;
}
/* Align the starting address to a cache line boundary */
startaddr &= ~PL310_CACHE_LINE_MASK;
/* Flush the L2 cache by cache line, enabling interrupts momentarily
* every PL310_GULP_SIZE bytes.
*/
while (startaddr < endaddr)
{
/* Get the size of the next gulp of cache lines to flush. We do
* this in small chunks so that we do not have to keep interrupts
* disabled throughout the whole flush.
*/
flushsize = endaddr - startaddr;
gulpend = startaddr + MIN(flushsize, PL310_GULP_SIZE);
/* Disable interrupts and flush the gulp */
while (startaddr < gulpend)
{
/* Flush the cache line by writing the address to the Clean
* Invalidate Physical Address Line Register (CIPALR).
*/
write32(startaddr, L2CC_CIPALR);
/* Start of the next cache line */
startaddr += PL310_CACHE_LINE_SIZE;
}
/* Enable interrupts momentarily */
}
/* Drain the STB. Operation complete when all buffers, LRB, LFB, STB, and
* EB, are empty.
*/
write32(0, L2CC_CSR);
}

View File

@ -0,0 +1,192 @@
/*
* Copyright (c) 2022 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file l2_cache.h
* @brief the general management of L2 cache
* @version 3.0
* @author AIIT XUOS Lab
* @date 2023/08/10
*/
/*************************************************
File name: l2_cache.h
Description: the general management of L2 cache
Others:
History:
1. Date: 2023-08-10
Author: AIIT XUOS Lab
Modification:
1define the l2 cache operations
*************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <stdint.h>
#define CONFIG_ARCH_L2CACHE
#ifdef CONFIG_ARCH_L2CACHE
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Public Data
****************************************************************************/
#ifndef __ASSEMBLY__
#ifdef __cplusplus
#define EXTERN extern "C"
extern "C"
{
#else
#define EXTERN extern
#endif
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
/****************************************************************************
* Name: arm_l2ccinitialize
*
* Description:
* One time configuration of the L2 cache. The L2 cache will be enabled
* upon return.
*
* Input Parameters:
* None. The L2 cache configuration is controlled by configuration
* settings.
*
* Returned Value:
* None
*
****************************************************************************/
void arm_l2ccinitialize(void);
void pl310_flush_all(void);
/****************************************************************************
* Name: l2cc_enable
*
* Description:
* Re-enable the L2CC-P310 L2 cache by setting the enable bit in the
* Control Register (CR)
*
****************************************************************************/
void EnableL2Cache(void);
/****************************************************************************
* Name: l2cc_disable
*
* Description:
* Disable the L2 cache
*
****************************************************************************/
void DisableL2Cache(void);
/****************************************************************************
* Name: l2cc_sync
*
* Description:
* Drain the L2 cache.
*
****************************************************************************/
void SyncL2Cache(void);
/****************************************************************************
* Name: l2cc_invalidate_all
*
* Description:
* Invalidate the entire L2 cache.
*
****************************************************************************/
void InvalidateL2CacheAll(void);
/****************************************************************************
* Name: l2cc_invalidate
*
* Description:
* Invalidate a range of addresses in the L2 cache
*
****************************************************************************/
void InvalidateL2Cache(uintptr_t startaddr, uintptr_t endaddr);
/****************************************************************************
* Name: l2cc_clean_all
*
* Description:
* Clean the entire L2 cache.
*
****************************************************************************/
void CleanL2CacheAll(void);
/****************************************************************************
* Name: l2cc_clean
*
* Description:
* Clean a range of address within the L2 cache.
*
****************************************************************************/
void CleanL2Cache(uintptr_t startaddr, uintptr_t endaddr);
/****************************************************************************
* Name: l2cc_flush_all
*
* Description:
* Flush the entire L2 cache.
*
****************************************************************************/
void FlushL2CacheAll(void);
/****************************************************************************
* Name: l2cc_flush
*
* Description:
* Flush a range of address within the L2 cache.
*
****************************************************************************/
void FlushL2Cache(uint32_t startaddr, uint32_t endaddr);
#undef EXTERN
#ifdef __cplusplus
}
#endif
#endif /* __ASSEMBLY__ */
#else /* CONFIG_ARCH_L2CACHE */
/* Provide simple definitions to concentrate the inline conditional
* compilation in one place.
*/
#define EnableL2Cache()
#define DisableL2Cache()
#define SyncL2Cache()
#define InvalidateL2CacheAll()
#define InvalidateL2Cache(s,e)
#define CleanL2CacheAll()
#define CleanL2Cache(s,e)
#define FlushL2CacheAll()
#define FlushL2Cache(s,e)
#endif /* CONFIG_ARCH_L2CACHE */

View File

@ -0,0 +1,504 @@
/****************************************************************************
* arch/arm/src/armv7-a/l2cc_pl310.h
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/* Reference: "CoreLink Level 2 Cache Controller L2C-310", Revision r3p2,
* Technical Reference Manual, ARM DDI 0246F (ID011711), ARM
*/
/**
* @file l2cc_pl310.h
* @brief define properties about pl310 cache controller
* @version 3.0
* @author AIIT XUOS Lab
* @date 2023/08/10
*/
/*************************************************
File name: l2cc_pl310.h
Description: define properties about pl310 cache controller
Others:
History:
1. Date: 2023-08-10
Author: AIIT XUOS Lab
Modification:
1define properties about pl310 cache controller according to xiuos
*************************************************/
#ifndef __ARCH_ARM_SRC_ARMV7_A_L2CC_PL310_H
#define __ARCH_ARM_SRC_ARMV7_A_L2CC_PL310_H
/****************************************************************************
* Included Files
****************************************************************************/
#include "mmio_access.h"
// clang-format off
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* General Definitions ******************************************************/
#define PL310_CACHE_LINE_SIZE 32
#ifdef CONFIG_PL310_LOCKDOWN_BY_MASTER
# define PL310_NLOCKREGS 8
#else
# define PL310_NLOCKREGS 1
#endif
/* L2CC Register Offsets ****************************************************/
#define IMX_ARMMP_PSECTION 0x00a00000 /* 00a00000-00afffff 8 KB ARM MP */
#define IMX_ARMMP_VSECTION IMX_ARMMP_PSECTION /* 8 KB ARM MP */
#define IMX_PL310_OFFSET 0x00002000 /* 00002000-00002fff 4 KB PL310 (L2 Cache controller) */
#define IMX_PL310_VBASE MMIO_P2V(IMX_ARMMP_VSECTION + IMX_PL310_OFFSET)
#define L2CC_VBASE IMX_PL310_VBASE
#define L2CC_IDR_OFFSET 0x0000 /* Cache ID Register */
#define L2CC_TYPR_OFFSET 0x0004 /* Cache Type Register */
#define L2CC_CR_OFFSET 0x0100 /* Control Register */
#define L2CC_ACR_OFFSET 0x0104 /* Auxiliary Control Register */
#define L2CC_TRCR_OFFSET 0x0108 /* Tag RAM Control Register */
#define L2CC_DRCR_OFFSET 0x010c /* Data RAM Control Register */
/* 0x0110-0x01fc Reserved */
#define L2CC_ECR_OFFSET 0x0200 /* Event Counter Control Register */
#define L2CC_ECFGR1_OFFSET 0x0204 /* Event Counter 1 Configuration Register */
#define L2CC_ECFGR0_OFFSET 0x0208 /* Event Counter 0 Configuration Register */
#define L2CC_EVR1_OFFSET 0x020c /* Event Counter 1 Value Register */
#define L2CC_EVR0_OFFSET 0x0210 /* Event Counter 0 Value Register */
#define L2CC_IMR_OFFSET 0x0214 /* Interrupt Mask Register */
#define L2CC_MISR_OFFSET 0x0218 /* Masked Interrupt Status Register */
#define L2CC_RISR_OFFSET 0x021c /* Raw Interrupt Status Register */
#define L2CC_ICR_OFFSET 0x0220 /* Interrupt Clear Register */
/* 0x0224-0x072c Reserved */
#define L2CC_CSR_OFFSET 0x0730 /* Cache Synchronization Register */
/* 0x0734-0x076c Reserved */
#define L2CC_IPALR_OFFSET 0x0770 /* Invalidate Physical Address Line Register */
/* 0x0774-0x0778 Reserved */
#define L2CC_IWR_OFFSET 0x077c /* Invalidate Way Register */
/* 0x0780-0x07af Reserved */
#define L2CC_CPALR_OFFSET 0x07b0 /* Clean Physical Address Line Register */
/* 0x07b4 Reserved */
#define L2CC_CIR_OFFSET 0x07b8 /* Clean Index Register */
#define L2CC_CWR_OFFSET 0x07bc /* Clean Way Register */
/* 0x07c0-0x07ec Reserved */
#define L2CC_CIPALR_OFFSET 0x07f0 /* Clean Invalidate Physical Address Line Register */
/* 0x07f4 Reserved */
#define L2CC_CIIR_OFFSET 0x07f8 /* Clean Invalidate Index Register */
#define L2CC_CIWR_OFFSET 0x07fc /* Clean Invalidate Way Register */
/* 0x0800-0x08fc Reserved */
/* Data and Instruction Lockdown registers where n=0-7.
* The registers for n > 0 are implemented if the option
* pl310_LOCKDOWN_BY_MASTER is enabled.
* Otherwise, they are unused
*/
#define L2CC_DLKR_OFFSET(n) (0x0900 + ((n) << 3)) /* Data Lockdown Register */
#define L2CC_ILKR_OFFSET(n) (0x0904 + ((n) << 3)) /* Instruction Lockdown Register */
/* 0x0940-0x0f4c Reserved */
#ifdef CONFIG_PL310_LOCKDOWN_BY_LINE
# define L2CC_LKLN_OFFSET 0x0950 /* Lock Line Enable Register */
# define L2CC_UNLKW_OFFSET 0x0954 /* Unlock Way Register */
#endif
/* 0x0958-0x0bfc Reserved */
#define L2CC_FLSTRT_OFFSET 0x0c00 /* Address filter start */
#define L2CC_FLEND_OFFSET 0x0c04 /* Address filter end */
/* 0x0c08-0x0f3c Reserved */
#define L2CC_DCR_OFFSET 0x0f40 /* Debug Control Register */
/* 0x0f44-0x0f5c Reserved */
#define L2CC_PCR_OFFSET 0x0f60 /* Prefetch Control Register */
/* 0x0f64-0x0f7c Reserved */
#define L2CC_POWCR_OFFSET 0x0f80 /* Power Control Register */
/* L2CC Register Addresses **************************************************/
#define L2CC_IDR (L2CC_VBASE+L2CC_IDR_OFFSET)
#define L2CC_TYPR (L2CC_VBASE+L2CC_TYPR_OFFSET)
#define L2CC_CR (L2CC_VBASE+L2CC_CR_OFFSET)
#define L2CC_ACR (L2CC_VBASE+L2CC_ACR_OFFSET)
#define L2CC_TRCR (L2CC_VBASE+L2CC_TRCR_OFFSET)
#define L2CC_DRCR (L2CC_VBASE+L2CC_DRCR_OFFSET)
#define L2CC_ECR (L2CC_VBASE+L2CC_ECR_OFFSET)
#define L2CC_ECFGR1 (L2CC_VBASE+L2CC_ECFGR1_OFFSET)
#define L2CC_ECFGR0 (L2CC_VBASE+L2CC_ECFGR0_OFFSET)
#define L2CC_EVR1 (L2CC_VBASE+L2CC_EVR1_OFFSET)
#define L2CC_EVR0 (L2CC_VBASE+L2CC_EVR0_OFFSET)
#define L2CC_IMR (L2CC_VBASE+L2CC_IMR_OFFSET)
#define L2CC_MISR (L2CC_VBASE+L2CC_MISR_OFFSET)
#define L2CC_RISR (L2CC_VBASE+L2CC_RISR_OFFSET)
#define L2CC_ICR (L2CC_VBASE+L2CC_ICR_OFFSET)
#define L2CC_CSR (L2CC_VBASE+L2CC_CSR_OFFSET)
#define L2CC_IPALR (L2CC_VBASE+L2CC_IPALR_OFFSET)
#define L2CC_IWR (L2CC_VBASE+L2CC_IWR_OFFSET)
#define L2CC_CPALR (L2CC_VBASE+L2CC_CPALR_OFFSET)
#define L2CC_CIR (L2CC_VBASE+L2CC_CIR_OFFSET)
#define L2CC_CWR (L2CC_VBASE+L2CC_CWR_OFFSET)
#define L2CC_CIPALR (L2CC_VBASE+L2CC_CIPALR_OFFSET)
#define L2CC_CIIR (L2CC_VBASE+L2CC_CIIR_OFFSET)
#define L2CC_CIWR (L2CC_VBASE+L2CC_CIWR_OFFSET)
#define L2CC_DLKR(n) (L2CC_VBASE+L2CC_DLKR_OFFSET(n))
#define L2CC_ILKR(n) (L2CC_VBASE+L2CC_ILKR_OFFSET(n))
#ifdef CONFIG_PL310_LOCKDOWN_BY_LINE
# define L2CC_LKLN (L2CC_VBASE+L2CC_LKLN_OFFSET)
# define L2CC_UNLKW (L2CC_VBASE+L2CC_UNLKW_OFFSET)
#endif
#define L2CC_FLSTRT (L2CC_VBASE+L2CC_FLSTRT_OFFSET)
#define L2CC_FLEND (L2CC_VBASE+L2CC_FLEND_OFFSET)
#define L2CC_DCR (L2CC_VBASE+L2CC_DCR_OFFSET)
#define L2CC_PCR (L2CC_VBASE+L2CC_PCR_OFFSET)
#define L2CC_POWCR (L2CC_VBASE+L2CC_POWCR_OFFSET)
/* L2CC Register Bit Definitions ********************************************/
/* Cache ID Register (32-bit ID) */
#define L2CC_IDR_REV_MASK 0x0000003f
#define L2CC_IDR_REV_R0P0 0x00000000
#define L2CC_IDR_REV_R1P0 0x00000002
#define L2CC_IDR_REV_R2P0 0x00000004
#define L2CC_IDR_REV_R3P0 0x00000005
#define L2CC_IDR_REV_R3P1 0x00000006
#define L2CC_IDR_REV_R3P2 0x00000008
/* Cache Type Register */
#define L2CC_TYPR_IL2ASS (1 << 6) /* Bit 6: Instruction L2 Cache Associativity */
#define L2CC_TYPR_IL2WSIZE_SHIFT (8) /* Bits 8-10: Instruction L2 Cache Way Size */
#define L2CC_TYPR_IL2WSIZE_MASK (7 << L2CC_TYPR_IL2WSIZE_SHIFT)
#define L2CC_TYPR_IL2WSIZE(n) ((uint32_t)(n) << L2CC_TYPR_IL2WSIZE_SHIFT)
#define L2CC_TYPR_DL2ASS (1 << 18) /* Bit 18: Data L2 Cache Associativity */
#define L2CC_TYPR_DL2WSIZE_SHIFT (20) /* Bits 20-22: Data L2 Cache Way Size */
#define L2CC_TYPR_DL2WSIZE_MASK (7 << L2CC_TYPR_DL2WSIZE_SHIFT)
#define L2CC_TYPR_DL2WSIZE(n) ((uint32_t)(n) << L2CC_TYPR_DL2WSIZE_SHIFT)
/* Control Register */
#define L2CC_CR_L2CEN (1 << 0) /* Bit 0: L2 Cache Enable */
/* Auxiliary Control Register */
#define L2CC_ACR_FLZE (1 << 0) /* Bit 0: Full line zero enable */
#define L2CC_ACR_HPSO (1 << 10) /* Bit 10: High Priority for SO and Dev Reads Enable */
#define L2CC_ACR_SBDLE (1 << 11) /* Bit 11: Store Buffer Device Limitation Enable */
#define L2CC_ACR_EXCC (1 << 12) /* Bit 12: Exclusive Cache Configuration */
#define L2CC_ACR_SAIE (1 << 13) /* Bit 13: Shared Attribute Invalidate Enable */
#define L2CC_ACR_ASS (1 << 16) /* Bit 16: Associativity */
#define L2CC_ACR_WAYSIZE_SHIFT (17) /* Bits 17-19: Way Size */
#define L2CC_ACR_WAYSIZE_MASK (7 << L2CC_ACR_WAYSIZE_SHIFT)
#define L2CC_ACR_WAYSIZE_16KB (1 << L2CC_ACR_WAYSIZE_SHIFT)
#define L2CC_ACR_WAYSIZE_32KB (2 << L2CC_ACR_WAYSIZE_SHIFT)
#define L2CC_ACR_WAYSIZE_64KB (3 << L2CC_ACR_WAYSIZE_SHIFT)
#define L2CC_ACR_WAYSIZE_128KB (4 << L2CC_ACR_WAYSIZE_SHIFT)
#define L2CC_ACR_WAYSIZE_256KB (5 << L2CC_ACR_WAYSIZE_SHIFT)
#define L2CC_ACR_WAYSIZE_512KB (6 << L2CC_ACR_WAYSIZE_SHIFT)
#define L2CC_ACR_EMBEN (1 << 20) /* Bit 20: Event Monitor Bus Enable */
#define L2CC_ACR_PEN (1 << 21) /* Bit 21: Parity Enable */
#define L2CC_ACR_SAOEN (1 << 22) /* Bit 22: Shared Attribute Override Enable */
#define L2CC_ACR_FWA_SHIFT (23) /* Bits 23-24: Force Write Allocate */
#define L2CC_ACR_FWA_MASK (3 << L2CC_ACR_FWA_SHIFT)
#define L2CC_ACR_FWA_AWCACHE (0 << L2CC_ACR_FWA_SHIFT) /* Use AWCACHE attributes for WA */
#define L2CC_ACR_FWA_NOALLOC (1 << L2CC_ACR_FWA_SHIFT) /* No allocate */
#define L2CC_ACR_FWA_OVERRIDE (2 << L2CC_ACR_FWA_SHIFT) /* Override AWCACHE attributes */
#define L2CC_ACR_FWA_MAPPED (3 << L2CC_ACR_FWA_SHIFT) /* Internally mapped to 00 */
#define L2CC_ACR_CRPOL (1 << 25) /* Bit 25: Cache Replacement Policy */
#define L2CC_ACR_NSLEN (1 << 26) /* Bit 26: Non-Secure Lockdown Enable */
#define L2CC_ACR_NSIAC (1 << 27) /* Bit 27: Non-Secure Interrupt Access Control */
#define L2CC_ACR_DPEN (1 << 28) /* Bit 28: Data Prefetch Enable */
#define L2CC_ACR_IPEN (1 << 29) /* Bit 29: Instruction Prefetch Enable */
#define L2CC_ACR_EBRESP (1 << 30) /* Bit 30: Early BRESP enable */
#define L2CC_ACR_SBZ (0x8000c1fe)
/* Tag RAM Control Register */
#define L2CC_TRCR_TSETLAT_SHIFT (0) /* Bits 0-2: Setup Latency */
#define L2CC_TRCR_TSETLAT_MASK (7 << L2CC_TRCR_TSETLAT_SHIFT)
#define L2CC_TRCR_TSETLAT(n) ((uint32_t)(n) << L2CC_TRCR_TSETLAT_SHIFT)
#define L2CC_TRCR_TRDLAT_SHIFT (4) /* Bits 4-6: Read Access Latency */
#define L2CC_TRCR_TRDLAT_MASK (7 << L2CC_TRCR_TRDLAT_SHIFT)
#define L2CC_TRCR_TRDLAT(n) ((uint32_t)(n) << L2CC_TRCR_TRDLAT_SHIFT)
#define L2CC_TRCR_TWRLAT_SHIFT (8) /* Bits 8-10: Write Access Latency */
#define L2CC_TRCR_TWRLAT_MASK (7 << L2CC_TRCR_TWRLAT_SHIFT)
#define L2CC_TRCR_TWRLAT(n) ((uint32_t)(n) << L2CC_TRCR_TWRLAT_SHIFT)
/* Data RAM Control Register */
#define L2CC_DRCR_DSETLAT_SHIFT (0) /* Bits 0-2: Setup Latency */
#define L2CC_DRCR_DSETLAT_MASK (7 << L2CC_DRCR_DSETLAT_SHIFT)
#define L2CC_DRCR_DSETLAT(n) ((uint32_t)(n) << L2CC_DRCR_DSETLAT_SHIFT)
#define L2CC_DRCR_DRDLAT_SHIFT (4) /* Bits 4-6: Read Access Latency */
#define L2CC_DRCR_DRDLAT_MASK (7 << L2CC_DRCR_DRDLAT_SHIFT)
#define L2CC_DRCR_DRDLAT(n) ((uint32_t)(n) << L2CC_DRCR_DRDLAT_SHIFT)
#define L2CC_DRCR_DWRLAT_SHIFT (8) /* Bits 8-10: Write Access Latency */
#define L2CC_DRCR_DWRLAT_MASK (7 << L2CC_DRCR_DWRLAT_SHIFT)
#define L2CC_DRCR_DWRLAT(n) ((uint32_t)(n) << L2CC_DRCR_DWRLAT_SHIFT)
/* Event Counter Control Register */
#define L2CC_ECR_EVCEN (1 << 0) /* Bit 0: Event Counter Enable */
#define L2CC_ECR_EVC0RST (1 << 1) /* Bit 1: Event Counter 0 Reset */
#define L2CC_ECR_EVC1RST (1 << 2) /* Bit 2: Event Counter 1 Reset */
/* Event Counter 1 Configuration Register */
#define L2CC_ECFGR1_EIGEN_SHIFT (0) /* Bits 0-1: Event Counter Interrupt Generation */
#define L2CC_ECFGR1_EIGEN_MASK (3 << L2CC_ECFGR1_EIGEN_SHIFT)
#define L2CC_ECFGR1_EIGEN_INTDIS (0 << L2CC_ECFGR1_EIGEN_SHIFT) /* Disables (default) */
#define L2CC_ECFGR1_EIGEN_INTENINCR (1 << L2CC_ECFGR1_EIGEN_SHIFT) /* Enables with Increment condition */
#define L2CC_ECFGR1_EIGEN_INTENOVER (2 << L2CC_ECFGR1_EIGEN_SHIFT) /* Enables with Overflow condition */
#define L2CC_ECFGR1_EIGEN_INTGENDIS (3 << L2CC_ECFGR1_EIGEN_SHIFT) /* Disables Interrupt generation */
#define L2CC_ECFGR1_ESRC_SHIFT (2) /* Bits 2-5: Event Counter Source */
#define L2CC_ECFGR1_ESRC_MASK (15 << L2CC_ECFGR1_ESRC_SHIFT)
#define L2CC_ECFGR1_ESRC_CNTDIS (0 << L2CC_ECFGR1_ESRC_SHIFT) /* Counter Disabled */
#define L2CC_ECFGR1_ESRC_CO (1 << L2CC_ECFGR1_ESRC_SHIFT) /* Source is CO */
#define L2CC_ECFGR1_ESRC_DRHIT (2 << L2CC_ECFGR1_ESRC_SHIFT) /* Source is DRHIT */
#define L2CC_ECFGR1_ESRC_DRREQ (3 << L2CC_ECFGR1_ESRC_SHIFT) /* Source is DRREQ */
#define L2CC_ECFGR1_ESRC_DWHIT (4 << L2CC_ECFGR1_ESRC_SHIFT) /* Source is DWHIT */
#define L2CC_ECFGR1_ESRC_DWREQ (5 << L2CC_ECFGR1_ESRC_SHIFT) /* Source is DWREQ */
#define L2CC_ECFGR1_ESRC_DWTREQ (6 << L2CC_ECFGR1_ESRC_SHIFT) /* Source is DWTREQ */
#define L2CC_ECFGR1_ESRC_IRHIT (7 << L2CC_ECFGR1_ESRC_SHIFT) /* Source is IRHIT */
#define L2CC_ECFGR1_ESRC_IRREQ (8 << L2CC_ECFGR1_ESRC_SHIFT) /* Source is IRREQ */
#define L2CC_ECFGR1_ESRC_WA (9 << L2CC_ECFGR1_ESRC_SHIFT) /* Source is WA */
#define L2CC_ECFGR1_ESRC_IPFALLOC (10 << L2CC_ECFGR1_ESRC_SHIFT) /* Source is IPFALLOC */
#define L2CC_ECFGR1_ESRC_EPFHIT (11 << L2CC_ECFGR1_ESRC_SHIFT) /* Source is EPFHIT */
#define L2CC_ECFGR1_ESRC_EPFALLOC (12 << L2CC_ECFGR1_ESRC_SHIFT) /* Source is EPFALLOC */
#define L2CC_ECFGR1_ESRC_SRRCVD (13 << L2CC_ECFGR1_ESRC_SHIFT) /* Source is SRRCVD */
#define L2CC_ECFGR1_ESRC_SRCONF (14 << L2CC_ECFGR1_ESRC_SHIFT) /* Source is SRCONF */
#define L2CC_ECFGR1_ESRC_EPFRCVD (15 << L2CC_ECFGR1_ESRC_SHIFT) /* Source is EPFRCVD */
/* Event Counter 0 Configuration Register */
#define L2CC_ECFGR0_EIGEN_SHIFT (0) /* Bits 0-1: Event Counter Interrupt Generation */
#define L2CC_ECFGR0_EIGEN_MASK (3 << L2CC_ECFGR0_EIGEN_SHIFT)
#define L2CC_ECFGR0_EIGEN_INTDIS (0 << L2CC_ECFGR0_EIGEN_SHIFT) /* Disables (default) */
#define L2CC_ECFGR0_EIGEN_INTENINCR (1 << L2CC_ECFGR0_EIGEN_SHIFT) /* Enables with Increment condition */
#define L2CC_ECFGR0_EIGEN_INTENOVER (2 << L2CC_ECFGR0_EIGEN_SHIFT) /* Enables with Overflow condition */
#define L2CC_ECFGR0_EIGEN_INTGENDIS (3 << L2CC_ECFGR0_EIGEN_SHIFT) /* Disables Interrupt generation */
#define L2CC_ECFGR0_ESRC_SHIFT (2) /* Bits 2-5: Event Counter Source */
#define L2CC_ECFGR0_ESRC_MASK (15 << L2CC_ECFGR0_ESRC_SHIFT)
#define L2CC_ECFGR0_ESRC_CNTDIS (0 << L2CC_ECFGR0_ESRC_SHIFT) /* Counter Disabled */
#define L2CC_ECFGR0_ESRC_CO (1 << L2CC_ECFGR0_ESRC_SHIFT) /* Source is CO */
#define L2CC_ECFGR0_ESRC_DRHIT (2 << L2CC_ECFGR0_ESRC_SHIFT) /* Source is DRHIT */
#define L2CC_ECFGR0_ESRC_DRREQ (3 << L2CC_ECFGR0_ESRC_SHIFT) /* Source is DRREQ */
#define L2CC_ECFGR0_ESRC_DWHIT (4 << L2CC_ECFGR0_ESRC_SHIFT) /* Source is DWHIT */
#define L2CC_ECFGR0_ESRC_DWREQ (5 << L2CC_ECFGR0_ESRC_SHIFT) /* Source is DWREQ */
#define L2CC_ECFGR0_ESRC_DWTREQ (6 << L2CC_ECFGR0_ESRC_SHIFT) /* Source is DWTREQ */
#define L2CC_ECFGR0_ESRC_IRHIT (7 << L2CC_ECFGR0_ESRC_SHIFT) /* Source is IRHIT */
#define L2CC_ECFGR0_ESRC_IRREQ (8 << L2CC_ECFGR0_ESRC_SHIFT) /* Source is IRREQ */
#define L2CC_ECFGR0_ESRC_WA (9 << L2CC_ECFGR0_ESRC_SHIFT) /* Source is WA */
#define L2CC_ECFGR0_ESRC_IPFALLOC (10 << L2CC_ECFGR0_ESRC_SHIFT) /* Source is IPFALLOC */
#define L2CC_ECFGR0_ESRC_EPFHIT (11 << L2CC_ECFGR0_ESRC_SHIFT) /* Source is EPFHIT */
#define L2CC_ECFGR0_ESRC_EPFALLOC (12 << L2CC_ECFGR0_ESRC_SHIFT) /* Source is EPFALLOC */
#define L2CC_ECFGR0_ESRC_SRRCVD (13 << L2CC_ECFGR0_ESRC_SHIFT) /* Source is SRRCVD */
#define L2CC_ECFGR0_ESRC_SRCONF (14 << L2CC_ECFGR0_ESRC_SHIFT) /* Source is SRCONF */
#define L2CC_ECFGR0_ESRC_EPFRCVD (15 << L2CC_ECFGR0_ESRC_SHIFT) /* Source is EPFRCVD */
/* Event Counter 1 Value Register (32-bit value) */
/* Event Counter 0 Value Register (32-bit value) */
/* Interrupt Mask Register, Masked Interrupt Status Register,
* Raw Interrupt Status Register, and Interrupt Clear Register.
*/
#define L2CC_INT_ECNTR (1 << 0) /* Bit 0: Event Counter 1/0 Overflow Increment */
#define L2CC_INT_PARRT (1 << 1) /* Bit 1: Parity Error on L2 Tag RAM, Read */
#define L2CC_INT_PARRD (1 << 2) /* Bit 2: Parity Error on L2 Data RAM, Read */
#define L2CC_INT_ERRWT (1 << 3) /* Bit 3: Error on L2 Tag RAM, Write */
#define L2CC_INT_ERRWD (1 << 4) /* Bit 4: Error on L2 Data RAM, Write */
#define L2CC_INT_ERRRT (1 << 5) /* Bit 5: Error on L2 Tag RAM, Read */
#define L2CC_INT_ERRRD (1 << 6) /* Bit 6: Error on L2 Data RAM, Read */
#define L2CC_INT_SLVERR (1 << 7) /* Bit 7: SLVERR from L3 Memory */
#define L2CC_INT_DECERR (1 << 8) /* Bit 8: DECERR from L3 Memory */
/* Cache Synchronization Register */
#define L2CC_CSR_C (1 << 0) /* Bit 0: Cache Synchronization Status */
/* Invalidate Physical Address Line Register */
#define L2CC_IPALR_C (1 << 0) /* Bit 0: Cache Synchronization Status */
#define L2CC_IPALR_IDX_SHIFT (5) /* Bits 5-13: Index Number */
#define L2CC_IPALR_IDX_MASK (0x1ff << L2CC_IPALR_IDX_SHIFT)
#define L2CC_IPALR_IDX(n) ((uint32_t)(n) << L2CC_IPALR_IDX_SHIFT)
#define L2CC_IPALR_TAG_SHIFT (14) /* Bits 14-31: Tag Number */
#define L2CC_IPALR_TAG_MASK (0x3ffff << L2CC_IPALR_TAG_SHIFT)
#define L2CC_IPALR_TAG(n) ((uint32_t)(n) << L2CC_IPALR_TAG_SHIFT)
/* Invalidate Way Register */
#define L2CC_IWR_WAY(n) (1 << (n)) /* Bist 0-7: Invalidate Way Number n, n=0..7 */
#define L2CC_IWR_WAY0 (1 << 0) /* Bit 0: Invalidate Way Number 0 */
#define L2CC_IWR_WAY1 (1 << 1) /* Bit 1: Invalidate Way Number 1 */
#define L2CC_IWR_WAY2 (1 << 2) /* Bit 2: Invalidate Way Number 2 */
#define L2CC_IWR_WAY3 (1 << 3) /* Bit 3: Invalidate Way Number 3 */
#define L2CC_IWR_WAY4 (1 << 4) /* Bit 4: Invalidate Way Number 4 */
#define L2CC_IWR_WAY5 (1 << 5) /* Bit 5: Invalidate Way Number 5 */
#define L2CC_IWR_WAY6 (1 << 6) /* Bit 6: Invalidate Way Number 6 */
#define L2CC_IWR_WAY7 (1 << 7) /* Bit 7: Invalidate Way Number 7 */
/* Clean Physical Address Line Register */
#define L2CC_CPALR_C (1 << 0) /* Bit 0: Cache Synchronization Status */
#define L2CC_CPALR_IDX_SHIFT (5) /* Bits 5-13: Index number */
#define L2CC_CPALR_IDX_MASK (0x1ff << L2CC_CPALR_IDX_SHIFT)
#define L2CC_CPALR_IDX(n) ((uint32_t)(n) << L2CC_CPALR_IDX_SHIFT)
#define L2CC_CPALR_TAG_SHIFT (14) /* Bits 14-31: Tag number */
#define L2CC_CPALR_TAG_MASK (0x3ffff << L2CC_CPALR_TAG_SHIFT)
#define L2CC_CPALR_TAG(n) ((uint32_t)(n) << L2CC_CPALR_TAG_SHIFT)
/* Clean Index Register */
#define L2CC_CIR_C (1 << 0) /* Bit 0: Cache Synchronization Status */
#define L2CC_CIR_IDX_SHIFT (5) /* Bits 5-13: Index number */
#define L2CC_CIR_IDX_MASK (0x1ff << L2CC_CIR_IDX_SHIFT)
#define L2CC_CIR_IDX(n) ((uint32_t)(n) << L2CC_CIR_IDX_SHIFT)
#define L2CC_CIR_WAY_SHIFT (28) /* Bits 28-30: Way number */
#define L2CC_CIR_WAY_MASK (7 << L2CC_CIR_WAY_SHIFT)
#define L2CC_CIR_WAY(n) ((uint32_t)(n) << L2CC_CIR_WAY_SHIFT)
/* Clean Way Register */
#define L2CC_CWR_WAY(n) (1 << (n)) /* Bits 0-7: Clean Way Number n, n=0..7 */
#define L2CC_CWR_WAY0 (1 << 0) /* Bit 0: Clean Way Number 0 */
#define L2CC_CWR_WAY1 (1 << 1) /* Bit 1: Clean Way Number 1 */
#define L2CC_CWR_WAY2 (1 << 2) /* Bit 2: Clean Way Number 2 */
#define L2CC_CWR_WAY3 (1 << 3) /* Bit 3: Clean Way Number 3 */
#define L2CC_CWR_WAY4 (1 << 4) /* Bit 4: Clean Way Number 4 */
#define L2CC_CWR_WAY5 (1 << 5) /* Bit 5: Clean Way Number 5 */
#define L2CC_CWR_WAY6 (1 << 6) /* Bit 6: Clean Way Number 6 */
#define L2CC_CWR_WAY7 (1 << 7) /* Bit 7: Clean Way Number 7 */
/* Clean Invalidate Physical Address Line Register */
#define L2CC_CIPALR_C (1 << 0) /* Bit 0: Cache Synchronization Status */
#define L2CC_CIPALR_IDX_SHIFT (5) /* Bits 5-13: Index Number */
#define L2CC_CIPALR_IDX_MASK (0x1ff << L2CC_CIPALR_IDX_SHIFT)
#define L2CC_CIPALR_IDX(n) ((uint32_t)(n) << L2CC_CIPALR_IDX_SHIFT)
#define L2CC_CIPALR_TAG_SHIFT (14) /* Bits 14-31: Tag Number */
#define L2CC_CIPALR_TAG_MASK (0x3ffff << L2CC_CIPALR_TAG_SHIFT)
#define L2CC_CIPALR_TAG(n) ((uint32_t)(n) << L2CC_CIPALR_TAG_SHIFT)
/* Clean Invalidate Index Register */
#define L2CC_CIIR_C (1 << 0) /* Bit 0: Cache Synchronization Status */
#define L2CC_CIIR_IDX_SHIFT (5) /* Bits 5-13: Index Number */
#define L2CC_CIIR_IDX_MASK (0x1ff << L2CC_CIIR_IDX_SHIFT)
#define L2CC_CIIR_IDX(n) ((uint32_t)(n) << L2CC_CIIR_IDX_SHIFT)
#define L2CC_CIIR_WAY_SHIFT (28) /* Bits 28-30: Way Number */
#define L2CC_CIIR_WAY_MASK (7 << L2CC_CIIR_WAY_SHIFT)
#define L2CC_CIIR_WAY(n) ((uint32_t)(n) << L2CC_CIIR_WAY_SHIFT)
/* Clean Invalidate Way Register */
#define L2CC_CIWR_WAY(n) (1 << (n)) /* Bits 0-7: Clean Invalidate Way Number n, n=1..7 */
#define L2CC_CIWR_WAY0 (1 << 0) /* Bit 0: Clean Invalidate Way Number 0 */
#define L2CC_CIWR_WAY1 (1 << 1) /* Bit 1: Clean Invalidate Way Number 1 */
#define L2CC_CIWR_WAY2 (1 << 2) /* Bit 2: Clean Invalidate Way Number 2 */
#define L2CC_CIWR_WAY3 (1 << 3) /* Bit 3: Clean Invalidate Way Number 3 */
#define L2CC_CIWR_WAY4 (1 << 4) /* Bit 4: Clean Invalidate Way Number 4 */
#define L2CC_CIWR_WAY5 (1 << 5) /* Bit 5: Clean Invalidate Way Number 5 */
#define L2CC_CIWR_WAY6 (1 << 6) /* Bit 6: Clean Invalidate Way Number 6 */
#define L2CC_CIWR_WAY7 (1 << 7) /* Bit 7: Clean Invalidate Way Number 7 */
/* Data Lockdown Register */
#define L2CC_DLKR_DLK(n) (1 << (n)) /* Bits 0-7: Data Lockdown in Way Number n, n=0..7 */
#define L2CC_DLKR_DLK0 (1 << 0) /* Bit 0: Data Lockdown in Way Number 0 */
#define L2CC_DLKR_DLK1 (1 << 1) /* Bit 1: Data Lockdown in Way Number 1 */
#define L2CC_DLKR_DLK2 (1 << 2) /* Bit 2: Data Lockdown in Way Number 2 */
#define L2CC_DLKR_DLK3 (1 << 3) /* Bit 3: Data Lockdown in Way Number 3 */
#define L2CC_DLKR_DLK4 (1 << 4) /* Bit 4: Data Lockdown in Way Number 4 */
#define L2CC_DLKR_DLK5 (1 << 5) /* Bit 5: Data Lockdown in Way Number 5 */
#define L2CC_DLKR_DLK6 (1 << 6) /* Bit 6: Data Lockdown in Way Number 6 */
#define L2CC_DLKR_DLK7 (1 << 7) /* Bit 7: Data Lockdown in Way Number 7 */
/* Instruction Lockdown Register */
#define L2CC_ILKR_ILK(n) (1 << (n)) /* Bits 0-7: Instruction Lockdown in Way Number n, n=0..7 */
#define L2CC_ILKR_ILK0 (1 << 0) /* Bit 0: Instruction Lockdown in Way Number 0 */
#define L2CC_ILKR_ILK1 (1 << 1) /* Bit 1: Instruction Lockdown in Way Number 1 */
#define L2CC_ILKR_ILK2 (1 << 2) /* Bit 2: Instruction Lockdown in Way Number 2 */
#define L2CC_ILKR_ILK3 (1 << 3) /* Bit 3: Instruction Lockdown in Way Number 3 */
#define L2CC_ILKR_ILK4 (1 << 4) /* Bit 4: Instruction Lockdown in Way Number 4 */
#define L2CC_ILKR_ILK5 (1 << 5) /* Bit 5: Instruction Lockdown in Way Number 5 */
#define L2CC_ILKR_ILK6 (1 << 6) /* Bit 6: Instruction Lockdown in Way Number 6 */
#define L2CC_ILKR_ILK7 (1 << 7) /* Bit 7: Instruction Lockdown in Way Number 7 */
/* Lock Line Enable Register */
#ifdef CONFIG_PL310_LOCKDOWN_BY_LINE
# define L2CC_LKLN_ENABLE (1 << 0) /* Bit 0: Lockdown by line enable */
#endif
/* Unlock Way Register */
#ifdef CONFIG_PL310_LOCKDOWN_BY_LINE
# define L2CC_UNLKW_WAY_SHIFT (0) /* Bits 0-15: Unlock line for corresponding way */
# define L2CC_UNLKW_WAY_MASK (0xffff << L2CC_UNLKW_WAY_SHIFT)
# define L2CC_UNLKW_WAY_SET(n) ((uint32_t)(n) << L2CC_UNLKW_WAY_SHIFT)
# define L2CC_UNLKW_WAY_BIT(n) ((1 << (n)) << L2CC_UNLKW_WAY_SHIFT)
#endif
/* Address filter start */
#ifdef PL310_ADDRESS_FILTERING
# define L2CC_FLSTRT_ENABLE (1 << 0) /* Bit 0: Address filter enable */
# define L2CC_FLSTRT_MASK (0xfff00000) /* Bits 20-31: Bits 20-31 of address mask */
#endif
/* Address filter end */
#ifdef PL310_ADDRESS_FILTERING
# define L2CC_FLEND_MASK (0xfff00000) /* Bits 20-31: Bits 20-31 of address mask */
#endif
/* Debug Control Register */
#define L2CC_DCR_DCL (1 << 0) /* Bit 0: Disable Cache Linefill */
#define L2CC_DCR_DWB (1 << 1) /* Bit 1: Disable Write-back, Force Write-through */
#define L2CC_DCR_SPNIDEN (1 << 2) /* Bit 2: SPNIDEN Value */
/* Prefetch Control Register */
#define L2CC_PCR_SHIFT (0) /* Bits 0-4: Prefetch Offset */
#define L2CC_PCR_MASK (31 << L2CC_PCR_SHIFT)
#define L2CC_PCR_PREFETCH(n) ((uint32_t)(n) << L2CC_PCR_SHIFT)
#define L2CC_PCR_NSIDEN (1 << 21) /* Bit 21: Not Same ID on Exclusive Sequence Enable */
#define L2CC_PCR_IDLEN (1 << 23) /* Bit 23: INCR Double Linefill Enable */
#define L2CC_PCR_PDEN (1 << 24) /* Bit 24: Prefetch Drop Enable */
#define L2CC_PCR_DLFWRDIS (1 << 27) /* Bit 27: Double Linefill on WRAP Read Disable */
#define L2CC_PCR_DATPEN (1 << 28) /* Bit 28: Data Prefetch Enable */
#define L2CC_PCR_INSPEN (1 << 29) /* Bit 29: Instruction Prefetch Enable */
#define L2CC_PCR_DLEN (1 << 30) /* Bit 30: Double Linefill Enable */
/* Power Control Register */
#define L2CC_POWCR_STBYEN (1 << 0) /* Bit 0: Standby Mode Enable */
#define L2CC_POWCR_DCKGATEN (1 << 1) /* Bit 1: Dynamic Clock Gating Enable */
// clang-format on
#endif /* __ARCH_ARM_SRC_ARMV7_A_L2CC_PL310_H */

View File

@ -0,0 +1,5 @@
SRC_DIR := L1
SRC_DIR += L2
SRC_FILES := cache_common_ope.c
include $(KERNEL_ROOT)/compiler.mk

View File

@ -0,0 +1,244 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file: cache_common_ope.c
* @brief: the general management of cache
* @version: 3.0
* @author: AIIT XUOS Lab
* @date: 2023/11/06
*
*/
/*************************************************
File name: cache_common_ope.c
Description: the general management of cache
Others:
History:
1. Date: 2023-11-06
Author: AIIT XUOS Lab
Modification:
1implement xiuos cache operations
*************************************************/
#include "cache_common_ope.h"
#include "l1_cache.h"
#include "l2_cache.h"
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: invalidate_dcache
*
* Description:
* Invalidate the data cache within the specified region; we will be
* performing a DMA operation in this region and we want to purge old data
* in the cache.
*
****************************************************************************/
static inline void invalidate_dcache(uintptr_t start, uintptr_t end)
{
InvalidateL1Dcache(start, end);
// InvalidateL2Cache(start, end);
}
/****************************************************************************
* Name: invalidate_dcache_all
*
* Description:
* Invalidate the entire contents of D cache.
*
* NOTE: This function forces L1 and L2 cache operations to be atomic
* by disabling interrupts.
*
****************************************************************************/
static inline void invalidate_dcache_all(void)
{
InvalidateL1DcacheAll();
// InvalidateL2CacheAll();
}
/****************************************************************************
* Name: invalidate_icache
*
* Description:
* Invalidate the instruction cache within the specified region.
*
****************************************************************************/
static inline void invalidate_icache(uintptr_t start, uintptr_t end)
{
InvalidateL1Icache(start, end);
}
/****************************************************************************
* Name: invalidate_icache_all
*
* Description:
* Invalidate all instruction caches to PoU, also flushes branch target
* cache
*
****************************************************************************/
static inline void invalidate_icache_all(void)
{
InvalidateL1IcacheAll();
}
/****************************************************************************
* Name: clean_dcache
*
* Description:
* Clean the data cache within the specified region by flushing the
* contents of the data cache to memory.
*
****************************************************************************/
static inline void clean_dcache(uintptr_t start, uintptr_t end)
{
CleanL1Dcache(start, end);
// CleanL2Cache(start, end);
}
/****************************************************************************
* Name: clean_dcache_all
*
* Description:
* Clean the entire data cache within the specified region by flushing the
* contents of the data cache to memory.
*
****************************************************************************/
static inline void clean_dcache_all(void)
{
CleanL1DcacheAll();
// CleanL2CacheAll();
}
/****************************************************************************
* Name: flush_dcache
*
* Description:
* Flush the data cache within the specified region by cleaning and
* invalidating the D cache.
*
****************************************************************************/
static inline void flush_dcache(uintptr_t start, uintptr_t end)
{
FlushL1Dcache(start, end);
// FlushL2Cache(start, end);
}
/****************************************************************************
* Name: flush_dcache_all
*
* Description:
* Flush the entire data cache by cleaning and invalidating the D cache.
*
****************************************************************************/
static inline void flush_dcache_all(void)
{
FlushL1DcacheAll();
// FlushL2CacheAll();
}
/****************************************************************************
* Name: enable_icache
*
* Description:
* Enable the I-Cache
*
****************************************************************************/
static inline void enable_icache(void)
{
EnableL1Icache();
}
/****************************************************************************
* Name: disable_icache
*
* Description:
* Disable the I-Cache
*
****************************************************************************/
static inline void disable_icache(void)
{
DisableL1Icache();
}
/****************************************************************************
* Name: enable_dcache
*
* Description:
* Enable the D-Cache
*
****************************************************************************/
static inline void enable_dcache(void)
{
EnableL1Dcache();
// EnableL2Cache();
}
/****************************************************************************
* Name: disable_dcache
*
* Description:
* Disable the D-Cache
*
****************************************************************************/
static inline void disable_dcache(void)
{
FlushL1DcacheAll();
// pl310_flush_all();
DisableL1Dcache();
// DisableL2Cache();
}
static struct ICacheDone icache_done = {
.enable = enable_icache,
.disable = disable_icache,
.invalidate = invalidate_icache,
.invalidateall = invalidate_icache_all,
};
static struct DCacheDone dcache_done = {
.enable = enable_dcache,
.disable = disable_dcache,
.clean = clean_dcache,
.flush = flush_dcache,
.invalidate = invalidate_dcache,
.cleanall = clean_dcache_all,
.flushall = flush_dcache_all,
.invalidateall = invalidate_dcache_all,
};
struct ICacheDone* hardkernel_icache_init(struct TraceTag* hardkernel_tag)
{
/* init icache */
icache_done.enable();
return &icache_done;
}
struct DCacheDone* hardkernel_dcache_init(struct TraceTag* hardkernel_tag)
{
/* init dcache */
dcache_done.enable();
return &dcache_done;
}

View File

@ -0,0 +1,87 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file: cache_common_ope.h
* @brief: the general management of cache
* @version: 3.0
* @author: AIIT XUOS Lab
* @date: 2023/11/06
*
*/
/*************************************************
File name: cache_common_ope.h
Description: the general management of cache
Others:
History:
1. Date: 2023-11-06
Author: AIIT XUOS Lab
Modification:
1define xiuos cache interfaces
*************************************************/
#ifndef __ASSEMBLY__
/****************************************************************************
* Included Files
****************************************************************************/
#include <stdint.h>
#include "actracer.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#ifdef __cplusplus
#define EXTERN extern "C"
extern "C" {
#else
#define EXTERN extern
#endif
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
struct ICacheDone {
void (*enable)(void);
void (*disable)(void);
void (*invalidate)(uintptr_t start, uintptr_t end);
void (*invalidateall)(void);
};
struct DCacheDone {
void (*enable)(void);
void (*disable)(void);
void (*clean)(uintptr_t start, uintptr_t end);
void (*flush)(uintptr_t start, uintptr_t end);
void (*invalidate)(uintptr_t start, uintptr_t end);
void (*cleanall)(void);
void (*flushall)(void);
void (*invalidateall)(void);
};
struct ICacheDone* hardkernel_icache_init(struct TraceTag* hardkernel_tag);
struct DCacheDone* hardkernel_dcache_init(struct TraceTag* hardkernel_tag);
void test_cache(void);
#undef EXTERN
#ifdef __cplusplus
}
#endif
#endif /* __ASSEMBLY__ */

View File

@ -0,0 +1,3 @@
SRC_DIR:= arm/armv7-a/cortex-a9/imx6q-sabrelite
include $(KERNEL_ROOT)/compiler.mk

View File

@ -0,0 +1,3 @@
SRC_FILES := ccm_pll.c clock.c gpt.c
include $(KERNEL_ROOT)/compiler.mk

View File

@ -0,0 +1,331 @@
/*
* 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 "soc_memory_map.h"
#include <stdbool.h>
#include <stdint.h>
#include "regsccm.h"
#include "regsccmanalog.h"
#include "regsgpc.h"
#include "regsgpt.h"
#include "regsuart.h"
#include "ccm_pll.h"
////////////////////////////////////////////////////////////////////////////////
// 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;
/// @todo: Add necessary gating only when you need
/// Should refer to original SDK
case GPT_BASE_ADDR:
ccm_ccgrx = HW_CCM_CCGR1_ADDR;
cgx_offset = CG(10);
break;
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 = *((volatile uint32_t*)(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
*((volatile uint32_t*)(HW_GPC_IMR1_ADDR + (reg_offset - 1) * 4)) = (gpc_imr);
} else {
// set the corresponding bit to mask the interrupt source
gpc_imr |= (1 << bit_offset);
// write the new mask
*((volatile uint32_t*)(HW_GPC_IMR1_ADDR + (reg_offset - 1) * 4)) = (gpc_imr);
}
}
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
////////////////////////////////////////////////////////////////////////////////

View File

@ -0,0 +1,78 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file clock.c
* @brief clock interfaces of hardkernel
* @version 3.0
* @author AIIT XUOS Lab
* @date 2023.08.25
*/
/*************************************************
File name: clock.c
Description: clock interfaces of hardkernel
Others:
History:
1. Date: 2023-08-28
Author: AIIT XUOS Lab
Modification:
1. first version
*************************************************/
#include <stdint.h>
#include "ccm_pll.h"
#include "gpt.h"
#include "timer.h"
#include "clock_common_op.h"
#include "irq_numbers.h"
static void _sys_clock_init()
{
uint32_t freq = get_main_clock(IPG_CLK);
gpt_init(CLKSRC_IPG_CLK, freq / 1000000, RESTART_MODE, WAIT_MODE_EN | STOP_MODE_EN);
gpt_set_compare_event(kGPTOutputCompare1, OUTPUT_CMP_DISABLE, 1000);
gpt_counter_enable(kGPTOutputCompare1);
}
static uint32_t _get_clock_int()
{
return IMX_INT_GPT;
}
static uint64_t _get_tick()
{
return 0;
}
static uint64_t _get_second()
{
return 0;
}
static void _clear_clock_intr()
{
gpt_get_compare_event(kGPTOutputCompare1);
}
static struct XiziClockDriver hardkernel_clock_driver = (struct XiziClockDriver) {
.sys_clock_init = _sys_clock_init,
.get_clock_int = _get_clock_int,
.get_tick = _get_tick,
.get_second = _get_second,
.clear_clock_intr = _clear_clock_intr,
};
struct XiziClockDriver* hardkernel_clock_init(struct TraceTag* hardkernel_tag)
{
hardkernel_clock_driver.sys_clock_init();
return &hardkernel_clock_driver;
}

View File

@ -34,16 +34,16 @@
*
* @ingroup diag_timer
*/
#include <stdint.h>
#include "sdk.h"
#include "gpt.h"
#include "soc_memory_map.h"
#include "ccm_pll.h"
#include "regsgpt.h"
#include "timer.h"
#include "registers/regsgpt.h"
#include <arch_interrupt.h>
#include <ccm_pll.h>
#include <irq_numbers.h>
#include <isr.h>
#include "gpt.h"
#include "trap_common.h"
////////////////////////////////////////////////////////////////////////////////
// Code
@ -56,67 +56,60 @@ static inline void gpt_clear_all_events(void)
uint32_t gpt_get_rollover_event(void)
{
// clear it if found set
if (HW_GPT_SR.B.ROV)
{
// clear it if found set
if (HW_GPT_SR.B.ROV) {
HW_GPT_SR_WR(BM_GPT_SR_ROV);
return kGPTRollover;
}
// return the read value before the bit was cleared
// return the read value before the bit was cleared
return 0;
}
uint32_t gpt_get_capture_event(uint8_t flag, uint32_t * capture_val)
uint32_t gpt_get_capture_event(uint8_t flag, uint32_t* capture_val)
{
// get the capture status bit
// get the capture status bit
flag &= kGPTInputCapture1 | kGPTInputCapture2;
uint32_t status_register = HW_GPT_SR_RD() & flag;
// Read the captured timer value.
if (capture_val)
{
if (status_register == kGPTInputCapture1)
{
*(uint32_t *) capture_val = HW_GPT_ICR1.B.CAPT;
}
else if (status_register == kGPTInputCapture2)
{
*(uint32_t *) capture_val = HW_GPT_ICR2.B.CAPT;
if (capture_val) {
if (status_register == kGPTInputCapture1) {
*(uint32_t*)capture_val = HW_GPT_ICR1.B.CAPT;
} else if (status_register == kGPTInputCapture2) {
*(uint32_t*)capture_val = HW_GPT_ICR2.B.CAPT;
}
}
// Clear the flag.
HW_GPT_SR_WR(status_register);
// return the read value before the bit was cleared
// return the read value before the bit was cleared
return status_register;
}
void gpt_set_capture_event(uint8_t cap_input, uint8_t cap_input_mode)
{
// set the new input mode
switch (cap_input)
{
case kGPTInputCapture1:
HW_GPT_CR.B.IM1 = cap_input_mode;
break;
case kGPTInputCapture2:
HW_GPT_CR.B.IM2 = cap_input_mode;
break;
// set the new input mode
switch (cap_input) {
case kGPTInputCapture1:
HW_GPT_CR.B.IM1 = cap_input_mode;
break;
case kGPTInputCapture2:
HW_GPT_CR.B.IM2 = cap_input_mode;
break;
}
}
uint32_t gpt_get_compare_event(uint8_t flag)
{
// get the active compare flags
// get the active compare flags
flag &= kGPTOutputCompare1 | kGPTOutputCompare2 | kGPTOutputCompare3;
uint32_t status_register = HW_GPT_SR_RD() & flag;
// clear flags which are active
if (status_register)
{
// clear flags which are active
if (status_register) {
HW_GPT_SR_WR(status_register);
}
@ -126,35 +119,34 @@ uint32_t gpt_get_compare_event(uint8_t flag)
void gpt_set_compare_event(uint8_t cmp_output, uint8_t cmp_output_mode, uint32_t cmp_value)
{
// set the value to compare with
switch (cmp_output)
{
case kGPTOutputCompare1:
BW_GPT_CR_OM1(cmp_output_mode);
HW_GPT_OCR1_WR(cmp_value);
break;
// set the value to compare with
switch (cmp_output) {
case kGPTOutputCompare1:
BW_GPT_CR_OM1(cmp_output_mode);
HW_GPT_OCR1_WR(cmp_value);
break;
case kGPTOutputCompare2:
BW_GPT_CR_OM2(cmp_output_mode);
HW_GPT_OCR2_WR(cmp_value);
break;
case kGPTOutputCompare2:
BW_GPT_CR_OM2(cmp_output_mode);
HW_GPT_OCR2_WR(cmp_value);
break;
case kGPTOutputCompare3:
BW_GPT_CR_OM3(cmp_output_mode);
HW_GPT_OCR3_WR(cmp_value);
break;
case kGPTOutputCompare3:
BW_GPT_CR_OM3(cmp_output_mode);
HW_GPT_OCR3_WR(cmp_value);
break;
}
}
void gpt_counter_disable(void)
{
// disable the counter
// disable the counter
HW_GPT_CR.B.EN = 0;
// ensure to leave the counter in a proper state by disabling the interrupt sources
HW_GPT_IR_WR(0);
// and by clearing possible remaining events
// and by clearing possible remaining events
gpt_clear_all_events();
}
@ -163,81 +155,54 @@ void gpt_counter_enable(uint32_t irq_mode)
// ensure to start the counter in a proper state by clearing possible remaining events
gpt_clear_all_events();
// enable the interrupts or clear the register for polling
// enable the interrupts or clear the register for polling
HW_GPT_IR_WR(irq_mode & kGPTAllEvents);
// finally, enable the counter
// finally, enable the counter
HW_GPT_CR.B.EN = 1;
}
void gpt_setup_interrupt(void (*irq_subroutine)(int vector, void *param), bool enableIt)
{
uint32_t irq_id = IMX_INT_GPT;
if (enableIt)
{
// register the IRQ sub-routine
// register_interrupt_routine(irq_id, irq_subroutine);
isrManager.done->registerIrq(irq_id, irq_subroutine,NULL);
// enable the IRQ
// enable_interrupt(irq_id, CPU_0, 0);
isrManager.done->enableIrq(irq_id,CPU_0);
}
else
{
// disable the IRQ
// disable_interrupt(irq_id, CPU_0);
isrManager.done->disableIrq(irq_id,CPU_0);
}
}
void gpt_init(uint32_t clock_src, uint32_t prescaler, uint32_t counter_mode, uint32_t low_power_mode)
{
uint32_t control_reg_tmp = 0;
uint32_t base = GPT_BASE_ADDR;
// enable the source clocks to the GPT port
clock_gating_config(base, CLOCK_ON);
// enable the source clocks to the GPT port
clock_gating_config(GPT_BASE_ADDR, CLOCK_ON);
// start with a known state by disabling and reseting the module
// start with a known state by disabling and reseting the module
HW_GPT_CR_WR(BM_GPT_CR_SWR);
// wait for the reset to complete
while (HW_GPT_CR.B.SWR != 0) ;
// set the reference source clock for the counter
if (clock_src == CLKSRC_CKIL)
{
// wait for the reset to complete
while (HW_GPT_CR.B.SWR != 0)
;
// set the reference source clock for the counter
if (clock_src == CLKSRC_CKIL) {
// CKIL source is 0x4 for GPT but 0x3 for EPIT
clock_src++;
}
control_reg_tmp |= BF_GPT_CR_CLKSRC(clock_src);
// the prescaler can be changed at any time, and
// the prescaler can be changed at any time, and
// this affects the output clock immediately
HW_GPT_PR_WR(BF_GPT_PR_PRESCALER(prescaler - 1));
// set the counter mode
// set the counter mode
control_reg_tmp |= BF_GPT_CR_FRR(counter_mode);
// set behavior for low power mode
if (low_power_mode & WAIT_MODE_EN)
{
// set behavior for low power mode
if (low_power_mode & WAIT_MODE_EN) {
control_reg_tmp |= BM_GPT_CR_WAITEN;
}
if (low_power_mode & STOP_MODE_EN)
{
if (low_power_mode & STOP_MODE_EN) {
control_reg_tmp |= BM_GPT_CR_STOPEN;
}
// specify from where the counter starts to count when enabled
// this code makes it start from 0
// specify from where the counter starts to count when enabled
// this code makes it start from 0
control_reg_tmp |= BM_GPT_CR_ENMOD;
// finally write the control register
// finally write the control register
HW_GPT_CR_WR(control_reg_tmp);
}

View File

@ -31,7 +31,8 @@
#ifndef _CCM_PLL_H_
#define _CCM_PLL_H_
#include "sdk_types.h"
#include <stdbool.h>
#include <stdint.h>
//! @addtogroup diag_clocks
//! @{
@ -40,15 +41,14 @@
// Definitions
////////////////////////////////////////////////////////////////////////////////
#define CLK_SRC_32K 32768
#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))
#define CG(x) (3 << (x * 2))
//! @brief Constants for CCM CCGR register fields.
enum _clock_gate_constants
{
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.

View File

@ -39,8 +39,7 @@
#ifndef __GPT_H__
#define __GPT_H__
#include "sdk.h"
#include "timer.h"
#include <stdbool.h>
////////////////////////////////////////////////////////////////////////////////
// Definitions
@ -55,45 +54,41 @@
//! Note that the values of these enums happen to be the bitmasks for the respective
//! fields in the HW_GPT_SR and HW_GPT_IR registers, so a mask constructed from them
//! can be used directly with register values.
enum _gpt_events
{
kGPTNoEvent = 0, //!< No events enabled.
kGPTRollover = 1 << 5, //!< Rollover event.
kGPTInputCapture1 = 1 << 3, //!< Input capture 1 event.
kGPTInputCapture2 = 1 << 4, //!< Input capture 2 event.
kGPTOutputCompare1 = 1 << 0, //!< Output compare 1 event.
kGPTOutputCompare2 = 1 << 1, //!< Output compare 2 event.
kGPTOutputCompare3 = 1 << 2, //!< Output compare 3 event.
enum _gpt_events {
kGPTNoEvent = 0, //!< No events enabled.
kGPTRollover = 1 << 5, //!< Rollover event.
kGPTInputCapture1 = 1 << 3, //!< Input capture 1 event.
kGPTInputCapture2 = 1 << 4, //!< Input capture 2 event.
kGPTOutputCompare1 = 1 << 0, //!< Output compare 1 event.
kGPTOutputCompare2 = 1 << 1, //!< Output compare 2 event.
kGPTOutputCompare3 = 1 << 2, //!< Output compare 3 event.
//! Combined mask of all GPT events.
kGPTAllEvents = kGPTRollover | kGPTInputCapture1 | kGPTInputCapture2
| kGPTOutputCompare1 | kGPTOutputCompare2 | kGPTOutputCompare3
| kGPTOutputCompare1 | kGPTOutputCompare2 | kGPTOutputCompare3
};
//! @brief GPT counter modes.
enum _gpt_counter_mode
{
enum _gpt_counter_mode {
RESTART_MODE = 0,
FREE_RUN_MODE = 1
};
//! @brief Supported input capture modes.
enum _gpt_capture_modes
{
INPUT_CAP_DISABLE = 0, //!< input capture event disabled
INPUT_CAP_RISING_EDGE = 1, //!< input capture event on a rising edge
enum _gpt_capture_modes {
INPUT_CAP_DISABLE = 0, //!< input capture event disabled
INPUT_CAP_RISING_EDGE = 1, //!< input capture event on a rising edge
INPUT_CAP_FALLING_EDGE = 2, //!< input capture event on a falling edge
INPUT_CAP_BOTH_EDGE = 3 //!< input capture event on a both edge
INPUT_CAP_BOTH_EDGE = 3 //!< input capture event on a both edge
};
//! @brief Supported output modes.
enum _gpt_compare_modes
{
OUTPUT_CMP_DISABLE = 0, //!< output disconnected from pad
OUTPUT_CMP_TOGGLE = 1, //!< output toggle mode
OUTPUT_CMP_CLEAR = 2, //!< output set low mode
OUTPUT_CMP_SET = 3, //!< output set high mode
OUTPUT_CMP_LOWPULSE = 4 //!< output set high mode
enum _gpt_compare_modes {
OUTPUT_CMP_DISABLE = 0, //!< output disconnected from pad
OUTPUT_CMP_TOGGLE = 1, //!< output toggle mode
OUTPUT_CMP_CLEAR = 2, //!< output set low mode
OUTPUT_CMP_SET = 3, //!< output set high mode
OUTPUT_CMP_LOWPULSE = 4 //!< output set high mode
};
////////////////////////////////////////////////////////////////////////////////
@ -125,7 +120,7 @@ void gpt_init(uint32_t clock_src, uint32_t prescaler, uint32_t counter_mode, uin
* @param irq_subroutine the GPT interrupt interrupt routine.
* @param enableIt Pass true to enable the interrupt.
*/
void gpt_setup_interrupt(void (*irq_subroutine)(int vector, void *param), bool enableIt);
void gpt_setup_interrupt(void (*irq_subroutine)(void), bool enableIt);
/*!
* @brief Enable the GPT module.
@ -177,7 +172,7 @@ uint32_t gpt_get_rollover_event(void);
* the specified event occurred. May be NULL if not required.
* @return Mask of input specified capture event that occurred, or 0 if no event occurred.
*/
uint32_t gpt_get_capture_event(uint8_t flag, uint32_t * capture_val);
uint32_t gpt_get_capture_event(uint8_t flag, uint32_t* capture_val);
/*!
* @brief Set the input capture mode.
@ -201,7 +196,7 @@ void gpt_set_capture_event(uint8_t cap_input, uint8_t cap_input_mode);
uint32_t gpt_get_compare_event(uint8_t flag);
/*!
* @brief Set a compare event by programming the compare register and
* @brief Set a compare event by programming the compare register and
* compare output mode.
*
* @param cmp_output The channel to configure. Must be one of #kGPTOutputCompare1,

View File

@ -0,0 +1,737 @@
/*
* Copyright (c) 2012, Freescale Semiconductor, Inc.
* All rights reserved.
*
* THIS SOFTWARE IS PROVIDED BY FREESCALE "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 FREESCALE 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.
*/
/*
* WARNING! DO NOT EDIT THIS FILE DIRECTLY!
*
* This file was generated automatically and any changes may be lost.
*/
#ifndef __HW_GPC_REGISTERS_H__
#define __HW_GPC_REGISTERS_H__
#include "regs.h"
/*
* i.MX6DQ GPC
*
* GPC
*
* Registers defined in this header file:
* - HW_GPC_CNTR - GPC Interface control register
* - HW_GPC_PGR - GPC Power Gating Register
* - HW_GPC_IMR1 - IRQ masking register 1
* - HW_GPC_IMR2 - IRQ masking register 2
* - HW_GPC_IMR3 - IRQ masking register 3
* - HW_GPC_IMR4 - IRQ masking register 4
* - HW_GPC_ISR1 - IRQ status resister 1
* - HW_GPC_ISR2 - IRQ status resister 2
* - HW_GPC_ISR3 - IRQ status resister 3
* - HW_GPC_ISR4 - IRQ status resister 4
*
* - hw_gpc_t - Struct containing all module registers.
*/
//! @name Module base addresses
//@{
#ifndef REGS_GPC_BASE
#define HW_GPC_INSTANCE_COUNT (1) //!< Number of instances of the GPC module.
#define REGS_GPC_BASE (0x020dc000) //!< Base address for GPC.
#endif
//@}
//-------------------------------------------------------------------------------------------
// HW_GPC_CNTR - GPC Interface control register
//-------------------------------------------------------------------------------------------
// #ifndef __LANGUAGE_ASM__
// /*!
// * @brief HW_GPC_CNTR - GPC Interface control register (RW)
// *
// * Reset value: 0x00100000
// */
// typedef union _hw_gpc_cntr
// {
// reg32_t U;
// struct _hw_gpc_cntr_bitfields
// {
// unsigned GPU_VPU_PDN_REQ : 1; //!< [0] GPU /VPU Power Down request.
// unsigned GPU_VPU_PUP_REQ : 1; //!< [1] GPU /VPU Power Up request.
// unsigned RESERVED2 : 14; //!< [15:2] Reserved.
// unsigned DVFS0CR : 1; //!< [16] DVFS0 (ARM) Change request (bit is read-only)
// unsigned RESERVED3 : 4; //!< [20:17] Reserved.
// unsigned GPCIRQM : 1; //!< [21] GPC interrupt/event masking
// unsigned RESERVED4 : 10; //!< [31:22] Reserved.
// } B;
// } hw_gpc_cntr_t;
// #endif
// /*!
// * @name Constants and macros for entire GPC_CNTR register
// */
// //@{
// #define HW_GPC_CNTR_ADDR (REGS_GPC_BASE + 0x0)
// #ifndef __LANGUAGE_ASM__
// #define HW_GPC_CNTR (*(volatile hw_gpc_cntr_t *) HW_GPC_CNTR_ADDR)
// #define HW_GPC_CNTR_RD() (HW_GPC_CNTR.U)
// #define HW_GPC_CNTR_WR(v) (HW_GPC_CNTR.U = (v))
// #define HW_GPC_CNTR_SET(v) (HW_GPC_CNTR_WR(HW_GPC_CNTR_RD() | (v)))
// #define HW_GPC_CNTR_CLR(v) (HW_GPC_CNTR_WR(HW_GPC_CNTR_RD() & ~(v)))
// #define HW_GPC_CNTR_TOG(v) (HW_GPC_CNTR_WR(HW_GPC_CNTR_RD() ^ (v)))
// #endif
// //@}
// /*
// * constants & macros for individual GPC_CNTR bitfields
// */
// /*! @name Register GPC_CNTR, field GPU_VPU_PDN_REQ[0] (RW)
// *
// * GPU /VPU Power Down request. Self-cleared bit. * Note: Power switch for GPU /VPU power domain is
// * controlled by ANALOG configuration, not GPU /VPU PGC signals
// *
// * Values:
// * - 0 - no request
// * - 1 - Request Power Down sequence to start for GPU /VPU
// */
// //@{
// #define BP_GPC_CNTR_GPU_VPU_PDN_REQ (0) //!< Bit position for GPC_CNTR_GPU_VPU_PDN_REQ.
// #define BM_GPC_CNTR_GPU_VPU_PDN_REQ (0x00000001) //!< Bit mask for GPC_CNTR_GPU_VPU_PDN_REQ.
// //! @brief Get value of GPC_CNTR_GPU_VPU_PDN_REQ from a register value.
// #define BG_GPC_CNTR_GPU_VPU_PDN_REQ(r) ((__REG_VALUE_TYPE((r), reg32_t) & BM_GPC_CNTR_GPU_VPU_PDN_REQ) >> BP_GPC_CNTR_GPU_VPU_PDN_REQ)
// //! @brief Format value for bitfield GPC_CNTR_GPU_VPU_PDN_REQ.
// #define BF_GPC_CNTR_GPU_VPU_PDN_REQ(v) ((__REG_VALUE_TYPE((v), reg32_t) << BP_GPC_CNTR_GPU_VPU_PDN_REQ) & BM_GPC_CNTR_GPU_VPU_PDN_REQ)
// #ifndef __LANGUAGE_ASM__
// //! @brief Set the GPU_VPU_PDN_REQ field to a new value.
// #define BW_GPC_CNTR_GPU_VPU_PDN_REQ(v) (HW_GPC_CNTR_WR((HW_GPC_CNTR_RD() & ~BM_GPC_CNTR_GPU_VPU_PDN_REQ) | BF_GPC_CNTR_GPU_VPU_PDN_REQ(v)))
// #endif
// //@}
// /*! @name Register GPC_CNTR, field GPU_VPU_PUP_REQ[1] (RW)
// *
// * GPU /VPU Power Up request. Self-cleared bit. * Note: Power switch for GPU /VPU power domain is
// * controlled by ANALOG configuration, not GPU /VPU PGC signals
// *
// * Values:
// * - 0 - no request
// * - 1 - Request Power Up sequence to start for GPU /VPU
// */
// //@{
// #define BP_GPC_CNTR_GPU_VPU_PUP_REQ (1) //!< Bit position for GPC_CNTR_GPU_VPU_PUP_REQ.
// #define BM_GPC_CNTR_GPU_VPU_PUP_REQ (0x00000002) //!< Bit mask for GPC_CNTR_GPU_VPU_PUP_REQ.
// //! @brief Get value of GPC_CNTR_GPU_VPU_PUP_REQ from a register value.
// #define BG_GPC_CNTR_GPU_VPU_PUP_REQ(r) ((__REG_VALUE_TYPE((r), reg32_t) & BM_GPC_CNTR_GPU_VPU_PUP_REQ) >> BP_GPC_CNTR_GPU_VPU_PUP_REQ)
// //! @brief Format value for bitfield GPC_CNTR_GPU_VPU_PUP_REQ.
// #define BF_GPC_CNTR_GPU_VPU_PUP_REQ(v) ((__REG_VALUE_TYPE((v), reg32_t) << BP_GPC_CNTR_GPU_VPU_PUP_REQ) & BM_GPC_CNTR_GPU_VPU_PUP_REQ)
// #ifndef __LANGUAGE_ASM__
// //! @brief Set the GPU_VPU_PUP_REQ field to a new value.
// #define BW_GPC_CNTR_GPU_VPU_PUP_REQ(v) (HW_GPC_CNTR_WR((HW_GPC_CNTR_RD() & ~BM_GPC_CNTR_GPU_VPU_PUP_REQ) | BF_GPC_CNTR_GPU_VPU_PUP_REQ(v)))
// #endif
// //@}
// /*! @name Register GPC_CNTR, field DVFS0CR[16] (RO)
// *
// * DVFS0 (ARM) Change request (bit is read-only)
// *
// * Values:
// * - 0 - DVFS0 has no request
// * - 1 - DVFS0 is requesting for frequency/voltage update
// */
// //@{
// #define BP_GPC_CNTR_DVFS0CR (16) //!< Bit position for GPC_CNTR_DVFS0CR.
// #define BM_GPC_CNTR_DVFS0CR (0x00010000) //!< Bit mask for GPC_CNTR_DVFS0CR.
// //! @brief Get value of GPC_CNTR_DVFS0CR from a register value.
// #define BG_GPC_CNTR_DVFS0CR(r) ((__REG_VALUE_TYPE((r), reg32_t) & BM_GPC_CNTR_DVFS0CR) >> BP_GPC_CNTR_DVFS0CR)
// //@}
// /*! @name Register GPC_CNTR, field GPCIRQM[21] (RW)
// *
// * GPC interrupt/event masking
// *
// * Values:
// * - 0 - not masked
// * - 1 - interrupt/event is masked
// */
// //@{
// #define BP_GPC_CNTR_GPCIRQM (21) //!< Bit position for GPC_CNTR_GPCIRQM.
// #define BM_GPC_CNTR_GPCIRQM (0x00200000) //!< Bit mask for GPC_CNTR_GPCIRQM.
// //! @brief Get value of GPC_CNTR_GPCIRQM from a register value.
// #define BG_GPC_CNTR_GPCIRQM(r) ((__REG_VALUE_TYPE((r), reg32_t) & BM_GPC_CNTR_GPCIRQM) >> BP_GPC_CNTR_GPCIRQM)
// //! @brief Format value for bitfield GPC_CNTR_GPCIRQM.
// #define BF_GPC_CNTR_GPCIRQM(v) ((__REG_VALUE_TYPE((v), reg32_t) << BP_GPC_CNTR_GPCIRQM) & BM_GPC_CNTR_GPCIRQM)
// #ifndef __LANGUAGE_ASM__
// //! @brief Set the GPCIRQM field to a new value.
// #define BW_GPC_CNTR_GPCIRQM(v) (HW_GPC_CNTR_WR((HW_GPC_CNTR_RD() & ~BM_GPC_CNTR_GPCIRQM) | BF_GPC_CNTR_GPCIRQM(v)))
// #endif
// //@}
// //-------------------------------------------------------------------------------------------
// // HW_GPC_PGR - GPC Power Gating Register
// //-------------------------------------------------------------------------------------------
// #ifndef __LANGUAGE_ASM__
// /*!
// * @brief HW_GPC_PGR - GPC Power Gating Register (RW)
// *
// * Reset value: 0x00000000
// */
// typedef union _hw_gpc_pgr
// {
// reg32_t U;
// struct _hw_gpc_pgr_bitfields
// {
// unsigned RESERVED0 : 29; //!< [28:0] Reserved
// unsigned DRCIC : 2; //!< [30:29] Debug ref cir in mux control
// unsigned RESERVED1 : 1; //!< [31] Reserved
// } B;
// } hw_gpc_pgr_t;
// #endif
// /*!
// * @name Constants and macros for entire GPC_PGR register
// */
// //@{
// #define HW_GPC_PGR_ADDR (REGS_GPC_BASE + 0x4)
// #ifndef __LANGUAGE_ASM__
// #define HW_GPC_PGR (*(volatile hw_gpc_pgr_t *) HW_GPC_PGR_ADDR)
// #define HW_GPC_PGR_RD() (HW_GPC_PGR.U)
// #define HW_GPC_PGR_WR(v) (HW_GPC_PGR.U = (v))
// #define HW_GPC_PGR_SET(v) (HW_GPC_PGR_WR(HW_GPC_PGR_RD() | (v)))
// #define HW_GPC_PGR_CLR(v) (HW_GPC_PGR_WR(HW_GPC_PGR_RD() & ~(v)))
// #define HW_GPC_PGR_TOG(v) (HW_GPC_PGR_WR(HW_GPC_PGR_RD() ^ (v)))
// #endif
// //@}
// /*
// * constants & macros for individual GPC_PGR bitfields
// */
// /*! @name Register GPC_PGR, field DRCIC[30:29] (RW)
// *
// * Debug ref cir in mux control
// *
// * Values:
// * - 00 - ccm_cosr_1_clk_in
// * - 01 - ccm_cosr_2_clk_in
// * - 10 - restricted
// * - 11 - restricted
// */
// //@{
// #define BP_GPC_PGR_DRCIC (29) //!< Bit position for GPC_PGR_DRCIC.
// #define BM_GPC_PGR_DRCIC (0x60000000) //!< Bit mask for GPC_PGR_DRCIC.
// //! @brief Get value of GPC_PGR_DRCIC from a register value.
// #define BG_GPC_PGR_DRCIC(r) ((__REG_VALUE_TYPE((r), reg32_t) & BM_GPC_PGR_DRCIC) >> BP_GPC_PGR_DRCIC)
// //! @brief Format value for bitfield GPC_PGR_DRCIC.
// #define BF_GPC_PGR_DRCIC(v) ((__REG_VALUE_TYPE((v), reg32_t) << BP_GPC_PGR_DRCIC) & BM_GPC_PGR_DRCIC)
// #ifndef __LANGUAGE_ASM__
// //! @brief Set the DRCIC field to a new value.
// #define BW_GPC_PGR_DRCIC(v) (HW_GPC_PGR_WR((HW_GPC_PGR_RD() & ~BM_GPC_PGR_DRCIC) | BF_GPC_PGR_DRCIC(v)))
// #endif
// //@}
// //-------------------------------------------------------------------------------------------
// // HW_GPC_IMR1 - IRQ masking register 1
// //-------------------------------------------------------------------------------------------
#ifndef __LANGUAGE_ASM__
/*!
* @brief HW_GPC_IMR1 - IRQ masking register 1 (RW)
*
* Reset value: 0x00000000
*
* IMR1 Register - masking of irq[63:32].
*/
typedef union _hw_gpc_imr1
{
reg32_t U;
struct _hw_gpc_imr1_bitfields
{
unsigned IMR1 : 32; //!< [31:0] IRQ[63:32] masking bits: 1-irq masked, 0-irq is not masked
} B;
} hw_gpc_imr1_t;
#endif
/*!
* @name Constants and macros for entire GPC_IMR1 register
*/
//@{
#define HW_GPC_IMR1_ADDR (REGS_GPC_BASE + 0x8)
#ifndef __LANGUAGE_ASM__
#define HW_GPC_IMR1 (*(volatile hw_gpc_imr1_t *) HW_GPC_IMR1_ADDR)
#define HW_GPC_IMR1_RD() (HW_GPC_IMR1.U)
#define HW_GPC_IMR1_WR(v) (HW_GPC_IMR1.U = (v))
#define HW_GPC_IMR1_SET(v) (HW_GPC_IMR1_WR(HW_GPC_IMR1_RD() | (v)))
#define HW_GPC_IMR1_CLR(v) (HW_GPC_IMR1_WR(HW_GPC_IMR1_RD() & ~(v)))
#define HW_GPC_IMR1_TOG(v) (HW_GPC_IMR1_WR(HW_GPC_IMR1_RD() ^ (v)))
#endif
//@}
// /*
// * constants & macros for individual GPC_IMR1 bitfields
// */
// /*! @name Register GPC_IMR1, field IMR1[31:0] (RW)
// *
// * IRQ[63:32] masking bits: 1-irq masked, 0-irq is not masked
// */
// //@{
// #define BP_GPC_IMR1_IMR1 (0) //!< Bit position for GPC_IMR1_IMR1.
// #define BM_GPC_IMR1_IMR1 (0xffffffff) //!< Bit mask for GPC_IMR1_IMR1.
// //! @brief Get value of GPC_IMR1_IMR1 from a register value.
// #define BG_GPC_IMR1_IMR1(r) ((__REG_VALUE_TYPE((r), reg32_t) & BM_GPC_IMR1_IMR1) >> BP_GPC_IMR1_IMR1)
// //! @brief Format value for bitfield GPC_IMR1_IMR1.
// #define BF_GPC_IMR1_IMR1(v) ((__REG_VALUE_TYPE((v), reg32_t) << BP_GPC_IMR1_IMR1) & BM_GPC_IMR1_IMR1)
// #ifndef __LANGUAGE_ASM__
// //! @brief Set the IMR1 field to a new value.
// #define BW_GPC_IMR1_IMR1(v) (HW_GPC_IMR1_WR((HW_GPC_IMR1_RD() & ~BM_GPC_IMR1_IMR1) | BF_GPC_IMR1_IMR1(v)))
// #endif
// //@}
// //-------------------------------------------------------------------------------------------
// // HW_GPC_IMR2 - IRQ masking register 2
// //-------------------------------------------------------------------------------------------
#ifndef __LANGUAGE_ASM__
/*!
* @brief HW_GPC_IMR2 - IRQ masking register 2 (RW)
*
* Reset value: 0x00000000
*
* IMR2 Register - masking of irq[95:64].
*/
typedef union _hw_gpc_imr2
{
reg32_t U;
struct _hw_gpc_imr2_bitfields
{
unsigned IMR2 : 32; //!< [31:0] IRQ[95:64] masking bits: 1-irq masked, 0-irq is not masked
} B;
} hw_gpc_imr2_t;
#endif
/*!
* @name Constants and macros for entire GPC_IMR2 register
*/
//@{
#define HW_GPC_IMR2_ADDR (REGS_GPC_BASE + 0xc)
#ifndef __LANGUAGE_ASM__
#define HW_GPC_IMR2 (*(volatile hw_gpc_imr2_t *) HW_GPC_IMR2_ADDR)
#define HW_GPC_IMR2_RD() (HW_GPC_IMR2.U)
#define HW_GPC_IMR2_WR(v) (HW_GPC_IMR2.U = (v))
#define HW_GPC_IMR2_SET(v) (HW_GPC_IMR2_WR(HW_GPC_IMR2_RD() | (v)))
#define HW_GPC_IMR2_CLR(v) (HW_GPC_IMR2_WR(HW_GPC_IMR2_RD() & ~(v)))
#define HW_GPC_IMR2_TOG(v) (HW_GPC_IMR2_WR(HW_GPC_IMR2_RD() ^ (v)))
#endif
//@}
// /*
// * constants & macros for individual GPC_IMR2 bitfields
// */
// /*! @name Register GPC_IMR2, field IMR2[31:0] (RW)
// *
// * IRQ[95:64] masking bits: 1-irq masked, 0-irq is not masked
// */
// //@{
// #define BP_GPC_IMR2_IMR2 (0) //!< Bit position for GPC_IMR2_IMR2.
// #define BM_GPC_IMR2_IMR2 (0xffffffff) //!< Bit mask for GPC_IMR2_IMR2.
// //! @brief Get value of GPC_IMR2_IMR2 from a register value.
// #define BG_GPC_IMR2_IMR2(r) ((__REG_VALUE_TYPE((r), reg32_t) & BM_GPC_IMR2_IMR2) >> BP_GPC_IMR2_IMR2)
// //! @brief Format value for bitfield GPC_IMR2_IMR2.
// #define BF_GPC_IMR2_IMR2(v) ((__REG_VALUE_TYPE((v), reg32_t) << BP_GPC_IMR2_IMR2) & BM_GPC_IMR2_IMR2)
// #ifndef __LANGUAGE_ASM__
// //! @brief Set the IMR2 field to a new value.
// #define BW_GPC_IMR2_IMR2(v) (HW_GPC_IMR2_WR((HW_GPC_IMR2_RD() & ~BM_GPC_IMR2_IMR2) | BF_GPC_IMR2_IMR2(v)))
// #endif
// //@}
// //-------------------------------------------------------------------------------------------
// // HW_GPC_IMR3 - IRQ masking register 3
// //-------------------------------------------------------------------------------------------
#ifndef __LANGUAGE_ASM__
/*!
* @brief HW_GPC_IMR3 - IRQ masking register 3 (RW)
*
* Reset value: 0x00000000
*
* IMR3 Register - masking of irq[127:96].
*/
typedef union _hw_gpc_imr3
{
reg32_t U;
struct _hw_gpc_imr3_bitfields
{
unsigned IMR3 : 32; //!< [31:0] IRQ[127:96] masking bits: 1-irq masked, 0-irq is not masked
} B;
} hw_gpc_imr3_t;
#endif
/*!
* @name Constants and macros for entire GPC_IMR3 register
*/
//@{
#define HW_GPC_IMR3_ADDR (REGS_GPC_BASE + 0x10)
#ifndef __LANGUAGE_ASM__
#define HW_GPC_IMR3 (*(volatile hw_gpc_imr3_t *) HW_GPC_IMR3_ADDR)
#define HW_GPC_IMR3_RD() (HW_GPC_IMR3.U)
#define HW_GPC_IMR3_WR(v) (HW_GPC_IMR3.U = (v))
#define HW_GPC_IMR3_SET(v) (HW_GPC_IMR3_WR(HW_GPC_IMR3_RD() | (v)))
#define HW_GPC_IMR3_CLR(v) (HW_GPC_IMR3_WR(HW_GPC_IMR3_RD() & ~(v)))
#define HW_GPC_IMR3_TOG(v) (HW_GPC_IMR3_WR(HW_GPC_IMR3_RD() ^ (v)))
#endif
//@}
// /*
// * constants & macros for individual GPC_IMR3 bitfields
// */
// /*! @name Register GPC_IMR3, field IMR3[31:0] (RW)
// *
// * IRQ[127:96] masking bits: 1-irq masked, 0-irq is not masked
// */
// //@{
// #define BP_GPC_IMR3_IMR3 (0) //!< Bit position for GPC_IMR3_IMR3.
// #define BM_GPC_IMR3_IMR3 (0xffffffff) //!< Bit mask for GPC_IMR3_IMR3.
// //! @brief Get value of GPC_IMR3_IMR3 from a register value.
// #define BG_GPC_IMR3_IMR3(r) ((__REG_VALUE_TYPE((r), reg32_t) & BM_GPC_IMR3_IMR3) >> BP_GPC_IMR3_IMR3)
// //! @brief Format value for bitfield GPC_IMR3_IMR3.
// #define BF_GPC_IMR3_IMR3(v) ((__REG_VALUE_TYPE((v), reg32_t) << BP_GPC_IMR3_IMR3) & BM_GPC_IMR3_IMR3)
// #ifndef __LANGUAGE_ASM__
// //! @brief Set the IMR3 field to a new value.
// #define BW_GPC_IMR3_IMR3(v) (HW_GPC_IMR3_WR((HW_GPC_IMR3_RD() & ~BM_GPC_IMR3_IMR3) | BF_GPC_IMR3_IMR3(v)))
// #endif
// //@}
// //-------------------------------------------------------------------------------------------
// // HW_GPC_IMR4 - IRQ masking register 4
// //-------------------------------------------------------------------------------------------
#ifndef __LANGUAGE_ASM__
/*!
* @brief HW_GPC_IMR4 - IRQ masking register 4 (RW)
*
* Reset value: 0x00000000
*
* IMR4 Register - masking of irq[159:128].
*/
typedef union _hw_gpc_imr4
{
reg32_t U;
struct _hw_gpc_imr4_bitfields
{
unsigned IMR4 : 32; //!< [31:0] IRQ[159:128] masking bits: 1-irq masked, 0-irq is not masked
} B;
} hw_gpc_imr4_t;
#endif
/*!
* @name Constants and macros for entire GPC_IMR4 register
*/
//@{
#define HW_GPC_IMR4_ADDR (REGS_GPC_BASE + 0x14)
#ifndef __LANGUAGE_ASM__
#define HW_GPC_IMR4 (*(volatile hw_gpc_imr4_t *) HW_GPC_IMR4_ADDR)
#define HW_GPC_IMR4_RD() (HW_GPC_IMR4.U)
#define HW_GPC_IMR4_WR(v) (HW_GPC_IMR4.U = (v))
#define HW_GPC_IMR4_SET(v) (HW_GPC_IMR4_WR(HW_GPC_IMR4_RD() | (v)))
#define HW_GPC_IMR4_CLR(v) (HW_GPC_IMR4_WR(HW_GPC_IMR4_RD() & ~(v)))
#define HW_GPC_IMR4_TOG(v) (HW_GPC_IMR4_WR(HW_GPC_IMR4_RD() ^ (v)))
#endif
//@}
// /*
// * constants & macros for individual GPC_IMR4 bitfields
// */
// /*! @name Register GPC_IMR4, field IMR4[31:0] (RW)
// *
// * IRQ[159:128] masking bits: 1-irq masked, 0-irq is not masked
// */
// //@{
// #define BP_GPC_IMR4_IMR4 (0) //!< Bit position for GPC_IMR4_IMR4.
// #define BM_GPC_IMR4_IMR4 (0xffffffff) //!< Bit mask for GPC_IMR4_IMR4.
// //! @brief Get value of GPC_IMR4_IMR4 from a register value.
// #define BG_GPC_IMR4_IMR4(r) ((__REG_VALUE_TYPE((r), reg32_t) & BM_GPC_IMR4_IMR4) >> BP_GPC_IMR4_IMR4)
// //! @brief Format value for bitfield GPC_IMR4_IMR4.
// #define BF_GPC_IMR4_IMR4(v) ((__REG_VALUE_TYPE((v), reg32_t) << BP_GPC_IMR4_IMR4) & BM_GPC_IMR4_IMR4)
// #ifndef __LANGUAGE_ASM__
// //! @brief Set the IMR4 field to a new value.
// #define BW_GPC_IMR4_IMR4(v) (HW_GPC_IMR4_WR((HW_GPC_IMR4_RD() & ~BM_GPC_IMR4_IMR4) | BF_GPC_IMR4_IMR4(v)))
// #endif
// //@}
// //-------------------------------------------------------------------------------------------
// // HW_GPC_ISR1 - IRQ status resister 1
// //-------------------------------------------------------------------------------------------
// #ifndef __LANGUAGE_ASM__
// /*!
// * @brief HW_GPC_ISR1 - IRQ status resister 1 (RO)
// *
// * Reset value: 0x00000000
// *
// * ISR1 Register - status of irq [63:32].
// */
// typedef union _hw_gpc_isr1
// {
// reg32_t U;
// struct _hw_gpc_isr1_bitfields
// {
// unsigned ISR1 : 32; //!< [31:0] IRQ[63:32] status, read only
// } B;
// } hw_gpc_isr1_t;
// #endif
// /*!
// * @name Constants and macros for entire GPC_ISR1 register
// */
// //@{
// #define HW_GPC_ISR1_ADDR (REGS_GPC_BASE + 0x18)
// #ifndef __LANGUAGE_ASM__
// #define HW_GPC_ISR1 (*(volatile hw_gpc_isr1_t *) HW_GPC_ISR1_ADDR)
// #define HW_GPC_ISR1_RD() (HW_GPC_ISR1.U)
// #endif
// //@}
// /*
// * constants & macros for individual GPC_ISR1 bitfields
// */
// /*! @name Register GPC_ISR1, field ISR1[31:0] (RO)
// *
// * IRQ[63:32] status, read only
// */
// //@{
// #define BP_GPC_ISR1_ISR1 (0) //!< Bit position for GPC_ISR1_ISR1.
// #define BM_GPC_ISR1_ISR1 (0xffffffff) //!< Bit mask for GPC_ISR1_ISR1.
// //! @brief Get value of GPC_ISR1_ISR1 from a register value.
// #define BG_GPC_ISR1_ISR1(r) ((__REG_VALUE_TYPE((r), reg32_t) & BM_GPC_ISR1_ISR1) >> BP_GPC_ISR1_ISR1)
// //@}
// //-------------------------------------------------------------------------------------------
// // HW_GPC_ISR2 - IRQ status resister 2
// //-------------------------------------------------------------------------------------------
// #ifndef __LANGUAGE_ASM__
// /*!
// * @brief HW_GPC_ISR2 - IRQ status resister 2 (RO)
// *
// * Reset value: 0x00000000
// *
// * ISR2 Register - status of irq [95:64].
// */
// typedef union _hw_gpc_isr2
// {
// reg32_t U;
// struct _hw_gpc_isr2_bitfields
// {
// unsigned ISR2 : 32; //!< [31:0] IRQ[95:64] status, read only
// } B;
// } hw_gpc_isr2_t;
// #endif
// /*!
// * @name Constants and macros for entire GPC_ISR2 register
// */
// //@{
// #define HW_GPC_ISR2_ADDR (REGS_GPC_BASE + 0x1c)
// #ifndef __LANGUAGE_ASM__
// #define HW_GPC_ISR2 (*(volatile hw_gpc_isr2_t *) HW_GPC_ISR2_ADDR)
// #define HW_GPC_ISR2_RD() (HW_GPC_ISR2.U)
// #endif
// //@}
// /*
// * constants & macros for individual GPC_ISR2 bitfields
// */
// /*! @name Register GPC_ISR2, field ISR2[31:0] (RO)
// *
// * IRQ[95:64] status, read only
// */
// //@{
// #define BP_GPC_ISR2_ISR2 (0) //!< Bit position for GPC_ISR2_ISR2.
// #define BM_GPC_ISR2_ISR2 (0xffffffff) //!< Bit mask for GPC_ISR2_ISR2.
// //! @brief Get value of GPC_ISR2_ISR2 from a register value.
// #define BG_GPC_ISR2_ISR2(r) ((__REG_VALUE_TYPE((r), reg32_t) & BM_GPC_ISR2_ISR2) >> BP_GPC_ISR2_ISR2)
// //@}
// //-------------------------------------------------------------------------------------------
// // HW_GPC_ISR3 - IRQ status resister 3
// //-------------------------------------------------------------------------------------------
// #ifndef __LANGUAGE_ASM__
// /*!
// * @brief HW_GPC_ISR3 - IRQ status resister 3 (RO)
// *
// * Reset value: 0x00000000
// *
// * ISR3 Register - status of irq [127:96].
// */
// typedef union _hw_gpc_isr3
// {
// reg32_t U;
// struct _hw_gpc_isr3_bitfields
// {
// unsigned ISR3 : 32; //!< [31:0] IRQ[127:96] status, read only
// } B;
// } hw_gpc_isr3_t;
// #endif
// /*!
// * @name Constants and macros for entire GPC_ISR3 register
// */
// //@{
// #define HW_GPC_ISR3_ADDR (REGS_GPC_BASE + 0x20)
// #ifndef __LANGUAGE_ASM__
// #define HW_GPC_ISR3 (*(volatile hw_gpc_isr3_t *) HW_GPC_ISR3_ADDR)
// #define HW_GPC_ISR3_RD() (HW_GPC_ISR3.U)
// #endif
// //@}
// /*
// * constants & macros for individual GPC_ISR3 bitfields
// */
// /*! @name Register GPC_ISR3, field ISR3[31:0] (RO)
// *
// * IRQ[127:96] status, read only
// */
// //@{
// #define BP_GPC_ISR3_ISR3 (0) //!< Bit position for GPC_ISR3_ISR3.
// #define BM_GPC_ISR3_ISR3 (0xffffffff) //!< Bit mask for GPC_ISR3_ISR3.
// //! @brief Get value of GPC_ISR3_ISR3 from a register value.
// #define BG_GPC_ISR3_ISR3(r) ((__REG_VALUE_TYPE((r), reg32_t) & BM_GPC_ISR3_ISR3) >> BP_GPC_ISR3_ISR3)
// //@}
// //-------------------------------------------------------------------------------------------
// // HW_GPC_ISR4 - IRQ status resister 4
// //-------------------------------------------------------------------------------------------
// #ifndef __LANGUAGE_ASM__
// /*!
// * @brief HW_GPC_ISR4 - IRQ status resister 4 (RO)
// *
// * Reset value: 0x00000000
// *
// * ISR4 Register - status of irq [159:128].
// */
// typedef union _hw_gpc_isr4
// {
// reg32_t U;
// struct _hw_gpc_isr4_bitfields
// {
// unsigned ISR4 : 32; //!< [31:0] IRQ[159:128] status, read only
// } B;
// } hw_gpc_isr4_t;
// #endif
// /*!
// * @name Constants and macros for entire GPC_ISR4 register
// */
// //@{
// #define HW_GPC_ISR4_ADDR (REGS_GPC_BASE + 0x24)
// #ifndef __LANGUAGE_ASM__
// #define HW_GPC_ISR4 (*(volatile hw_gpc_isr4_t *) HW_GPC_ISR4_ADDR)
// #define HW_GPC_ISR4_RD() (HW_GPC_ISR4.U)
// #endif
// //@}
// /*
// * constants & macros for individual GPC_ISR4 bitfields
// */
// /*! @name Register GPC_ISR4, field ISR4[31:0] (RO)
// *
// * IRQ[159:128] status, read only
// */
// //@{
// #define BP_GPC_ISR4_ISR4 (0) //!< Bit position for GPC_ISR4_ISR4.
// #define BM_GPC_ISR4_ISR4 (0xffffffff) //!< Bit mask for GPC_ISR4_ISR4.
// //! @brief Get value of GPC_ISR4_ISR4 from a register value.
// #define BG_GPC_ISR4_ISR4(r) ((__REG_VALUE_TYPE((r), reg32_t) & BM_GPC_ISR4_ISR4) >> BP_GPC_ISR4_ISR4)
// //@}
//-------------------------------------------------------------------------------------------
// hw_gpc_t - module struct
//-------------------------------------------------------------------------------------------
/*!
* @brief All GPC module registers.
*/
#ifndef __LANGUAGE_ASM__
#pragma pack(1)
// typedef struct _hw_gpc
// {
// volatile hw_gpc_cntr_t CNTR; //!< GPC Interface control register
// volatile hw_gpc_pgr_t PGR; //!< GPC Power Gating Register
// volatile hw_gpc_imr1_t IMR1; //!< IRQ masking register 1
// volatile hw_gpc_imr2_t IMR2; //!< IRQ masking register 2
// volatile hw_gpc_imr3_t IMR3; //!< IRQ masking register 3
// volatile hw_gpc_imr4_t IMR4; //!< IRQ masking register 4
// volatile hw_gpc_isr1_t ISR1; //!< IRQ status resister 1
// volatile hw_gpc_isr2_t ISR2; //!< IRQ status resister 2
// volatile hw_gpc_isr3_t ISR3; //!< IRQ status resister 3
// volatile hw_gpc_isr4_t ISR4; //!< IRQ status resister 4
// } hw_gpc_t;
// #pragma pack()
// //! @brief Macro to access all GPC registers.
// //! @return Reference (not a pointer) to the registers struct. To get a pointer to the struct,
// //! use the '&' operator, like <code>&HW_GPC</code>.
// #define HW_GPC (*(hw_gpc_t *) REGS_GPC_BASE)
#endif
#endif // __HW_GPC_REGISTERS_H__
// v18/121106/1.2.2
// EOF

View File

@ -39,7 +39,7 @@
#ifndef __TIMER_H__
#define __TIMER_H__
#include "sdk.h"
#include <stdint.h>
////////////////////////////////////////////////////////////////////////////////
// Constants
@ -49,20 +49,18 @@
//!
//! These constants are bit masks that are or'd together to select in which low
//! power modes the timer will continue counting.
enum _timer_low_power_modes
{
WAIT_MODE_EN = 1, //!< Timer is enabled in wait mode.
STOP_MODE_EN = 2 //!< Timer is enabled in stop mode.
enum _timer_low_power_modes {
WAIT_MODE_EN = 1, //!< Timer is enabled in wait mode.
STOP_MODE_EN = 2 //!< Timer is enabled in stop mode.
};
//! @brief Available clock sources for the timers.
enum _timer_clock_sources
{
CLKSRC_OFF = 0, //!< clock source is OFF
enum _timer_clock_sources {
CLKSRC_OFF = 0, //!< clock source is OFF
CLKSRC_IPG_CLK = 1, //!< clock source is peripheral clock
CLKSRC_PER_CLK = 2, //!< clock source is high-freq reference clock
CLKSRC_CLKIN = 3, //!< clock source is external from a CLKIN input
CLKSRC_CKIL = 3 //!< clock source is low-freq reference clock
CLKSRC_CLKIN = 3, //!< clock source is external from a CLKIN input
CLKSRC_CKIL = 3 //!< clock source is low-freq reference clock
};
//! @brief Do not enable interrupts.

View File

@ -0,0 +1,47 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file clock_common_op.h
* @brief clock interfaces of hardkernel
* @version 3.0
* @author AIIT XUOS Lab
* @date 2023.08.25
*/
/*************************************************
File name: clock_common_op.h
Description: clock interfaces of hardkernel
Others:
History:
1. Date: 2023-08-28
Author: AIIT XUOS Lab
Modification:
1. first version
*************************************************/
#pragma once
#include <stdint.h>
#include "actracer.h"
struct XiziClockDriver {
void (*sys_clock_init)();
uint32_t (*get_clock_int)();
void (*clear_clock_intr)();
uint64_t (*get_tick)();
uint64_t (*get_second)();
};
struct XiziClockDriver* hardkernel_clock_init(struct TraceTag* hardkernel_tag);
bool clock_intr_handler_init(struct TraceTag* p_clock_driver_tag);
int xizi_clock_handler(int irq, void* context, void* arg);

View File

@ -0,0 +1,199 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file hardkerenl_init.c
* @brief init hardkernel
* @version 3.0
* @author AIIT XUOS Lab
* @date 2023.08.25
*/
/*************************************************
File name: hardkerenl_init.c
Description: init hardkernel
Others:
History:
1. Date: 2023-08-28
Author: AIIT XUOS Lab
Modification:
1. first version
*************************************************/
#include "kern_init.h"
#include "cache_common_ope.h"
#include "clock_common_op.h"
#include "mmu_common.h"
#include "trap_common.h"
#include "uart_common_ope.h"
#include "assert.h"
#define KERN_BOOT_DRIVER(n, bi, f) \
{ \
n, bi, f \
}
static struct TraceTag hardkernel_tag;
static bool xizi_uart_init()
{
struct XiziSerialDriver* p_uart_driver = hardkernel_uart_init(&hardkernel_tag);
if (p_uart_driver == NULL) {
ERROR("uart driver init failed\n");
return false;
}
struct TraceTag uart_driver_tag;
if (!CreateResourceTag(&uart_driver_tag, &hardkernel_tag, "uart-ac-resource", TRACER_HARDKERNEL_AC_RESOURCE, p_uart_driver)) {
ERROR("Create uart resource failed.\n");
return false;
}
serial_init(&uart_driver_tag);
return true;
}
static bool xizi_intr_init()
{
/* init intr driver */
struct XiziTrapDriver* p_intr_driver = hardkernel_intr_init(&hardkernel_tag);
if (UNLIKELY(p_intr_driver == NULL)) {
ERROR("intr driver init failed\n");
return false;
}
struct TraceTag intr_driver_tag = {};
if (!CreateResourceTag(&intr_driver_tag, &hardkernel_tag, "intr-ac-resource", TRACER_HARDKERNEL_AC_RESOURCE, p_intr_driver)) {
ERROR("Create intr resource failed.\n");
return false;
}
/* grant rights to intr dispatcher */
struct IrqDispatcherRightGroup irq_dispatcher_rights = { .intr_driver_tag = intr_driver_tag };
if (!intr_distributer_init(&irq_dispatcher_rights)) {
ERROR("init intr distributer failed.\n");
return false;
}
/* grant rights to syscall dispatcher */
struct SwiDispatcherRightGroup swi_dispatcher_rights = { .intr_driver_tag = intr_driver_tag };
if (!swi_distributer_init(&swi_dispatcher_rights)) {
ERROR("init syscall distributer failed.\n");
return false;
}
/* grant rights to spinlock module*/
if (!module_spinlock_use_intr_init()) {
ERROR("spinlock init using interrupt failed\n");
return false;
}
return true;
}
static bool xizi_gpt_init()
{
/* init clock driver and create clock driver tag */
struct XiziClockDriver* p_clock_driver = hardkernel_clock_init(&hardkernel_tag);
if (UNLIKELY(p_clock_driver == NULL)) {
ERROR("clock driver init failed\n");
return false;
}
struct TraceTag clock_driver_tag;
if (!CreateResourceTag(&clock_driver_tag, &hardkernel_tag, "clock-ac-resource", TRACER_HARDKERNEL_AC_RESOURCE, p_clock_driver)) {
ERROR("Create clock resource failed.\n");
return false;
}
/* enable clock interrupt */
if (!clock_intr_handler_init(&clock_driver_tag)) {
ERROR("clock interrupt init failed.\n");
return false;
}
// get intr driver tag
struct TraceTag intr_driver_tag;
if (!AchieveResourceTag(&intr_driver_tag, &hardkernel_tag, "intr-ac-resource")) {
ERROR("Achieve intr resource failed.\n");
return false;
}
// register clock handler to intr
struct XiziTrapDriver* p_intr_driver = (struct XiziTrapDriver*)AchieveResource(&intr_driver_tag);
p_intr_driver->bind_irq_handler(p_clock_driver->get_clock_int(), xizi_clock_handler);
p_intr_driver->single_irq_enable(p_clock_driver->get_clock_int(), 0, 0);
return true;
}
static bool xizi_cache_init()
{
struct TraceTag icache_driver_tag, dcache_driver_tag;
struct ICacheDone* p_icache_done = hardkernel_icache_init(&hardkernel_tag);
if (UNLIKELY(p_icache_done == NULL)) {
ERROR("icache driver init failed.\n");
return false;
}
if (!CreateResourceTag(&icache_driver_tag, &hardkernel_tag, "icache-ac-resource", TRACER_HARDKERNEL_AC_RESOURCE, p_icache_done)) {
ERROR("Create icache resource failed.\n");
return false;
}
struct DCacheDone* p_dcache_done = hardkernel_dcache_init(&hardkernel_tag);
if (UNLIKELY(p_dcache_done == NULL)) {
ERROR("dcache driver init failed.\n");
return false;
}
if (!CreateResourceTag(&dcache_driver_tag, &hardkernel_tag, "dcache-ac-resource", TRACER_HARDKERNEL_AC_RESOURCE, p_dcache_done)) {
ERROR("Create dcache resource failed.\n");
return false;
}
return true;
}
static bool xizi_mmu_init()
{
struct MmuCommonDone* p_mmu_done = hardkernel_mmu_init(&hardkernel_tag, "icache-ac-resource", "dcache-ac-resource");
if (UNLIKELY(p_mmu_done == NULL)) {
ERROR("mmu driver init failed\n");
return false;
}
/* create trace for mmu driver */
struct TraceTag mmu_driver_tag;
CreateResourceTag(&mmu_driver_tag, &hardkernel_tag, "mmu-ac-resource", TRACER_HARDKERNEL_AC_RESOURCE, p_mmu_done);
return true;
}
struct XiziBootNode hardkernel_init_array[] = {
KERN_BOOT_DRIVER("uart", "Xizi uart driver initialized successfully.", xizi_uart_init),
KERN_BOOT_DRIVER("intr", "Xizi interrupt driver initialized successfully.", xizi_intr_init),
KERN_BOOT_DRIVER("cache", "Xizi cache driver initialized successfully.", xizi_cache_init),
KERN_BOOT_DRIVER("mmu", "Xizi mmu driver initialized successfully.", xizi_mmu_init),
KERN_BOOT_DRIVER("clock", "Xizi clock driver initialized successfully.", xizi_gpt_init),
};
bool hardkernel_init(struct TraceTag* _hardkernel_tag)
{
hardkernel_tag = *_hardkernel_tag;
for (uint32_t i = 0; i < sizeof(hardkernel_init_array) / sizeof(struct XiziBootNode); i++) {
if (!hardkernel_init_array[i].init()) {
return false;
}
LOG_PRINTF(hardkernel_init_array[i].bootinfo);
LOG_PRINTF("\n");
}
return true;
}

View File

@ -0,0 +1,3 @@
SRC_DIR := arm/armv7-a/cortex-a9
include $(KERNEL_ROOT)/compiler.mk

View File

@ -0,0 +1,4 @@
SRC_DIR := gicv2
SRC_FILES := vector.S trampoline.S trap_common.c error_debug.c spinlock.c hard_spinlock.S
include $(KERNEL_ROOT)/compiler.mk

View File

@ -0,0 +1,141 @@
/* Copyright (c) 2006-2018 Frans Kaashoek, Robert Morris, Russ Cox,
* Massachusetts Institute of Technology
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/**
* @file error_debug.c
* @brief handle program abort
* @version 3.0
* @author AIIT XUOS Lab
* @date 2024.11.23
*/
/*************************************************
File name: error_debug.c
Description: handle program abort
Others:
History:
1. Date: 2024-11-23
Author: AIIT XUOS Lab
Modification:
1. first version
*************************************************/
#include "core.h"
#include "memlayout.h"
#include "log.h"
#include "multicores.h"
#include "syscall.h"
__attribute__((always_inline)) static inline void _abort_reason(uint32_t fault_status)
{
if ((fault_status & 0xd) == 0x1) // Alignment failure
KPrintf("reason: alignment\n");
else if ((fault_status & 0xd) == 0x5) // External abort "on translation"
KPrintf("reason: ext. abort on trnslt.\n");
else if ((fault_status & 0xd) == 0x5) // Translation
KPrintf("reason: sect. translation\n");
else if ((fault_status & 0xd) == 0x9) // Domain
KPrintf("reason: sect. domain\n");
else if ((fault_status & 0xd) == 0xd) // Permission
KPrintf("reason: sect. permission\n");
else if ((fault_status & 0xd) == 0x8) // External abort
KPrintf("reason: ext. abort\n");
else
KPrintf("reason: unknown???\n");
}
void dump_tf(struct trapframe* tf)
{
KPrintf("lr_svc: 0x%x\n", tf->lr_svc);
KPrintf(" spsr: 0x%x\n", tf->spsr);
KPrintf(" r0: 0x%x\n", tf->r0);
KPrintf(" r1: 0x%x\n", tf->r1);
KPrintf(" r2: 0x%x\n", tf->r2);
KPrintf(" r3: 0x%x\n", tf->r3);
KPrintf(" r4: 0x%x\n", tf->r4);
KPrintf(" r5: 0x%x\n", tf->r5);
KPrintf(" r6: 0x%x\n", tf->r6);
KPrintf(" r7: 0x%x\n", tf->r7);
KPrintf(" r8: 0x%x\n", tf->r8);
KPrintf(" r9: 0x%x\n", tf->r9);
KPrintf(" r10: 0x%x\n", tf->r10);
KPrintf(" r11: 0x%x\n", tf->r11);
KPrintf(" r12: 0x%x\n", tf->r12);
KPrintf(" pc: 0x%x\n", tf->pc);
}
void handle_undefined_instruction(struct trapframe* tf)
{
// unimplemented trap handler
KPrintf("undefined instruction at %x\n", tf->pc);
panic("");
}
void dabort_handler(struct trapframe* r)
{
uint32_t dfs, dfa;
__asm__ __volatile__("mrc p15, 0, %0, c5, c0, 0" : "=r"(dfs)::);
__asm__ __volatile__("mrc p15, 0, %0, c6, c0, 0" : "=r"(dfa)::);
if (r->pc < KERN_MEM_BASE) { // Exception occured in User space: exit
ERROR("dabort in user space: %s\n", cur_cpu()->task->name);
LOG("program counter: 0x%x(%s) caused\n", r->pc, cur_cpu()->task);
LOG("data abort at 0x%x, status 0x%x\n", dfa, dfs);
_abort_reason(dfs);
dump_tf(r);
}
if (cur_cpu()->task != NULL) {
sys_exit();
} else { // Exception occured in Kernel space: panic
LOG("program counter: 0x%x(%s) caused\n", r->pc, cur_cpu()->task);
LOG("data abort at 0x%x, status 0x%x\n", dfa, dfs);
_abort_reason(dfs);
dump_tf(r);
panic("data abort exception\n");
}
}
void iabort_handler(struct trapframe* r)
{
uint32_t ifs, ifa;
__asm__ __volatile__("mrc p15, 0, %0, c5, c0, 1" : "=r"(ifs)::);
__asm__ __volatile__("mrc p15, 0, %0, c6, c0, 2" : "=r"(ifa)::);
if (r->pc < KERN_MEM_BASE) { // Exception occured in User space: exit
ERROR("iabort in user space: %s\n", cur_cpu()->task->name);
LOG("program counter: 0x%x(%s) caused\n", r->pc, cur_cpu()->task);
LOG("prefetch abort at 0x%x, status 0x%x\n", ifa, ifs);
_abort_reason(ifs);
dump_tf(r);
}
if (cur_cpu()->task != NULL) {
sys_exit();
} else { // Exception occured in Kernel space: panic
LOG("program counter: 0x%x(%s) caused\n", r->pc, cur_cpu()->task);
LOG("prefetch abort at 0x%x, status 0x%x\n", ifa, ifs);
_abort_reason(ifs);
dump_tf(r);
panic("prefetch abort exception\n");
}
}

View File

@ -0,0 +1,4 @@
SRC_FILES := gicv2_distributer_to_device.c \
gicv2_interface_to_core.c \
include $(KERNEL_ROOT)/compiler.mk

View File

@ -27,10 +27,40 @@
* (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 __GIC_H__
#define __GIC_H__
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file gicv2_common_opa.c
* @brief gicv2 operation
* @version 3.0
* @author AIIT XUOS Lab
* @date 2023.08.25
*/
#include "sdk_types.h"
/*************************************************
File name: gicv2_common_opa.c
Description: gicv2 operation
Others:
History:
1. Date: 2023-08-28
Author: AIIT XUOS Lab
Modification:
*************************************************/
#pragma once
#include <stdbool.h>
#include <stdint.h>
#include <mmio_access.h>
//! @addtogroup gic
//! @{
@ -44,15 +74,14 @@
//! These options are used for the @a filter_list parameter of the gic_send_sgi()
//! function. They control how to select which CPUs that the interrupt is
//! sent to.
enum _gicd_sgi_filter
{
enum _gicd_sgi_filter {
//! Forward the interrupt to the CPU interfaces specified in the @a target_list parameter.
kGicSgiFilter_UseTargetList = 0,
//! Forward the interrupt to all CPU interfaces except that of the processor that requested
//! the interrupt.
kGicSgiFilter_AllOtherCPUs = 1,
//! Forward the interrupt only to the CPU interface of the processor that requested the
//! interrupt.
kGicSgiFilter_OnlyThisCPU = 2
@ -66,6 +95,26 @@ enum _gicd_sgi_filter
extern "C" {
#endif
__attribute__((__always_inline__)) static inline uint32_t get_arm_private_peripheral_base()
{
return MMIO_P2V(0x00A00000);
}
__attribute__((__always_inline__)) static inline uint32_t irq_get_register_offset(uint32_t irqID)
{
return irqID / 32;
}
__attribute__((__always_inline__)) static inline uint32_t irq_get_bit_offset(uint32_t irqID)
{
return irqID & 0x1f;
}
__attribute__((__always_inline__)) static inline uint32_t irq_get_bit_mask(uint32_t irqID)
{
return 1 << irq_get_bit_offset(irqID);
}
//! @name Initialization
//@{
//! @brief Init interrupt handling.
@ -170,14 +219,12 @@ uint32_t gic_read_irq_ack(void);
void gic_write_end_of_irq(uint32_t irq_id);
//@}
#if defined(__cplusplus)
}
#endif
//! @}
#endif // __GIC_H__
////////////////////////////////////////////////////////////////////////////////
// EOF
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Freescale Semiconductor, Inc.
* Copyright (c) 2011-2012, Freescale Semiconductor, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -27,63 +27,43 @@
* (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 <assert.h>
#include "gic.h"
#include "gic_registers.h"
#include "cortex_a9.h"
/**
* @file gicv2_distributer_to_device.c
* @brief gicv2 operation
* @version 3.0
* @author AIIT XUOS Lab
* @date 2023.08.25
*/
////////////////////////////////////////////////////////////////////////////////
// Prototypes
////////////////////////////////////////////////////////////////////////////////
/*************************************************
File name: gicv2_distributer_to_device.c
Description: gicv2 operation
Others:
History:
1. Date: 2023-08-28
Author: AIIT XUOS Lab
Modification:
1. take only gicd part
*************************************************/
#include "gicv2_common_opa.h"
#include "gicv2_registers.h"
static inline gicd_t * gic_get_gicd(void);
static inline gicc_t * gic_get_gicc(void);
static inline uint32_t irq_get_register_offset(uint32_t irqID);
static inline uint32_t irq_get_bit_offset(uint32_t irqID);
static inline uint32_t irq_get_bit_mask(uint32_t irqID);
static inline gicd_t* gic_get_gicd(void);
////////////////////////////////////////////////////////////////////////////////
// Code
////////////////////////////////////////////////////////////////////////////////
static inline gicd_t * gic_get_gicd(void)
static inline gicd_t* gic_get_gicd(void)
{
uint32_t base = get_arm_private_peripheral_base() + kGICDBaseOffset;
return (gicd_t *)base;
}
static inline gicc_t * gic_get_gicc(void)
{
uint32_t base = get_arm_private_peripheral_base() + kGICCBaseOffset;
return (gicc_t *)base;
}
static inline uint32_t irq_get_register_offset(uint32_t irqID)
{
return irqID / 32;
}
static inline uint32_t irq_get_bit_offset(uint32_t irqID)
{
return irqID & 0x1f;
}
static inline uint32_t irq_get_bit_mask(uint32_t irqID)
{
return 1 << irq_get_bit_offset(irqID);
return (gicd_t*)base;
}
void gic_enable(bool enableIt)
{
gicd_t * gicd = gic_get_gicd();
if (enableIt)
{
gicd_t* gicd = gic_get_gicd();
if (enableIt) {
// Enable both secure and non-secure.
gicd->CTLR |= kBM_GICD_CTLR_EnableGrp0 | kBM_GICD_CTLR_EnableGrp1;
}
else
{
} else {
// Clear the enable bits.
gicd->CTLR &= ~(kBM_GICD_CTLR_EnableGrp0 | kBM_GICD_CTLR_EnableGrp1);
}
@ -91,18 +71,15 @@ void gic_enable(bool enableIt)
void gic_set_irq_security(uint32_t irqID, bool isSecure)
{
gicd_t * gicd = gic_get_gicd();
gicd_t* gicd = gic_get_gicd();
uint32_t reg = irq_get_register_offset(irqID);
uint32_t mask = irq_get_bit_mask(irqID);
uint32_t value = gicd->IGROUPRn[reg];
if (!isSecure)
{
if (!isSecure) {
value &= ~mask;
}
else
{
} else {
value |= mask;
}
gicd->IGROUPRn[reg] = value;
@ -110,26 +87,23 @@ void gic_set_irq_security(uint32_t irqID, bool isSecure)
void gic_enable_irq(uint32_t irqID, bool isEnabled)
{
gicd_t * gicd = gic_get_gicd();
gicd_t* gicd = gic_get_gicd();
uint32_t reg = irq_get_register_offset(irqID);
uint32_t mask = irq_get_bit_mask(irqID);
// Select set-enable or clear-enable register based on enable flag.
if (isEnabled)
{
if (isEnabled) {
gicd->ISENABLERn[reg] = mask;
}
else
{
} else {
gicd->ICENABLERn[reg] = mask;
}
}
void gic_set_irq_priority(uint32_t ID, uint32_t priority)
{
gicd_t * gicd = gic_get_gicd();
gicd_t* gicd = gic_get_gicd();
// Update the priority register. The priority registers are byte accessible, and the register
// struct has the priority registers as a byte array, so we can just index directly by the
// interrupt ID.
@ -139,105 +113,49 @@ void gic_set_irq_priority(uint32_t ID, uint32_t priority)
void gic_set_cpu_target(uint32_t irqID, unsigned cpuNumber, bool enableIt)
{
// Make sure the CPU number is valid.
assert(cpuNumber <= 7);
gicd_t * gicd = gic_get_gicd();
// assert(cpuNumber <= 7);
gicd_t* gicd = gic_get_gicd();
uint8_t cpuMask = 1 << cpuNumber;
// Like the priority registers, the target registers are byte accessible, and the register
// struct has the them as a byte array, so we can just index directly by the
// interrupt ID.
if (enableIt)
{
if (enableIt) {
gicd->ITARGETSRn[irqID] |= (cpuMask & 0xff);
}
else
{
} else {
gicd->ITARGETSRn[irqID] &= ~(cpuMask & 0xff);
}
}
void gic_send_sgi(uint32_t irqID, uint32_t target_list, uint32_t filter_list)
{
gicd_t * gicd = gic_get_gicd();
gicd_t* gicd = gic_get_gicd();
gicd->SGIR = (filter_list << kBP_GICD_SGIR_TargetListFilter)
| (target_list << kBP_GICD_SGIR_CPUTargetList)
| (irqID & 0xf);
}
void gic_cpu_enable(bool enableIt)
{
gicc_t * gicc = gic_get_gicc();
if (enableIt)
{
gicc->CTLR |= kBM_GICC_CTLR_EnableS | kBM_GICC_CTLR_EnableNS;
}
else
{
gicc->CTLR &= ~(kBM_GICC_CTLR_EnableS | kBM_GICC_CTLR_EnableNS);
}
}
void gic_set_cpu_priority_mask(uint32_t priority)
{
gicc_t * gicc = gic_get_gicc();
gicc->PMR = priority & 0xff;
}
uint32_t gic_read_irq_ack(void)
{
gicc_t * gicc = gic_get_gicc();
return gicc->IAR;
}
void gic_write_end_of_irq(uint32_t irqID)
{
gicc_t * gicc = gic_get_gicc();
gicc->EOIR = irqID;
| (target_list << kBP_GICD_SGIR_CPUTargetList)
| (irqID & 0xf);
}
void gic_init(void)
{
gicd_t * gicd = gic_get_gicd();
gicd_t* gicd = gic_get_gicd();
// First disable the distributor.
gic_enable(false);
// Clear all pending interrupts.
int i;
for (i = 0; i < 32; ++i)
{
gicd->ICPENDRn[i] = 0xffffffff;
}
// Set all interrupts to secure.
for (i = 0; i < 8; ++i)
{
for (uint32_t i = 0; i < 8; i++) {
gicd->IGROUPRn[i] = 0;
}
for (uint32_t i = 0; i < 255; i++) {
*(uint32_t*)(&gicd->IPRIORITYRn[i * sizeof(uint32_t)]) = (uint32_t)0x80808080;
*(uint32_t*)(&gicd->ITARGETSRn[i * sizeof(uint32_t)]) = (uint32_t)0x01010101;
}
// Init the GIC CPU interface.
gic_init_cpu();
// Now enable the distributor.
gic_enable(true);
}
void gic_init_cpu(void)
{
// Init the GIC CPU interface.
gic_set_cpu_priority_mask(0xff);
// Disable preemption.
gicc_t * gicc = gic_get_gicc();
gicc->BPR = 7;
// Enable signaling the CPU.
gic_cpu_enable(true);
}
////////////////////////////////////////////////////////////////////////////////
// EOF
////////////////////////////////////////////////////////////////////////////////

View File

@ -27,42 +27,71 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#if !defined(__PRINT_CLOCK_INFO_H__)
#define __PRINT_CLOCK_INFO_H__
#include "sdk.h"
//! @addtogroup app_common
//! @{
////////////////////////////////////////////////////////////////////////////////
// API
////////////////////////////////////////////////////////////////////////////////
#if defined(__cplusplus)
extern "C" {
#endif
/*!
* @brief Display module frequency
/**
* @file gicv2_distributer_to_core.c
* @brief gicv2 operation
* @version 3.0
* @author AIIT XUOS Lab
* @date 2023.08.25
*/
void show_freq(void);
/*!
* @brief Display the board's DDR configuration
*/
void show_ddr_config(void);
/*************************************************
File name: gicv2_distributer_to_core.c
Description: gicv2 operation
Others:
History:
1. Date: 2023-08-28
Author: AIIT XUOS Lab
Modification:
1. take only gicc part
*************************************************/
#include "gicv2_common_opa.h"
#include "gicv2_registers.h"
#if defined(__cplusplus)
static inline gicc_t* gic_get_gicc(void)
{
uint32_t base = get_arm_private_peripheral_base() + kGICCBaseOffset;
return (gicc_t*)base;
}
#endif
//! @}
void gic_cpu_enable(bool enableIt)
{
gicc_t* gicc = gic_get_gicc();
#endif // __PRINT_CLOCK_INFO_H__
////////////////////////////////////////////////////////////////////////////////
// EOF
////////////////////////////////////////////////////////////////////////////////
if (enableIt) {
gicc->CTLR |= kBM_GICC_CTLR_EnableS | kBM_GICC_CTLR_EnableNS;
} else {
gicc->CTLR &= ~(kBM_GICC_CTLR_EnableS | kBM_GICC_CTLR_EnableNS);
}
}
void gic_set_cpu_priority_mask(uint32_t priority)
{
gicc_t* gicc = gic_get_gicc();
gicc->PMR = priority & 0xff;
}
inline uint32_t gic_read_irq_ack(void)
{
gicc_t* gicc = gic_get_gicc();
return gicc->IAR;
}
void gic_write_end_of_irq(uint32_t irqID)
{
gicc_t* gicc = gic_get_gicc();
gicc->EOIR = irqID;
}
void gic_init_cpu(void)
{
// Init the GIC CPU interface.
gic_set_cpu_priority_mask(0xff);
// Disable preemption.
gicc_t* gicc = gic_get_gicc();
gicc->BPR = 7;
// Enable signaling the CPU.
gic_cpu_enable(true);
}

View File

@ -27,17 +27,33 @@
* (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_types.h"
/**
* @file gicv2_registers.c
* @brief gicv2 registers
* @version 3.0
* @author AIIT XUOS Lab
* @date 2023.08.25
*/
/*************************************************
File name: gicv2_registers.c
Description: gicv2 registers
Others:
History:
1. Date: 2023-08-28
Author: AIIT XUOS Lab
Modification:
*************************************************/
#include <stdint.h>
////////////////////////////////////////////////////////////////////////////////
// Definitions
////////////////////////////////////////////////////////////////////////////////
//! @brief Offsets to the GIC registers.
enum _gic_base_offsets
{
kGICDBaseOffset = 0x1000, //!< GIC distributor offset.
kGICCBaseOffset = 0x100 //!< GIC CPU interface offset.
enum _gic_base_offsets {
kGICDBaseOffset = 0x1000, //!< GIC distributor offset.
kGICCBaseOffset = 0x100 //!< GIC CPU interface offset.
};
//! @brief GIC distributor registers.
@ -47,48 +63,45 @@ enum _gic_base_offsets
//! The IPRIORITYRn and ITARGETSRn registers are byte accessible, so their types are uint8_t
//! instead of uint32_t to reflect this. These members are indexed directly with the interrupt
//! number.
struct _gicd_registers
{
uint32_t CTLR; //!< Distributor Control Register.
uint32_t TYPER; //!< Interrupt Controller Type Register.
uint32_t IIDR; //!< Distributor Implementer Identification Register.
struct _gicd_registers {
uint32_t CTLR; //!< Distributor Control Register.
uint32_t TYPER; //!< Interrupt Controller Type Register.
uint32_t IIDR; //!< Distributor Implementer Identification Register.
uint32_t _reserved0[29];
uint32_t IGROUPRn[8]; //!< Interrupt Group Registers.
uint32_t IGROUPRn[8]; //!< Interrupt Group Registers.
uint32_t _reserved1[24];
uint32_t ISENABLERn[32]; //!< Interrupt Set-Enable Registers.
uint32_t ICENABLERn[32]; //!< Interrupt Clear-Enable Registers.
uint32_t ISPENDRn[32]; //!< Interrupt Set-Pending Registers.
uint32_t ICPENDRn[32]; //!< Interrupt Clear-Pending Registers.
uint32_t ICDABRn[32]; //!< Active Bit Registers.
uint32_t ISENABLERn[32]; //!< Interrupt Set-Enable Registers.
uint32_t ICENABLERn[32]; //!< Interrupt Clear-Enable Registers.
uint32_t ISPENDRn[32]; //!< Interrupt Set-Pending Registers.
uint32_t ICPENDRn[32]; //!< Interrupt Clear-Pending Registers.
uint32_t ICDABRn[32]; //!< Active Bit Registers.
uint32_t _reserved2[32];
uint8_t IPRIORITYRn[255 * sizeof(uint32_t)]; //!< Interrupt Priority Registers. (Byte accessible)
uint8_t IPRIORITYRn[255 * sizeof(uint32_t)]; //!< Interrupt Priority Registers. (Byte accessible)
uint32_t _reserved3;
uint8_t ITARGETSRn[255 * sizeof(uint32_t)]; //!< Interrupt Processor Targets Registers. (Byte accessible)
uint8_t ITARGETSRn[255 * sizeof(uint32_t)]; //!< Interrupt Processor Targets Registers. (Byte accessible)
uint32_t _reserved4;
uint32_t ICFGRn[64]; //!< Interrupt Configuration Registers.
uint32_t ICFGRn[64]; //!< Interrupt Configuration Registers.
uint32_t _reserved5[128];
uint32_t SGIR; //!< Software Generated Interrupt Register
uint32_t SGIR; //!< Software Generated Interrupt Register
};
//! @brief Bitfields constants for the GICD_CTLR register.
enum _gicd_ctlr_fields
{
enum _gicd_ctlr_fields {
kBM_GICD_CTLR_EnableGrp1 = (1 << 1),
kBM_GICD_CTLR_EnableGrp0 = (1 << 0)
};
//! @brief Bitfields constants for the GICD_SGIR register.
enum _gicd_sgir_fields
{
enum _gicd_sgir_fields {
kBP_GICD_SGIR_TargetListFilter = 24,
kBM_GICD_SGIR_TargetListFilter = (0x3 << kBP_GICD_SGIR_TargetListFilter),
kBP_GICD_SGIR_CPUTargetList = 16,
kBM_GICD_SGIR_CPUTargetList = (0xff << kBP_GICD_SGIR_CPUTargetList),
kBP_GICD_SGIR_NSATT = 15,
kBM_GICD_SGIR_NSATT = (1 << kBP_GICD_SGIR_NSATT),
kBP_GICD_SGIR_SGIINTID = 0,
kBM_GICD_SGIR_SGIINTID = 0xf
};
@ -96,35 +109,33 @@ enum _gicd_sgir_fields
//! @brief GIC CPU interface registers.
//!
//! Uses the GICv2 register names. Does not include GICv2 registers.
struct _gicc_registers
{
uint32_t CTLR; //!< CPU Interface Control Register.
uint32_t PMR; //!< Interrupt Priority Mask Register.
uint32_t BPR; //!< Binary Point Register.
uint32_t IAR; //!< Interrupt Acknowledge Register.
uint32_t EOIR; //!< End of Interrupt Register.
uint32_t RPR; //!< Running Priority Register.
struct _gicc_registers {
uint32_t CTLR; //!< CPU Interface Control Register.
uint32_t PMR; //!< Interrupt Priority Mask Register.
uint32_t BPR; //!< Binary Point Register.
uint32_t IAR; //!< Interrupt Acknowledge Register.
uint32_t EOIR; //!< End of Interrupt Register.
uint32_t RPR; //!< Running Priority Register.
uint32_t HPPIR; //!< Highest Priority Pending Interrupt Register.
uint32_t ABPR; //!< Aliased Binary Point Register. (only visible with a secure access)
uint32_t ABPR; //!< Aliased Binary Point Register. (only visible with a secure access)
uint32_t _reserved[56];
uint32_t IIDR; //!< CPU Interface Identification Register.
uint32_t IIDR; //!< CPU Interface Identification Register.
};
//! @brief Bitfields constants for the GICC_CTLR register.
enum _gicc_ctlr_fields
{
enum _gicc_ctlr_fields {
kBP_GICC_CTLR_EnableS = 0,
kBM_GICC_CTLR_EnableS = (1 << 0),
kBP_GICC_CTLR_EnableNS = 1,
kBM_GICC_CTLR_EnableNS = (1 << 1),
kBP_GICC_CTLR_AckCtl = 2,
kBM_GICC_CTLR_AckCtl = (1 << 2),
kBP_GICC_CTLR_FIQEn = 3,
kBM_GICC_CTLR_FIQEn = (1 << 3),
kBP_GICC_CTLR_SBPR = 4,
kBM_GICC_CTLR_SBPR = (1 << 4)
};

View File

@ -0,0 +1,112 @@
/*
* Copyright (c) 2013, 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.
*/
/*
* Portions Copyright (c) 2011-2012 ARM Ltd. All rights reserved.
*/
/**
* @file hard_spinlock.S
* @brief spinlock implementation
* @version 3.0
* @author AIIT XUOS Lab
* @date 2023.08.25
*/
/*************************************************
File name: hard_spinlock.S
Description: spinlock implementation
Others:
History:
1. Date: 2023-08-28
Author: AIIT XUOS Lab
Modification:
1. add return of _spinlock_lock
*************************************************/
.code 32
.section ".text","ax"
.global cpu_get_current
#define UNLOCKED 0xFF
// int spinlock_lock(spinlock_t * lock, uint32_t timeout)
.global _spinlock_lock
.func _spinlock_lock
_spinlock_lock:
ldrex r1, [r0] // check if the spinlock is currently unlocked
cmp r1, #UNLOCKED
wfene // wait for an event signal
bne _spinlock_lock
mrc p15, 0, r1, c0, c0, 5 // get our CPU ID
and r1, r1, #3
strex r2, r1, [r0] // attempt to grab lock by writing CPU number into spinlock
cmp r2, #0 // check if the write was successful
bne _spinlock_lock // if the write failed, start over
dmb // Ensure that accesses to shared resource have completed
mov r0, #0
bx lr // return to caller
.endfunc // spinlock_lock
// void spinlock_unlock(spinlock_t * lock)
.global _spinlock_unlock
.func _spinlock_unlock
_spinlock_unlock:
mrc p15, 0, r1, c0, c0, 5 // get our CPU ID
and r1, r1, #3
ldr r2, [r0] // read lock field of spinlock
cmp r1, r2 // compare lock field with our CPU ID
movne r0, #1 // doesn't match, so exit with failure
bxne lr
dmb // Ensure that accesses to shared resource have completed
mov r1, #UNLOCKED // load unlocked value
str r1, [r0] // write into lock field of spinlock
dsb // Ensure that no instructions following the barrier execute until
// all memory accesses prior to the barrier have completed.
sev // send event to wake up other cores waiting on spinlock
mov r0, #0 // return success
bx lr
.endfunc
.end

View File

@ -0,0 +1,247 @@
/*
* 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.
*/
/**
* @file irq_numbers.c
* @brief irq numbers
* @version 3.0
* @author AIIT XUOS Lab
* @date 2023.08.25
*/
/*************************************************
File name: irq_numbers.c
Description: irq numbers
Others:
History:
1. Date: 2023-08-28
Author: AIIT XUOS Lab
Modification:
1. Add HW_NR_IRQS
*************************************************/
#if !defined(__IRQ_NUMBERS_H__)
#define __IRQ_NUMBERS_H__
#define HW_NR_IRQS IMX_INTERRUPT_COUNT
////////////////////////////////////////////////////////////////////////////////
// Definitions
////////////////////////////////////////////////////////////////////////////////
//! @brief i.MX6 interrupt numbers.
//!
//! This enumeration lists the numbers for all of the interrupts available on the i.MX6 series.
//! Use these numbers when specifying an interrupt to the GIC.
//!
//! The first 16 interrupts are special in that they are reserved for software interrupts generated
//! by the SWI instruction.
enum _imx_interrupts {
SW_INTERRUPT_0 = 0, //!< Software interrupt 0.
SW_INTERRUPT_1 = 1, //!< Software interrupt 1.
SW_INTERRUPT_2 = 2, //!< Software interrupt 2.
SW_INTERRUPT_3 = 3, //!< Software interrupt 3.
SW_INTERRUPT_4 = 4, //!< Software interrupt 4.
SW_INTERRUPT_5 = 5, //!< Software interrupt 5.
SW_INTERRUPT_6 = 6, //!< Software interrupt 6.
SW_INTERRUPT_7 = 7, //!< Software interrupt 7.
SW_INTERRUPT_8 = 8, //!< Software interrupt 8.
SW_INTERRUPT_9 = 9, //!< Software interrupt 9.
SW_INTERRUPT_10 = 10, //!< Software interrupt 10.
SW_INTERRUPT_11 = 11, //!< Software interrupt 11.
SW_INTERRUPT_12 = 12, //!< Software interrupt 12.
SW_INTERRUPT_13 = 13, //!< Software interrupt 13.
SW_INTERRUPT_14 = 14, //!< Software interrupt 14.
SW_INTERRUPT_15 = 15, //!< Software interrupt 15.
RSVD_INTERRUPT_16 = 16, //!< Reserved.
RSVD_INTERRUPT_17 = 17, //!< Reserved.
RSVD_INTERRUPT_18 = 18, //!< Reserved.
RSVD_INTERRUPT_19 = 19, //!< Reserved.
RSVD_INTERRUPT_20 = 20, //!< Reserved.
RSVD_INTERRUPT_21 = 21, //!< Reserved.
RSVD_INTERRUPT_22 = 22, //!< Reserved.
RSVD_INTERRUPT_23 = 23, //!< Reserved.
RSVD_INTERRUPT_24 = 24, //!< Reserved.
RSVD_INTERRUPT_25 = 25, //!< Reserved.
RSVD_INTERRUPT_26 = 26, //!< Reserved.
RSVD_INTERRUPT_27 = 27, //!< Reserved.
RSVD_INTERRUPT_28 = 28, //!< Reserved.
RSVD_INTERRUPT_29 = 29, //!< Reserved.
RSVD_INTERRUPT_30 = 30, //!< Reserved.
RSVD_INTERRUPT_31 = 31, //!< Reserved.
IMX_INT_IOMUXC_GPR = 32, //!< General Purpose Register 1 from IOMUXC. Used to notify cores on exception condition while boot.
IMX_INT_CHEETAH_CSYSPWRUPREQ = 33, //!< @todo Listed as DAP in RM
IMX_INT_SDMA = 34, //!< Logical OR of all 48 SDMA interrupt requests/events from all channels.
IMX_INT_VPU_JPG = 35, //!< JPEG codec interrupt request.
IMX_INT_SNVS_LP_SET_PWR_OFF = 36, //!< PMIC power off request.
IMX_INT_IPU1_ERR = 37, //!< IPU1 error interrupt request.
IMX_INT_IPU1_FUNC = 38, //!< IPU1 sync interrupt request.
IMX_INT_IPU2_ERR = 39, //!< IPU2 error interrupt request.
IMX_INT_IPU2_FUNC = 40, //!< IPU2 sync interrupt request.
IMX_INT_GPU3D = 41, //!< GPU3D interrupt request.
IMX_INT_GPU2D = 42, //!< Idle interrupt from GPU2D (for S/W power gating).
IMX_INT_OPENVG_XAQ2 = 43, //!< GPU2D general interrupt request.
IMX_INT_VPU_IPI = 44, //!< VPU interrupt request.
IMX_INT_APBHDMA = 45, //!< Logical OR of 4 signals: dma_chan[0-3]_irq, GPMI operation channel description complete interrupt.
IMX_INT_EIM = 46, //!< EIM interrupt request.
IMX_INT_BCH = 47, //!< BCH operation complete interrupt.
IMX_INT_GPMI = 48, //!< GPMI operation timeout error interrupt.
IMX_INT_DTCP = 49, //!< DTCP interrupt request.
IMX_INT_VDOA = 50, //!< Logical OR of VDOA interrupt requests.
IMX_INT_SNVS = 51, //!< SNVS consolidated interrupt.
IMX_INT_SNVS_SEC = 52, //!< SNVS security interrupt.
IMX_INT_CSU = 53, //!< CSU interrupt request 1. Indicates to the processor that one or more alarm inputs were asserted.
IMX_INT_USDHC1 = 54, //!< uSDHC1 (Enhanced SDHC) interrupt request.
IMX_INT_USDHC2 = 55, //!< uSDHC2 (Enhanced SDHC) interrupt request.
IMX_INT_USDHC3 = 56, //!< uSDHC3 (Enhanced SDHC) interrupt request.
IMX_INT_USDHC4 = 57, //!< uSDHC4 (Enhanced SDHC) interrupt request.
IMX_INT_UART1 = 58, //!< Logical OR of UART1 interrupt requests.
IMX_INT_UART2 = 59, //!< Logical OR of UART2 interrupt requests.
IMX_INT_UART3 = 60, //!< Logical OR of UART3 interrupt requests.
IMX_INT_UART4 = 61, //!< Logical OR of UART4 interrupt requests.
IMX_INT_UART5 = 62, //!< Logical OR of UART5 interrupt requests.
IMX_INT_ECSPI1 = 63, //!< eCSPI1 interrupt request.
IMX_INT_ECSPI2 = 64, //!< eCSPI2 interrupt request.
IMX_INT_ECSPI3 = 65, //!< eCSPI3 interrupt request.
IMX_INT_ECSPI4 = 66, //!< eCSPI4 interrupt request.
IMX_INT_ECSPI5 = 67, //!< eCSPI5 interrupt request.
IMX_INT_I2C1 = 68, //!< I2C1 interrupt request.
IMX_INT_I2C2 = 69, //!< I2C2 interrupt request.
IMX_INT_I2C3 = 70, //!< I2C3 interrupt request.
IMX_INT_SATA = 71, //!< SATA interrupt request.
IMX_INT_USBOH3_UH1 = 72, //!< USB Host 1 interrupt request.
IMX_INT_USBOH3_UH2 = 73, //!< USB Host 2 interrupt request.
IMX_INT_USBOH3_UH3 = 74, //!< USB Host 3 interrupt request.
IMX_INT_USBOH3_UOTG = 75, //!< USB OTG interrupt request.
IMX_INT_USB_UTMI0 = 76, //!< UTMI0 interrupt request.
IMX_INT_USB_UTMI1 = 77, //!< UTMI1 interrupt request.
IMX_INT_SSI1 = 78, //!< SSI1 interrupt request.
IMX_INT_SSI2 = 79, //!< SSI2 interrupt request.
IMX_INT_SSI3 = 80, //!< SSI3 interrupt request.
IMX_INT_TEMPERATURE = 81, //!< Temperature Sensor (temp. greater than threshold) interrupt request.
IMX_INT_ASRC = 82, //!< ASRC interrupt request.
IMX_INT_ESAI = 83, //!< ESAI interrupt request.
IMX_INT_SPDIF = 84, //!< Logical OR of SPDIF TX and SPDIF RX interrupts.
IMX_INT_MLB = 85, //!< MLB error interrupt request.
IMX_INT_PMU_ANA_BO = 86, //!< PMU analog regulator brown-out interrupt request.
IMX_INT_GPT = 87, //!< Logical OR of GPT rollover interrupt line, input capture 1 & 2 lines, output compare 1, 2 & 3 interrupt lines.
IMX_INT_EPIT1 = 88, //!< EPIT1 output compare interrupt.
IMX_INT_EPIT2 = 89, //!< EPIT2 output compare interrupt.
IMX_INT_GPIO1_INT7 = 90, //!< INT7 interrupt request.
IMX_INT_GPIO1_INT6 = 91, //!< INT6 interrupt request.
IMX_INT_GPIO1_INT5 = 92, //!< INT5 interrupt request.
IMX_INT_GPIO1_INT4 = 93, //!< INT4 interrupt request.
IMX_INT_GPIO1_INT3 = 94, //!< INT3 interrupt request.
IMX_INT_GPIO1_INT2 = 95, //!< INT2 interrupt request.
IMX_INT_GPIO1_INT1 = 96, //!< INT1 interrupt request.
IMX_INT_GPIO1_INT0 = 97, //!< INT0 interrupt request.
IMX_INT_GPIO1_INT15_0 = 98, //!< Combined interrupt indication for GPIO1 signals 0 - 15.
IMX_INT_GPIO1_INT31_16 = 99, //!< Combined interrupt indication for GPIO1 signals 16 - 31.
IMX_INT_GPIO2_INT15_0 = 100, //!< Combined interrupt indication for GPIO2 signals 0 - 15.
IMX_INT_GPIO2_INT31_16 = 101, //!< Combined interrupt indication for GPIO2 signals 16 - 31.
IMX_INT_GPIO3_INT15_0 = 102, //!< Combined interrupt indication for GPIO3 signals 0 - 15.
IMX_INT_GPIO3_INT31_16 = 103, //!< Combined interrupt indication for GPIO3 signals 16 - 31.
IMX_INT_GPIO4_INT15_0 = 104, //!< Combined interrupt indication for GPIO4 signals 0 - 15.
IMX_INT_GPIO4_INT31_16 = 105, //!< Combined interrupt indication for GPIO4 signals 16 - 31.
IMX_INT_GPIO5_INT15_0 = 106, //!< Combined interrupt indication for GPIO5 signals 0 - 15.
IMX_INT_GPIO5_INT31_16 = 107, //!< Combined interrupt indication for GPIO5 signals 16 - 31.
IMX_INT_GPIO6_INT15_0 = 108, //!< Combined interrupt indication for GPIO6 signals 0 - 15.
IMX_INT_GPIO6_INT31_16 = 109, //!< Combined interrupt indication for GPIO6 signals 16 - 31.
IMX_INT_GPIO7_INT15_0 = 110, //!< Combined interrupt indication for GPIO7 signals 0 - 15.
IMX_INT_GPIO7_INT31_16 = 111, //!< Combined interrupt indication for GPIO7 signals 16 - 31.
IMX_INT_WDOG1 = 112, //!< WDOG1 timer reset interrupt request.
IMX_INT_WDOG2 = 113, //!< WDOG2 timer reset interrupt request.
IMX_INT_KPP = 114, //!< Key Pad interrupt request.
IMX_INT_PWM1 = 115, //!< Cumulative interrupt line for PWM1. Logical OR of rollover, compare, and FIFO waterlevel crossing interrupts.
IMX_INT_PWM2 = 116, //!< Cumulative interrupt line for PWM2. Logical OR of rollover, compare, and FIFO waterlevel crossing interrupts.
IMX_INT_PWM3 = 117, //!< Cumulative interrupt line for PWM3. Logical OR of rollover, compare, and FIFO waterlevel crossing interrupts.
IMX_INT_PWM4 = 118, //!< Cumulative interrupt line for PWM4. Logical OR of rollover, compare, and FIFO waterlevel crossing interrupts.
IMX_INT_CCM_INT1 = 119, //!< CCM interrupt request 1.
IMX_INT_CCM_INT2 = 120, //!< CCM interrupt request 2.
IMX_INT_GPC_INT1 = 121, //!< GPC interrupt request 1.
IMX_INT_GPC_INT2 = 122, //!< GPC interrupt request 2.
IMX_INT_SRC = 123, //!< SRC interrupt request.
IMX_INT_CHEETAH_L2 = 124, //!< Logical OR of all L2 interrupt requests.
IMX_INT_CHEETAH_PARITY = 125, //!< Parity Check error interrupt request.
IMX_INT_CHEETAH_PERFORM = 126, //!< Logical OR of Performance Unit interrupts.
IMX_INT_CHEETAH_TRIGGER = 127, //!< Logical OR of CTI trigger outputs.
IMX_INT_SRC_CPU_WDOG = 128, //!< Combined CPU wdog interrupts (4x) out of SRC.
IMX_INT_INTERRUPT_129 = 129, //!< Reserved.
IMX_INT_INTERRUPT_130 = 130, //!< Reserved.
IMX_INT_INTERRUPT_131 = 131, //!< Reserved.
IMX_INT_CSI_INTR1 = 132, //!< MIPI CSI interrupt request 1.
IMX_INT_CSI_INTR2 = 133, //!< MIPI CSI interrupt request 2.
IMX_INT_DSI = 134, //!< MIPI DSI interrupt request.
IMX_INT_HSI = 135, //!< MIPI HSI interrupt request.
IMX_INT_SJC = 136, //!< SJC interrupt from General Purpose register.
IMX_INT_CAAM_INT0 = 137, //!< CAAM job ring 0 interrupt.
IMX_INT_CAAM_INT1 = 138, //!< CAAM job ring 1 interrupt.
IMX_INT_INTERRUPT_139 = 139, //!< Reserved.
IMX_INT_TZASC1 = 140, //!< ASC1 interrupt request.
IMX_INT_TZASC2 = 141, //!< ASC2 interrupt request.
IMX_INT_FLEXCAN1 = 142, //!< FLEXCAN1 combined interrupt. Logical OR of ini_int_busoff, ini_int_error, ipi_int_mbor, ipi_int_rxwarning, ipi_int_txwarning and ipi_int_wakein.
IMX_INT_FLEXCAN2 = 143, //!< FLEXCAN2 combined interrupt. Logical OR of ini_int_busoff, ini_int_error, ipi_int_mbor, ipi_int_rxwarning, ipi_int_txwarning and ipi_int_wakein.
IMX_INT_PERFMON1 = 144, //!< Reserved.
IMX_INT_PERFMON2 = 145, //!< Reserved.
IMX_INT_PERFMON3 = 146, //!< Reserved.
IMX_INT_HDMI_TX = 147, //!< HDMI master interrupt request.
IMX_INT_HDMI_TX_WAKEUP = 148, //!< HDMI CEC engine dedicated interrupt signal raised by a wake-up event.
IMX_INT_MLB_AHB0 = 149, //!< Channels [31:0] interrupt requests.
IMX_INT_ENET = 150, //!< MAC 0 IRQ, Logical OR of:
//! - MAC 0 Periodic Timer Overflow
//! - MAC 0 Time Stamp Available
//! - MAC 0 Payload Receive Error
//! - MAC 0 Transmit FIFO Underrun
//! - MAC 0 Collision Retry Limit
//! - MAC 0 Late Collision
//! - MAC 0 Ethernet Bus Error
//! - MAC 0 MII Data Transfer Done
//! - MAC 0 Receive Buffer Done
//! - MAC 0 Receive Frame Done
//! - MAC 0 Transmit Buffer Done
//! - MAC 0 Transmit Frame Done
//! - MAC 0 Graceful Stop
//! - MAC 0 Babbling Transmit Error
//! - MAC 0 Babbling Receive Error
//! - MAC 0 Wakeup Request [synchronous]
IMX_INT_ENET_1588 = 151, //!< MAC 0 1588 Timer interrupt [synchronous] request.
IMX_INT_PCIE_1 = 152, //!< PCIe interrupt request 1.
IMX_INT_PCIE_2 = 153, //!< PCIe interrupt request 2.
IMX_INT_PCIE_3 = 154, //!< PCIe interrupt request 3.
IMX_INT_PCIE_4 = 155, //!< PCIe interrupt request 4.
IMX_INT_DCIC1 = 156, //!< Logical OR of DCIC1 interrupt requests.
IMX_INT_DCIC2 = 157, //!< Logical OR of DCIC2 interrupt requests.
IMX_INT_MLB_AHB1 = 158, //!< Logical OR of channel[63:32] interrupt requests.
IMX_INT_PMU_DIG_BO = 159, //!< //!< PMU digital regulator brown-out interrupt request.
IMX_INTERRUPT_COUNT = 160 //!< Total number of interrupts.
};
#endif // __IRQ_NUMBERS_H__
////////////////////////////////////////////////////////////////////////////////
// EOF
////////////////////////////////////////////////////////////////////////////////

View File

@ -0,0 +1,50 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#include <stdint.h>
#include <string.h>
#include "assert.h"
#include "spinlock.h"
bool module_spinlock_use_intr_init(void)
{
return true;
}
#define SPINLOCK_STATE_UNLOCK 0xFF
enum {
SPINLOCK_LOCK_NOWAIT = 0,
SPINLOCK_LOCK_WAITFOREVER = 0xFFFFFFFF,
};
void spinlock_init(struct spinlock* lock, char* name)
{
lock->owner_cpu = SPINLOCK_STATE_UNLOCK;
strncpy(lock->name, name, 24);
}
extern int _spinlock_lock(struct spinlock* lock, uint32_t timeout);
void spinlock_lock(struct spinlock* lock)
{
if (lock->owner_cpu != SPINLOCK_STATE_UNLOCK) {
ERROR("spinlock %s lock double locked by core %d\n", lock->name, lock->owner_cpu);
panic("");
}
assert(_spinlock_lock(lock, SPINLOCK_LOCK_WAITFOREVER) == 0);
}
void _spinlock_unlock(struct spinlock* lock);
void spinlock_unlock(struct spinlock* lock)
{
_spinlock_unlock(lock);
}

View File

@ -0,0 +1,255 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file trampoline.S
* @brief trap in and out code
* @version 3.0
* @author AIIT XUOS Lab
* @date 2023.08.25
*/
/*************************************************
File name: trampoline.S.c
Description: trap in and out code
Others:
History:
1. Date: 2023-08-28
Author: AIIT XUOS Lab
Modification:
1. first version
*************************************************/
#include "memlayout.h"
#include "core.h"
.globl trap_return
.globl user_trap_swi_enter
.globl trap_irq_enter
.globl trap_reset_enter
.globl trap_iabort
.globl trap_dabort
.globl trap_undefined_instruction
.globl init_stack
trap_return:
# restore context from trapframe
ldm r13, {sp, lr}^
add r13, r13, #8
ldmfd r13!, {r14}
ldmfd r13!, {r2}
msr spsr_cxsf, r2
ldr r0, [r13], #4
ldr r1, [r13], #4
ldr r2, [r13], #4
ldr r3, [r13], #4
ldr r4, [r13], #4
ldr r5, [r13], #4
ldr r6, [r13], #4
ldr r7, [r13], #4
ldr r8, [r13], #4
ldr r9, [r13], #4
ldr r10, [r13], #4
ldr r11, [r13], #4
ldr r12, [r13], #4
ldm r13!, {pc}^
user_trap_swi_enter:
# save trapframe to swi stack
sub sp, sp, #56
str r14, [sp, #52]
str r12, [sp, #48]
str r11, [sp, #44]
str r10, [sp, #40]
str r9, [sp, #36]
str r8, [sp, #32]
str r7, [sp, #28]
str r6, [sp, #24]
str r5, [sp, #20]
str r4, [sp, #16]
str r3, [sp, #12]
str r2, [sp, #8]
str r1, [sp, #4]
str r0, [sp]
mrs r2, spsr
stmfd r13!, {r2}
stmfd r13!, {r14}
stmfd r13, {sp, lr}^
sub r13, r13, #8
# call syscall handler
mov r0, r13
bl software_irq_dispatch
b trap_return
trap_irq_enter:
# save context in irq stack
sub r14, r14, #4
sub sp, sp, #16
str r14, [sp, #12]
str r2, [sp, #8]
str r1, [sp, #4]
str r0, [sp]
mrs r1, spsr
mov r0, r13 // irq stack stop
add r13, r13, #16 // reset IRQ stack
# switch to the SVC mode
mrs r2, cpsr
bic r2, r2, #ARM_CPSR_MODE_MASK
orr r2, r2, #ARM_MODE_SVC
msr cpsr_cxsf, r2
# build the trap frame
ldr r2, [r0, #12]
stmfd r13!, {r2}
sub r13, r13, #40
str r12, [r13, #36]
str r11, [r13, #32]
str r10, [r13, #28]
str r9, [r13, #24]
str r8, [r13, #20]
str r7, [r13, #16]
str r6, [r13, #12]
str r5, [r13, #8]
str r4, [r13, #4]
str r3, [r13]
ldmfd r0, {r3-r5}
stmfd r13!, {r3-r5}
stmfd r13!, {r1}
stmfd r13!, {lr}
stmfd r13, {sp, lr}^
sub r13, r13, #8
mov r0, r13 // trapframe as parameters
bl intr_irq_dispatch
b trap_return
trap_reset_enter:
mov r14, #0
sub r13, r13, #56
str r14, [r13, #52]
str r12, [r13, #48]
str r11, [r13, #44]
str r10, [r13, #40]
str r9, [r13, #36]
str r8, [r13, #32]
str r7, [r13, #28]
str r6, [r13, #24]
str r5, [r13, #20]
str r4, [r13, #16]
str r3, [r13, #12]
str r2, [r13, #8]
str r1, [r13, #4]
str r0, [r13]
mrs r2, spsr
stmfd r13!, {r2}
stmfd r13!, {r14}
stmfd r13, {sp, lr}^
sub r13, r13, #8
mov r0, r13
bl _vector_jumper
trap_dabort:
sub r14, r14, #8
sub r13, r13, #56
str r14, [r13, #52]
str r12, [r13, #48]
str r11, [r13, #44]
str r10, [r13, #40]
str r9, [r13, #36]
str r8, [r13, #32]
str r7, [r13, #28]
str r6, [r13, #24]
str r5, [r13, #20]
str r4, [r13, #16]
str r3, [r13, #12]
str r2, [r13, #8]
str r1, [r13, #4]
str r0, [r13]
mrs r2, spsr
stmfd r13!, {r2}
stmfd r13!, {r14}
stmfd r13, {sp, lr}^
sub r13, r13, #8
mov r0, r13
bl dabort_handler
trap_iabort:
sub r14, r14, #4
sub r13, r13, #56
str r14, [r13, #52]
str r12, [r13, #48]
str r11, [r13, #44]
str r10, [r13, #40]
str r9, [r13, #36]
str r8, [r13, #32]
str r7, [r13, #28]
str r6, [r13, #24]
str r5, [r13, #20]
str r4, [r13, #16]
str r3, [r13, #12]
str r2, [r13, #8]
str r1, [r13, #4]
str r0, [r13]
mrs r2, spsr
stmfd r13!, {r2}
stmfd r13!, {r14}
stmfd r13, {sp, lr}^
sub r13, r13, #8
mov r0, r13
bl iabort_handler
trap_undefined_instruction:
sub r13, r13, #56
str r14, [r13, #52]
str r12, [r13, #48]
str r11, [r13, #44]
str r10, [r13, #40]
str r9, [r13, #36]
str r8, [r13, #32]
str r7, [r13, #28]
str r6, [r13, #24]
str r5, [r13, #20]
str r4, [r13, #16]
str r3, [r13, #12]
str r2, [r13, #8]
str r1, [r13, #4]
str r0, [r13]
mrs r2, spsr
stmfd r13!, {r2}
stmfd r13!, {r14}
stmfd r13, {sp, lr}^
sub r13, r13, #8
mov r0, r13
bl handle_undefined_instruction
init_stack:
# set the stack for Other mode
mrs r2, cpsr
bic r2, r2, #ARM_CPSR_MODE_MASK
orr r2, r2, r0
msr cpsr_cxsf, r2
# switch back to the SVC mode
mov sp, r1
bic r2, r2, #ARM_CPSR_MODE_MASK
orr r2, r2, #ARM_MODE_SVC
msr cpsr_cxsf, r2
bx lr

View File

@ -0,0 +1,240 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file trap_common.c
* @brief trap interface of hardkernel
* @version 3.0
* @author AIIT XUOS Lab
* @date 2023.08.25
*/
/*************************************************
File name: trap_common.c
Description: trap interface of hardkernel
Others:
History:
1. Date: 2023-08-28
Author: AIIT XUOS Lab
Modification:
1. first version
*************************************************/
#include <string.h>
#include "core.h"
#include "gicv2_common_opa.h"
#include "trap_common.h"
#include "log.h"
extern void init_stack(uint32_t, uint32_t);
extern void user_trap_swi_enter(void);
extern void trap_iabort(void);
extern void trap_dabort(void);
extern void trap_irq_enter(void);
extern void trap_undefined_instruction(void);
static struct XiziTrapDriver xizi_trap_driver;
void panic(char* s)
{
xizi_trap_driver.cpu_irq_disable();
KPrintf("panic: %s\n", s);
for (;;)
;
}
/* stack for different mode*/
static char mode_stack_pages[NR_CPU][NR_MODE_STACKS][MODE_STACK_SIZE];
extern uint32_t _vector_jumper;
extern uint32_t _vector_start;
extern uint32_t _vector_end;
void init_cpu_mode_stacks(int cpu_id)
{
uint32_t modes[] = { ARM_MODE_FIQ, ARM_MODE_IRQ, ARM_MODE_ABT, ARM_MODE_UND };
// initialize the stacks for different mode
for (int i = 0; i < sizeof(modes) / sizeof(uint32_t); i++) {
memset(mode_stack_pages[cpu_id][i], 0, MODE_STACK_SIZE);
init_stack(modes[i], (uint32_t)mode_stack_pages[cpu_id][i]);
}
}
void handle_reserved(void)
{
// unimplemented trap handler
LOG("Unimplemented Reserved\n");
panic("");
}
void handle_fiq(void)
{
LOG("Unimplemented FIQ\n");
panic("");
}
static void _sys_irq_init()
{
/* load exception vectors */
volatile uint32_t* vector_base = &_vector_start;
// Set Interrupt handler start address
vector_base[1] = (uint32_t)trap_undefined_instruction; // Undefined Instruction
vector_base[2] = (uint32_t)user_trap_swi_enter; // Software Interrupt
vector_base[3] = (uint32_t)trap_iabort; // Prefetch Abort
vector_base[4] = (uint32_t)trap_dabort; // Data Abort
vector_base[5] = (uint32_t)handle_reserved; // Reserved
vector_base[6] = (uint32_t)trap_irq_enter; // IRQ
vector_base[7] = (uint32_t)handle_fiq; // FIQ
init_cpu_mode_stacks(0);
/* active hardware irq responser */
gic_init();
xizi_trap_driver.switch_hw_irqtbl((uint32_t*)&_vector_jumper);
}
static void _cpu_irq_enable(void)
{
arm_set_interrupt_state(true);
}
static void _cpu_irq_disable(void)
{
arm_set_interrupt_state(false);
}
static void _single_irq_enable(int irq, int cpu, int prio)
{
gic_set_irq_priority(irq, prio);
gic_set_irq_security(irq, false); // set IRQ as non-secure
gic_set_cpu_target(irq, cpu, true);
gic_enable_irq(irq, true);
}
static void _single_irq_disable(int irq, int cpu)
{
gic_enable_irq(irq, false);
gic_set_cpu_target(irq, cpu, false);
}
#define VBAR
static inline uint32_t* _switch_hw_irqtbl(uint32_t* new_tbl_base)
{
// get old irq table base addr
uint32_t old_tbl_base = 0;
_ARM_MRC(15, 0, old_tbl_base, 12, 0, 0);
// set new irq table base addr
_ARM_MCR(15, 0, new_tbl_base, 12, 0, 0);
// set sctlr to use VBAR
uint32_t sctlr = 0;
_ARM_MRC(15, 0, sctlr, 1, 0, 0);
sctlr &= ~(1 << 13);
_ARM_MCR(15, 0, sctlr, 1, 0, 0);
return (uint32_t*)old_tbl_base;
}
static void _bind_irq_handler(int irq, irq_handler_t handler)
{
xizi_trap_driver.sw_irqtbl[irq].handler = handler;
}
static bool _send_sgi(uint32_t irq, uint32_t bitmask, enum SgiFilterType type)
{
if (bitmask > (1 << NR_CPU) - 1) {
return false;
}
enum _gicd_sgi_filter sgi_filter;
switch (type) {
case SgiFilter_TargetList:
sgi_filter = kGicSgiFilter_UseTargetList;
break;
case SgiFilter_AllOtherCPUs:
sgi_filter = kGicSgiFilter_AllOtherCPUs;
break;
default:
sgi_filter = kGicSgiFilter_OnlyThisCPU;
break;
}
gic_send_sgi(irq, bitmask, sgi_filter);
return true;
}
static uint32_t _hw_before_irq()
{
uint32_t vectNum = gic_read_irq_ack();
if (vectNum & 0x200) {
gic_write_end_of_irq(vectNum);
return 0;
}
return vectNum;
}
static uint32_t _hw_cur_int_num(uint32_t int_info)
{
return int_info & 0x1FF;
}
static uint32_t _hw_cur_int_cpu(uint32_t int_info)
{
return (int_info >> 10) & 0x7;
}
static void _hw_after_irq(uint32_t int_info)
{
gic_write_end_of_irq(int_info);
}
static int _is_interruptable(void)
{
uint32_t val;
__asm__ __volatile__(
"mrs %0, cpsr"
: "=r"(val)
:
:);
return !(val & DIS_INT);
}
static struct XiziTrapDriver xizi_trap_driver = (struct XiziTrapDriver) {
.sys_irq_init = _sys_irq_init,
.cpu_irq_enable = _cpu_irq_enable,
.cpu_irq_disable = _cpu_irq_disable,
.single_irq_enable = _single_irq_enable,
.single_irq_disable = _single_irq_disable,
.switch_hw_irqtbl = _switch_hw_irqtbl,
.bind_irq_handler = _bind_irq_handler,
.send_sgi = _send_sgi,
.is_interruptable = _is_interruptable,
.hw_before_irq = _hw_before_irq,
.hw_cur_int_num = _hw_cur_int_num,
.hw_cur_int_cpu = _hw_cur_int_cpu,
.hw_after_irq = _hw_after_irq,
};
struct XiziTrapDriver* hardkernel_intr_init(struct TraceTag* hardkernel_tag)
{
xizi_trap_driver.sys_irq_init();
xizi_trap_driver.cpu_irq_enable();
return &xizi_trap_driver;
}

View File

@ -0,0 +1,75 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file vector_table.S
* @brief define vector table function
* @version 3.0
* @author AIIT XUOS Lab
* @date 2023.08.15
*/
/*************************************************
File name: vector_table.S
Description: cortex-a9 vector table
Others:
History:
1. Date: 2023-08-28
Author: AIIT XUOS Lab
Modification:
1. first version
*************************************************/
.globl _vector_jumper
.globl _vector_start
.globl _vector_end
.global _start
.section .vectors, "ax"
.globl _vector_jumper
/* These will be relocated to VECTOR_BASE. */
_vector_jumper:
ldr pc, .LOCATION_resethandler /* 0x00: Reset */
ldr pc, .LOCATION_undefinedhandler /* 0x04: Undefined instruction */
ldr pc, .LOCATION_svchandler /* 0x08: Software interrupt */
ldr pc, .LOCATION_prefetchaborthandler /* 0x0c: Prefetch abort */
ldr pc, .LOCATION_dataaborthandler /* 0x10: Data abort */
ldr pc, .LOCATION_addrexcptnhandler /* 0x14: Address exception (reserved) */
ldr pc, .LOCATION_irqhandler /* 0x18: IRQ */
ldr pc, .LOCATION_fiqhandler /* 0x1c: FIQ */
.globl _vector_start
_vector_start:
.LOCATION_resethandler:
.long _boot_start
.LOCATION_undefinedhandler:
.long _boot_start
.LOCATION_svchandler:
.long _boot_start
.LOCATION_prefetchaborthandler:
.long _boot_start
.LOCATION_dataaborthandler:
.long _boot_start
.LOCATION_addrexcptnhandler:
.long _boot_start
.LOCATION_irqhandler:
.long _boot_start
.LOCATION_fiqhandler:
.long _boot_start
.globl _vector_end
_vector_end:
.size _vector_start, . - _vector_start
.end

View File

@ -0,0 +1,44 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file spinlock.h
* @brief spinlock header
* @version 3.0
* @author AIIT XUOS Lab
* @date 2023.08.25
*/
/*************************************************
File name: spinlock.h
Description: spinlock header
Others:
History:
1. Date: 2023-08-28
Author: AIIT XUOS Lab
Modification:
1. first version
*************************************************/
#pragma once
#include <stdbool.h>
#include <stdint.h>
#define STACK_DEPTH 32
struct spinlock { // Mutex.
uint32_t owner_cpu; // 1 for locked, 0 for unlocked
char name[28]; // The call stack (an array of program counters)
} __attribute__((aligned(32)));
bool module_spinlock_use_intr_init(void);
void spinlock_init(struct spinlock* lock, char* name);
void spinlock_lock(struct spinlock* lock);
void spinlock_unlock(struct spinlock* lock);

View File

@ -0,0 +1,103 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file trap_common.h
* @brief image vector table configuration for imx6q
* @version 3.0
* @author AIIT XUOS Lab
* @date 2023.08.25
*/
/*************************************************
File name: trap_common.h
Description: trap interface of hardkernel
Others:
History:
1. Date: 2023-08-28
Author: AIIT XUOS Lab
Modification:
1. first version
*************************************************/
#pragma once
#include <stdbool.h>
#include <stdint.h>
#include "core.h"
#include "irq_numbers.h"
#include "memlayout.h"
#include "actracer.h"
#define NR_IRQS HW_NR_IRQS
#define NR_MODE_STACKS 4
enum SgiFilterType {
SgiFilter_TargetList = 0,
SgiFilter_AllOtherCPUs = 1,
SgiFilter_OnlyThisCPU = 2,
};
typedef int (*irq_handler_t)(int irq, void* context, void* arg);
struct irq_table_entry {
irq_handler_t handler;
};
struct XiziTrapDriver {
/* irq number table*/
struct irq_table_entry sw_irqtbl[NR_IRQS];
/* current irq number happening in cpu*/
uint32_t curr_int[NR_CPU];
void (*sys_irq_init)();
void (*cpu_irq_enable)();
void (*cpu_irq_disable)();
void (*single_irq_enable)(int irq, int cpu, int prio);
void (*single_irq_disable)(int irq, int cpu);
uint32_t* (*switch_hw_irqtbl)(uint32_t*);
bool (*send_sgi)(uint32_t, uint32_t, enum SgiFilterType);
void (*bind_irq_handler)(int, irq_handler_t);
/* check if no if interruptable */
int (*is_interruptable)();
/* code runs before irq handling */
uint32_t (*hw_before_irq)();
uint32_t (*hw_cur_int_num)(uint32_t int_info);
uint32_t (*hw_cur_int_cpu)(uint32_t int_info);
/* code runs after irq handling */
void (*hw_after_irq)(uint32_t int_info);
};
struct IrqDispatcherRightGroup {
struct TraceTag intr_driver_tag;
};
struct SwiDispatcherRightGroup {
struct TraceTag intr_driver_tag;
};
struct XiziTrapDriver* hardkernel_intr_init(struct TraceTag* hardkernel_tag);
static inline int cur_cpuid(void)
{
return cpu_get_current();
}
void panic(char* s);
bool intr_distributer_init(struct IrqDispatcherRightGroup*);
void intr_irq_dispatch(struct trapframe* tf);
bool swi_distributer_init(struct SwiDispatcherRightGroup*);
void software_irq_dispatch(struct trapframe* tf);

View File

@ -1,4 +1,4 @@
SRC_FILES := imx_uart.c
SRC_DIR := arm
include $(KERNEL_ROOT)/compiler.mk

View File

@ -1,4 +1,4 @@
SRC_FILES := timer.c gpt.c epit.c
SRC_DIR := armv7-a
include $(KERNEL_ROOT)/compiler.mk

View File

@ -0,0 +1,4 @@
SRC_DIR := cortex-a9
include $(KERNEL_ROOT)/compiler.mk

View File

@ -0,0 +1,4 @@
SRC_DIR := src
include $(KERNEL_ROOT)/compiler.mk

View File

@ -0,0 +1,74 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file memlayout.h
* @brief virtual memory and physical memory layout
* @version 1.0
* @author AIIT XUOS Lab
* @date 2024-01-25
*/
/*************************************************
File name: memlayout.h
Description: virtual memory and physical memory layout
Others:
History:
1. Date: 2023-08-28
Author: AIIT XUOS Lab
Modification:
1. first version
*************************************************/
#pragma once
// Memory layout
// clang-format off
#define ARCH_BIT 32
/* A9 physical memory layout */
#define PHY_MEM_BASE (0x10000000)
#define PHY_USER_FREEMEM_BASE (0x40000000)
#define PHY_USER_FREEMEM_TOP (0x50000000)
#define PHY_MEM_STOP (0x50000000)
/* PTE-PAGE_SIZE */
#define LEVEL4_PTE_SHIFT 12
#define LEVEL4_PTE_SIZE (1 << LEVEL4_PTE_SHIFT)
/* PDE-SECTION_SIZE */
#define LEVEL3_PDE_SHIFT 20
#define LEVEL3_PDE_SIZE (1 << LEVEL3_PDE_SHIFT)
#define NUM_LEVEL3_PDE (1 << (ARCH_BIT - LEVEL3_PDE_SHIFT)) // how many PTE in a PT
#define NUM_LEVEL4_PTE (1 << (LEVEL3_PDE_SHIFT - LEVEL4_PTE_SHIFT)) // how many PTE in a PT
#define NUM_TOPLEVEL_PDE NUM_LEVEL3_PDE
#define PAGE_SIZE LEVEL4_PTE_SIZE
#define MAX_NR_FREE_PAGES ((PHY_MEM_STOP - PHY_MEM_BASE) >> LEVEL4_PTE_SHIFT)
/* User memory layout */
#define USER_STACK_SIZE PAGE_SIZE
#define USER_MEM_BASE (0x00000000)
#define USER_MEM_TOP DEV_VRTMEM_BASE
#define USER_IPC_SPACE_BASE (0x70000000)
#define USER_IPC_SPACE_TOP (USER_MEM_TOP - USER_STACK_SIZE)
/* Deivce memory layout */
#define DEV_PHYMEM_BASE (0x00000000)
#define DEV_VRTMEM_BASE (0x80000000)
#define DEV_MEM_SZ (0x10000000)
/* Kernel memory layout */
#define KERN_MEM_BASE (0x90000000) // First kernel virtual address
#define KERN_OFFSET (KERN_MEM_BASE - PHY_MEM_BASE)
// clang-format on

View File

@ -0,0 +1,106 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file mmu.h
* @brief mmu related configure and registers
* @version 1.0
* @author AIIT XUOS Lab
* @date 2024-01-25
*/
/*************************************************
File name: mmu.h
Description: mmu related configure and registers
Others:
History:
1. Date: 2023-08-28
Author: AIIT XUOS Lab
Modification:
1. first version
*************************************************/
#pragma once
#include <stdint.h>
#include "memlayout.h"
#include "page_table_entry.h"
#define PAGE_DIR_COARSE (1 << 0) // page dir entry attributes
#define PAGE_4K (1 << 1) // page table entry descriptor attributes
/*
Access permission properties.
*/
enum AccessPermission {
AccessPermission_NoAccess = 0,
AccessPermission_KernelOnly = 1,
AccessPermission_KernelUser = 3,
};
void GetDevPteAttr(uintptr_t* attr);
void GetUsrPteAttr(uintptr_t* attr);
void GetUsrDevPteAttr(uintptr_t* attr);
void GetKernPteAttr(uintptr_t* attr);
void GetPdeAttr(uintptr_t* attr);
/*
Enable MMU, cache, write buffer, etc.
*/
#define SCTLR_R(val) __asm__ volatile("mrc p15, 0, %0, c1, c0, 0" : "=r"(val))
#define SCTLR_W(val) __asm__ volatile("mcr p15, 0, %0, c1, c0, 0" ::"r"(val))
/*
Read and write mmu pagetable register base addr
*/
#define TTBR0_R(val) __asm__ volatile("mrc p15, 0, %0, c2, c0, 0" : "=r"(val))
#define TTBR0_W(val) __asm__ volatile("mcr p15, 0, %0, c2, c0, 0" ::"r"(val))
/*
TTBCR is used for choosing TTBR0 and TTBR1 as page table register.
When TTBCR is set to 0, TTBR0 is selected by default.
*/
#define TTBCR_R(val) __asm__ volatile("mrc p15, 0, %0, c2, c0, 2" : "=r"(val))
#define TTBCR_W(val) __asm__ volatile("mcr p15, 0, %0, c2, c0, 2" ::"r"(val))
/*
DACR registers are used to control memory privilage.
The 32-bit is divided into 16 fields, each of which can be 0x00(no access), 0x01(client), 0x10(reserved), or 0x11(manager).
The domain value is usually 0x01. The memory privilage will be controled by pte AP/APX
*/
#define DACR_R(val) __asm__ volatile("mrc p15, 0, %0, c3, c0, 0" : "=r"(val))
#define DACR_W(val) __asm__ volatile("mcr p15, 0, %0, c3, c0, 0" ::"r"(val))
/*
Flush TLB when loading a new page table.
@note If nG is not set in the pte attribute, process switching need flush tlb.
*/
#define CLEARTLB(val) __asm__ volatile("mcr p15, 0, %0, c8, c7, 0" ::"r"(val))
/*
When nG is set in the pte attribute, the process is assigned an ASID, which is stored in the lower 8 bits of the CONTEXTIDR register.
When the process switches, the flush TLB is no longer required anymore.
*/
#define CONTEXTIDR_R(val) __asm__ volatile("mrc p15, 0, %0, c13, c0, 1" : "=r"(val))
#define CONTEXTIDR_W(val) __asm__ volatile("mcr p15, 0, %0, c13, c0, 1" ::"r"(val))
/* virtual and physical addr translate */
#define V2P(a) ((uint32_t)((uint32_t)(a)-KERN_OFFSET))
#define P2V(a) ((void*)((void*)(a) + KERN_OFFSET))
#define V2P_WO(x) ((x)-KERN_OFFSET) // same as V2P, but without casts
#define P2V_WO(x) ((x) + KERN_OFFSET) // same as V2P, but without casts
#ifndef __ASSEMBLER__
#include <stdint.h>
__attribute__((always_inline)) static inline uint32_t v2p(void* a) { return ((uint32_t)(a)) - KERN_MEM_BASE; }
__attribute__((always_inline)) static inline void* p2v(uint32_t a) { return (void*)((a) + KERN_MEM_BASE); }
#endif

View File

@ -0,0 +1,87 @@
/*
* 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 page_table_entry.h
* @brief mmu related configure and registers
* @version 1.0
* @author AIIT XUOS Lab
* @date 2024-01-25
*/
/*************************************************
File name: page_table_entry.h
Description: mmu related configure and registers
Others: take imx_platform_sdk sdk/core/src/mmu.c for references
https://github.com/flit/imx6_platform_sdk
History:
1. Date: 2024-01-25
Author: AIIT XUOS Lab
Modification:
1. modify the L1-level page table name and properties name
*************************************************/
#pragma once
#include <stdint.h>
typedef union {
uintptr_t entry;
struct {
uint32_t desc_type : 2; // (Invalid, PageTable, Section, SuperSection)
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 section_addr : 12; // Section Physical base address
};
} __attribute__((packed)) PageDirEntry;
typedef union {
uintptr_t entry;
struct {
uint32_t desc_type : 2; // (Invalid, Large page, Small page)
uint32_t B : 1; // Bufferable
uint32_t C : 1; // Cacheable
uint32_t AP1_0 : 2;
uint32_t TEX : 3;
uint32_t AP2 : 1;
uint32_t S : 1; // Shareable
uint32_t NG : 1; // Not-global
uint32_t page_addr : 20;
};
} __attribute__((packed)) PageTblEntry;

View File

@ -0,0 +1,4 @@
SRC_FILES := bootmmu.c mmu.c pagetable_attr.c
include $(KERNEL_ROOT)/compiler.mk

View File

@ -0,0 +1,99 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file bootmmu.c
* @brief build pagetable and enable mmu in boot time
* @version 3.0
* @author AIIT XUOS Lab
* @date 2023.08.25
*/
/*************************************************
File name: bootmmu.c
Description: build pagetable and enable mmu in boot time
Others:
History:
1. Date: 2023-08-28
Author: AIIT XUOS Lab
Modification:
1. first version
*************************************************/
#include "core.h"
#include "memlayout.h"
#include "mmu.h"
#include "mmio_access.h"
#include <stdint.h>
#include <string.h>
extern uint32_t kernel_data_end[];
extern uint32_t kernel_data_begin[];
#define NR_PDE_ENTRIES 4096
#define L1_TYPE_SEC (2 << 0)
#define L1_SECT_DEV ((0b010) << 12)
#define L1_SECT_AP0 (1 << 10)
uint32_t boot_pgdir[NR_PDE_ENTRIES] __attribute__((aligned(0x4000))) = { 0 };
static void build_boot_pgdir()
{
// dev mem
uint32_t dev_mem_end_idx = (DEV_PHYMEM_BASE + DEV_MEM_SZ) >> LEVEL3_PDE_SHIFT;
for (uint32_t i = DEV_PHYMEM_BASE >> LEVEL3_PDE_SHIFT; i < dev_mem_end_idx; i++) {
boot_pgdir[i] = (i << LEVEL3_PDE_SHIFT) | L1_TYPE_SEC | L1_SECT_DEV | L1_SECT_AP0;
boot_pgdir[MMIO_P2V_WO(i << LEVEL3_PDE_SHIFT) >> LEVEL3_PDE_SHIFT] = (i << LEVEL3_PDE_SHIFT) | L1_TYPE_SEC | L1_SECT_DEV | L1_SECT_AP0;
}
// identical mem
uint32_t idn_mem_start_idx = PHY_MEM_BASE >> LEVEL3_PDE_SHIFT;
uint32_t idn_mem_end_idx = PHY_MEM_STOP >> LEVEL3_PDE_SHIFT;
for (uint32_t i = idn_mem_start_idx; i < idn_mem_end_idx; i++) {
boot_pgdir[i] = i << LEVEL3_PDE_SHIFT | L1_TYPE_SEC | L1_SECT_AP0;
}
// kern mem
uint32_t kern_mem_start_idx = KERN_MEM_BASE >> LEVEL3_PDE_SHIFT;
uint32_t kern_mem_end_idx = (KERN_MEM_BASE + (PHY_MEM_STOP - PHY_MEM_BASE)) >> LEVEL3_PDE_SHIFT;
for (uint32_t i = kern_mem_start_idx; i < kern_mem_end_idx; i++) {
boot_pgdir[i] = V2P(i << LEVEL3_PDE_SHIFT) | L1_TYPE_SEC | L1_SECT_AP0;
}
}
static void load_boot_pgdir()
{
uint32_t val;
DACR_W(0x55555555); // set domain access control as client
TTBCR_W(0x0);
TTBR0_W((uint32_t)boot_pgdir);
// Enable paging using read/modify/write
SCTLR_R(val);
val |= 0x3805; // Enable MMU, cache, write buffer, high vector tbl. Disable subpage.
SCTLR_W(val);
// flush all TLB
DSB();
CLEARTLB(0);
ISB();
}
extern void main(void);
void bootmain()
{
build_boot_pgdir();
load_boot_pgdir();
__asm__ __volatile__("add sp, sp, %0" ::"r"(KERN_MEM_BASE - PHY_MEM_BASE));
memset(&kernel_data_begin, 0x00, (uint32_t)kernel_data_end - (uint32_t)kernel_data_begin);
main();
}

View File

@ -0,0 +1,104 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file mmu.c
* @brief mmu operations
* @version 3.0
* @author AIIT XUOS Lab
* @date 2023.08.25
*/
/*************************************************
File name: mmu.c
Description: mmu operations
Others:
History:
1. Date: 2023-08-28
Author: AIIT XUOS Lab
Modification:
1. first version
*************************************************/
#include <string.h>
#include "mmu.h"
#include "cache_common_ope.h"
#include "mmu_common.h"
#include "trap_common.h"
// extern struct MmuCommonDone mmu_common_done;
static struct MmuDriverRightGroup right_group;
void load_pgdir_critical(uintptr_t pgdir_paddr, struct TraceTag* intr_driver_tag)
{
/* get cache driver */
struct ICacheDone* p_icache_done = AchieveResource(&right_group.icache_driver_tag);
struct DCacheDone* p_dcache_done = AchieveResource(&right_group.dcache_driver_tag);
/* get intr driver */
struct XiziTrapDriver* p_intr_driver = AchieveResource(intr_driver_tag);
p_intr_driver->cpu_irq_disable();
TTBR0_W((uint32_t)pgdir_paddr);
CLEARTLB(0);
p_icache_done->invalidateall();
p_dcache_done->flushall();
p_intr_driver->cpu_irq_enable();
}
void load_pgdir(uintptr_t pgdir_paddr)
{
/* get cache driver */
struct ICacheDone* p_icache_done = AchieveResource(&right_group.icache_driver_tag);
struct DCacheDone* p_dcache_done = AchieveResource(&right_group.dcache_driver_tag);
TTBR0_W((uint32_t)pgdir_paddr);
CLEARTLB(0);
p_icache_done->invalidateall();
p_dcache_done->flushall();
}
__attribute__((always_inline)) inline static void _tlb_flush(uintptr_t va)
{
__asm__ volatile("mcr p15, 0, %0, c8, c7, 1" ::"r"(va) :);
}
static void tlb_flush_range(uintptr_t vstart, int len)
{
uintptr_t vaddr = vstart;
uintptr_t vend = vaddr + len;
for (; vaddr <= vend; vaddr += PAGE_SIZE) {
_tlb_flush(vaddr);
}
}
static struct MmuCommonDone mmu_common_done = {
.MmuDevPteAttr = GetDevPteAttr,
.MmuPdeAttr = GetPdeAttr,
.MmuUsrPteAttr = GetUsrPteAttr,
.MmuUsrDevPteAttr = GetUsrDevPteAttr,
.MmuKernPteAttr = GetKernPteAttr,
.LoadPgdirCrit = load_pgdir_critical,
.LoadPgdir = load_pgdir,
.TlbFlush = tlb_flush_range,
};
struct MmuCommonDone* hardkernel_mmu_init(struct TraceTag* hardkernel_tag, char* icache_name, char* dcache_name)
{
/* init right group for mmu driver */
AchieveResourceTag(&right_group.icache_driver_tag, hardkernel_tag, icache_name);
AchieveResourceTag(&right_group.dcache_driver_tag, hardkernel_tag, dcache_name);
return &mmu_common_done;
}

View File

@ -0,0 +1,96 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file pagetable_attr.c
* @brief mmu entry attributes
* @version 3.0
* @author AIIT XUOS Lab
* @date 2023.08.25
*/
/*************************************************
File name: pagetable_attr.c
Description: mmu entry attributes
Others:
History:
1. Date: 2023-08-28
Author: AIIT XUOS Lab
Modification:
1. first version
*************************************************/
#include "mmu.h"
#include "mmu_common.h"
void GetDevPteAttr(uintptr_t* attr)
{
static char init = 0;
static PageTblEntry dev_pte_attr;
if (init == 0) {
init = 1;
dev_pte_attr.entry = 0;
dev_pte_attr.desc_type = PAGE_4K;
dev_pte_attr.AP1_0 = AccessPermission_KernelOnly;
}
*attr = dev_pte_attr.entry;
}
void GetUsrPteAttr(uintptr_t* attr)
{
static char init = 0;
static PageTblEntry usr_pte_attr;
if (init == 0) {
init = 1;
usr_pte_attr.entry = 0;
usr_pte_attr.desc_type = PAGE_4K;
usr_pte_attr.B = 1;
usr_pte_attr.C = 1;
usr_pte_attr.AP1_0 = AccessPermission_KernelUser;
}
*attr = usr_pte_attr.entry;
}
void GetUsrDevPteAttr(uintptr_t* attr)
{
static char init = 0;
static PageTblEntry usr_pte_attr;
if (init == 0) {
init = 1;
usr_pte_attr.entry = 0;
usr_pte_attr.desc_type = PAGE_4K;
usr_pte_attr.AP1_0 = AccessPermission_KernelUser;
}
*attr = usr_pte_attr.entry;
}
void GetKernPteAttr(uintptr_t* attr)
{
static char init = 0;
static PageTblEntry kern_pte_attr;
if (init == 0) {
init = 1;
kern_pte_attr.entry = 0;
kern_pte_attr.desc_type = PAGE_4K;
kern_pte_attr.B = 1;
kern_pte_attr.C = 1;
kern_pte_attr.AP1_0 = AccessPermission_KernelOnly;
}
*attr = kern_pte_attr.entry;
}
void GetPdeAttr(uintptr_t* attr)
{
*attr = PAGE_DIR_COARSE;
}

Some files were not shown because too many files have changed in this diff Show More