Compare commits

...

10 Commits

241 changed files with 17706 additions and 295713 deletions

3
.gitignore vendored
View File

@ -2,4 +2,5 @@
*.o
*libmusl.a
*liblwip.a
.DS_Store
*/build/*
.DS_Store

View File

@ -1,18 +0,0 @@
#
# Automatically generated file; DO NOT EDIT.
# XiZi_AIoT Project Configuration
#
CONFIG_BOARD_IMX6Q_SABRELITE_EVB=y
CONFIG_ARCH_ARM=y
#
# imx6q sabrelite feature
#
#
# Lib
#
CONFIG_LIB=y
CONFIG_LIB_POSIX=y
CONFIG_LIB_NEWLIB=y
# CONFIG_LIB_MUSLLIB is not set

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/imx6q/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 softkernel
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; \

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,3 @@
SRC_DIR := arch abstraction
SRC_DIR := boot mmu uart trap gpt cpu cache
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,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,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,3 @@
SRC_FILES := boot.S cache.S exception.S cortexA9.S gic.c interrupt.c mmu.c ccm_pll.c
SRC_DIR:= imx6q
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,97 +0,0 @@
#include <asm_defines.h>
.global ExceptionVectors
.section ".startup","ax"
.globl _reset
.extern init
_reset:
/* set the cpu to SVC32 mode and disable interrupt */
mrs r0, cpsr
bic r0, r0, #0x1f
orr r0, r0, #0x13
msr cpsr_c, r0
/* 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
ldr r0, =stack_top
@ get cpu id, and subtract the offset from the stacks base address
mrc p15,0,r2,c0,c0,5 @ read multiprocessor affinity register
and r2, r2, #3 @ mask off, leaving CPU ID field
mov r5, r2 @ save cpu id for later
@ Set the startup stack for svc
mov sp, r0
@ 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}
blt 1b
/* 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

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,3 +1,3 @@
SRC_FILES := schedule.c ipc.c
SRC_DIR:=
include $(KERNEL_ROOT)/compiler.mk

View File

@ -1,8 +1,8 @@
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,--gc-sections,-Map=XiZi-imx6q-sabrelite.map,-cref,-u,_boot_start -T $(KERNEL_ROOT)/hardkernel/arch/arm/armv7-a/cortex-a9/imx6q/imx6q_boot.lds
export CXXFLAGS :=
ifeq ($(CONFIG_LIB_MUSLLIB), y)
@ -11,10 +11,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

@ -0,0 +1,211 @@
/*
* 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 imx6q_boot.lds
* @brief imx6q boot 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 = 0x1000;
RAM_VECTORS_SIZE = 72;
/* Specify the memory areas */
MEMORY
{
ocram (rwx) : ORIGIN = 0x00900000, LENGTH = 256K
ddr3 (rwx) : ORIGIN = 0x27800000, LENGTH = 648M
virt_ddr3 (WRX) : ORIGIN = 0x800A0000, LENGTH = 648M
}
SECTIONS
{
. = ORIGIN(ddr3);
. = ALIGN(4);
_start_image_add = .;
.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. */
start_boot.o(.text)
boot.o(.text .text.*)
lowlevel_init.o(.text .text.*)
bootmmu.o(.text .text.*)
bootdriver.o(.text .text.*)
start_boot.o(.rodata .rodata.*)
boot.o(.rodata .rodata.*)
lowlevel_init.o(.rodata .rodata.*)
bootmmu.o(.rodata .rodata.*)
bootdriver.o(.rodata .rodata.*)
/* already initialized to zero. */
start_boot.o(.data .data.*)
boot.o(.data .data.*)
lowlevel_init.o(.data .data.*)
bootmmu.o(.data .data.*)
bootdriver.o(.data .data.*)
/* initialization start checkpoint. */
PROVIDE(boot_start_addr = .);
start_boot.o(.bss .bss.* COMMON)
boot.o(.bss .bss.* COMMON)
lowlevel_init.o(.bss .bss.* COMMON)
bootmmu.o(.bss .bss.* COMMON)
bootdriver.o(.bss .bss.* COMMON)
/* DEVBASE Coarse Page Tables (num: 2, 0x400 unit) */
. = ALIGN(0x400);
PROVIDE(_dev_pte = .);
. += 0xC000;
/* DRAM Coarse Page Tables (num: 128, 0x400 unit) */
. = ALIGN(0x400);
PROVIDE(_pte = .);
. += 0x80000;
/* stack for booting code. */
. = ALIGN(0x1000);
. += BOOT_STACK_SIZE;
PROVIDE(svc_stack = .);
/* Kernel page table. 16K */
. = ALIGN(0x4000);
PROVIDE(_kt = .);
. += 0x4000;
/* User page table. 16K */
PROVIDE(_ut = .);
. += 0x4000;
/* initialization end checkpoint. */
PROVIDE(boot_end_addr = .);
} > ddr3
/* Other Kernel code is placed over 0x80000000 + 128KB. */
.text : AT(0x278A0000) {
*(.vectors)
*(.text .text.* .gnu.linkonce.t.*)
} > virt_ddr3
. = ALIGN(0x1000);
/* Other Kernel code text checkpoint. */
PROVIDE(kern_text = .);
.data : {
*(.data .data.*)
PROVIDE(_binary_initcode_start = .);
*(.rawdata_initcode*)
PROVIDE(_binary_initcode_end = .);
PROVIDE(_binary_fs_img_start = .);
*(.rawdata_fs_img*)
PROVIDE(_binary_fs_img_end = .);
} > virt_ddr3
PROVIDE(kern_data = .);
_image_size = . - 0x80000000;
.bss : {
*(.bss .bss.* COMMON)
} > virt_ddr3
. = ALIGN(0x1000);
PROVIDE(kern_end = .);
}

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_DIR := src sdk/imx6
include $(KERNEL_ROOT)/compiler.mk

View File

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

View File

@ -0,0 +1,59 @@
/*
* 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 imx6q.h
* @brief support imx6q arch define
* @version 3.0
* @author AIIT XUOS Lab
* @date 2023.09.08
*/
#ifndef IMX6Q_H
#define IMX6Q_H
#include <arm_cp_registers.h>
#include <crm_regs.h>
#include <iomux_v3.h>
#include <registers.h>
#include <regs_anadig.h>
#include <regs_pins.h>
#include <regsuart.h>
#include <soc_memory_map.h>
#include <stddef.h>
#include <stdint.h>
#define SNVS_LPGPR_OFFSET 0x68
#define IOMUXC_GPR1_OFFSET 0x4
//! @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 _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))
#endif

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"
//#################################################
//#

View File

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

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

@ -28,6 +28,25 @@
* 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;
@ -38,7 +57,7 @@ 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"))) ={
/** @ref hdr word with tag #HAB_TAG_IVT, length and HAB version fields
@ -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,
@ -62,7 +81,8 @@ struct hab_ivt input_ivt __attribute__ ((section (".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

View File

@ -0,0 +1,7 @@
SRC_FILES := imx6q_init.c \
boot.c \
start_boot.S \
lowlevel_init.S \
vector_table.S
include $(KERNEL_ROOT)/compiler.mk

View File

@ -0,0 +1,54 @@
/*
* 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 spl_boot.c
* @brief spl boot function
* @version 3.0
* @author AIIT XUOS Lab
* @date 2023.09.07
*/
/*************************************************
File name: boot.c
Description: cortex-a9 boot function
Others:
History:
1. Date: 2023-08-28
Author: AIIT XUOS Lab
Modification:
1. first version
*************************************************/
#include "memlayout.h"
#include <mmu.h>
#include <string.h>
#include "bootdriver.h"
#include "serial.h"
extern uint32_t kern_data;
extern uint32_t kern_end;
extern void kmain(void);
void bootmain(void)
{
xizi_boot_driver_init();
__asm__ __volatile__("add sp, sp, %0" ::"r"(KERNBASE - PHYMEMBASE));
/* -- PAGING START -- */
memset(&kern_data, 0x00, (uint32_t)&kern_end - (uint32_t)&kern_data);
kmain();
}

View File

@ -0,0 +1,168 @@
/*
* 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 imx6q_init.c
* @brief imx6q init function
* @version 3.0
* @author AIIT XUOS Lab
* @date 2023.08.25
*/
/*************************************************
File name: imx6q_init.c
Description: imx6q board init function, support CPUCacheSerial
Others:
History:
1. Date: 2023-08-28
Author: AIIT XUOS Lab
Modification:
1. first version
*************************************************/
#include <imx6q.h>
#include <uart.h>
void DcacheEnable()
{
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
_ARM_DSB();
}
}
void DcacheDisable()
{
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
_ARM_DSB();
}
void IcacheEnable()
{
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
_ARM_ISB();
}
}
void IcacheDisable()
{
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
_ARM_ISB();
}
void ArchCpuInit(void)
{
int val;
/* Due to hardware limitation, on MX6Q we need to gate/ungate all PFDs
* to make sure PFD is working right, otherwise, PFDs may
* not output clock after reset, MX6DL and MX6SL have added 396M pfd
* workaround in ROM code, as bus clock need it
*/
WriteReg(BM_ANADIG_PFD_480_PFD3_CLKGATE | BM_ANADIG_PFD_480_PFD2_CLKGATE | BM_ANADIG_PFD_480_PFD1_CLKGATE | BM_ANADIG_PFD_480_PFD0_CLKGATE,
ANATOP_BASE_ADDR + HW_ANADIG_PFD_480_SET);
WriteReg(BM_ANADIG_PFD_528_PFD3_CLKGATE | BM_ANADIG_PFD_528_PFD2_CLKGATE | BM_ANADIG_PFD_528_PFD1_CLKGATE | BM_ANADIG_PFD_528_PFD0_CLKGATE,
ANATOP_BASE_ADDR + HW_ANADIG_PFD_528_SET);
WriteReg(BM_ANADIG_PFD_480_PFD3_CLKGATE | BM_ANADIG_PFD_480_PFD2_CLKGATE | BM_ANADIG_PFD_480_PFD1_CLKGATE | BM_ANADIG_PFD_480_PFD0_CLKGATE,
ANATOP_BASE_ADDR + HW_ANADIG_PFD_480_CLR);
WriteReg(BM_ANADIG_PFD_528_PFD3_CLKGATE | BM_ANADIG_PFD_528_PFD2_CLKGATE | BM_ANADIG_PFD_528_PFD1_CLKGATE | BM_ANADIG_PFD_528_PFD0_CLKGATE,
ANATOP_BASE_ADDR + HW_ANADIG_PFD_528_CLR);
IcacheEnable();
DcacheEnable();
/* Need to power down xPU in GPC before turn off PU LDO */
val = ReadReg(GPC_BASE_ADDR + GPC_PGC_GPU_PGCR_OFFSET);
WriteReg(val | 0x1, GPC_BASE_ADDR + GPC_PGC_GPU_PGCR_OFFSET);
val = ReadReg(GPC_BASE_ADDR + GPC_CNTR_OFFSET);
WriteReg(val | 0x1, GPC_BASE_ADDR + GPC_CNTR_OFFSET);
while (ReadReg(GPC_BASE_ADDR + GPC_CNTR_OFFSET) & 0x1)
;
/* Increase the VDDSOC to 1.2V and disable VDDPU */
val = REG_RD(ANATOP_BASE_ADDR, HW_ANADIG_REG_CORE);
val &= ~BM_ANADIG_REG_CORE_REG2_TRG;
val &= ~BM_ANADIG_REG_CORE_REG1_TRG;
val |= BF_ANADIG_REG_CORE_REG2_TRG(0x14);
REG_WR(ANATOP_BASE_ADDR, HW_ANADIG_REG_CORE, val);
/* Need to power down PCIe */
val = REG_RD(IOMUXC_BASE_ADDR, IOMUXC_GPR1_OFFSET);
val |= (0x1 << 18);
REG_WR(IOMUXC_BASE_ADDR, IOMUXC_GPR1_OFFSET, val);
// /*clear PowerDown Enable bit of WDOGx_WMCR*/
// WriteReg(0, WDOG1_BASE_ADDR + 0x08);
// WriteReg(0, WDOG2_BASE_ADDR + 0x08);
}
void ArchDriverInit(void)
{
mxc_iomux_v3_init((void*)IOMUXC_BASE_ADDR);
InitUart(UART_INSTANCE, UART_BAUD_RATE);
}

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 lowlevel_init.S
* @brief support imx6q lowlevel init function
* @version 3.0
* @author AIIT XUOS Lab
* @date 2023.08.15
*/
/*************************************************
File name: 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

@ -0,0 +1,55 @@
/*
* 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 start_boot.S
* @brief boot function
* @version 3.0
* @author AIIT XUOS Lab
* @date 2023.08.15
*/
/*************************************************
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
*************************************************/
.global _boot_start
.global CpuInitCrit
_boot_start:
@ msr CPSR_cxsf, #(SVC_MODE|NO_INT)
mrs r0, cpsr /*Enter SVC mode*/
bic r0, r0, #0x1f
orr r0, r0, #0xd3
msr cpsr,r0
bl CpuInitCrit
ldr r1, =boot_start_addr
ldr r2, =boot_end_addr
mov r3, #0
1:
cmp r1, r2
stmltia r1!, {r3}
blt 1b
ldr sp, =svc_stack
bl bootmain
b .

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, .Lresethandler /* 0x00: Reset */
ldr pc, .Lundefinedhandler /* 0x04: Undefined instruction */
ldr pc, .Lsvchandler /* 0x08: Software interrupt */
ldr pc, .Lprefetchaborthandler /* 0x0c: Prefetch abort */
ldr pc, .Ldataaborthandler /* 0x10: Data abort */
ldr pc, .Laddrexcptnhandler /* 0x14: Address exception (reserved) */
ldr pc, .Lirqhandler /* 0x18: IRQ */
ldr pc, .Lfiqhandler /* 0x1c: FIQ */
.globl _vector_start
_vector_start:
.Lresethandler:
.long _boot_start
.Lundefinedhandler:
.long _boot_start
.Lsvchandler:
.long _boot_start
.Lprefetchaborthandler:
.long _boot_start
.Ldataaborthandler:
.long _boot_start
.Laddrexcptnhandler:
.long _boot_start
.Lirqhandler:
.long _boot_start
.Lfiqhandler:
.long _boot_start
.globl _vector_end
_vector_end:
.size _vector_start, . - _vector_start
.end

View File

@ -0,0 +1,2 @@
SRC_FILES :=l1cache.c l2cc_pl310.c cache.c
include $(KERNEL_ROOT)/compiler.mk

View File

@ -0,0 +1,305 @@
/*
* 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 cache
* @version: 3.0
* @author: AIIT XUOS Lab
* @date: 2023/11/6
*
*/
#include "bootdriver.h"
#include "irq_numbers.h"
#include "trap.h"
#include "serial.h"
#include "cache.h"
#include "l1cache.h"
#include "l2cc.h"
/****************************************************************************
* Public Functions
****************************************************************************/
struct ICacheDone
{
void (*enable) (void );
void (*disable) (void);
void (*invalidate) (uintptr_t start, uintptr_t end);
void (*invalidateall) (void );
};
struct ICacheDone icache_done =
{
.enable = enable_icache,
.disable = disable_icache,
.invalidate = invalidate_icache,
.invalidateall = invalidate_icache_all,
};
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 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,
};
/****************************************************************************
* 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.
*
****************************************************************************/
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.
*
****************************************************************************/
void invalidate_dcache_all(void)
{
InvalidateL1DcacheAll();
InvalidateL2CacheAll();
}
/****************************************************************************
* Name: invalidate_icache
*
* Description:
* Invalidate the instruction cache within the specified region.
*
****************************************************************************/
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
*
****************************************************************************/
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.
*
****************************************************************************/
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.
*
****************************************************************************/
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.
*
****************************************************************************/
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.
*
****************************************************************************/
void flush_dcache_all(void)
{
FlushL1DcacheAll();
FlushL2CacheAll();
}
/****************************************************************************
* Name: enable_icache
*
* Description:
* Enable the I-Cache
*
****************************************************************************/
void enable_icache(void)
{
EnableL1Icache();
}
/****************************************************************************
* Name: disable_icache
*
* Description:
* Disable the I-Cache
*
****************************************************************************/
void disable_icache(void)
{
DisableL1Icache();
}
/****************************************************************************
* Name: enable_dcache
*
* Description:
* Enable the D-Cache
*
****************************************************************************/
void enable_dcache(void)
{
EnableL1Dcache();
EnableL2Cache();
}
/****************************************************************************
* Name: disable_dcache
*
* Description:
* Disable the D-Cache
*
****************************************************************************/
void disable_dcache(void)
{
FlushL1DcacheAll();
pl310_flush_all();
DisableL1Dcache();
DisableL2Cache();
}
extern int system_tick;
void test_cache(void)
{
int *block = (int *)kalloc();
block = (int *)kalloc();
block = (int *)kalloc();
block = (int *)kalloc();
block = (int *)kalloc();
int size=10000;
xizi_trap_driver.cpu_irq_disable();
enable_icache();
enable_dcache();
xizi_trap_driver.cpu_irq_enable();
for (int i=0;i<2;i++)
{
KPrintf("start.\r\n");
// xizi_trap_driver.cpu_irq_disable();
// enable_dcache();
// xizi_trap_driver.cpu_irq_enable();
int temp=0;
int tick0=system_tick;
for(int i = 0; i < size; ++i)
{
block[i]=0;
temp += block[i];
}
int tick1=system_tick;
KPrintf("tick1:%d.\r\n",tick1-tick0);
temp = 0;
tick1=system_tick;
for(int i = 0; i < size; ++i)
temp += block[i];
int tick2=system_tick;
KPrintf("tick2:%d.\r\n",tick2-tick1);
xizi_trap_driver.cpu_irq_disable();
flush_dcache_all();
xizi_trap_driver.cpu_irq_enable();
KPrintf("ok.\r\n");
}
}

View File

@ -0,0 +1,138 @@
/****************************************************************************
* arch/arm/src/armv7-a/cp15_coherent_dcache.S
*
* Copyright (C) 2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Portions of this file derive from Atmel sample code for the SAMA5D3
* Cortex-A5 which also has a modified BSD-style license:
*
* Copyright (c) 2012, Atmel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor Atmel nor the names of the contributors may
* be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/* References:
*
* "Cortex-A5 MPCore, Technical Reference Manual", Revision: r0p1,
* Copyright (c) 2010 ARM. All rights reserved. ARM DDI 0434B (ID101810)
* "ARM Architecture Reference Manual, ARMv7-A and ARMv7-R edition",
* Copyright (c) 1996-1998, 2000, 2004-2012 ARM. All rights reserved. ARM
* DDI 0406C.b (ID072512)
*/
/****************************************************************************
* Included Files
****************************************************************************/
#include "cp15.h"
.file "cp15_coherent_dcache.S"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Public Symbols
****************************************************************************/
.globl cp15_coherent_dcache
/****************************************************************************
* Public Functions
****************************************************************************/
.text
/****************************************************************************
* Name: cp15_coherent_dcache
*
* Description:
* Ensure that the I and D caches are coherent within specified region
* by cleaning the D cache (i.e., flushing the D cache contents to memory
* and invalidating the I cache. This is typically used when code has been
* written to a memory region, and will be executed.
*
* Input Parameters:
* start - virtual start address of region
* end - virtual end address of region + 1
*
* Returned Value:
* None
*
****************************************************************************/
.globl cp15_coherent_dcache
.type cp15_coherent_dcache, function
cp15_coherent_dcache:
mrc CP15_CTR(r3) /* Read the Cache Type Register */
lsr r3, r3, #16 /* Isolate the DMinLine field */
and r3, r3, #0xf
mov r2, #4
mov r2, r2, lsl r3 /* Get the cache line size in bytes */
sub r3, r2, #1 /* R3=Cache line size mask */
bic r12, r0, r3 /* R12=aligned start address */
/* Loop, flushing each D cache line to memory */
1:
mcr CP15_DCCMVAU(r12) /* Clean data or unified cache line by VA to PoU */
add r12, r12, r2 /* R12=Next cache line */
cmp r12, r1 /* Loop until all cache lines have been cleaned */
blo 1b
dsb
mrc CP15_CTR(r3) /* Read the Cache Type Register */
and r3, r3, #0xf /* Isolate the IminLine field */
mov r2, #4
mov r2, r2, lsl r3 /* Get the cache line size in bytes */
sub r3, r2, #1 /* R3=Cache line size mask */
bic r12, r0, r3 /* R12=aligned start address */
/* Loop, invalidating each I cache line to memory */
1:
mcr CP15_ICIMVAU(r12) /* Invalidate instruction cache by VA to PoU */
add r12, r12, r2 /* R12=Next cache line */
cmp r12, r1 /* Loop until all cache lines have been invalidated */
blo 1b
mov r0, #0
mcr CP15_BPIALLIS(r0) /* Invalidate entire branch predictor array Inner Shareable */
mcr CP15_BPIALL(r0) /* Invalidate entire branch predictor array Inner Shareable */
dsb
isb
bx lr
.size cp15_coherent_dcache, . - cp15_coherent_dcache
.end

View File

@ -0,0 +1,293 @@
/*
* 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: l1cache.c
* @brief: the general management of L1 cache
* @version: 3.0
* @author: AIIT XUOS Lab
* @date: 2023/11/6
*
*/
#include "l1cache.h"
void InvalidateL1Dcache(uintptr_t start, uintptr_t end)
{
size_t length=end-start;
void* addr=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 = (const void *) ((uint32_t)addr + line_size);
} while (addr < end_addr);
// All Cache, Branch predictor and TLB maintenance operations before followed instruction complete
_ARM_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
_ARM_DSB();
}
void CleanL1Dcache(uintptr_t start, uintptr_t end)
{
void* addr=start;
size_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 = (const void *) ((uint32_t)addr + line_size);
} while (addr < end_addr);
// All Cache, Branch predictor and TLB maintenance operations before followed instruction complete
_ARM_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
_ARM_DSB();
}
void FlushL1Dcache(uintptr_t start, uintptr_t end)
{
void* addr=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 = (const void *) ((uint32_t)addr + line_size);
} while (addr < end_addr);
// All Cache, Branch predictor and TLB maintenance operations before followed instruction complete
_ARM_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
_ARM_DSB();
}
void InvalidateL1IcacheAll()
{
uint32_t SBZ = 0x0u;
_ARM_MCR(15, 0, SBZ, 7, 5, 0);
// synchronize context on this processor
_ARM_ISB();
}
void InvalidateL1Icache(uintptr_t start, uintptr_t end)
{
void* addr=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 = (const void *) ((uint32_t)addr + line_size);
} while (addr < end_addr);
// synchronize context on this processor
_ARM_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
_ARM_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
_ARM_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
_ARM_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
_ARM_DSB();
}

View File

@ -0,0 +1,132 @@
/*
* 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: l1cache.h
* @brief: the general management of L1 cache
* @version: 3.0
* @author: AIIT XUOS Lab
* @date: 2023/4/27
*
*/
#include <stdint.h>
#include <sys/types.h>
#include "cortex_a9.h"
/* Terms:
* 1) Point of coherency (PoC)
* The PoC is the point at which all agents that can access memory are
* guaranteed to see the same copy of a memory location
* 2) Point of unification (PoU)
* The PoU is the point by which the instruction and data caches and the
* translation table walks of the processor are guaranteed to see the same
* copy of a memory location.
*
* L1 Cache Operations:
*
* CP15 Register: ICIALLUIS
* Description: Invalidate entire instruction cache Inner Shareable.
* Register Format: Should be zero (SBZ)
* Instruction: MCR p15, 0, <Rd>, c7, c1, 0
* CP15 Register: BPIALLIS
* Description: Invalidate entire branch predictor array Inner
* Shareable.
* Register Format: Should be zero (SBZ)
* Instruction: MCR p15, 0, <Rd>, c7, c1, 6
* CP15 Register: ICIALLU
* Description: Invalidate all instruction caches to PoU. Also flushes
* branch target cache.
* Register Format: Should be zero (SBZ)
* Instruction: MCR p15, 0, <Rd>, c7, c5, 0
* CP15 Register: ICIMVAU
* Description: Invalidate instruction cache by VA to PoU.
* Register Format: VA
* Instruction: MCR p15, 0, <Rd>, c7, c5, 1
* CP15 Register: CP15ISB
* Description: Instruction Synchronization Barrier operation
* NOTE: Deprecated and no longer documented
* Instruction: MCR p15, 0, <Rd>, c7, c5, 4
* CP15 Register: BPIALL
* Description: Invalidate entire branch predictor array.
* Register Format: Should be zero (SBZ)
* Instruction: MCR p15, 0, <Rd>, c7, c5, 6
* CP15 Register: BPIMVA
* Description: Invalidate VA from branch predictor array.
* Register Format: Should be zero (SBZ)
* Instruction: MCR p15, 0, <Rd>, c7, c5, 7
* CP15 Register: DCIMVAC
* Description: Invalidate data cache line by VA to PoC.
* Register Format: VA
* Instruction: MCR p15, 0, <Rd>, c7, c6, 1
* CP15 Register: DCISW
* Description: Invalidate data cache line by Set/Way.
* Register Format: Set/Way
* Instruction: MCR p15, 0, <Rd>, c7, c6, 2
* CP15 Register: DCCMVAC
* Description: Clean data cache line to PoC by VA.
* Register Format: VA
* Instruction: MCR p15, 0, <Rd>, c7, c10, 1
* CP15 Register: DCCSW
* Description: Clean data cache line by Set/Way.
* Register Format: Set/Way
* Instruction: MCR p15, 0, <Rd>, c7, c10, 2
* CP15 Register: CP15DSB
* Description: Data Synchronization Barrier operation
* NOTE: Deprecated and no longer documented
* Instruction: MCR p15, 0, <Rd>, c7, c10, 4
* CP15 Register: CP15DMB
* Description: Data Memory Barrier operation
* NOTE: Deprecated and no longer documented
* Instruction: MCR p15, 0, <Rd>, c7, c10, 5
* CP15 Register: DCCMVAU
* Description: Clean data or unified cache line by VA to PoU.
* Register Format: VA
* Instruction: MCR p15, 0, <Rd>, c7, c11, 1
* CP15 Register: DCCIMVAC
* Description: Clean and invalidate data cache line by VA to PoC.
* Register Format: VA
* Instruction: MCR p15, 0, <Rd>, c7, c14, 1
* CP15 Register: DCCISW
* Description: Clean and invalidate data cache line by Set/Way.
* Register Format: Set/Way
* Instruction: MCR p15, 0, <Rd>, c7, c14, 2
*/
#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,180 @@
/*
* 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 l2cc.h
* @brief the general management of L2 cache
* @version 3.0
* @author AIIT XUOS Lab
* @date 2023.8.10
*/
/****************************************************************************
* Included Files
****************************************************************************/
#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,745 @@
/*
* 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 l2cc_pl310.c
* @brief the general management of L2 cache
* @version 3.0
* @author AIIT XUOS Lab
* @date 2023.8.10
*/
#include <stdint.h>
#include <assert.h>
#include <imx6q.h>
#include "l2cc.h"
#include "l2cc_pl310.h"
#include "serial.h"
#define CONFIG_ARMV7A_ASSOCIATIVITY_16WAY
#define CONFIG_ARMV7A_WAYSIZE_16KB
#define getreg8(a) (*(volatile uint8_t *)(a))
#define putreg8(v,a) (*(volatile uint8_t *)(a) = (v))
#define getreg16(a) (*(volatile uint16_t *)(a))
#define putreg16(v,a) (*(volatile uint16_t *)(a) = (v))
#define getreg32(a) (*(volatile uint32_t *)(a))
#define putreg32(v,a) (*(volatile uint32_t *)(a) = (v))
#ifdef CONFIG_HAVE_FILENAME
# define PANIC() _assert(__FILE__, __LINE__)
#else
# define PANIC() _assert("unknown", 0)
#endif
#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)
{
/* Flush all ways by writing the set of ways to be cleaned to the Clean
* Invalidate Way Register (CIWR).
*/
putreg32(PL310_WAY_MASK, L2CC_CIWR);
/* Wait for cache operation by way to complete */
// uint32_t res=*(volatile uint32_t *)(L2CC_CIWR); // 0x00a027fc
// KPrintf("%d\r\n",res);
while ((getreg32(L2CC_CIWR) & PL310_WAY_MASK) != 0){}
/* Drain the STB. Operation complete when all buffers, LRB, LFB, STB, and
* EB, are empty.
*/
putreg32(0, L2CC_CSR);
// KPrintf("%d\r\n",res);
}
/****************************************************************************
* 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;
/* Make sure that this is a PL310 cache, version r3p2.
*
* REVISIT: The SAMA5D4 is supposed to report its ID as 0x410000C8 which
* is r3p2, but the chip that I have actually* reports 0x410000C9 which
* is some later revision.
*/
/* DEBUGASSERT((getreg32(L2CC_IDR) & L2CC_IDR_REV_MASK) ==
* L2CC_IDR_REV_R3P2);
*/
/* Make sure that actual cache configuration agrees with the configured
* cache configuration.
*/
#if defined(CONFIG_ARMV7A_ASSOCIATIVITY_8WAY)
DEBUGASSERT((getreg32(L2CC_ACR) & L2CC_ACR_ASS) == 0);
#elif defined(CONFIG_ARMV7A_ASSOCIATIVITY_16WAY)
DEBUGASSERT((getreg32(L2CC_ACR) & L2CC_ACR_ASS) == L2CC_ACR_ASS);
#else
# error No associativity selected
#endif
#if defined(CONFIG_ARMV7A_WAYSIZE_16KB)
DEBUGASSERT((getreg32(L2CC_ACR) & L2CC_ACR_WAYSIZE_MASK) ==
L2CC_ACR_WAYSIZE_16KB);
#elif defined(CONFIG_ARMV7A_WAYSIZE_32KB)
DEBUGASSERT((getreg32(L2CC_ACR) & L2CC_ACR_WAYSIZE_MASK) ==
L2CC_ACR_WAYSIZE_32KB);
#elif defined(CONFIG_ARMV7A_WAYSIZE_64KB)
DEBUGASSERT((getreg32(L2CC_ACR) & L2CC_ACR_WAYSIZE_MASK) ==
L2CC_ACR_WAYSIZE_64KB);
#elif defined(CONFIG_ARMV7A_WAYSIZE_128KB)
DEBUGASSERT((getreg32(L2CC_ACR) & L2CC_ACR_WAYSIZE_MASK) ==
L2CC_ACR_WAYSIZE_128KB);
#elif defined(CONFIG_ARMV7A_WAYSIZE_256KB)
DEBUGASSERT((getreg32(L2CC_ACR) & L2CC_ACR_WAYSIZE_MASK) ==
L2CC_ACR_WAYSIZE_256KB);
#elif defined(CONFIG_ARMV7A_WAYSIZE_512KB)
DEBUGASSERT((getreg32(L2CC_ACR) & L2CC_ACR_WAYSIZE_MASK) ==
L2CC_ACR_WAYSIZE_512KB);
#else
# error No way size selected
#endif
/* L2 configuration can only be changed if the cache is disabled,
*
* NOTE: This register access will fail if we are not in secure more.
*/
if ((getreg32(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);
putreg32(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);
putreg32(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;
putreg32(regval, L2CC_FLEND);
regval = (CONFIG_PL310_FLSTRT & L2CC_FLSTRT_MASK) | L2CC_FLSTRT_ENABLE;
putreg32(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++)
{
putreg32(0, L2CC_DLKR(i));
putreg32(0, L2CC_ILKR(i));
}
/* Configure the cache properties */
regval = getreg32(L2CC_ACR);
regval &= ~L2CC_ACR_CONFIGMASK;
regval |= L2CC_ACR_CONFIG;
putreg32(regval, L2CC_ACR);
/* Invalidate and enable the cache */
InvalidateL2CacheAll();
putreg32(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)
{
/* Invalidate and enable the cache (must be disabled to do this!) */
//KPrintf("L2 cache\n");
InvalidateL2CacheAll();
putreg32(L2CC_CR_L2CEN, L2CC_CR);
}
/****************************************************************************
* Name: l2cc_disable
*
* Description:
* Disable the L2CC-P310 L2 cache by clearing the Control Register (CR)
*
*
****************************************************************************/
void DisableL2Cache(void)
{
putreg32(0, L2CC_CR);
_ARM_DSB();
}
/****************************************************************************
* Name: l2cc_sync
*
* Description:
* Drain the STB. Operation complete when all buffers, LRB, LFB, STB, and
* EB, are empty.
*
****************************************************************************/
void SyncL2Cache(void)
{
putreg32(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 = getreg32(L2CC_CR);
DisableL2Cache();
/* Invalidate all ways by writing the bit mask of ways to be invalidated
* the Invalidate Way Register (IWR).
*/
putreg32(PL310_WAY_MASK, L2CC_IWR);
/* Wait for cache operation by way to complete */
//KPrintf("wait invalidate\n");
while ((getreg32(L2CC_IWR) & PL310_WAY_MASK) != 0);
/* Drain the STB. Operation complete when all buffers, LRB, LFB, STB, and
* EB, are empty.
*/
putreg32(0, L2CC_CSR);
/* Then re-enable the L2 cache if it was enabled before */
putreg32(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;
putreg32(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;
putreg32(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).
*/
putreg32(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.
*/
putreg32(0, L2CC_CSR);
}
/****************************************************************************
* Name: l2cc_clean_all
*
* Description:
* Clean all ways by using the Clean Ways Register (CWR).
*
****************************************************************************/
void CleanL2CacheAll(void)
{
putreg32(PL310_WAY_MASK, L2CC_CWR);
/* Wait for cache operation by way to complete */
while ((getreg32(L2CC_CWR) & PL310_WAY_MASK) != 0);
/* Drain the STB. Operation complete when all buffers, LRB, LFB, STB, and
* EB, are empty.
*/
putreg32(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).
*/
putreg32(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.
*/
putreg32(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).
*/
putreg32(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.
*/
putreg32(0, L2CC_CSR);
}

View File

@ -0,0 +1,483 @@
/****************************************************************************
* 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<6E> Level 2 Cache Controller L2C-310", Revision r3p2,
* Technical Reference Manual, ARM DDI 0246F (ID011711), ARM
*/
#ifndef __ARCH_ARM_SRC_ARMV7_A_L2CC_PL310_H
#define __ARCH_ARM_SRC_ARMV7_A_L2CC_PL310_H
/****************************************************************************
* Included Files
****************************************************************************/
/****************************************************************************
* 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 (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 */
#endif /* __ARCH_ARM_SRC_ARMV7_A_L2CC_PL310_H */

View File

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

View File

@ -0,0 +1,152 @@
#pragma once
// Interrupt control bits
#define NO_INT 0xc0 // disable IRQ.
#define DIS_INT 0x80 // disable both IRQ and FIQ.
// ARM modes.
#define MODE_MASK 0x1f
#define USR_MODE 0x10
#define FIQ_MODE 0x11
#define IRQ_MODE 0x12
#define SVC_MODE 0x13
#define ABT_MODE 0x17
#define UND_MODE 0x1b
#define SYS_MODE 0x1f
// vector table
#define TRAP_RESET 0
#define TRAP_UND 1
#define TRAP_SWI 2
#define TRAP_IABT 3
#define TRAP_DABT 4
#define TRAP_NA 5
#define TRAP_IRQ 6
#define TRAP_FIQ 7
#ifndef __ASSEMBLER__
#include "memlayout.h"
#include <stdint.h>
#define NR_CPU 4
#define DMB() __asm__ __volatile__("dmb" ::: "memory")
__attribute__((always_inline)) static inline uint32_t spsr_usr()
{
uint32_t val;
__asm__ __volatile__(
"mrs %0, cpsr"
: "=r"(val)
:
:);
val &= ~DIS_INT;
val &= ~MODE_MASK;
val |= USR_MODE;
return val;
}
__attribute__((always_inline)) static inline int is_int()
{
uint32_t val;
__asm__ __volatile__(
"mrs %0, cpsr"
: "=r"(val)
:
:);
return !(val & DIS_INT);
}
__attribute__((always_inline)) static inline void flush_tlb(void)
{
uint32_t val = 0;
__asm__ __volatile__("mcr p15, 0, %0, c8, c7, 0" : : "r"(val) :);
// invalid entire data and instruction cache
__asm__ __volatile__("mcr p15, 0, %0, c7, c10, 0" : : "r"(val) :);
__asm__ __volatile__("mcr p15, 0, %0, c7, c11, 0" : : "r"(val) :);
}
__attribute__((always_inline)) static inline uint32_t ldrex(volatile uint32_t* addr)
{
// Load link.
uint32_t res;
__asm__ __volatile__(
"ldrex %0, [%1]\n"
: "=&r"(res)
: "r"(addr)
: "memory", "cc");
return res;
}
__attribute__((always_inline)) static inline uint32_t strex(volatile uint32_t* addr, uint32_t newval)
{
// Load link.
uint32_t res;
__asm__ __volatile__(
" strex %0, %1, [%2]\n"
: "=&r"(res)
: "r"(newval), "r"(addr)
: "memory", "cc");
return res;
}
__attribute__((always_inline)) static inline uint32_t xchg(volatile uint32_t* addr, uint32_t newval)
{
// reference:
// https://github.com/torvalds/linux/blob/master/arch/arm/include/asm/atomic.h
// https://github.com/torvalds/linux/blob/master/arch/arm/include/asm/cmpxchg.h
uint32_t res, tmp;
__asm__ __volatile__(
"1: ldrex %0, [%3]\n"
" strex %1, %2, [%3]\n"
" cmp %1, #0\n"
" bne 1b"
: "=&r"(res), "=&r"(tmp)
: "r"(newval), "r"(addr)
: "memory", "cc");
return res;
}
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;
};
struct trapframe {
uint32_t sp_usr; // user mode sp
uint32_t lr_usr; // user mode lr
uint32_t r14_svc; // r14_svc (r14_svc == pc if SWI)
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; // (lr on entry) instruction to resume execution
};
#endif

View File

@ -0,0 +1,584 @@
/*
* Copyright (C) 2010-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 crm_regs.h
* @brief support imx6q clock control module define, reference from u-boot-2009-08/cpu/arm_cortexa8/mx6/crm_regs.h
* @version 3.0
* @author AIIT XUOS Lab
* @date 2023.09.08
*/
#ifndef __ARCH_ARM_MACH_MX6_CRM_REGS_H__
#define __ARCH_ARM_MACH_MX6_CRM_REGS_H__
#define MXC_CCM_BASE CCM_BASE_ADDR
/* Register addresses of CCM*/
#define MXC_CCM_CCR (MXC_CCM_BASE + 0x00)
#define MXC_CCM_CCDR (MXC_CCM_BASE + 0x04)
#define MXC_CCM_CSR (MXC_CCM_BASE + 0x08)
#define MXC_CCM_CCSR (MXC_CCM_BASE + 0x0C)
#define MXC_CCM_CACRR (MXC_CCM_BASE + 0x10)
#define MXC_CCM_CBCDR (MXC_CCM_BASE + 0x14)
#define MXC_CCM_CBCMR (MXC_CCM_BASE + 0x18)
#define MXC_CCM_CSCMR1 (MXC_CCM_BASE + 0x1C)
#define MXC_CCM_CSCMR2 (MXC_CCM_BASE + 0x20)
#define MXC_CCM_CSCDR1 (MXC_CCM_BASE + 0x24)
#define MXC_CCM_CS1CDR (MXC_CCM_BASE + 0x28)
#define MXC_CCM_CS2CDR (MXC_CCM_BASE + 0x2C)
#define MXC_CCM_CDCDR (MXC_CCM_BASE + 0x30)
#define MXC_CCM_CHSCDR (MXC_CCM_BASE + 0x34)
#define MXC_CCM_CSCDR2 (MXC_CCM_BASE + 0x38)
#define MXC_CCM_CSCDR3 (MXC_CCM_BASE + 0x3C)
#define MXC_CCM_CSCDR4 (MXC_CCM_BASE + 0x40)
#define MXC_CCM_CWDR (MXC_CCM_BASE + 0x44)
#define MXC_CCM_CDHIPR (MXC_CCM_BASE + 0x48)
#define MXC_CCM_CDCR (MXC_CCM_BASE + 0x4C)
#define MXC_CCM_CTOR (MXC_CCM_BASE + 0x50)
#define MXC_CCM_CLPCR (MXC_CCM_BASE + 0x54)
#define MXC_CCM_CISR (MXC_CCM_BASE + 0x58)
#define MXC_CCM_CIMR (MXC_CCM_BASE + 0x5C)
#define MXC_CCM_CCOSR (MXC_CCM_BASE + 0x60)
#define MXC_CCM_CGPR (MXC_CCM_BASE + 0x64)
#define MXC_CCM_CCGR0 (MXC_CCM_BASE + 0x68)
#define MXC_CCM_CCGR1 (MXC_CCM_BASE + 0x6C)
#define MXC_CCM_CCGR2 (MXC_CCM_BASE + 0x70)
#define MXC_CCM_CCGR3 (MXC_CCM_BASE + 0x74)
#define MXC_CCM_CCGR4 (MXC_CCM_BASE + 0x78)
#define MXC_CCM_CCGR5 (MXC_CCM_BASE + 0x7C)
#define MXC_CCM_CCGR6 (MXC_CCM_BASE + 0x80)
#define MXC_CCM_CCGR7 (MXC_CCM_BASE + 0x80)
#define MXC_CCM_CMEOR (MXC_CCM_BASE + 0x88)
/* Define the bits in register CCR */
#define MXC_CCM_CCR_RBC_EN (1 << 27)
#define MXC_CCM_CCR_REG_BYPASS_CNT_MASK (0x3F << 21)
#define MXC_CCM_CCR_REG_BYPASS_CNT_OFFSET (21)
#define MXC_CCM_CCR_WB_COUNT_MASK (0x7)
#define MXC_CCM_CCR_WB_COUNT_OFFSET (1 << 16)
#define MXC_CCM_CCR_COSC_EN (1 << 12)
#define MXC_CCM_CCR_OSCNT_MASK (0xFF)
#define MXC_CCM_CCR_OSCNT_OFFSET (0)
/* Define the bits in register CCDR */
#define MXC_CCM_CCDR_MMDC_CH1_HS_MASK (1 << 16)
#define MXC_CCM_CCDR_MMDC_CH0_HS_MASK (1 << 17)
/* Define the bits in register CSR */
#define MXC_CCM_CSR_COSC_READY (1 << 5)
#define MXC_CCM_CSR_REF_EN_B (1 << 0)
/* Define the bits in register CCSR */
#define MXC_CCM_CCSR_PDF_540M_AUTO_DIS (1 << 15)
#define MXC_CCM_CCSR_PDF_720M_AUTO_DIS (1 << 14)
#define MXC_CCM_CCSR_PDF_454M_AUTO_DIS (1 << 13)
#define MXC_CCM_CCSR_PDF_508M_AUTO_DIS (1 << 12)
#define MXC_CCM_CCSR_PDF_594M_AUTO_DIS (1 << 11)
#define MXC_CCM_CCSR_PDF_352M_AUTO_DIS (1 << 10)
#define MXC_CCM_CCSR_PDF_400M_AUTO_DIS (1 << 9)
#define MXC_CCM_CCSR_STEP_SEL (1 << 8)
#define MXC_CCM_CCSR_PLL1_SW_CLK_SEL (1 << 2)
#define MXC_CCM_CCSR_PLL2_SW_CLK_SEL (1 << 1)
#define MXC_CCM_CCSR_PLL3_SW_CLK_SEL (1 << 0)
/* Define the bits in register CACRR */
#define MXC_CCM_CACRR_ARM_PODF_OFFSET (0)
#define MXC_CCM_CACRR_ARM_PODF_MASK (0x7)
/* Define the bits in register CBCDR */
#define MXC_CCM_CBCDR_PERIPH_CLK2_PODF_MASK (0x7 << 27)
#define MXC_CCM_CBCDR_PERIPH_CLK2_PODF_OFFSET (27)
#define MXC_CCM_CBCDR_PERIPH2_CLK2_SEL (1 << 26)
#define MXC_CCM_CBCDR_PERIPH_CLK_SEL (1 << 25)
#define MXC_CCM_CBCDR_MMDC_CH0_PODF_MASK (0x7 << 19)
#define MXC_CCM_CBCDR_MMDC_CH0_PODF_OFFSET (19)
#define MXC_CCM_CBCDR_AXI_PODF_MASK (0x7 << 16)
#define MXC_CCM_CBCDR_AXI_PODF_OFFSET (16)
#define MXC_CCM_CBCDR_AHB_PODF_MASK (0x7 << 10)
#define MXC_CCM_CBCDR_AHB_PODF_OFFSET (10)
#define MXC_CCM_CBCDR_IPG_PODF_MASK (0x3 << 8)
#define MXC_CCM_CBCDR_IPG_PODF_OFFSET (8)
#define MXC_CCM_CBCDR_AXI_ALT_SEL (1 << 7)
#define MXC_CCM_CBCDR_AXI_SEL (1 << 6)
#define MXC_CCM_CBCDR_MMDC_CH1_PODF_MASK (0x7 << 3)
#define MXC_CCM_CBCDR_MMDC_CH1_PODF_OFFSET (3)
#define MXC_CCM_CBCDR_PERIPH2_CLK2_PODF_MASK (0x7 << 0)
#define MXC_CCM_CBCDR_PERIPH2_CLK2_PODF_OFFSET (0)
/* Define the bits in register CBCMR */
#define MXC_CCM_CBCMR_GPU3D_SHADER_PODF_MASK (0x7 << 29)
#define MXC_CCM_CBCMR_GPU3D_SHADER_PODF_OFFSET (29)
#define MXC_CCM_CBCMR_GPU3D_CORE_PODF_MASK (0x7 << 26)
#define MXC_CCM_CBCMR_GPU3D_CORE_PODF_OFFSET (26)
#define MXC_CCM_CBCMR_GPU2D_CORE_PODF_MASK (0x7 << 23)
#define MXC_CCM_CBCMR_GPU2D_CORE_PODF_OFFSET (23)
#define MXC_CCM_CBCMR_PRE_PERIPH2_CLK_SEL_MASK (0x3 << 21)
#define MXC_CCM_CBCMR_PRE_PERIPH2_CLK_SEL_OFFSET (21)
#define MXC_CCM_CBCMR_PRE_PERIPH2_CLK2_SEL (1 << 20)
#define MXC_CCM_CBCMR_PRE_PERIPH_CLK_SEL_MASK (0x3 << 18)
#define MXC_CCM_CBCMR_PRE_PERIPH_CLK_SEL_OFFSET (18)
#define MXC_CCM_CBCMR_GPU2D_CLK_SEL_MASK (0x3 << 16)
#define MXC_CCM_CBCMR_GPU2D_CLK_SEL_OFFSET (16)
#define MXC_CCM_CBCMR_VPU_AXI_CLK_SEL_MASK (0x3 << 14)
#define MXC_CCM_CBCMR_VPU_AXI_CLK_SEL_OFFSET (14)
#define MXC_CCM_CBCMR_PERIPH_CLK2_SEL_MASK (0x3 << 12)
#define MXC_CCM_CBCMR_PERIPH_CLK2_SEL_OFFSET (12)
#define MXC_CCM_CBCMR_VDOAXI_CLK_SEL (1 << 11)
#define MXC_CCM_CBCMR_PCIE_AXI_CLK_SEL (1 << 10)
#define MXC_CCM_CBCMR_GPU3D_SHADER_CLK_SEL_MASK (0x3 << 8)
#define MXC_CCM_CBCMR_GPU3D_SHADER_CLK_SEL_OFFSET (8)
#define MXC_CCM_CBCMR_GPU3D_CORE_CLK_SEL_MASK (0x3 << 4)
#define MXC_CCM_CBCMR_GPU3D_CORE_CLK_SEL_OFFSET (4)
#define MXC_CCM_CBCMR_GPU3D_AXI_CLK_SEL (1 << 1)
#define MXC_CCM_CBCMR_GPU2D_AXI_CLK_SEL (1 << 0)
/* Define the bits in register CSCMR1 */
#define MXC_CCM_CSCMR1_ACLK_EMI_SLOW_MASK (0x3 << 29)
#define MXC_CCM_CSCMR1_ACLK_EMI_SLOW_OFFSET (29)
#define MXC_CCM_CSCMR1_ACLK_EMI_MASK (0x3 << 27)
#define MXC_CCM_CSCMR1_ACLK_EMI_OFFSET (27)
#define MXC_CCM_CSCMR1_ACLK_EMI_SLOW_PODF_MASK (0x7 << 23)
#define MXC_CCM_CSCMR1_ACLK_EMI_SLOW_PODF_OFFSET (23)
#define MXC_CCM_CSCMR1_ACLK_EMI_PODF_MASK (0x7 << 20)
#define MXC_CCM_CSCMR1_ACLK_EMI_PODF_OFFSET (20)
#define MXC_CCM_CSCMR1_USDHC4_CLK_SEL (1 << 19)
#define MXC_CCM_CSCMR1_USDHC3_CLK_SEL (1 << 18)
#define MXC_CCM_CSCMR1_USDHC2_CLK_SEL (1 << 17)
#define MXC_CCM_CSCMR1_USDHC1_CLK_SEL (1 << 16)
#define MXC_CCM_CSCMR1_SSI3_CLK_SEL_MASK (0x3 << 14)
#define MXC_CCM_CSCMR1_SSI3_CLK_SEL_OFFSET (14)
#define MXC_CCM_CSCMR1_SSI2_CLK_SEL_MASK (0x3 << 12)
#define MXC_CCM_CSCMR1_SSI2_CLK_SEL_OFFSET (12)
#define MXC_CCM_CSCMR1_SSI1_CLK_SEL_MASK (0x3 << 10)
#define MXC_CCM_CSCMR1_SSI1_CLK_SEL_OFFSET (10)
#define MXC_CCM_CSCMR1_PERCLK_PODF_MASK (0x3F)
/* On SoloLite */
#define MXC_CCM_CSCMR1_PERCLK_SEL (1 << 6)
/* Define the bits in register CSCMR2 */
#define MXC_CCM_CSCMR2_ESAI_PRE_SEL_MASK (0x3 << 19)
#define MXC_CCM_CSCMR2_ESAI_PRE_SEL_OFFSET (19)
#define MXC_CCM_CSCMR2_LDB_DI1_IPU_DIV (1 << 11)
#define MXC_CCM_CSCMR2_LDB_DI0_IPU_DIV (1 << 10)
#define MXC_CCM_CSCMR2_CAN_CLK_SEL_MASK (0x3F << 2)
#define MXC_CCM_CSCMR2_CAN_CLK_SEL_OFFSET (2)
/* On SoloLite */
#define MXC_CCM_CSCMR2_EXTAUDIO_CLK_SEL_MASK (0x3 << 19)
#define MXC_CCM_CSCMR2_EXTAUDIO_CLK_SEL_OFFSET 19
/* Define the bits in register CSCDR1 */
#define MXC_CCM_CSCDR1_VPU_AXI_PODF_MASK (0x7 << 25)
#define MXC_CCM_CSCDR1_VPU_AXI_PODF_OFFSET (25)
#define MXC_CCM_CSCDR1_USDHC4_PODF_MASK (0x7 << 22)
#define MXC_CCM_CSCDR1_USDHC4_PODF_OFFSET (22)
#define MXC_CCM_CSCDR1_USDHC3_PODF_MASK (0x7 << 19)
#define MXC_CCM_CSCDR1_USDHC3_PODF_OFFSET (19)
#define MXC_CCM_CSCDR1_USDHC2_PODF_MASK (0x7 << 16)
#define MXC_CCM_CSCDR1_USDHC2_PODF_OFFSET (16)
#define MXC_CCM_CSCDR1_USDHC1_PODF_MASK (0x7 << 11)
#define MXC_CCM_CSCDR1_USDHC1_PODF_OFFSET (11)
#define MXC_CCM_CSCDR1_USBOH3_CLK_PRED_OFFSET (8)
#define MXC_CCM_CSCDR1_USBOH3_CLK_PRED_MASK (0x7 << 8)
#define MXC_CCM_CSCDR1_USBOH3_CLK_PODF_OFFSET (6)
#define MXC_CCM_CSCDR1_USBOH3_CLK_PODF_MASK (0x3 << 6)
#define MXC_CCM_CSCDR1_UART_CLK_PODF_MASK (0x3F)
#define MXC_CCM_CSCDR1_UART_CLK_PODF_OFFSET (0)
/* On Sololite */
#define MXC_CCM_CSCDR1_UART_CLK_SEL (1 << 6)
/* Define the bits in register CS1CDR */
#define MXC_CCM_CS1CDR_ESAI_CLK_PODF_MASK (0x3F << 25)
#define MXC_CCM_CS1CDR_ESAI_CLK_PODF_OFFSET (25)
#define MXC_CCM_CS1CDR_SSI3_CLK_PODF_MASK (0x3F << 16)
#define MXC_CCM_CS1CDR_SSI3_CLK_PODF_OFFSET (16)
#define MXC_CCM_CS1CDR_ESAI_CLK_PRED_MASK (0x3 << 9)
#define MXC_CCM_CS1CDR_ESAI_CLK_PRED_OFFSET (9)
#define MXC_CCM_CS1CDR_SSI1_CLK_PRED_MASK (0x7 << 6)
#define MXC_CCM_CS1CDR_SSI1_CLK_PRED_OFFSET (6)
#define MXC_CCM_CS1CDR_SSI1_CLK_PODF_MASK (0x3F)
#define MXC_CCM_CS1CDR_SSI1_CLK_PODF_OFFSET (0)
/* On SoloLite */
#define MXC_CCM_CS1CDR_EXTAUDIO_CLK_PODF_MASK (0x7 << 25)
#define MXC_CCM_CS1CDR_EXTAUDIO_CLK_PODF_OFFSET 25
#define MXC_CCM_CS1CDR_EXTAUDIO_CLK_PRED_MASK (0x7 << 9)
#define MXC_CCM_CS1CDR_EXTAUDIO_CLK_PRED_OFFSET 9
/* Define the bits in register CS2CDR */
#define MXC_CCM_CS2CDR_ENFC_CLK_PODF_MASK (0x3F << 21)
#define MXC_CCM_CS2CDR_ENFC_CLK_PODF_OFFSET (21)
#define MXC_CCM_CS2CDR_ENFC_CLK_PRED_MASK (0x7 << 18)
#define MXC_CCM_CS2CDR_ENFC_CLK_PRED_OFFSET (18)
#define MXC_CCM_CS2CDR_ENFC_CLK_SEL_MASK (0x3 << 16)
#define MXC_CCM_CS2CDR_ENFC_CLK_SEL_OFFSET (16)
#define MXC_CCM_CS2CDR_LDB_DI1_CLK_SEL_MASK (0x7 << 12)
#define MXC_CCM_CS2CDR_LDB_DI1_CLK_SEL_OFFSET (12)
#define MXC_CCM_CS2CDR_LDB_DI0_CLK_SEL_MASK (0x7 << 9)
#define MXC_CCM_CS2CDR_LDB_DI0_CLK_SEL_OFFSET (9)
#define MXC_CCM_CS2CDR_SSI2_CLK_PRED_MASK (0x7 << 6)
#define MXC_CCM_CS2CDR_SSI2_CLK_PRED_OFFSET (6)
#define MXC_CCM_CS2CDR_SSI2_CLK_PODF_MASK (0x3F)
#define MXC_CCM_CS2CDR_SSI2_CLK_PODF_OFFSET (0)
/* Define the bits in register CDCDR */
#define MXC_CCM_CDCDR_HSI_TX_PODF_MASK (0x7 << 29)
#define MXC_CCM_CDCDR_HSI_TX_PODF_OFFSET (29)
#define MXC_CCM_CDCDR_HSI_TX_CLK_SEL (1 << 28)
#define MXC_CCM_CDCDR_SPDIF0_CLK_PRED_MASK (0x7 << 25)
#define MXC_CCM_CDCDR_SPDIF0_CLK_PRED_OFFSET (25)
#define MXC_CCM_CDCDR_SPDIF0_CLK_PODF_MASK (0x7 << 19)
#define MXC_CCM_CDCDR_SPDIF0_CLK_PODF_OFFSET (19)
#define MXC_CCM_CDCDR_SPDIF0_CLK_SEL_MASK (0x3 << 20)
#define MXC_CCM_CDCDR_SPDIF0_CLK_SEL_OFFSET (20)
#define MXC_CCM_CDCDR_SPDIF1_CLK_PRED_MASK (0x7 << 12)
#define MXC_CCM_CDCDR_SPDIF1_CLK_PRED_OFFSET (12)
#define MXC_CCM_CDCDR_SPDIF1_CLK_PODF_MASK (0x7 << 9)
#define MXC_CCM_CDCDR_SPDIF1_CLK_PODF_OFFSET (9)
#define MXC_CCM_CDCDR_SPDIF1_CLK_SEL_MASK (0x3 << 7)
#define MXC_CCM_CDCDR_SPDIF1_CLK_SEL_OFFSET (7)
/* On SoloLite */
#define MXC_CCM_CDCDR_MSHC_XMSCKI_PODF_MASK (0x7 << 29)
#define MXC_CCM_CDCDR_MSHC_XMSCKI_PODF_OFFSET 29
#define MXC_CCM_CDCDR_MSHC_XMSCLI_CLK_SEL (0x1 << 28)
/* Define the bits in register CHSCCDR */
#define MXC_CCM_CHSCCDR_IPU1_DI1_PRE_CLK_SEL_MASK (0x7 << 15)
#define MXC_CCM_CHSCCDR_IPU1_DI1_PRE_CLK_SEL_OFFSET (15)
#define MXC_CCM_CHSCCDR_IPU1_DI1_PODF_MASK (0x7 << 12)
#define MXC_CCM_CHSCCDR_IPU1_DI1_PODF_OFFSET (12)
#define MXC_CCM_CHSCCDR_IPU1_DI1_CLK_SEL_MASK (0x7 << 9)
#define MXC_CCM_CHSCCDR_IPU1_DI1_CLK_SEL_OFFSET (9)
#define MXC_CCM_CHSCCDR_IPU1_DI0_PRE_CLK_SEL_MASK (0x7 << 6)
#define MXC_CCM_CHSCCDR_IPU1_DI0_PRE_CLK_SEL_OFFSET (6)
#define MXC_CCM_CHSCCDR_IPU1_DI0_PODF_MASK (0x7 << 3)
#define MXC_CCM_CHSCCDR_IPU1_DI0_PODF_OFFSET (3)
#define MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_MASK (0x7)
#define MXC_CCM_CHSCCDR_IPU1_DI0_CLK_SEL_OFFSET (0)
/* On Sololite */
#define MXC_CCM_CHSCCDR_EPDC_AXI_PRE_CLK_SEL_MASK (0x7 << 15)
#define MXC_CCM_CHSCCDR_EPDC_AXI_PRE_CLK_SEL_OFFSET 15
#define MXC_CCM_CHSCCDR_EPDC_AXI_PODF_MASK (0x7 << 12)
#define MXC_CCM_CHSCCDR_EPDC_AXI_PODF_OFFSET 12
#define MXC_CCM_CHSCCDR_EPDC_AXI_CLK_SEL_MASK (0x7 << 9)
#define MXC_CCM_CHSCCDR_EPDC_AXI_CLK_SEL_OFFSET 9
#define MXC_CCM_CHSCCDR_PXP_AXI_PRE_CLK_SEL_MASK (0x7 << 6)
#define MXC_CCM_CHSCCDR_PXP_AXI_PRE_CLK_SEL_OFFSET 6
#define MXC_CCM_CHSCCDR_PXP_AXI_PODF_MASK (0x7 << 3)
#define MXC_CCM_CHSCCDR_PXP_AXI_PODF_OFFSET 3
#define MXC_CCM_CHSCCDR_PXP_AXI_CLK_SEL_MASK 0x7
#define MXC_CCM_CHSCCDR_PXP_AXI_CLK_SEL_OFFSET 0
/* Define the bits in register CSCDR2 */
#define MXC_CCM_CSCDR2_ECSPI_CLK_PODF_MASK (0x3F << 19)
#define MXC_CCM_CSCDR2_ECSPI_CLK_PODF_OFFSET (19)
#define MXC_CCM_CHSCCDR_IPU2_DI1_PRE_CLK_SEL_MASK (0x7 << 15)
#define MXC_CCM_CHSCCDR_IPU2_DI1_PRE_CLK_SEL_OFFSET (15)
#define MXC_CCM_CHSCCDR_IPU2_DI1_PODF_MASK (0x7 << 12)
#define MXC_CCM_CHSCCDR_IPU2_DI1_PODF_OFFSET (12)
#define MXC_CCM_CHSCCDR_IPU2_DI1_CLK_SEL_MASK (0x7 << 9)
#define MXC_CCM_CHSCCDR_IPU2_DI1_CLK_SEL_OFFSET (9)
#define MXC_CCM_CHSCCDR_IPU2_DI0_PRE_CLK_SEL_MASK (0x7 << 6)
#define MXC_CCM_CHSCCDR_IPU2_DI0_PRE_CLK_SEL_OFFSET (6)
#define MXC_CCM_CHSCCDR_IPU2_DI0_PODF_MASK (0x7 << 3)
#define MXC_CCM_CHSCCDR_IPU2_DI0_PODF_OFFSET (3)
#define MXC_CCM_CHSCCDR_IPU2_DI0_CLK_SEL_MASK (0x7)
#define MXC_CCM_CHSCCDR_IPU2_DI0_CLK_SEL_OFFSET (0)
/* On SoloLite */
#define MXC_CCM_CSCDR2_ECSPI_CLK_SEL (0x1 << 18)
#define MXC_CCM_CSCDR2_EPDC_PIX_PRE_CLK_SEL_MASK (0x7 << 15)
#define MXC_CCM_CSCDR2_EPDC_PIX_PRE_CLK_SEL_OFFSET 15
#define MXC_CCM_CSCDR2_EPDC_PIX_PODF_MASK (0x7 << 12)
#define MXC_CCM_CSCDR2_EPDC_PIX_PODF_OFFSET 12
#define MXC_CCM_CSCDR2_EPDC_PIX_CLK_SEL_MASK (0X7 << 9)
#define MXC_CCM_CSCDR2_EPDC_PIX_CLK_SEL_OFFSET 9
#define MXC_CCM_CSCDR2_LCDIF_PIX_PRE_CLK_SEL_MASK (0x7 << 6)
#define MXC_CCM_CSCDR2_LCDIF_PIX_PRE_CLK_SEL_OFFSET 6
#define MXC_CCM_CSCDR2_LCDIF_PIX_PODF_MASK (0x7 << 3)
#define MXC_CCM_CSCDR2_LCDIF_PIX_PODF_OFFSET 3
#define MXC_CCM_CSCDR2_LCDIF_PIX_CLK_SEL_MASK 0x7
#define MXC_CCM_CSCDR2_LCDIF_PIX_CLK_SEL_OFFSET 0
/* Define the bits in register CSCDR3 */
#define MXC_CCM_CSCDR3_IPU2_HSP_PODF_MASK (0x7 << 16)
#define MXC_CCM_CSCDR3_IPU2_HSP_PODF_OFFSET (16)
#define MXC_CCM_CSCDR3_IPU2_HSP_CLK_SEL_MASK (0x3 << 14)
#define MXC_CCM_CSCDR3_IPU2_HSP_CLK_SEL_OFFSET (14)
#define MXC_CCM_CSCDR3_IPU1_HSP_PODF_MASK (0x7 << 11)
#define MXC_CCM_CSCDR3_IPU1_HSP_PODF_OFFSET (11)
#define MXC_CCM_CSCDR3_IPU1_HSP_CLK_SEL_MASK (0x3 << 9)
#define MXC_CCM_CSCDR3_IPU1_HSP_CLK_SEL_OFFSET (9)
/* Define the bits in register CDHIPR */
#define MXC_CCM_CDHIPR_ARM_PODF_BUSY (1 << 16)
#define MXC_CCM_CDHIPR_PERIPH_CLK_SEL_BUSY (1 << 5)
#define MXC_CCM_CDHIPR_MMDC_CH0_PODF_BUSY (1 << 4)
#define MXC_CCM_CDHIPR_PERIPH2_CLK_SEL_BUSY (1 << 3)
#define MXC_CCM_CDHIPR_MMDC_CH1_PODF_BUSY (1 << 2)
#define MXC_CCM_CDHIPR_AHB_PODF_BUSY (1 << 1)
#define MXC_CCM_CDHIPR_AXI_PODF_BUSY (1)
/* Define the bits in register CLPCR */
#define MXC_CCM_CLPCR_MASK_L2CC_IDLE (1 << 27)
#define MXC_CCM_CLPCR_MASK_SCU_IDLE (1 << 26)
#define MXC_CCM_CLPCR_MASK_CORE3_WFI (1 << 25)
#define MXC_CCM_CLPCR_MASK_CORE2_WFI (1 << 24)
#define MXC_CCM_CLPCR_MASK_CORE1_WFI (1 << 23)
#define MXC_CCM_CLPCR_MASK_CORE0_WFI (1 << 22)
#define MXC_CCM_CLPCR_BYP_MMDC_CH1_LPM_HS (1 << 21)
#define MXC_CCM_CLPCR_BYP_MMDC_CH0_LPM_HS (1 << 19)
#define MXC_CCM_CLPCR_WB_CORE_AT_LPM (1 << 17)
#define MXC_CCM_CLPCR_WB_PER_AT_LPM (1 << 16)
#define MXC_CCM_CLPCR_COSC_PWRDOWN (1 << 11)
#define MXC_CCM_CLPCR_STBY_COUNT_MASK (0x3 << 9)
#define MXC_CCM_CLPCR_STBY_COUNT_OFFSET (9)
#define MXC_CCM_CLPCR_VSTBY (1 << 8)
#define MXC_CCM_CLPCR_DIS_REF_OSC (1 << 7)
#define MXC_CCM_CLPCR_SBYOS (1 << 6)
#define MXC_CCM_CLPCR_ARM_CLK_DIS_ON_LPM (1 << 5)
#define MXC_CCM_CLPCR_LPSR_CLK_SEL_MASK (0x3 << 3)
#define MXC_CCM_CLPCR_LPSR_CLK_SEL_OFFSET (3)
#define MXC_CCM_CLPCR_BYPASS_PMIC_VFUNC_READY (1 << 2)
#define MXC_CCM_CLPCR_LPM_MASK (0x3)
#define MXC_CCM_CLPCR_LPM_OFFSET (0)
/* Define the bits in register CISR */
#define MXC_CCM_CISR_ARM_PODF_LOADED (1 << 26)
#define MXC_CCM_CISR_MMDC_CH0_PODF_LOADED (1 << 23)
#define MXC_CCM_CISR_PERIPH_CLK_SEL_LOADED (1 << 22)
#define MXC_CCM_CISR_MMDC_CH1_PODF_LOADED (1 << 21)
#define MXC_CCM_CISR_AHB_PODF_LOADED (1 << 20)
#define MXC_CCM_CISR_PERIPH2_CLK_SEL_LOADED (1 << 19)
#define MXC_CCM_CISR_AXI_PODF_LOADED (1 << 17)
#define MXC_CCM_CISR_COSC_READY (1 << 6)
#define MXC_CCM_CISR_LRF_PLL (1)
/* Define the bits in register CIMR */
#define MXC_CCM_CIMR_MASK_ARM_PODF_LOADED (1 << 26)
#define MXC_CCM_CIMR_MASK_MMDC_CH0_PODF_LOADED (1 << 23)
#define MXC_CCM_CIMR_MASK_PERIPH_CLK_SEL_LOADED (1 << 22)
#define MXC_CCM_CIMR_MASK_MMDC_CH1_PODF_LOADED (1 << 21)
#define MXC_CCM_CIMR_MASK_AHB_PODF_LOADED (1 << 20)
#define MXC_CCM_CIMR_MASK_PERIPH2_CLK_SEL_LOADED (1 << 22)
#define MXC_CCM_CIMR_MASK_AXI_PODF_LOADED (1 << 17)
#define MXC_CCM_CIMR_MASK_COSC_READY (1 << 6)
#define MXC_CCM_CIMR_MASK_LRF_PLL (1)
/* Define the bits in register CCOSR */
#define MXC_CCM_CCOSR_CKO2_EN_OFFSET (1 << 24)
#define MXC_CCM_CCOSR_CKO2_DIV_MASK (0x7 << 21)
#define MXC_CCM_CCOSR_CKO2_DIV_OFFSET (21)
#define MXC_CCM_CCOSR_CKO2_SEL_OFFSET (16)
#define MXC_CCM_CCOSR_CKO2_SEL_MASK (0x1F << 16)
#define MXC_CCM_CCOSR_CLKO2_CLKO1_SEL (0x1 << 8)
#define MXC_CCM_CCOSR_CKO1_EN (0x1 << 7)
#define MXC_CCM_CCOSR_CKO1_DIV_MASK (0x7 << 4)
#define MXC_CCM_CCOSR_CKO1_DIV_OFFSET (4)
#define MXC_CCM_CCOSR_CKO1_SEL_MASK (0xF)
#define MXC_CCM_CCOSR_CKO1_SEL_OFFSET (0)
/* Define the bits in registers CGPR */
#define MXC_CCM_CGPR_EFUSE_PROG_SUPPLY_GATE (1 << 4)
#define MXC_CCM_CGPR_MMDC_EXT_CLK_DIS (1 << 2)
#define MXC_CCM_CGPR_PMIC_DELAY_SCALER (1)
/* On SoloLite */
#define MXC_CCM_CGPR_MEM_IPG_STOP_MASK (0x1 << 1)
/* Define the bits in registers CCGRx */
#define MXC_CCM_CCGR_CG_MASK 3
#define MXC_CCM_CCGR0_CG15_OFFSET 30
#define MXC_CCM_CCGR0_CG15_MASK (0x3 << 30)
#define MXC_CCM_CCGR0_CG14_OFFSET 28
#define MXC_CCM_CCGR0_CG14_MASK (0x3 << 28)
#define MXC_CCM_CCGR0_CG13_OFFSET 26
#define MXC_CCM_CCGR0_CG13_MASK (0x3 << 26)
#define MXC_CCM_CCGR0_CG12_OFFSET 24
#define MXC_CCM_CCGR0_CG12_MASK (0x3 << 24)
#define MXC_CCM_CCGR0_CG11_OFFSET 22
#define MXC_CCM_CCGR0_CG11_MASK (0x3 << 22)
#define MXC_CCM_CCGR0_CG10_OFFSET 20
#define MXC_CCM_CCGR0_CG10_MASK (0x3 << 20)
#define MXC_CCM_CCGR0_CG9_OFFSET 18
#define MXC_CCM_CCGR0_CG9_MASK (0x3 << 18)
#define MXC_CCM_CCGR0_CG8_OFFSET 16
#define MXC_CCM_CCGR0_CG8_MASK (0x3 << 16)
#define MXC_CCM_CCGR0_CG7_OFFSET 14
#define MXC_CCM_CCGR0_CG6_OFFSET 12
#define MXC_CCM_CCGR0_CG5_OFFSET 10
#define MXC_CCM_CCGR0_CG5_MASK (0x3 << 10)
#define MXC_CCM_CCGR0_CG4_OFFSET 8
#define MXC_CCM_CCGR0_CG4_MASK (0x3 << 8)
#define MXC_CCM_CCGR0_CG3_OFFSET 6
#define MXC_CCM_CCGR0_CG3_MASK (0x3 << 6)
#define MXC_CCM_CCGR0_CG2_OFFSET 4
#define MXC_CCM_CCGR0_CG2_MASK (0x3 << 4)
#define MXC_CCM_CCGR0_CG1_OFFSET 2
#define MXC_CCM_CCGR0_CG1_MASK (0x3 << 2)
#define MXC_CCM_CCGR0_CG0_OFFSET 0
#define MXC_CCM_CCGR0_CG0_MASK 3
#define MXC_CCM_CCGR1_CG15_OFFSET 30
#define MXC_CCM_CCGR1_CG14_OFFSET 28
#define MXC_CCM_CCGR1_CG13_OFFSET 26
#define MXC_CCM_CCGR1_CG12_OFFSET 24
#define MXC_CCM_CCGR1_CG11_OFFSET 22
#define MXC_CCM_CCGR1_CG10_OFFSET 20
#define MXC_CCM_CCGR1_CG9_OFFSET 18
#define MXC_CCM_CCGR1_CG8_OFFSET 16
#define MXC_CCM_CCGR1_CG7_OFFSET 14
#define MXC_CCM_CCGR1_CG6_OFFSET 12
#define MXC_CCM_CCGR1_CG5_OFFSET 10
#define MXC_CCM_CCGR1_CG4_OFFSET 8
#define MXC_CCM_CCGR1_CG3_OFFSET 6
#define MXC_CCM_CCGR1_CG2_OFFSET 4
#define MXC_CCM_CCGR1_CG1_OFFSET 2
#define MXC_CCM_CCGR1_CG0_OFFSET 0
#define MXC_CCM_CCGR2_CG15_OFFSET 30
#define MXC_CCM_CCGR2_CG14_OFFSET 28
#define MXC_CCM_CCGR2_CG13_OFFSET 26
#define MXC_CCM_CCGR2_CG12_OFFSET 24
#define MXC_CCM_CCGR2_CG11_OFFSET 22
#define MXC_CCM_CCGR2_CG10_OFFSET 20
#define MXC_CCM_CCGR2_CG9_OFFSET 18
#define MXC_CCM_CCGR2_CG8_OFFSET 16
#define MXC_CCM_CCGR2_CG7_OFFSET 14
#define MXC_CCM_CCGR2_CG6_OFFSET 12
#define MXC_CCM_CCGR2_CG5_OFFSET 10
#define MXC_CCM_CCGR2_CG4_OFFSET 8
#define MXC_CCM_CCGR2_CG3_OFFSET 6
#define MXC_CCM_CCGR2_CG2_OFFSET 4
#define MXC_CCM_CCGR2_CG1_OFFSET 2
#define MXC_CCM_CCGR2_CG0_OFFSET 0
#define MXC_CCM_CCGR3_CG15_OFFSET 30
#define MXC_CCM_CCGR3_CG14_OFFSET 28
#define MXC_CCM_CCGR3_CG13_OFFSET 26
#define MXC_CCM_CCGR3_CG12_OFFSET 24
#define MXC_CCM_CCGR3_CG11_OFFSET 22
#define MXC_CCM_CCGR3_CG10_OFFSET 20
#define MXC_CCM_CCGR3_CG9_OFFSET 18
#define MXC_CCM_CCGR3_CG8_OFFSET 16
#define MXC_CCM_CCGR3_CG7_OFFSET 14
#define MXC_CCM_CCGR3_CG6_OFFSET 12
#define MXC_CCM_CCGR3_CG5_OFFSET 10
#define MXC_CCM_CCGR3_CG4_OFFSET 8
#define MXC_CCM_CCGR3_CG3_OFFSET 6
#define MXC_CCM_CCGR3_CG2_OFFSET 4
#define MXC_CCM_CCGR3_CG1_OFFSET 2
#define MXC_CCM_CCGR3_CG0_OFFSET 0
#define MXC_CCM_CCGR4_CG15_OFFSET 30
#define MXC_CCM_CCGR4_CG14_OFFSET 28
#define MXC_CCM_CCGR4_CG13_OFFSET 26
#define MXC_CCM_CCGR4_CG12_OFFSET 24
#define MXC_CCM_CCGR4_CG11_OFFSET 22
#define MXC_CCM_CCGR4_CG10_OFFSET 20
#define MXC_CCM_CCGR4_CG9_OFFSET 18
#define MXC_CCM_CCGR4_CG8_OFFSET 16
#define MXC_CCM_CCGR4_CG7_OFFSET 14
#define MXC_CCM_CCGR4_CG6_OFFSET 12
#define MXC_CCM_CCGR4_CG5_OFFSET 10
#define MXC_CCM_CCGR4_CG4_OFFSET 8
#define MXC_CCM_CCGR4_CG3_OFFSET 6
#define MXC_CCM_CCGR4_CG2_OFFSET 4
#define MXC_CCM_CCGR4_CG1_OFFSET 2
#define MXC_CCM_CCGR4_CG0_OFFSET 0
#define MXC_CCM_CCGR5_CG15_OFFSET 30
#define MXC_CCM_CCGR5_CG14_OFFSET 28
#define MXC_CCM_CCGR5_CG14_MASK (0x3 << 28)
#define MXC_CCM_CCGR5_CG13_OFFSET 26
#define MXC_CCM_CCGR5_CG13_MASK (0x3 << 26)
#define MXC_CCM_CCGR5_CG12_OFFSET 24
#define MXC_CCM_CCGR5_CG12_MASK (0x3 << 24)
#define MXC_CCM_CCGR5_CG11_OFFSET 22
#define MXC_CCM_CCGR5_CG11_MASK (0x3 << 22)
#define MXC_CCM_CCGR5_CG10_OFFSET 20
#define MXC_CCM_CCGR5_CG10_MASK (0x3 << 20)
#define MXC_CCM_CCGR5_CG9_OFFSET 18
#define MXC_CCM_CCGR5_CG9_MASK (0x3 << 18)
#define MXC_CCM_CCGR5_CG8_OFFSET 16
#define MXC_CCM_CCGR5_CG8_MASK (0x3 << 16)
#define MXC_CCM_CCGR5_CG7_OFFSET 14
#define MXC_CCM_CCGR5_CG7_MASK (0x3 << 14)
#define MXC_CCM_CCGR5_CG6_OFFSET 12
#define MXC_CCM_CCGR5_CG6_MASK (0x3 << 12)
#define MXC_CCM_CCGR5_CG5_OFFSET 10
#define MXC_CCM_CCGR5_CG4_OFFSET 8
#define MXC_CCM_CCGR5_CG3_OFFSET 6
#define MXC_CCM_CCGR5_CG2_OFFSET 4
#define MXC_CCM_CCGR5_CG2_MASK (0x3 << 4)
#define MXC_CCM_CCGR5_CG1_OFFSET 2
#define MXC_CCM_CCGR5_CG0_OFFSET 0
#define MXC_CCM_CCGR6_CG15_OFFSET 30
#define MXC_CCM_CCGR6_CG14_OFFSET 28
#define MXC_CCM_CCGR6_CG14_MASK (0x3 << 28)
#define MXC_CCM_CCGR6_CG13_OFFSET 26
#define MXC_CCM_CCGR6_CG13_MASK (0x3 << 26)
#define MXC_CCM_CCGR6_CG12_OFFSET 24
#define MXC_CCM_CCGR6_CG12_MASK (0x3 << 24)
#define MXC_CCM_CCGR6_CG11_OFFSET 22
#define MXC_CCM_CCGR6_CG11_MASK (0x3 << 22)
#define MXC_CCM_CCGR6_CG10_OFFSET 20
#define MXC_CCM_CCGR6_CG10_MASK (0x3 << 20)
#define MXC_CCM_CCGR6_CG9_OFFSET 18
#define MXC_CCM_CCGR6_CG9_MASK (0x3 << 18)
#define MXC_CCM_CCGR6_CG8_OFFSET 16
#define MXC_CCM_CCGR6_CG8_MASK (0x3 << 16)
#define MXC_CCM_CCGR6_CG7_OFFSET 14
#define MXC_CCM_CCGR6_CG7_MASK (0x3 << 14)
#define MXC_CCM_CCGR6_CG6_OFFSET 12
#define MXC_CCM_CCGR6_CG6_MASK (0x3 << 12)
#define MXC_CCM_CCGR6_CG5_OFFSET 10
#define MXC_CCM_CCGR6_CG4_OFFSET 8
#define MXC_CCM_CCGR6_CG3_OFFSET 6
#define MXC_CCM_CCGR6_CG2_OFFSET 4
#define MXC_CCM_CCGR6_CG2_MASK (0x3 << 4)
#define MXC_CCM_CCGR6_CG1_OFFSET 2
#define MXC_CCM_CCGR6_CG0_OFFSET 0
#define MXC_CCM_CCGR7_CG15_OFFSET 30
#define MXC_CCM_CCGR7_CG14_OFFSET 28
#define MXC_CCM_CCGR7_CG14_MASK (0x3 << 28)
#define MXC_CCM_CCGR7_CG13_OFFSET 26
#define MXC_CCM_CCGR7_CG13_MASK (0x3 << 26)
#define MXC_CCM_CCGR7_CG12_OFFSET 24
#define MXC_CCM_CCGR7_CG12_MASK (0x3 << 24)
#define MXC_CCM_CCGR7_CG11_OFFSET 22
#define MXC_CCM_CCGR7_CG11_MASK (0x3 << 22)
#define MXC_CCM_CCGR7_CG10_OFFSET 20
#define MXC_CCM_CCGR7_CG10_MASK (0x3 << 20)
#define MXC_CCM_CCGR7_CG9_OFFSET 18
#define MXC_CCM_CCGR7_CG9_MASK (0x3 << 18)
#define MXC_CCM_CCGR7_CG8_OFFSET 16
#define MXC_CCM_CCGR7_CG8_MASK (0x3 << 16)
#define MXC_CCM_CCGR7_CG7_OFFSET 14
#define MXC_CCM_CCGR7_CG7_MASK (0x3 << 14)
#define MXC_CCM_CCGR7_CG6_OFFSET 12
#define MXC_CCM_CCGR7_CG6_MASK (0x3 << 12)
#define MXC_CCM_CCGR7_CG5_OFFSET 10
#define MXC_CCM_CCGR7_CG4_OFFSET 8
#define MXC_CCM_CCGR7_CG3_OFFSET 6
#define MXC_CCM_CCGR7_CG2_OFFSET 4
#define MXC_CCM_CCGR7_CG2_MASK (0x3 << 4)
#define MXC_CCM_CCGR7_CG1_OFFSET 2
#define MXC_CCM_CCGR7_CG0_OFFSET 0
#endif /* __ARCH_ARM_MACH_MX6_CRM_REGS_H__ */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,829 @@
/*
* 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
/*
* 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")))
#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

@ -0,0 +1,3 @@
SRC_FILES += switch.S
include $(KERNEL_ROOT)/compiler.mk

View File

@ -0,0 +1,25 @@
# Context switch
#
# void swtch(struct context **old, struct context *new);
#
# Save current register context in old
# and then load register context from new.
# The stack is as r4_svc-r12_svc, lr_svc, sp_usr, lr_usr, and pc_usr
.global proc_switch
proc_switch:
stmfd r13!, {r4-r12, lr} // push svc r4-r12, lr to the stack
# switch the stack
str r13, [r0] // save current sp to the old PCB (**old)
mov r13, r1 // load the next stack
# load the new registers. pc_usr is not restored here because
# LDMFD^ will switch mode if pc_usr is loaded. We just simply
# pop it out as pc_usr is saved on the stack, and will be loaded
# when we return from kernel to user space (swi or interrupt return)
ldmfd r13!, {r4-r12, lr} // pop svc r4-r12, lr
# return to the caller
bx lr

View File

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

View File

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

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,9 +39,10 @@
#ifndef __GPT_H__
#define __GPT_H__
#include "sdk.h"
#include "timer.h"
#include <stdbool.h>
////////////////////////////////////////////////////////////////////////////////
// Definitions
////////////////////////////////////////////////////////////////////////////////
@ -55,45 +56,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 +122,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 +174,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 +198,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

@ -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,3 @@
SRC_FILES := gpt.c ccm_pll.c
include $(KERNEL_ROOT)/compiler.mk

View File

@ -28,30 +28,35 @@
* 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"
#include "regsccm.h"
#include "regsccmanalog.h"
#include "regsecspi.h"
#include "regsepit.h"
#include "regsgpc.h"
#include "regsgpt.h"
#include "regsi2c.h"
#include "regsiomuxc.h"
#include "regssdmaarm.h"
#include "regsspba.h"
#include "regsspdif.h"
#include "regsssi.h"
#include "regsuart.h"
#if defined(CHIP_MX6DQ)
#include "registers/regssata.h"
#include "regssata.h"
#endif
#if !defined(CHIP_MX6SL)
#include "registers/regsgpmi.h"
#include "registers/regsesai.h"
#include "regsesai.h"
#include "regsgpmi.h"
#endif
#include "ccm_pll.h"
#include "soc_memory_map.h"
#include <stdbool.h>
#include <stdint.h>
////////////////////////////////////////////////////////////////////////////////
// Variables
////////////////////////////////////////////////////////////////////////////////
@ -72,19 +77,19 @@ void ccm_init(void)
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)
#if !defined(CHIP_MX6SL)
HW_CCM_ANALOG_PLL_ENET.B.DIV_SELECT = 0x3;
#else
HW_CCM_ANALOG_PLL_ENET.B.DIV_SELECT = 0x1;
HW_CCM_ANALOG_PLL_ENET.B.DIV_SELECT = 0x1;
#endif
// Ungate clocks that are not enabled in a driver - need to be updated
// 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_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_CCGR4_WR(0x00FFFF03); // GPMI, Perfmon enabled by driver
HW_CCM_CCGR5_WR(0xF0FFFFCF); // UART, SATA enabled by driver
HW_CCM_CCGR6_WR(0xffffffff);
/*
@ -95,7 +100,7 @@ void ccm_init(void)
* => by default, ipg_podf divides by 2 => IPG_CLK@66MHz.
*/
HW_CCM_CBCDR.U = BF_CCM_CBCDR_AHB_PODF(3)
#if !defined (CHIP_MX6SL)
#if !defined(CHIP_MX6SL)
| BF_CCM_CBCDR_AXI_PODF(1)
#endif
| BF_CCM_CBCDR_IPG_PODF(1);
@ -104,11 +109,11 @@ void ccm_init(void)
* 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 =
// 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
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);
@ -125,7 +130,7 @@ uint32_t get_main_clock(main_clocks_t clock)
case CPU_CLK:
ret_val = PLL1_OUTPUT;
break;
#if !defined (CHIP_MX6SL)
#if !defined(CHIP_MX6SL)
case AXI_CLK:
ret_val = PLL2_OUTPUT[pre_periph_clk_sel] / (HW_CCM_CBCDR.B.AXI_PODF + 1);
break;
@ -137,17 +142,12 @@ uint32_t get_main_clock(main_clocks_t clock)
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);
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);
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)
#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;
@ -163,37 +163,34 @@ 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
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;
default:
break;
}
return ret_val;
@ -207,13 +204,10 @@ uint32_t get_peri_clock(peri_clocks_t clock)
*/
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;
if (gating_mode == CLOCK_ON) {
*(volatile uint32_t*)(ccm_ccgrx) |= cgx_offset;
} else {
*(volatile uint32_t*)(ccm_ccgrx) &= ~cgx_offset;
}
}
@ -222,113 +216,111 @@ 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;
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;
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;
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;
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;
#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;
default:
break;
}
// apply changes only if a valid address was found
if (ccm_ccgrx != 0)
{
// apply changes only if a valid address was found
if (ccm_ccgrx != 0) {
ccm_ccgr_config(ccm_ccgrx, cgx_offset, gating_mode);
}
}
@ -348,18 +340,18 @@ void ccm_set_lpm_wakeup_source(uint32_t irq_id, bool doEnable)
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);
gpc_imr = *((volatile uint32_t*)(HW_GPC_IMR1_ADDR + (reg_offset - 1) * 4));
if (doEnable) {
// clear the corresponding bit to unmask the interrupt source
// 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);
// 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
// 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);
// write the new mask
*((volatile uint32_t*)(HW_GPC_IMR1_ADDR + (reg_offset - 1) * 4)) = (gpc_imr);
}
}
@ -367,34 +359,33 @@ 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
// 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)
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
// 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;");
// 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)
#if !defined(CHIP_MX6SL)
/*!
* @brief Configure ipu 1 and 2 hsp clk to default 264MHz
*
@ -404,35 +395,34 @@ 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)
| 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)
| 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
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
// 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
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
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

View File

@ -35,15 +35,14 @@
* @ingroup diag_timer
*/
#include "sdk.h"
#include "gpt.h"
#include "ccm_pll.h"
#include "interrupt.h"
#include "regsgpt.h"
#include "soc_memory_map.h"
#include "timer.h"
#include "registers/regsgpt.h"
#include <arch_interrupt.h>
#include <ccm_pll.h>
#include <irq_numbers.h>
#include <isr.h>
#include "trap.h"
////////////////////////////////////////////////////////////////////////////////
// Code
@ -56,67 +55,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 +118,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 +154,71 @@ 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;
// void gpt_setup_interrupt(void (*irq_subroutine)(void), 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);
// if (enableIt) {
// // register the IRQ sub-routine
// register_interrupt_routine(irq_id, irq_subroutine);
}
else
{
// disable the IRQ
// disable_interrupt(irq_id, CPU_0);
isrManager.done->disableIrq(irq_id,CPU_0);
}
}
// // enable the IRQ
// enable_interrupt(irq_id, CPU_0, 0);
// } else {
// // disable the IRQ
// disable_interrupt(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
// enable the source clocks to the GPT port
clock_gating_config(base, 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

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

View File

@ -0,0 +1,45 @@
#include "clock.h"
#include "ccm_pll.h"
#include "gpt.h"
#include "irq_numbers.h"
#include <stdint.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, 1);
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_int()
{
gpt_get_compare_event(kGPTOutputCompare1);
}
struct XiziClockDriver xizi_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_int = _clear_clock_int,
};

View File

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

View File

@ -0,0 +1,35 @@
#ifndef _MEMLAYOUT_H_
#define _MEMLAYOUT_H_
// Memory layout
#define NUM_PDE (1 << (ARCH_BIT - PDE_SHIFT)) // how many PTE in a PT
#define NUM_PTE (1 << (PDE_SHIFT - PTE_SHIFT)) // how many PTE in a PT
#define PGSIZE 65536 // set large page(64K).
#define DEVBASE 0x00000000
#define DEV_MEM_SZ 0x03000000
#define PHYMEMBASE (0x27800000)
#define PHYSTOP (0x47000000)
#define KERNBASE (0x80000000) // First kernel virtual address
#define KERN_OFFSET (KERNBASE - PHYMEMBASE)
#define ALIGNUP(sz, al) (((uint32_t)(sz) + (uint32_t)(al)-1) & ~((uint32_t)(al)-1))
#define ALIGNDOWN(sz, al) ((uint32_t)(sz) & ~((uint32_t)(al)-1))
#define KERN_OFFSET (KERNBASE - PHYMEMBASE)
#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)) - KERNBASE; }
__attribute__((always_inline)) static inline void* p2v(uint32_t a) { return (void*)((a) + KERNBASE); }
#endif
#endif

View File

@ -0,0 +1,96 @@
#ifndef _MMU_H_
#define _MMU_H_
#include <stdint.h>
// ARM has 2 page tables: one for kernel, other for user.
// Use 4K pages in both tables.
#define ARCH_BIT 32
// access permission for page directory/page table entries.
// Use these values for section tables only!
#define AP_NA 0x0 // no access
#define AP_KO 0x1 // privilaged access, kernel: RW, user: no access
#define AP_KUR 0x2 // no write access from user, read allowed
#define AP_KU 0x3 // full access
// Domain Access Control definition entries
#define DM_NA 0x0 // any access causing a domain fault
#define DM_CLIENT 0x1 // any access checked against TLB (page table)
#define DM_RESRVED 0x2 // reserved: always falut.
#define DM_MANAGER 0x3 // no access check
#define PDE_TYPES 0x3 // mask for PDE type
#define PDE_INVALID 0x0 // PDE(L1 descriptor): invalid
#define PDE_COARSE 0x1 // PDE(L1 descriptor): coarse
#define PDE_SECTION 0x2 // PDE(L1 descriptor): section
#define PDE_FINE 0x3 // PDE(L1 descriptor): fine
#define PTE_TYPES 0x3 // mask for PTE type
#define PTE_INVALID 0x0 // PTE(L2 descriptor): invalid
#define PTE_LARGE 0x1 // PTE(L2 descriptor): 64KB page
#define PTE_SMALL 0x2 // PTE(L2 descriptor): 4KB page
#define PTE_TINY 0x3 // PTE(L2 descriptor): 1KB page
#define PTE_BUF 0x4 // bufferable
#define PTE_CACHE 0x8 // cachable
// PTE_INVALID has same value with PTE bit.
// | SVC | USR |
// |-------|-------|
#define PTE_PA 0x010 // | R/W | 0 |
#define PTE_URO 0x020 // | R/W | R |
#define PTE_FULL 0x030 // | R/W | R/W |
#define PTE_PR 0x210 // | R | 0 |
#define PTE_RO 0x220 // | R | R |
// I will use Coarse, Small pages only.
#define PGSIZE 65536 // set large page(64K).
// size of two-level page tables
#define UADDR_BITS 28 // maximum user-application memory, 256MB
#define UADDR_SZ (1 << UADDR_BITS) // maximum user address space size
/* ARM System Registers */
#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))
#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 TTBR1_R(val) __asm__ volatile("mrc p15, 0, %0, c2, c0, 1" : "=r"(val))
#define TTBR1_W(val) __asm__ volatile("mcr p15, 0, %0, c2, c0, 1" ::"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 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))
#define DISABLETLB(val) __asm__ volatile("mcr p15, 0, %0, c7, c5, 6" ::"r"(val))
#define CLEARTLB(val) __asm__ volatile("mcr p15, 0, %0, c8, c7, 0" ::"r"(val))
#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))
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
};
} PageEntry;
#endif

View File

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

View File

@ -0,0 +1,134 @@
#include "memlayout.h"
#include "mmu.h"
#include "vm.h"
#include <stdint.h>
extern uint32_t _dev_pte;
extern uint32_t _pte;
extern uint32_t _kt;
extern uint32_t _ut;
static void init_pgtbl(struct PageTable* pgtbl, uint32_t* pd_addr, uintptr_t paddr, uintptr_t len, PageEntry attr)
{
pgtbl->pd_addr = pd_addr;
pgtbl->mem_region.paddr_start = paddr;
pgtbl->mem_region.len = len;
attr.section_addr = 0;
pgtbl->mem_attr = attr.entry;
}
static void map_pgtbl(struct PageTable* pgtbl)
{
uint32_t pte_prange = (pgtbl->mem_region.len) >> PTE_SHIFT;
uint32_t pte_base = pgtbl->mem_region.paddr_start >> PTE_SHIFT;
for (uint32_t i = 0; i < pte_prange; i++) {
pgtbl->pd_addr[i] = ((i + pte_base) << PTE_SHIFT) | pgtbl->mem_attr;
}
}
static void init_pgdir(struct PageDirectory* pgdir, uint32_t* pd_addr, uintptr_t vrange)
{
pgdir->pd_addr = pd_addr;
pgdir->vrange = vrange;
}
static void map_pgdir(struct PageDirectory* pgdir, struct PageTable* pgtbl, uintptr_t vaddr)
{
uint32_t pgdir_offset = PDE_IDX(vaddr);
uint32_t pte_shift_offset = PDE_SHIFT - PTE_SHIFT;
uint32_t pde_range = pgtbl->mem_region.len >> PDE_SHIFT;
for (uint32_t i = 0; i < pde_range; i++) {
pgdir->pd_addr[i + pgdir_offset] = (uint32_t)(&pgtbl->pd_addr[i << pte_shift_offset]) | PDE_COARSE;
}
}
static void build_pages()
{
// attributes of kernel page table entry
PageEntry mem_attr;
mem_attr.entry = 0;
mem_attr.B = 1;
mem_attr.C = 1;
mem_attr.XN = 1;
mem_attr.desc_type = 0x2;
/* pte[0, PHYSTOP - PHYMEMBASE) -> [PHYMEMBASE, PHYSTOP) */
init_pgtbl(&boot_pgtbl, &_pte, PHYMEMBASE, PHYSTOP - PHYMEMBASE, mem_attr);
map_pgtbl(&boot_pgtbl);
/* ut[PHYMEMBASE, PHYSTOP) -> [PHYMEMBASE, PHYSTOP)
* kt[KERNBASE, VIRTMEM_END)-> [PHYMEMBASE, PHYSTOP)
*/
init_pgdir(&kpgdir, &_kt, PHYSTOP);
map_pgdir(&kpgdir, &boot_pgtbl, PHYMEMBASE);
map_pgdir(&kpgdir, &boot_pgtbl, KERNBASE);
// set_bootpgtbl(VEC_TBL, 0, 1 << PDE_SHIFT, 0);
// kt[(VEC_TBL >> PDE_SHIFT)] = (uint32_t)pte | PDE_COARSE;
/*identical mapping for dev memory
* currently for [0x00000000, 0x03000000)
*/
PageEntry dev_attr;
dev_attr.entry = 0;
dev_attr.XN = 1;
dev_attr.desc_type = 0x2;
init_pgtbl(&dev_pgtbl, &_dev_pte, DEVBASE, DEV_MEM_SZ, dev_attr);
map_pgtbl(&dev_pgtbl);
map_pgdir(&kpgdir, &dev_pgtbl, DEVBASE);
}
static void load_pgtbl()
{
uint32_t val;
DACR_W(0x55555555); // set domain access control as client
TTBCR_W(0x0);
TTBR0_W((uint32_t)kpgdir.pd_addr);
// 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
CLEARTLB(0);
}
void _active_vm()
{
build_pages();
load_pgtbl();
}
void _cancel_vm()
{
}
void _load_pgtbl(uintptr_t pgtbl_paddr)
{
uint32_t val;
SCTLR_R(val);
val &= ~0x3805; // Enable MMU, cache, write buffer, high vector tbl. Disable subpage.
SCTLR_W(val);
TTBR0_W(pgtbl_paddr);
// TTBR1_W((uint32_t)kpgdir.pd_addr);
SCTLR_R(val);
val |= 0x3805; // Enable MMU, cache, write buffer, high vector tbl. Disable subpage.
SCTLR_W(val);
CLEARTLB(0);
}
struct XiziVmDriver xizi_vm_driver = (struct XiziVmDriver) {
.active_vm = _active_vm,
.cancel_vm = _cancel_vm,
.load_pgtbl = _load_pgtbl,
};

View File

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

View File

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

View File

@ -30,7 +30,8 @@
#ifndef __GIC_H__
#define __GIC_H__
#include "sdk_types.h"
#include <stdbool.h>
#include <stdint.h>
//! @addtogroup gic
//! @{
@ -44,15 +45,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
@ -170,7 +170,6 @@ uint32_t gic_read_irq_ack(void);
void gic_write_end_of_irq(uint32_t irq_id);
//@}
#if defined(__cplusplus)
}
#endif

View File

@ -27,17 +27,16 @@
* (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"
#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 +46,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 +92,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

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011-2012, Freescale Semiconductor, Inc.
* Copyright (c) 2009-2012, Freescale Semiconductor, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -27,15 +27,34 @@
* (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 __INTERRUPT_H__
#define __INTERRUPT_H__
#if !defined(__PRINT_CLOCK_INFO_H__)
#define __PRINT_CLOCK_INFO_H__
#include "irq_numbers.h"
#include "sdk.h"
//! @addtogroup app_common
//! @addtogroup diag_interrupt
//! @{
/*!
* @file interrupt.h
* @brief Interface for the interrupt manager.
*/
////////////////////////////////////////////////////////////////////////////////
// Definitions
////////////////////////////////////////////////////////////////////////////////
//! @brief
typedef enum {
CPU_0,
CPU_1,
CPU_2,
CPU_3,
} cpuid_e;
//! @brief Interrupt service routine.
typedef void (*irq_hdlr_t)(void);
////////////////////////////////////////////////////////////////////////////////
// API
////////////////////////////////////////////////////////////////////////////////
@ -44,17 +63,30 @@
extern "C" {
#endif
//! @brief Enable an interrupt.
//!
//! Sets the interrupt priority and makes it non-secure. Then the interrupt is
//! enabled on the CPU specified by @a cpu_id.
//!
//! @param irq_id The interrupt number to enable.
//! @param cpu_id The index of the CPU for which the interrupt will be enabled.
//! @param priority The interrupt priority, from 0-255. Lower numbers have higher priority.
void enable_interrupt(uint32_t irq_id, uint32_t cpu_id, uint32_t priority);
/*!
* @brief Display module frequency
*/
void show_freq(void);
//! @brief Disable an interrupt on the specified CPU.
//!
//! @param irq_id The interrupt number to disabled.
//! @param cpu_id The index of the CPU for which the interrupt will be disabled.
void disable_interrupt(uint32_t irq_id, uint32_t cpu_id);
/*!
* @brief Display the board's DDR configuration
*/
void show_ddr_config(void);
//! @brief Set the interrupt service routine for the specified interrupt.
//!
//! @param irq_id The interrupt number.
//! @param isr Function that will be called to handle the interrupt.
void register_interrupt_routine(uint32_t irq_id, irq_hdlr_t isr);
//! @brief Interrupt handler that simply prints a message.
void default_interrupt_routine(void);
#if defined(__cplusplus)
}
@ -62,7 +94,7 @@ void show_ddr_config(void);
//! @}
#endif // __PRINT_CLOCK_INFO_H__
#endif
////////////////////////////////////////////////////////////////////////////////
// EOF
////////////////////////////////////////////////////////////////////////////////

View File

@ -0,0 +1,229 @@
/*
* 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.
*/
#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,5 @@
SRC_FILES := gic.c \
trap_entrance.S \
cortexA9.S
include $(KERNEL_ROOT)/compiler.mk

View File

@ -118,7 +118,8 @@ disable_L1_cache:
get_arm_private_peripheral_base:
@ Get base address of private perpherial space
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
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

@ -27,17 +27,17 @@
* (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"
#include "gic_registers.h"
#include <assert.h>
////////////////////////////////////////////////////////////////////////////////
// Prototypes
////////////////////////////////////////////////////////////////////////////////
static inline gicd_t * gic_get_gicd(void);
static inline gicc_t * gic_get_gicc(void);
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);
@ -46,16 +46,16 @@ static inline uint32_t irq_get_bit_mask(uint32_t irqID);
// 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;
return (gicd_t*)base;
}
static inline gicc_t * gic_get_gicc(void)
static inline gicc_t* gic_get_gicc(void)
{
uint32_t base = get_arm_private_peripheral_base() + kGICCBaseOffset;
return (gicc_t *)base;
return (gicc_t*)base;
}
static inline uint32_t irq_get_register_offset(uint32_t irqID)
@ -70,20 +70,17 @@ static inline uint32_t irq_get_bit_offset(uint32_t irqID)
static inline uint32_t irq_get_bit_mask(uint32_t irqID)
{
return 1 << irq_get_bit_offset(irqID);
return 1 << irq_get_bit_offset(irqID);
}
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 +88,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 +104,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,88 +130,78 @@ 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);
| (target_list << kBP_GICD_SGIR_CPUTargetList)
| (irqID & 0xf);
}
void gic_cpu_enable(bool enableIt)
{
gicc_t * gicc = gic_get_gicc();
if (enableIt)
{
gicc_t* gicc = gic_get_gicc();
if (enableIt) {
gicc->CTLR |= kBM_GICC_CTLR_EnableS | kBM_GICC_CTLR_EnableNS;
}
else
{
} 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;
gicc_t* gicc = gic_get_gicc();
gicc->PMR = priority & 0xff;
}
uint32_t gic_read_irq_ack(void)
inline uint32_t gic_read_irq_ack(void)
{
gicc_t * gicc = gic_get_gicc();
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_t* gicc = gic_get_gicc();
gicc->EOIR = irqID;
}
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);
}
@ -231,7 +212,7 @@ void gic_init_cpu(void)
gic_set_cpu_priority_mask(0xff);
// Disable preemption.
gicc_t * gicc = gic_get_gicc();
gicc_t* gicc = gic_get_gicc();
gicc->BPR = 7;
// Enable signaling the CPU.

View File

@ -0,0 +1,113 @@
//low-level trap handler glue code
#include "cpu.h"
.text
.code 32
.global trap_irq_enter
.global trap_reset_enter
.global trap_iabort
.global trap_return
.global init_stack
.global get_fp
# restore states
trap_return:
ldmfd r13, {sp, lr}^ // restore user mode sp and lr
add r13, r13, #8
ldmfd r13!, {r14} // restore r14
ldmfd r13!, {r2} // restore spsr
msr spsr_cxsf, r2
ldmfd r13!,{r0-r12, pc}^ // restore context and return
# handle IRQ, we allow nested IRQs
trap_irq_enter:
# save a few registers to the irq stack to provide scratch regs.
# r14 (lr_irq) contains the instruction (pc) to return to, need to
# save it on the stack as r14 is banked
sub r14, r14, #4 // r14 (lr) contains the interrupted PC
stmfd r13!, {r0-r2, r14} //
mrs r1, spsr // save spsr_irq
mov r0, r13 // save stack stop (r13_irq)
add r13, r13, #16 // reset the IRQ stack
# switch to the SVC mode
mrs r2, cpsr
bic r2, r2, #MODE_MASK
orr r2, r2, #SVC_MODE
msr cpsr_cxsf, r2
# now, in SVC mode, sp, lr, pc (r13, r14, r15) are all banked
# build the trap frame
ldr r2, [r0, #12] // read the r14_irq, then save it
stmfd r13!, {r2}
stmfd r13!, {r3-r12} // r4-r12 are preserved (non-banked)
ldmfd r0, {r3-r5} // copy r0-r2 over from irq stack
stmfd r13!, {r3-r5}
stmfd r13!, {r1} // save spsr
stmfd r13!, {lr} // save r14_svc
stmfd r13, {sp, lr}^ // save user mode sp and lr
sub r13, r13, #8
# get the parameters, then call the handler
mov r0, r13 // points to
bl irq_distribute
# restore the previous status
b trap_return
# handle reset/undefine instruction/abort/not-assigned/fiq
# these handler does not allow nested handling
trap_reset_enter:
mov r14, #0 // lr: not defined on reset
stmfd r13!, {r0-r12, r14}
mrs r2, spsr // copy spsr to r2
stmfd r13!, {r2} // save r2(spsr) to the stack
stmfd r13!, {r14} // save r14 again (it is not really correct)
stmfd r13, {sp, lr}^ // save user mode sp and lr
sub r13, r13, #8
# call traps (trapframe *fp)
mov r0, r13 // copy r13_svc to r0
bl _vector_jumper
trap_iabort:
sub r14, r14, #4 // lr: instruction causing the abort
stmfd r13!, {r0-r12, r14}
mrs r2, spsr // copy spsr to r2
stmfd r13!, {r2} // save r2(spsr) to the stack
stmfd r13!, {r14} // save r14 again (it is not really correct)
stmfd r13, {sp, lr}^ // save user mode sp and lr
sub r13, r13, #8
# call traps (trapframe *fp)
mov r0, r13 // save trapframe as the first parameter
bl iabort_handler
# set the stack for IRQ mode, we can use r0-r3 for free
# input: r0 = #mode, r1 = stk
init_stack:
# switch to the IRQ mode
mrs r2, cpsr
bic r2, r2, #MODE_MASK
orr r2, r2, r0
msr cpsr_cxsf, r2
# set the stack pointer, sp register is banked, so we need to switch mode
mov sp, r1
# switch back to the SVC mode
bic r2, r2, #MODE_MASK
orr r2, r2, #SVC_MODE
msr cpsr_cxsf, r2
# return
bx lr
get_fp:
mov r0, fp
bx lr

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