diff --git a/drivers/rz/CMakeLists.txt b/drivers/rz/CMakeLists.txt index 05148bc0..0abf9f29 100644 --- a/drivers/rz/CMakeLists.txt +++ b/drivers/rz/CMakeLists.txt @@ -4,6 +4,7 @@ string(SUBSTRING ${CONFIG_SOC_SERIES} 0 3 SOC_SERIES_PREFIX) add_subdirectory(fsp/src/${SOC_SERIES_PREFIX}) +add_subdirectory_ifdef(CONFIG_BUILD_WITH_RZA_IPL ipl/${SOC_SERIES_PREFIX}) set(include_dirs fsp/inc diff --git a/drivers/rz/README b/drivers/rz/fsp/README similarity index 100% rename from drivers/rz/README rename to drivers/rz/fsp/README diff --git a/drivers/rz/ipl/rza/CMakeLists.txt b/drivers/rz/ipl/rza/CMakeLists.txt new file mode 100644 index 00000000..b48333ac --- /dev/null +++ b/drivers/rz/ipl/rza/CMakeLists.txt @@ -0,0 +1,33 @@ +# SPDX-License-Identifier: Apache-2.0 + +if(CONFIG_BUILD_WITH_RZA_IPL) + set(rza_ipl_binary_dir ${CMAKE_BINARY_DIR}/rza_ipl) + + file(MAKE_DIRECTORY ${rza_ipl_binary_dir}) + + include(ExternalProject) + + set(rza_ipl_image_info MAP "name: rza_ipl, source-dir: ${CMAKE_CURRENT_SOURCE_DIR}") + build_info(images VALUE ${rza_ipl_image_info}) + + if(CONFIG_RZA_IPL_BUILD_DEBUG) + set(ipl_build_debug "1") + else() + set(ipl_build_debug "0") + endif() + + ExternalProject_Add( + rza_ipl + SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR} + BINARY_DIR ${rza_ipl_binary_dir} + CONFIGURE_COMMAND "" + BUILD_COMMAND make -C ${CMAKE_CURRENT_SOURCE_DIR} + DEBUG=${ipl_build_debug} + CROSS_COMPILE=${CROSS_COMPILE} + BUILD_BASE=${rza_ipl_binary_dir} + PLAT=${RZA_PLAT} BOARD=${RZA_BOARD} all + INSTALL_COMMAND "" + BUILD_ALWAYS True + USES_TERMINAL_BUILD True + ) +endif() diff --git a/drivers/rz/ipl/rza/Makefile b/drivers/rz/ipl/rza/Makefile new file mode 100644 index 00000000..2376b9ac --- /dev/null +++ b/drivers/rz/ipl/rza/Makefile @@ -0,0 +1,1389 @@ +# +# Copyright (c) 2013-2021, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# +# Trusted Firmware Version +# +VERSION_MAJOR := 2 +VERSION_MINOR := 5 + +# Default goal is build all images +.DEFAULT_GOAL := all + +# Avoid any implicit propagation of command line variable definitions to +# sub-Makefiles, like CFLAGS that we reserved for the firmware images' +# usage. Other command line options like "-s" are still propagated as usual. +MAKEOVERRIDES = + +MAKE_HELPERS_DIRECTORY := make_helpers/ +include ${MAKE_HELPERS_DIRECTORY}build_macros.mk +include ${MAKE_HELPERS_DIRECTORY}build_env.mk + +################################################################################ +# Default values for build configurations, and their dependencies +################################################################################ + +include ${MAKE_HELPERS_DIRECTORY}defaults.mk + +# Assertions enabled for DEBUG builds by default +ENABLE_ASSERTIONS := ${DEBUG} +ENABLE_PMF := ${ENABLE_RUNTIME_INSTRUMENTATION} +PLAT := ${DEFAULT_PLAT} + +################################################################################ +# Checkpatch script options +################################################################################ + +CHECKCODE_ARGS := --no-patch +# Do not check the coding style on imported library files or documentation files +INC_ARM_DIRS_TO_CHECK := $(sort $(filter-out \ + include/drivers/arm/cryptocell, \ + $(wildcard include/drivers/arm/*))) +INC_ARM_DIRS_TO_CHECK += include/drivers/arm/cryptocell/*.h +INC_DRV_DIRS_TO_CHECK := $(sort $(filter-out \ + include/drivers/arm, \ + $(wildcard include/drivers/*))) +INC_LIB_DIRS_TO_CHECK := $(sort $(filter-out \ + include/lib/libfdt \ + include/lib/libc, \ + $(wildcard include/lib/*))) +INC_DIRS_TO_CHECK := $(sort $(filter-out \ + include/lib \ + include/drivers, \ + $(wildcard include/*))) +LIB_DIRS_TO_CHECK := $(sort $(filter-out \ + lib/compiler-rt \ + lib/libfdt% \ + lib/libc, \ + $(wildcard lib/*))) +ROOT_DIRS_TO_CHECK := $(sort $(filter-out \ + lib \ + include \ + docs \ + %.rst, \ + $(wildcard *))) +CHECK_PATHS := ${ROOT_DIRS_TO_CHECK} \ + ${INC_DIRS_TO_CHECK} \ + ${INC_LIB_DIRS_TO_CHECK} \ + ${LIB_DIRS_TO_CHECK} \ + ${INC_DRV_DIRS_TO_CHECK} \ + ${INC_ARM_DIRS_TO_CHECK} + + +################################################################################ +# Process build options +################################################################################ + +# Verbose flag +ifeq (${V},0) + Q:=@ + ECHO:=@echo + CHECKCODE_ARGS += --no-summary --terse +else + Q:= + ECHO:=$(ECHO_QUIET) +endif + +ifneq ($(findstring s,$(filter-out --%,$(MAKEFLAGS))),) + Q:=@ + ECHO:=$(ECHO_QUIET) +endif + +export Q ECHO + +# The cert_create tool cannot generate certificates individually, so we use the +# target 'certificates' to create them all +ifneq (${GENERATE_COT},0) + FIP_DEPS += certificates + FWU_FIP_DEPS += fwu_certificates +endif + +# Process BRANCH_PROTECTION value and set +# Pointer Authentication and Branch Target Identification flags +ifeq (${BRANCH_PROTECTION},0) + # Default value turns off all types of branch protection + BP_OPTION := none +else ifneq (${ARCH},aarch64) + $(error BRANCH_PROTECTION requires AArch64) +else ifeq (${BRANCH_PROTECTION},1) + # Enables all types of branch protection features + BP_OPTION := standard + ENABLE_BTI := 1 + ENABLE_PAUTH := 1 +else ifeq (${BRANCH_PROTECTION},2) + # Return address signing to its standard level + BP_OPTION := pac-ret + ENABLE_PAUTH := 1 +else ifeq (${BRANCH_PROTECTION},3) + # Extend the signing to include leaf functions + BP_OPTION := pac-ret+leaf + ENABLE_PAUTH := 1 +else ifeq (${BRANCH_PROTECTION},4) + # Turn on branch target identification mechanism + BP_OPTION := bti + ENABLE_BTI := 1 +else + $(error Unknown BRANCH_PROTECTION value ${BRANCH_PROTECTION}) +endif + +# USE_SPINLOCK_CAS requires AArch64 build +ifeq (${USE_SPINLOCK_CAS},1) +ifneq (${ARCH},aarch64) + $(error USE_SPINLOCK_CAS requires AArch64) +else + $(info USE_SPINLOCK_CAS is an experimental feature) +endif +endif + +# USE_DEBUGFS experimental feature recommended only in debug builds +ifeq (${USE_DEBUGFS},1) +ifeq (${DEBUG},1) + $(warning DEBUGFS experimental feature is enabled.) +else + $(warning DEBUGFS experimental, recommended in DEBUG builds ONLY) +endif +endif + +ifneq (${DECRYPTION_SUPPORT},none) +ENC_ARGS += -f ${FW_ENC_STATUS} +ENC_ARGS += -k ${ENC_KEY} +ENC_ARGS += -n ${ENC_NONCE} +FIP_DEPS += enctool +FWU_FIP_DEPS += enctool +endif + +################################################################################ +# Toolchain +################################################################################ + +HOSTCC := gcc +export HOSTCC + +CC := ${CROSS_COMPILE}gcc +CPP := ${CROSS_COMPILE}cpp +AS := ${CROSS_COMPILE}gcc +AR := ${CROSS_COMPILE}ar +LINKER := ${CROSS_COMPILE}ld +OC := ${CROSS_COMPILE}objcopy +OD := ${CROSS_COMPILE}objdump +NM := ${CROSS_COMPILE}nm +PP := ${CROSS_COMPILE}gcc -E +DTC := dtc + +# Use ${LD}.bfd instead if it exists (as absolute path or together with $PATH). +ifneq ($(strip $(wildcard ${LD}.bfd) \ + $(foreach dir,$(subst :, ,${PATH}),$(wildcard ${dir}/${LINKER}.bfd))),) +LINKER := ${LINKER}.bfd +endif + +ifeq (${ARM_ARCH_MAJOR},7) +target32-directive = -target arm-none-eabi +# Will set march32-directive from platform configuration +else +target32-directive = -target armv8a-none-eabi + +# Set the compiler's target architecture profile based on +# ARM_ARCH_MAJOR ARM_ARCH_MINOR options +ifeq (${ARM_ARCH_MINOR},0) +march32-directive = -march=armv${ARM_ARCH_MAJOR}-a +march64-directive = -march=armv${ARM_ARCH_MAJOR}-a +else +march32-directive = -march=armv${ARM_ARCH_MAJOR}.${ARM_ARCH_MINOR}-a +march64-directive = -march=armv${ARM_ARCH_MAJOR}.${ARM_ARCH_MINOR}-a +endif +endif + +# Memory tagging is supported in architecture Armv8.5-A AArch64 and onwards +ifeq ($(ARCH), aarch64) +# Check if revision is greater than or equal to 8.5 +ifeq "8.5" "$(word 1, $(sort 8.5 $(ARM_ARCH_MAJOR).$(ARM_ARCH_MINOR)))" +mem_tag_arch_support = yes +endif +endif + +# Get architecture feature modifiers +arch-features = ${ARM_ARCH_FEATURE} + +# Enable required options for memory stack tagging. +# Currently, these options are enabled only for clang and armclang compiler. +ifeq (${SUPPORT_STACK_MEMTAG},yes) +ifdef mem_tag_arch_support +# Check for armclang and clang compilers +ifneq ( ,$(filter $(notdir $(CC)),armclang clang)) +# Add "memtag" architecture feature modifier if not specified +ifeq ( ,$(findstring memtag,$(arch-features))) +arch-features := $(arch-features)+memtag +endif # memtag +ifeq ($(notdir $(CC)),armclang) +TF_CFLAGS += -mmemtag-stack +else ifeq ($(notdir $(CC)),clang) +TF_CFLAGS += -fsanitize=memtag +endif # armclang +endif # armclang clang +else +$(error "Error: stack memory tagging is not supported for architecture \ + ${ARCH},armv${ARM_ARCH_MAJOR}.${ARM_ARCH_MINOR}-a") +endif # mem_tag_arch_support +endif # SUPPORT_STACK_MEMTAG + +# Set the compiler's architecture feature modifiers +ifneq ($(arch-features), none) +# Strip "none+" from arch-features +arch-features := $(subst none+,,$(arch-features)) +ifeq ($(ARCH), aarch32) +march32-directive := $(march32-directive)+$(arch-features) +else +march64-directive := $(march64-directive)+$(arch-features) +endif +# Print features +$(info Arm Architecture Features specified: $(subst +, ,$(arch-features))) +endif # arch-features + +# Determine if FEAT_RNG is supported +ENABLE_FEAT_RNG = $(if $(findstring rng,${arch-features}),1,0) + +# Determine if FEAT_SB is supported +ENABLE_FEAT_SB = $(if $(findstring sb,${arch-features}),1,0) + +ifeq "8.5" "$(word 1, $(sort 8.5 $(ARM_ARCH_MAJOR).$(ARM_ARCH_MINOR)))" +ENABLE_FEAT_SB = 1 +endif + +ifneq ($(findstring armclang,$(notdir $(CC))),) +TF_CFLAGS_aarch32 = -target arm-arm-none-eabi $(march32-directive) +TF_CFLAGS_aarch64 = -target aarch64-arm-none-eabi $(march64-directive) +LD = $(LINKER) +AS = $(CC) -c -x assembler-with-cpp $(TF_CFLAGS_$(ARCH)) +CPP = $(CC) -E $(TF_CFLAGS_$(ARCH)) +PP = $(CC) -E $(TF_CFLAGS_$(ARCH)) +else ifneq ($(findstring clang,$(notdir $(CC))),) +CLANG_CCDIR = $(if $(filter-out ./,$(dir $(CC))),$(dir $(CC)),) +TF_CFLAGS_aarch32 = $(target32-directive) $(march32-directive) +TF_CFLAGS_aarch64 = -target aarch64-elf $(march64-directive) +LD = $(CLANG_CCDIR)ld.lld +ifeq (, $(shell which $(LD))) +$(error "No $(LD) in PATH, make sure it is installed or set LD to a different linker") +endif +AS = $(CC) -c -x assembler-with-cpp $(TF_CFLAGS_$(ARCH)) +CPP = $(CC) -E +PP = $(CC) -E +else ifneq ($(findstring gcc,$(notdir $(CC))),) +TF_CFLAGS_aarch32 = $(march32-directive) +TF_CFLAGS_aarch64 = $(march64-directive) +ifeq ($(ENABLE_LTO),1) + # Enable LTO only for aarch64 + ifeq (${ARCH},aarch64) + LTO_CFLAGS = -flto + # Use gcc as a wrapper for the ld, recommended for LTO + LINKER := ${CROSS_COMPILE}gcc + endif +endif +LD = $(LINKER) +else +TF_CFLAGS_aarch32 = $(march32-directive) +TF_CFLAGS_aarch64 = $(march64-directive) +LD = $(LINKER) +endif + +# Process Debug flag +$(eval $(call add_define,DEBUG)) +ifneq (${DEBUG}, 0) + BUILD_TYPE := debug + TF_CFLAGS += -g + + ifneq ($(findstring clang,$(notdir $(CC))),) + ASFLAGS += -g + else + ASFLAGS += -g -Wa,--gdwarf-2 + endif + + # Use LOG_LEVEL_INFO by default for debug builds + LOG_LEVEL := 40 +else + BUILD_TYPE := release + # Use LOG_LEVEL_NOTICE by default for release builds + LOG_LEVEL := 20 +endif + +# Default build string (git branch and commit) +ifeq (${BUILD_STRING},) + BUILD_STRING := $(shell git describe --always --dirty --tags 2> /dev/null) +endif +VERSION_STRING := v${VERSION_MAJOR}.${VERSION_MINOR}(${BUILD_TYPE}):${BUILD_STRING} + +ifeq (${AARCH32_INSTRUCTION_SET},A32) +TF_CFLAGS_aarch32 += -marm +else ifeq (${AARCH32_INSTRUCTION_SET},T32) +TF_CFLAGS_aarch32 += -mthumb +else +$(error Error: Unknown AArch32 instruction set ${AARCH32_INSTRUCTION_SET}) +endif + +TF_CFLAGS_aarch32 += -mno-unaligned-access +TF_CFLAGS_aarch64 += -mgeneral-regs-only -mstrict-align + +ifneq (${BP_OPTION},none) +TF_CFLAGS_aarch64 += -mbranch-protection=${BP_OPTION} +endif + +ASFLAGS_aarch32 = $(march32-directive) +ASFLAGS_aarch64 = $(march64-directive) + +# General warnings +WARNINGS := -Wall -Wmissing-include-dirs -Wunused \ + -Wdisabled-optimization -Wvla -Wshadow \ + -Wno-unused-parameter -Wredundant-decls + +# Additional warnings +# Level 1 +WARNING1 := -Wextra +WARNING1 += -Wmissing-format-attribute +WARNING1 += -Wmissing-prototypes +WARNING1 += -Wold-style-definition + +# Level 2 +WARNING2 := -Waggregate-return +WARNING2 += -Wcast-align +WARNING2 += -Wnested-externs + +WARNING3 := -Wbad-function-cast +WARNING3 += -Wcast-qual +WARNING3 += -Wconversion +WARNING3 += -Wpacked +WARNING3 += -Wpointer-arith +WARNING3 += -Wswitch-default + +ifeq (${W},1) +WARNINGS += $(WARNING1) +else ifeq (${W},2) +WARNINGS += $(WARNING1) $(WARNING2) +else ifeq (${W},3) +WARNINGS += $(WARNING1) $(WARNING2) $(WARNING3) +endif + +# Compiler specific warnings +ifeq ($(findstring clang,$(notdir $(CC))),) +# not using clang +WARNINGS += -Wunused-but-set-variable -Wmaybe-uninitialized \ + -Wpacked-bitfield-compat -Wshift-overflow=2 \ + -Wlogical-op +else +# using clang +WARNINGS += -Wshift-overflow -Wshift-sign-overflow \ + -Wlogical-op-parentheses +endif + +ifneq (${E},0) +ERRORS := -Werror +endif + +CPPFLAGS = ${DEFINES} ${INCLUDES} ${MBEDTLS_INC} -nostdinc \ + $(ERRORS) $(WARNINGS) +ASFLAGS += $(CPPFLAGS) $(ASFLAGS_$(ARCH)) \ + -ffreestanding -Wa,--fatal-warnings +TF_CFLAGS += $(CPPFLAGS) $(TF_CFLAGS_$(ARCH)) \ + -ffunction-sections -fdata-sections \ + -ffreestanding -fno-builtin -fno-common \ + -Os -std=gnu99 + +ifeq (${SANITIZE_UB},on) +TF_CFLAGS += -fsanitize=undefined -fno-sanitize-recover +endif +ifeq (${SANITIZE_UB},trap) +TF_CFLAGS += -fsanitize=undefined -fno-sanitize-recover \ + -fsanitize-undefined-trap-on-error +endif + +GCC_V_OUTPUT := $(shell $(CC) -v 2>&1) + +# LD = armlink +ifneq ($(findstring armlink,$(notdir $(LD))),) +TF_LDFLAGS += --diag_error=warning --lto_level=O1 +TF_LDFLAGS += --remove --info=unused,unusedsymbols +TF_LDFLAGS += $(TF_LDFLAGS_$(ARCH)) + +# LD = gcc (used when GCC LTO is enabled) +else ifneq ($(findstring gcc,$(notdir $(LD))),) +# Pass ld options with Wl or Xlinker switches +TF_LDFLAGS += -Wl,--fatal-warnings -O1 +TF_LDFLAGS += -Wl,--gc-sections +ifeq ($(ENABLE_LTO),1) + ifeq (${ARCH},aarch64) + TF_LDFLAGS += -flto -fuse-linker-plugin + endif +endif +# GCC automatically adds fix-cortex-a53-843419 flag when used to link +# which breaks some builds, so disable if errata fix is not explicitly enabled +ifneq (${ERRATA_A53_843419},1) + TF_LDFLAGS += -mno-fix-cortex-a53-843419 +endif +TF_LDFLAGS += -nostdlib +TF_LDFLAGS += $(subst --,-Xlinker --,$(TF_LDFLAGS_$(ARCH))) + +# LD = gcc-ld (ld) or llvm-ld (ld.lld) or other +else +TF_LDFLAGS += --fatal-warnings -O1 +TF_LDFLAGS += --gc-sections +# ld.lld doesn't recognize the errata flags, +# therefore don't add those in that case +ifeq ($(findstring ld.lld,$(notdir $(LD))),) +TF_LDFLAGS += $(TF_LDFLAGS_$(ARCH)) +endif +endif + +DTC_FLAGS += -I dts -O dtb +DTC_CPPFLAGS += -P -nostdinc -Iinclude -Ifdts -undef \ + -x assembler-with-cpp $(DEFINES) + +ifeq ($(MEASURED_BOOT),1) +DTC_CPPFLAGS += -DMEASURED_BOOT -DBL2_HASH_SIZE=${TCG_DIGEST_SIZE} +endif + +################################################################################ +# Common sources and include directories +################################################################################ +include lib/compiler-rt/compiler-rt.mk + +BL_COMMON_SOURCES += common/bl_common.c \ + common/tf_log.c \ + common/${ARCH}/debug.S \ + drivers/console/multi_console.c \ + lib/${ARCH}/cache_helpers.S \ + lib/${ARCH}/misc_helpers.S \ + plat/common/plat_bl_common.c \ + plat/common/plat_log_common.c \ + plat/common/${ARCH}/plat_common.c \ + plat/common/${ARCH}/platform_helpers.S \ + ${COMPILER_RT_SRCS} + +ifeq ($(notdir $(CC)),armclang) +BL_COMMON_SOURCES += lib/${ARCH}/armclang_printf.S +endif + +ifeq (${SANITIZE_UB},on) +BL_COMMON_SOURCES += plat/common/ubsan.c +endif + +INCLUDES += -Iinclude \ + -Iinclude/arch/${ARCH} \ + -Iinclude/lib/cpus/${ARCH} \ + -Iinclude/lib/el3_runtime/${ARCH} \ + ${PLAT_INCLUDES} \ + ${SPD_INCLUDES} + +include common/backtrace/backtrace.mk + +################################################################################ +# Generic definitions +################################################################################ + +include ${MAKE_HELPERS_DIRECTORY}plat_helpers.mk + +ifeq (${BUILD_BASE},) + BUILD_BASE := ./build +endif +BUILD_PLAT := $(abspath ${BUILD_BASE})/${PLAT}/${BUILD_TYPE} + +SPDS := $(sort $(filter-out none, $(patsubst services/spd/%,%,$(wildcard services/spd/*)))) + +# Platforms providing their own TBB makefile may override this value +INCLUDE_TBBR_MK := 1 + + +################################################################################ +# Include SPD Makefile if one has been specified +################################################################################ + +ifneq (${SPD},none) + ifeq (${ARCH},aarch32) + $(error "Error: SPD is incompatible with AArch32.") + endif + + ifdef EL3_PAYLOAD_BASE + $(warning "SPD and EL3_PAYLOAD_BASE are incompatible build options.") + $(warning "The SPD and its BL32 companion will be present but ignored.") + endif + + ifeq (${SPD},spmd) + $(warning "SPMD is an experimental feature") + # SPMD is located in std_svc directory + SPD_DIR := std_svc + + ifeq ($(SPMD_SPM_AT_SEL2),1) + ifeq ($(CTX_INCLUDE_EL2_REGS),0) + $(error SPMD with SPM at S-EL2 requires CTX_INCLUDE_EL2_REGS option) + endif + endif + + ifeq ($(findstring optee_sp,$(ARM_SPMC_MANIFEST_DTS)),optee_sp) + DTC_CPPFLAGS += -DOPTEE_SP_FW_CONFIG + endif + else + # All other SPDs in spd directory + SPD_DIR := spd + endif + + # We expect to locate an spd.mk under the specified SPD directory + SPD_MAKE := $(wildcard services/${SPD_DIR}/${SPD}/${SPD}.mk) + + ifeq (${SPD_MAKE},) + $(error Error: No services/${SPD_DIR}/${SPD}/${SPD}.mk located) + endif + $(info Including ${SPD_MAKE}) + include ${SPD_MAKE} + + # If there's BL32 companion for the chosen SPD, we expect that the SPD's + # Makefile would set NEED_BL32 to "yes". In this case, the build system + # supports two mutually exclusive options: + # * BL32 is built from source: then BL32_SOURCES must contain the list + # of source files to build BL32 + # * BL32 is a prebuilt binary: then BL32 must point to the image file + # that will be included in the FIP + # If both BL32_SOURCES and BL32 are defined, the binary takes precedence + # over the sources. +endif + +################################################################################ +# Include the platform specific Makefile after the SPD Makefile (the platform +# makefile may use all previous definitions in this file) +################################################################################ + +include ${PLAT_MAKEFILE_FULL} + +$(eval $(call MAKE_PREREQ_DIR,${BUILD_PLAT})) + +ifeq (${ARM_ARCH_MAJOR},7) +include make_helpers/armv7-a-cpus.mk +endif + +PIE_FOUND := $(findstring --enable-default-pie,${GCC_V_OUTPUT}) +ifneq ($(PIE_FOUND),) + TF_CFLAGS += -fno-PIE +endif + +ifneq ($(findstring gcc,$(notdir $(LD))),) + PIE_LDFLAGS += -Wl,-pie -Wl,--no-dynamic-linker +else + PIE_LDFLAGS += -pie --no-dynamic-linker +endif + +ifeq ($(ENABLE_PIE),1) +ifeq ($(BL2_AT_EL3),1) +ifneq ($(BL2_IN_XIP_MEM),1) + BL2_CFLAGS += -fpie + BL2_LDFLAGS += $(PIE_LDFLAGS) +endif +endif + BL31_CFLAGS += -fpie + BL31_LDFLAGS += $(PIE_LDFLAGS) + BL32_CFLAGS += -fpie + BL32_LDFLAGS += $(PIE_LDFLAGS) +endif + +ifeq (${ARCH},aarch64) +BL1_CPPFLAGS += -DIMAGE_AT_EL3 +ifeq ($(BL2_AT_EL3),1) +BL2_CPPFLAGS += -DIMAGE_AT_EL3 +else +BL2_CPPFLAGS += -DIMAGE_AT_EL1 +endif +BL2U_CPPFLAGS += -DIMAGE_AT_EL1 +BL31_CPPFLAGS += -DIMAGE_AT_EL3 +BL32_CPPFLAGS += -DIMAGE_AT_EL1 +endif + +# Include the CPU specific operations makefile, which provides default +# values for all CPU errata workarounds and CPU specific optimisations. +# This can be overridden by the platform. +include lib/cpus/cpu-ops.mk + +ifeq (${ARCH},aarch32) +NEED_BL32 := yes + +################################################################################ +# Build `AARCH32_SP` as BL32 image for AArch32 +################################################################################ +ifneq (${AARCH32_SP},none) +# We expect to locate an sp.mk under the specified AARCH32_SP directory +AARCH32_SP_MAKE := $(wildcard bl32/${AARCH32_SP}/${AARCH32_SP}.mk) + +ifeq (${AARCH32_SP_MAKE},) + $(error Error: No bl32/${AARCH32_SP}/${AARCH32_SP}.mk located) +endif + +$(info Including ${AARCH32_SP_MAKE}) +include ${AARCH32_SP_MAKE} +endif + +endif + +################################################################################ +# Include libc if not overridden +################################################################################ +ifeq (${OVERRIDE_LIBC},0) +include lib/libc/libc.mk +endif + +################################################################################ +# Check incompatible options +################################################################################ + +ifdef EL3_PAYLOAD_BASE + ifdef PRELOADED_BL33_BASE + $(warning "PRELOADED_BL33_BASE and EL3_PAYLOAD_BASE are \ + incompatible build options. EL3_PAYLOAD_BASE has priority.") + endif + ifneq (${GENERATE_COT},0) + $(error "GENERATE_COT and EL3_PAYLOAD_BASE are incompatible build options.") + endif + ifneq (${TRUSTED_BOARD_BOOT},0) + $(error "TRUSTED_BOARD_BOOT and EL3_PAYLOAD_BASE are incompatible build options.") + endif +endif + +ifeq (${NEED_BL33},yes) + ifdef EL3_PAYLOAD_BASE + $(warning "BL33 image is not needed when option \ + BL33_PAYLOAD_BASE is used and won't be added to the FIP file.") + endif + ifdef PRELOADED_BL33_BASE + $(warning "BL33 image is not needed when option \ + PRELOADED_BL33_BASE is used and won't be added to the FIP \ + file.") + endif +endif + +# When building for systems with hardware-assisted coherency, there's no need to +# use USE_COHERENT_MEM. Require that USE_COHERENT_MEM must be set to 0 too. +ifeq ($(HW_ASSISTED_COHERENCY)-$(USE_COHERENT_MEM),1-1) +$(error USE_COHERENT_MEM cannot be enabled with HW_ASSISTED_COHERENCY) +endif + +#For now, BL2_IN_XIP_MEM is only supported when BL2_AT_EL3 is 1. +ifeq ($(BL2_AT_EL3)-$(BL2_IN_XIP_MEM),0-1) +$(error "BL2_IN_XIP_MEM is only supported when BL2_AT_EL3 is enabled") +endif + +# For RAS_EXTENSION, require that EAs are handled in EL3 first +ifeq ($(RAS_EXTENSION),1) + ifneq ($(HANDLE_EA_EL3_FIRST),1) + $(error For RAS_EXTENSION, HANDLE_EA_EL3_FIRST must also be 1) + endif +endif + +# When FAULT_INJECTION_SUPPORT is used, require that RAS_EXTENSION is enabled +ifeq ($(FAULT_INJECTION_SUPPORT),1) + ifneq ($(RAS_EXTENSION),1) + $(error For FAULT_INJECTION_SUPPORT, RAS_EXTENSION must also be 1) + endif +endif + +# DYN_DISABLE_AUTH can be set only when TRUSTED_BOARD_BOOT=1 +ifeq ($(DYN_DISABLE_AUTH), 1) + ifeq (${TRUSTED_BOARD_BOOT}, 0) + $(error "TRUSTED_BOARD_BOOT must be enabled for DYN_DISABLE_AUTH to be set.") + endif +endif + +# SDEI_IN_FCONF is only supported when SDEI_SUPPORT is enabled. +ifeq ($(SDEI_SUPPORT)-$(SDEI_IN_FCONF),0-1) +$(error "SDEI_IN_FCONF is an experimental feature and is only supported when \ + SDEI_SUPPORT is enabled") +endif + +ifeq ($(COT_DESC_IN_DTB),1) + $(info CoT in device tree is an experimental feature) +endif + +# If pointer authentication is used in the firmware, make sure that all the +# registers associated to it are also saved and restored. +# Not doing it would leak the value of the keys used by EL3 to EL1 and S-EL1. +ifeq ($(ENABLE_PAUTH),1) + ifeq ($(CTX_INCLUDE_PAUTH_REGS),0) + $(error Pointer Authentication requires CTX_INCLUDE_PAUTH_REGS=1) + endif +endif + +ifeq ($(CTX_INCLUDE_PAUTH_REGS),1) + ifneq (${ARCH},aarch64) + $(error CTX_INCLUDE_PAUTH_REGS requires AArch64) + else + $(info CTX_INCLUDE_PAUTH_REGS is an experimental feature) + endif +endif + +ifeq ($(ENABLE_PAUTH),1) + $(info Pointer Authentication is an experimental feature) +endif + +ifeq ($(ENABLE_BTI),1) + $(info Branch Protection is an experimental feature) +endif + +ifeq ($(CTX_INCLUDE_MTE_REGS),1) + ifneq (${ARCH},aarch64) + $(error CTX_INCLUDE_MTE_REGS requires AArch64) + else + $(info CTX_INCLUDE_MTE_REGS is an experimental feature) + endif +endif + +ifeq ($(MEASURED_BOOT),1) + ifneq (${TRUSTED_BOARD_BOOT},1) + $(error MEASURED_BOOT requires TRUSTED_BOARD_BOOT=1) + else + $(info MEASURED_BOOT is an experimental feature) + endif +endif + +ifeq (${ARM_XLAT_TABLES_LIB_V1}, 1) + ifeq (${ALLOW_RO_XLAT_TABLES}, 1) + $(error "ALLOW_RO_XLAT_TABLES requires translation tables library v2") + endif +endif + +ifneq (${DECRYPTION_SUPPORT},none) + ifeq (${TRUSTED_BOARD_BOOT}, 0) + $(error TRUSTED_BOARD_BOOT must be enabled for DECRYPTION_SUPPORT to be set) + else + $(info DECRYPTION_SUPPORT is an experimental feature) + endif +endif + +################################################################################ +# Process platform overrideable behaviour +################################################################################ + +# Using BL2 implies that a BL33 image also needs to be supplied for the FIP and +# Certificate generation tools. This flag can be overridden by the platform. +ifdef BL2_SOURCES + ifdef EL3_PAYLOAD_BASE + # If booting an EL3 payload there is no need for a BL33 image + # in the FIP file. + NEED_BL33 := no + else + ifdef PRELOADED_BL33_BASE + # If booting a BL33 preloaded image there is no need of + # another one in the FIP file. + NEED_BL33 := no + else + NEED_BL33 ?= yes + endif + endif +endif + +# If SCP_BL2 is given, we always want FIP to include it. +ifdef SCP_BL2 + NEED_SCP_BL2 := yes +endif + +# For AArch32, BL31 is not currently supported. +ifneq (${ARCH},aarch32) + ifdef BL31_SOURCES + # When booting an EL3 payload, there is no need to compile the BL31 image nor + # put it in the FIP. + ifndef EL3_PAYLOAD_BASE + NEED_BL31 := yes + endif + endif +endif + +# Process TBB related flags +ifneq (${GENERATE_COT},0) + # Common cert_create options + ifneq (${CREATE_KEYS},0) + $(eval CRT_ARGS += -n) + $(eval FWU_CRT_ARGS += -n) + ifneq (${SAVE_KEYS},0) + $(eval CRT_ARGS += -k) + $(eval FWU_CRT_ARGS += -k) + endif + endif + # Include TBBR makefile (unless the platform indicates otherwise) + ifeq (${INCLUDE_TBBR_MK},1) + include make_helpers/tbbr/tbbr_tools.mk + endif +endif + +ifneq (${FIP_ALIGN},0) +FIP_ARGS += --align ${FIP_ALIGN} +endif + +################################################################################ +# Include libraries' Makefile that are used in all BL +################################################################################ + +include lib/stack_protector/stack_protector.mk + +################################################################################ +# Auxiliary tools (fiptool, cert_create, etc) +################################################################################ + +# Variables for use with Certificate Generation Tool +CRTTOOLPATH ?= tools/cert_create +CRTTOOL ?= ${CRTTOOLPATH}/cert_create${BIN_EXT} + +# Variables for use with Firmware Encryption Tool +ENCTOOLPATH ?= tools/encrypt_fw +ENCTOOL ?= ${ENCTOOLPATH}/encrypt_fw${BIN_EXT} + +# Variables for use with Firmware Image Package +FIPTOOLPATH ?= tools/fiptool +FIPTOOL ?= ${FIPTOOLPATH}/fiptool${BIN_EXT} + +# Variables for use with sptool +SPTOOLPATH ?= tools/sptool +SPTOOL ?= ${SPTOOLPATH}/sptool${BIN_EXT} +SP_MK_GEN ?= ${SPTOOLPATH}/sp_mk_generator.py + +# Variables for use with ROMLIB +ROMLIBPATH ?= lib/romlib + +# Variable for use with Python +PYTHON ?= python3 + +# Variables for use with PRINT_MEMORY_MAP +PRINT_MEMORY_MAP_PATH ?= tools/memory +PRINT_MEMORY_MAP ?= ${PRINT_MEMORY_MAP_PATH}/print_memory_map.py + +# Variables for use with documentation build using Sphinx tool +DOCS_PATH ?= docs + +################################################################################ +# Include BL specific makefiles +################################################################################ +ifdef BL1_SOURCES +NEED_BL1 := yes +include bl1/bl1.mk +endif + +ifdef BL2_SOURCES +NEED_BL2 := yes +include bl2/bl2.mk +endif + +ifdef BL2U_SOURCES +NEED_BL2U := yes +include bl2u/bl2u.mk +endif + +ifeq (${NEED_BL31},yes) +ifdef BL31_SOURCES +include bl31/bl31.mk +endif +endif + +ifdef FDT_SOURCES +NEED_FDT := yes +endif + +################################################################################ +# Build options checks +################################################################################ + +$(eval $(call assert_booleans,\ + $(sort \ + ALLOW_RO_XLAT_TABLES \ + COLD_BOOT_SINGLE_CPU \ + CREATE_KEYS \ + CTX_INCLUDE_AARCH32_REGS \ + CTX_INCLUDE_FPREGS \ + CTX_INCLUDE_PAUTH_REGS \ + CTX_INCLUDE_MTE_REGS \ + CTX_INCLUDE_EL2_REGS \ + CTX_INCLUDE_NEVE_REGS \ + DEBUG \ + DISABLE_MTPMU \ + DYN_DISABLE_AUTH \ + EL3_EXCEPTION_HANDLING \ + ENABLE_AMU \ + AMU_RESTRICT_COUNTERS \ + ENABLE_ASSERTIONS \ + ENABLE_MPAM_FOR_LOWER_ELS \ + ENABLE_PIE \ + ENABLE_PMF \ + ENABLE_PSCI_STAT \ + ENABLE_RUNTIME_INSTRUMENTATION \ + ENABLE_SPE_FOR_LOWER_ELS \ + ENABLE_SVE_FOR_NS \ + ERROR_DEPRECATED \ + FAULT_INJECTION_SUPPORT \ + GENERATE_COT \ + GICV2_G0_FOR_EL3 \ + HANDLE_EA_EL3_FIRST \ + HW_ASSISTED_COHERENCY \ + INVERTED_MEMMAP \ + MEASURED_BOOT \ + NS_TIMER_SWITCH \ + OVERRIDE_LIBC \ + PL011_GENERIC_UART \ + PROGRAMMABLE_RESET_ADDRESS \ + PSCI_EXTENDED_STATE_ID \ + RAS_EXTENSION \ + RESET_TO_BL31 \ + SAVE_KEYS \ + SEPARATE_CODE_AND_RODATA \ + SEPARATE_NOBITS_REGION \ + SPIN_ON_BL1_EXIT \ + SPM_MM \ + SPMD_SPM_AT_SEL2 \ + TRUSTED_BOARD_BOOT \ + USE_COHERENT_MEM \ + USE_DEBUGFS \ + ARM_IO_IN_DTB \ + SDEI_IN_FCONF \ + SEC_INT_DESC_IN_FCONF \ + USE_ROMLIB \ + USE_TBBR_DEFS \ + WARMBOOT_ENABLE_DCACHE_EARLY \ + BL2_AT_EL3 \ + BL2_IN_XIP_MEM \ + BL2_INV_DCACHE \ + USE_SPINLOCK_CAS \ + ENCRYPT_BL31 \ + ENCRYPT_BL32 \ + ERRATA_SPECULATIVE_AT \ + RAS_TRAP_LOWER_EL_ERR_ACCESS \ + COT_DESC_IN_DTB \ + USE_SP804_TIMER \ + ENABLE_FEAT_RNG \ + ENABLE_FEAT_SB \ +))) + +$(eval $(call assert_numerics,\ + $(sort \ + ARM_ARCH_MAJOR \ + ARM_ARCH_MINOR \ + BRANCH_PROTECTION \ + FW_ENC_STATUS \ +))) + +ifdef KEY_SIZE + $(eval $(call assert_numeric,KEY_SIZE)) +endif + +ifeq ($(filter $(SANITIZE_UB), on off trap),) + $(error "Invalid value for SANITIZE_UB: can be one of on, off, trap") +endif + +################################################################################ +# Add definitions to the cpp preprocessor based on the current build options. +# This is done after including the platform specific makefile to allow the +# platform to overwrite the default options +################################################################################ + +$(eval $(call add_defines,\ + $(sort \ + ALLOW_RO_XLAT_TABLES \ + ARM_ARCH_MAJOR \ + ARM_ARCH_MINOR \ + COLD_BOOT_SINGLE_CPU \ + CTX_INCLUDE_AARCH32_REGS \ + CTX_INCLUDE_FPREGS \ + CTX_INCLUDE_PAUTH_REGS \ + EL3_EXCEPTION_HANDLING \ + CTX_INCLUDE_MTE_REGS \ + CTX_INCLUDE_EL2_REGS \ + CTX_INCLUDE_NEVE_REGS \ + DECRYPTION_SUPPORT_${DECRYPTION_SUPPORT} \ + DISABLE_MTPMU \ + ENABLE_AMU \ + AMU_RESTRICT_COUNTERS \ + ENABLE_ASSERTIONS \ + ENABLE_BTI \ + ENABLE_MPAM_FOR_LOWER_ELS \ + ENABLE_PAUTH \ + ENABLE_PIE \ + ENABLE_PMF \ + ENABLE_PSCI_STAT \ + ENABLE_RUNTIME_INSTRUMENTATION \ + ENABLE_SPE_FOR_LOWER_ELS \ + ENABLE_SVE_FOR_NS \ + ENCRYPT_BL31 \ + ENCRYPT_BL32 \ + ERROR_DEPRECATED \ + FAULT_INJECTION_SUPPORT \ + GICV2_G0_FOR_EL3 \ + HANDLE_EA_EL3_FIRST \ + HW_ASSISTED_COHERENCY \ + LOG_LEVEL \ + MEASURED_BOOT \ + NS_TIMER_SWITCH \ + PL011_GENERIC_UART \ + PLAT_${PLAT} \ + PROGRAMMABLE_RESET_ADDRESS \ + PSCI_EXTENDED_STATE_ID \ + RAS_EXTENSION \ + RESET_TO_BL31 \ + SEPARATE_CODE_AND_RODATA \ + SEPARATE_NOBITS_REGION \ + RECLAIM_INIT_CODE \ + SPD_${SPD} \ + SPIN_ON_BL1_EXIT \ + SPM_MM \ + SPMD_SPM_AT_SEL2 \ + TRUSTED_BOARD_BOOT \ + TRNG_SUPPORT \ + USE_COHERENT_MEM \ + USE_DEBUGFS \ + ARM_IO_IN_DTB \ + SDEI_IN_FCONF \ + SEC_INT_DESC_IN_FCONF \ + USE_ROMLIB \ + USE_TBBR_DEFS \ + WARMBOOT_ENABLE_DCACHE_EARLY \ + BL2_AT_EL3 \ + BL2_IN_XIP_MEM \ + BL2_INV_DCACHE \ + USE_SPINLOCK_CAS \ + ERRATA_SPECULATIVE_AT \ + RAS_TRAP_LOWER_EL_ERR_ACCESS \ + COT_DESC_IN_DTB \ + USE_SP804_TIMER \ + ENABLE_FEAT_RNG \ + ENABLE_FEAT_SB \ +))) + +ifeq (${SANITIZE_UB},trap) + $(eval $(call add_define,MONITOR_TRAPS)) +endif + +# Define the EL3_PAYLOAD_BASE flag only if it is provided. +ifdef EL3_PAYLOAD_BASE + $(eval $(call add_define,EL3_PAYLOAD_BASE)) +else + # Define the PRELOADED_BL33_BASE flag only if it is provided and + # EL3_PAYLOAD_BASE is not defined, as it has priority. + ifdef PRELOADED_BL33_BASE + $(eval $(call add_define,PRELOADED_BL33_BASE)) + endif +endif + +# Define the DYN_DISABLE_AUTH flag only if set. +ifeq (${DYN_DISABLE_AUTH},1) +$(eval $(call add_define,DYN_DISABLE_AUTH)) +endif + +ifneq ($(findstring armlink,$(notdir $(LD))),) +$(eval $(call add_define,USE_ARM_LINK)) +endif + +# Generate and include sp_gen.mk if SPD is spmd and SP_LAYOUT_FILE is defined +ifeq (${SPD},spmd) +ifdef SP_LAYOUT_FILE + ifeq (${SPMD_SPM_AT_SEL2},0) + $(error "SPMD with SPM at S-EL1 does not require SP_LAYOUT_FILE") + endif + -include $(BUILD_PLAT)/sp_gen.mk + FIP_DEPS += sp + CRT_DEPS += sp + NEED_SP_PKG := yes +else + ifeq (${SPMD_SPM_AT_SEL2},1) + $(error "SPMD with SPM at S-EL2 require SP_LAYOUT_FILE") + endif +endif +endif + +################################################################################ +# Build targets +################################################################################ + +.PHONY: all msg_start clean realclean distclean cscope locate-checkpatch checkcodebase checkpatch fiptool sptool fip sp fwu_fip certtool dtbs memmap doc enctool +.SUFFIXES: + +all: msg_start + +msg_start: + @echo "Building ${PLAT}" + +ifeq (${ERROR_DEPRECATED},0) +# Check if deprecated declarations and cpp warnings should be treated as error or not. +ifneq ($(findstring clang,$(notdir $(CC))),) + CPPFLAGS += -Wno-error=deprecated-declarations +else + CPPFLAGS += -Wno-error=deprecated-declarations -Wno-error=cpp +endif +endif # !ERROR_DEPRECATED + +$(eval $(call MAKE_LIB_DIRS)) +$(eval $(call MAKE_LIB,c)) + +# Expand build macros for the different images +ifeq (${NEED_BL1},yes) +$(eval $(call MAKE_BL,1)) +endif + +ifeq (${NEED_BL2},yes) +ifeq (${BL2_AT_EL3}, 0) +FIP_BL2_ARGS := tb-fw +endif + +$(if ${BL2}, $(eval $(call TOOL_ADD_IMG,bl2,--${FIP_BL2_ARGS})),\ + $(eval $(call MAKE_BL,2,${FIP_BL2_ARGS}))) +endif + +ifeq (${NEED_SCP_BL2},yes) +$(eval $(call TOOL_ADD_IMG,scp_bl2,--scp-fw)) +endif + +ifeq (${NEED_BL31},yes) +BL31_SOURCES += ${SPD_SOURCES} +# Sort BL31 source files to remove duplicates +BL31_SOURCES := $(sort ${BL31_SOURCES}) +ifneq (${DECRYPTION_SUPPORT},none) +$(if ${BL31}, $(eval $(call TOOL_ADD_IMG,bl31,--soc-fw,,$(ENCRYPT_BL31))),\ + $(eval $(call MAKE_BL,31,soc-fw,,$(ENCRYPT_BL31)))) +else +$(if ${BL31}, $(eval $(call TOOL_ADD_IMG,bl31,--soc-fw)),\ + $(eval $(call MAKE_BL,31,soc-fw))) +endif +endif + +# If a BL32 image is needed but neither BL32 nor BL32_SOURCES is defined, the +# build system will call TOOL_ADD_IMG to print a warning message and abort the +# process. Note that the dependency on BL32 applies to the FIP only. +ifeq (${NEED_BL32},yes) +# Sort BL32 source files to remove duplicates +BL32_SOURCES := $(sort ${BL32_SOURCES}) +BUILD_BL32 := $(if $(BL32),,$(if $(BL32_SOURCES),1)) + +ifneq (${DECRYPTION_SUPPORT},none) +$(if ${BUILD_BL32}, $(eval $(call MAKE_BL,32,tos-fw,,$(ENCRYPT_BL32))),\ + $(eval $(call TOOL_ADD_IMG,bl32,--tos-fw,,$(ENCRYPT_BL32)))) +else +$(if ${BUILD_BL32}, $(eval $(call MAKE_BL,32,tos-fw)),\ + $(eval $(call TOOL_ADD_IMG,bl32,--tos-fw))) +endif +endif + +# Add the BL33 image if required by the platform +ifeq (${NEED_BL33},yes) +$(eval $(call TOOL_ADD_IMG,bl33,--nt-fw)) +endif + +ifeq (${NEED_BL2U},yes) +$(if ${BL2U}, $(eval $(call TOOL_ADD_IMG,bl2u,--ap-fwu-cfg,FWU_)),\ + $(eval $(call MAKE_BL,2u,ap-fwu-cfg,FWU_))) +endif + +# Expand build macros for the different images +ifeq (${NEED_FDT},yes) + $(eval $(call MAKE_DTBS,$(BUILD_PLAT)/fdts,$(FDT_SOURCES))) +endif + +# Add Secure Partition packages +ifeq (${NEED_SP_PKG},yes) +$(BUILD_PLAT)/sp_gen.mk: ${SP_MK_GEN} ${SP_LAYOUT_FILE} | ${BUILD_PLAT} + ${Q}${PYTHON} "$<" "$@" $(filter-out $<,$^) $(BUILD_PLAT) ${COT} +sp: $(SPTOOL) $(DTBS) $(BUILD_PLAT)/sp_gen.mk + ${Q}$(SPTOOL) $(SPTOOL_ARGS) + @${ECHO_BLANK_LINE} + @echo "Built SP Images successfully" + @${ECHO_BLANK_LINE} +endif + +locate-checkpatch: +ifndef CHECKPATCH + $(error "Please set CHECKPATCH to point to the Linux checkpatch.pl file, eg: CHECKPATCH=../linux/scripts/checkpatch.pl") +else +ifeq (,$(wildcard ${CHECKPATCH})) + $(error "The file CHECKPATCH points to cannot be found, use eg: CHECKPATCH=../linux/scripts/checkpatch.pl") +endif +endif + +clean: + @echo " CLEAN" + $(call SHELL_REMOVE_DIR,${BUILD_PLAT}) +ifdef UNIX_MK + ${Q}${MAKE} --no-print-directory -C ${FIPTOOLPATH} clean +else +# Clear the MAKEFLAGS as we do not want +# to pass the gnumake flags to nmake. + ${Q}set MAKEFLAGS= && ${MSVC_NMAKE} /nologo /f ${FIPTOOLPATH}/Makefile.msvc FIPTOOLPATH=$(subst /,\,$(FIPTOOLPATH)) FIPTOOL=$(subst /,\,$(FIPTOOL)) clean +endif + ${Q}${MAKE} PLAT=${PLAT} --no-print-directory -C ${CRTTOOLPATH} clean + ${Q}${MAKE} PLAT=${PLAT} --no-print-directory -C ${ENCTOOLPATH} clean + ${Q}${MAKE} --no-print-directory -C ${ROMLIBPATH} clean + +realclean distclean: + @echo " REALCLEAN" + $(call SHELL_REMOVE_DIR,${BUILD_BASE}) + $(call SHELL_DELETE_ALL, ${CURDIR}/cscope.*) +ifdef UNIX_MK + ${Q}${MAKE} --no-print-directory -C ${FIPTOOLPATH} clean +else +# Clear the MAKEFLAGS as we do not want +# to pass the gnumake flags to nmake. + ${Q}set MAKEFLAGS= && ${MSVC_NMAKE} /nologo /f ${FIPTOOLPATH}/Makefile.msvc FIPTOOLPATH=$(subst /,\,$(FIPTOOLPATH)) FIPTOOL=$(subst /,\,$(FIPTOOL)) realclean +endif + ${Q}${MAKE} --no-print-directory -C ${SPTOOLPATH} clean + ${Q}${MAKE} PLAT=${PLAT} --no-print-directory -C ${CRTTOOLPATH} clean + ${Q}${MAKE} PLAT=${PLAT} --no-print-directory -C ${ENCTOOLPATH} realclean + ${Q}${MAKE} --no-print-directory -C ${ROMLIBPATH} clean + +checkcodebase: locate-checkpatch + @echo " CHECKING STYLE" + @if test -d .git ; then \ + git ls-files | grep -E -v 'libfdt|libc|docs|\.rst' | \ + while read GIT_FILE ; \ + do ${CHECKPATCH} ${CHECKCODE_ARGS} -f $$GIT_FILE ; \ + done ; \ + else \ + find . -type f -not -iwholename "*.git*" \ + -not -iwholename "*build*" \ + -not -iwholename "*libfdt*" \ + -not -iwholename "*libc*" \ + -not -iwholename "*docs*" \ + -not -iwholename "*.rst" \ + -exec ${CHECKPATCH} ${CHECKCODE_ARGS} -f {} \; ; \ + fi + +checkpatch: locate-checkpatch + @echo " CHECKING STYLE" + @if test -n "${CHECKPATCH_OPTS}"; then \ + echo " with ${CHECKPATCH_OPTS} option(s)"; \ + fi + ${Q}COMMON_COMMIT=$$(git merge-base HEAD ${BASE_COMMIT}); \ + for commit in `git rev-list $$COMMON_COMMIT..HEAD`; do \ + printf "\n[*] Checking style of '$$commit'\n\n"; \ + git log --format=email "$$commit~..$$commit" \ + -- ${CHECK_PATHS} | \ + ${CHECKPATCH} ${CHECKPATCH_OPTS} - || true; \ + git diff --format=email "$$commit~..$$commit" \ + -- ${CHECK_PATHS} | \ + ${CHECKPATCH} ${CHECKPATCH_OPTS} - || true; \ + done + +certtool: ${CRTTOOL} + +${CRTTOOL}: FORCE + ${Q}${MAKE} PLAT=${PLAT} USE_TBBR_DEFS=${USE_TBBR_DEFS} COT=${COT} OPENSSL_DIR=${OPENSSL_DIR} CRTTOOL=${CRTTOOL} --no-print-directory -C ${CRTTOOLPATH} + @${ECHO_BLANK_LINE} + @echo "Built $@ successfully" + @${ECHO_BLANK_LINE} + +ifneq (${GENERATE_COT},0) +certificates: ${CRT_DEPS} ${CRTTOOL} + ${Q}${CRTTOOL} ${CRT_ARGS} + @${ECHO_BLANK_LINE} + @echo "Built $@ successfully" + @echo "Certificates can be found in ${BUILD_PLAT}" + @${ECHO_BLANK_LINE} +endif + +${BUILD_PLAT}/${FIP_NAME}: ${FIP_DEPS} ${FIPTOOL} + $(eval ${CHECK_FIP_CMD}) + ${Q}${FIPTOOL} create ${FIP_ARGS} $@ + ${Q}${FIPTOOL} info $@ + @${ECHO_BLANK_LINE} + @echo "Built $@ successfully" + @${ECHO_BLANK_LINE} + +ifneq (${GENERATE_COT},0) +fwu_certificates: ${FWU_CRT_DEPS} ${CRTTOOL} + ${Q}${CRTTOOL} ${FWU_CRT_ARGS} + @${ECHO_BLANK_LINE} + @echo "Built $@ successfully" + @echo "FWU certificates can be found in ${BUILD_PLAT}" + @${ECHO_BLANK_LINE} +endif + +${BUILD_PLAT}/${FWU_FIP_NAME}: ${FWU_FIP_DEPS} ${FIPTOOL} + $(eval ${CHECK_FWU_FIP_CMD}) + ${Q}${FIPTOOL} create ${FWU_FIP_ARGS} $@ + ${Q}${FIPTOOL} info $@ + @${ECHO_BLANK_LINE} + @echo "Built $@ successfully" + @${ECHO_BLANK_LINE} + +fiptool: ${FIPTOOL} +fip: ${BUILD_PLAT}/${FIP_NAME} +fwu_fip: ${BUILD_PLAT}/${FWU_FIP_NAME} + +${FIPTOOL}: FORCE +ifdef UNIX_MK + ${Q}${MAKE} CPPFLAGS="-DVERSION='\"${VERSION_STRING}\"'" FIPTOOL=${FIPTOOL} --no-print-directory -C ${FIPTOOLPATH} +else +# Clear the MAKEFLAGS as we do not want +# to pass the gnumake flags to nmake. + ${Q}set MAKEFLAGS= && ${MSVC_NMAKE} /nologo /f ${FIPTOOLPATH}/Makefile.msvc FIPTOOLPATH=$(subst /,\,$(FIPTOOLPATH)) FIPTOOL=$(subst /,\,$(FIPTOOL)) +endif + +sptool: ${SPTOOL} +${SPTOOL}: FORCE + ${Q}${MAKE} CPPFLAGS="-DVERSION='\"${VERSION_STRING}\"'" SPTOOL=${SPTOOL} --no-print-directory -C ${SPTOOLPATH} + +romlib.bin: libraries FORCE + ${Q}${MAKE} PLAT_DIR=${PLAT_DIR} BUILD_PLAT=${BUILD_PLAT} ENABLE_BTI=${ENABLE_BTI} ARM_ARCH_MINOR=${ARM_ARCH_MINOR} INCLUDES='${INCLUDES}' DEFINES='${DEFINES}' --no-print-directory -C ${ROMLIBPATH} all + +# Call print_memory_map tool +memmap: all + ${Q}${PYTHON} ${PRINT_MEMORY_MAP} ${BUILD_PLAT} ${INVERTED_MEMMAP} + +doc: + @echo " BUILD DOCUMENTATION" + ${Q}${MAKE} --no-print-directory -C ${DOCS_PATH} html + +enctool: ${ENCTOOL} + +${ENCTOOL}: FORCE + ${Q}${MAKE} PLAT=${PLAT} BUILD_INFO=0 OPENSSL_DIR=${OPENSSL_DIR} ENCTOOL=${ENCTOOL} --no-print-directory -C ${ENCTOOLPATH} + @${ECHO_BLANK_LINE} + @echo "Built $@ successfully" + @${ECHO_BLANK_LINE} + +cscope: + @echo " CSCOPE" + ${Q}find ${CURDIR} -name "*.[chsS]" > cscope.files + ${Q}cscope -b -q -k + +help: + @echo "usage: ${MAKE} [PLAT=] [OPTIONS] [TARGET]" + @echo "" + @echo "PLAT is used to specify which platform you wish to build." + @echo "If no platform is specified, PLAT defaults to: ${DEFAULT_PLAT}" + @echo "" + @echo "platform = ${PLATFORM_LIST}" + @echo "" + @echo "Please refer to the User Guide for a list of all supported options." + @echo "Note that the build system doesn't track dependencies for build " + @echo "options. Therefore, if any of the build options are changed " + @echo "from a previous build, a clean build must be performed." + @echo "" + @echo "Supported Targets:" + @echo " all Build all individual bootloader binaries" + @echo " bl1 Build the BL1 binary" + @echo " bl2 Build the BL2 binary" + @echo " bl2u Build the BL2U binary" + @echo " bl31 Build the BL31 binary" + @echo " bl32 Build the BL32 binary. If ARCH=aarch32, then " + @echo " this builds secure payload specified by AARCH32_SP" + @echo " certificates Build the certificates (requires 'GENERATE_COT=1')" + @echo " fip Build the Firmware Image Package (FIP)" + @echo " fwu_fip Build the FWU Firmware Image Package (FIP)" + @echo " checkcodebase Check the coding style of the entire source tree" + @echo " checkpatch Check the coding style on changes in the current" + @echo " branch against BASE_COMMIT (default origin/master)" + @echo " clean Clean the build for the selected platform" + @echo " cscope Generate cscope index" + @echo " distclean Remove all build artifacts for all platforms" + @echo " certtool Build the Certificate generation tool" + @echo " enctool Build the Firmware encryption tool" + @echo " fiptool Build the Firmware Image Package (FIP) creation tool" + @echo " sp Build the Secure Partition Packages" + @echo " sptool Build the Secure Partition Package creation tool" + @echo " dtbs Build the Device Tree Blobs (if required for the platform)" + @echo " memmap Print the memory map of the built binaries" + @echo " doc Build html based documentation using Sphinx tool" + @echo "" + @echo "Note: most build targets require PLAT to be set to a specific platform." + @echo "" + @echo "example: build all targets for the FVP platform:" + @echo " CROSS_COMPILE=aarch64-none-elf- make PLAT=fvp all" + +.PHONY: FORCE +FORCE:; diff --git a/drivers/rz/ipl/rza/README b/drivers/rz/ipl/rza/README new file mode 100644 index 00000000..781a5910 --- /dev/null +++ b/drivers/rz/ipl/rza/README @@ -0,0 +1,38 @@ +Initial Program Loader (IPL) for Renesas RZ/A Series +#################################################### + +Origin: + Renesas Electronics Corporation + https://github.com/renesas/rza-initial-program-loader + +Status: + v2.1.0 + +Purpose: + Initial Program Loader (IPL) for Renesas RZ/A Series. + +Description: + IPL is a boot program sample code for RZ/A Series. + + When the RZ/A MPU is started, the IPL initializes peripheral I/O modules, + Flash memory, DDR SDRAM, etc., and starts the application software developed in + Renesas FSP environment with the execution state of AARch64, Exception Level EL3. + + IPL consists of functions such as PLL and clock control driver, peripheral I/O + module driver, Serial Flash Memory driver, and Octa Memory Control driver, etc. + +Dependencies: + None. + +URL: + https://github.com/renesas/rza-initial-program-loader + Commit: 606a8ae021d8037e6e1c27366ca6acddfe8a63dc + +Maintained-by: + Renesas Electronics Corporation + +License: + BSD-3-Clause + +License Link: + https://opensource.org/licenses/BSD-3-Clause diff --git a/drivers/rz/ipl/rza/bl2/aarch64/bl2_arch_setup.c b/drivers/rz/ipl/rza/bl2/aarch64/bl2_arch_setup.c new file mode 100644 index 00000000..54052f7d --- /dev/null +++ b/drivers/rz/ipl/rza/bl2/aarch64/bl2_arch_setup.c @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include "../bl2_private.h" + +/******************************************************************************* + * Place holder function to perform any S-EL1 specific architectural setup. At + * the moment there is nothing to do. + ******************************************************************************/ +void bl2_arch_setup(void) +{ + /* Give access to FP/SIMD registers */ + write_cpacr(CPACR_EL1_FPEN(CPACR_EL1_FP_TRAP_NONE)); +} diff --git a/drivers/rz/ipl/rza/bl2/aarch64/bl2_el3_entrypoint.S b/drivers/rz/ipl/rza/bl2/aarch64/bl2_el3_entrypoint.S new file mode 100644 index 00000000..63f82f1d --- /dev/null +++ b/drivers/rz/ipl/rza/bl2/aarch64/bl2_el3_entrypoint.S @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include + + .globl bl2_entrypoint + .globl bl2_el3_run_image + .globl bl2_run_next_image + +#if BL2_IN_XIP_MEM +#define FIXUP_SIZE 0 +#else +#define FIXUP_SIZE ((BL2_LIMIT) - (BL2_BASE)) +#endif + +#if RZA3 +#define SYS_REG_BASE (0x1102) +#define SYS_REG_LSI_MODE (0xA00) +#define SYS_BITPOS_LSI_MODE_STAT_DEBUGEN (9) + +#define WAIT_CNT_HIGH16 (0x100) +#define WAIT_CNT_LOW16 (0) +#endif + +func bl2_entrypoint +#if RZA3 + /* clear icache (SCTLR_EL3 init) */ + mov_imm x4, (SCTLR_RESET_VAL & ~(SCTLR_EE_BIT | SCTLR_WXN_BIT \ + | SCTLR_SA_BIT | SCTLR_A_BIT | SCTLR_DSSBS_BIT)) + msr sctlr_el3, x4 + isb + + /* check DEBUGEN */ + mov x4, #SYS_REG_LSI_MODE + movk x4, #SYS_REG_BASE, LSL #16 + ldr w5, [x4] + /* skip wait if DEBUGEN = 0 */ + tbz x5, #SYS_BITPOS_LSI_MODE_STAT_DEBUGEN, skip_wait + + mov x4, #WAIT_CNT_LOW16 + /* wait */ + movk x4, #WAIT_CNT_HIGH16, LSL #16 +wait_loop: + cbz x4, skip_wait + sub x4, x4, #1 + b wait_loop +skip_wait: +#endif + + /* Save arguments x0-x3 from previous Boot loader */ + mov x20, x0 + mov x21, x1 + mov x22, x2 + mov x23, x3 + + el3_entrypoint_common \ + _init_sctlr=1 \ + _warm_boot_mailbox=!PROGRAMMABLE_RESET_ADDRESS \ + _secondary_cold_boot=!COLD_BOOT_SINGLE_CPU \ + _init_memory=1 \ + _init_c_runtime=1 \ + _exception_vectors=bl2_el3_exceptions \ + _pie_fixup_size=FIXUP_SIZE + + /* --------------------------------------------- + * Restore parameters of boot rom + * --------------------------------------------- + */ + mov x0, x20 + mov x1, x21 + mov x2, x22 + mov x3, x23 + + /* --------------------------------------------- + * Perform BL2 setup + * --------------------------------------------- + */ + bl bl2_el3_setup + +#if ENABLE_PAUTH + /* --------------------------------------------- + * Program APIAKey_EL1 and enable pointer authentication. + * --------------------------------------------- + */ + bl pauth_init_enable_el3 +#endif /* ENABLE_PAUTH */ + + /* --------------------------------------------- + * Jump to main function. + * --------------------------------------------- + */ + bl bl2_main + + /* --------------------------------------------- + * Should never reach this point. + * --------------------------------------------- + */ + no_ret plat_panic_handler +endfunc bl2_entrypoint + +func bl2_run_next_image + mov x20,x0 + /* --------------------------------------------- + * MMU needs to be disabled because both BL2 and BL31 execute + * in EL3, and therefore share the same address space. + * BL31 will initialize the address space according to its + * own requirement. + * --------------------------------------------- + */ + bl disable_mmu_icache_el3 + tlbi alle3 + bl bl2_el3_plat_prepare_exit + +#if ENABLE_PAUTH + /* --------------------------------------------- + * Disable pointer authentication before jumping + * to next boot image. + * --------------------------------------------- + */ + bl pauth_disable_el3 +#endif /* ENABLE_PAUTH */ + + ldp x0, x1, [x20, #ENTRY_POINT_INFO_PC_OFFSET] + msr elr_el3, x0 + msr spsr_el3, x1 + + ldp x6, x7, [x20, #(ENTRY_POINT_INFO_ARGS_OFFSET + 0x30)] + ldp x4, x5, [x20, #(ENTRY_POINT_INFO_ARGS_OFFSET + 0x20)] + ldp x2, x3, [x20, #(ENTRY_POINT_INFO_ARGS_OFFSET + 0x10)] + ldp x0, x1, [x20, #(ENTRY_POINT_INFO_ARGS_OFFSET + 0x0)] + exception_return +endfunc bl2_run_next_image diff --git a/drivers/rz/ipl/rza/bl2/aarch64/bl2_el3_exceptions.S b/drivers/rz/ipl/rza/bl2/aarch64/bl2_el3_exceptions.S new file mode 100644 index 00000000..3d580513 --- /dev/null +++ b/drivers/rz/ipl/rza/bl2/aarch64/bl2_el3_exceptions.S @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +/* ----------------------------------------------------------------------------- + * Very simple stackless exception handlers used by BL2. + * ----------------------------------------------------------------------------- + */ + .globl bl2_el3_exceptions + +vector_base bl2_el3_exceptions + + /* ----------------------------------------------------- + * Current EL with SP0 : 0x0 - 0x200 + * ----------------------------------------------------- + */ +vector_entry SynchronousExceptionSP0 + mov x0, #SYNC_EXCEPTION_SP_EL0 + bl plat_report_exception + no_ret plat_panic_handler +end_vector_entry SynchronousExceptionSP0 + +vector_entry IrqSP0 + mov x0, #IRQ_SP_EL0 + bl plat_report_exception + no_ret plat_panic_handler +end_vector_entry IrqSP0 + +vector_entry FiqSP0 + mov x0, #FIQ_SP_EL0 + bl plat_report_exception + no_ret plat_panic_handler +end_vector_entry FiqSP0 + +vector_entry SErrorSP0 + mov x0, #SERROR_SP_EL0 + bl plat_report_exception + no_ret plat_panic_handler +end_vector_entry SErrorSP0 + + /* ----------------------------------------------------- + * Current EL with SPx: 0x200 - 0x400 + * ----------------------------------------------------- + */ +vector_entry SynchronousExceptionSPx + mov x0, #SYNC_EXCEPTION_SP_ELX + bl plat_report_exception + no_ret plat_panic_handler +end_vector_entry SynchronousExceptionSPx + +vector_entry IrqSPx + mov x0, #IRQ_SP_ELX + bl plat_report_exception + no_ret plat_panic_handler +end_vector_entry IrqSPx + +vector_entry FiqSPx + mov x0, #FIQ_SP_ELX + bl plat_report_exception + no_ret plat_panic_handler +end_vector_entry FiqSPx + +vector_entry SErrorSPx + mov x0, #SERROR_SP_ELX + bl plat_report_exception + no_ret plat_panic_handler +end_vector_entry SErrorSPx + + /* ----------------------------------------------------- + * Lower EL using AArch64 : 0x400 - 0x600 + * ----------------------------------------------------- + */ +vector_entry SynchronousExceptionA64 + mov x0, #SYNC_EXCEPTION_AARCH64 + bl plat_report_exception + no_ret plat_panic_handler +end_vector_entry SynchronousExceptionA64 + +vector_entry IrqA64 + mov x0, #IRQ_AARCH64 + bl plat_report_exception + no_ret plat_panic_handler +end_vector_entry IrqA64 + +vector_entry FiqA64 + mov x0, #FIQ_AARCH64 + bl plat_report_exception + no_ret plat_panic_handler +end_vector_entry FiqA64 + +vector_entry SErrorA64 + mov x0, #SERROR_AARCH64 + bl plat_report_exception + no_ret plat_panic_handler +end_vector_entry SErrorA64 + + /* ----------------------------------------------------- + * Lower EL using AArch32 : 0x600 - 0x800 + * ----------------------------------------------------- + */ +vector_entry SynchronousExceptionA32 + mov x0, #SYNC_EXCEPTION_AARCH32 + bl plat_report_exception + no_ret plat_panic_handler +end_vector_entry SynchronousExceptionA32 + +vector_entry IrqA32 + mov x0, #IRQ_AARCH32 + bl plat_report_exception + no_ret plat_panic_handler +end_vector_entry IrqA32 + +vector_entry FiqA32 + mov x0, #FIQ_AARCH32 + bl plat_report_exception + no_ret plat_panic_handler +end_vector_entry FiqA32 + +vector_entry SErrorA32 + mov x0, #SERROR_AARCH32 + bl plat_report_exception + no_ret plat_panic_handler +end_vector_entry SErrorA32 diff --git a/drivers/rz/ipl/rza/bl2/aarch64/bl2_entrypoint.S b/drivers/rz/ipl/rza/bl2/aarch64/bl2_entrypoint.S new file mode 100644 index 00000000..a021e424 --- /dev/null +++ b/drivers/rz/ipl/rza/bl2/aarch64/bl2_entrypoint.S @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + + + .globl bl2_entrypoint + + + +func bl2_entrypoint + /*--------------------------------------------- + * Save arguments x0 - x3 from BL1 for future + * use. + * --------------------------------------------- + */ + mov x20, x0 + mov x21, x1 + mov x22, x2 + mov x23, x3 + + /* --------------------------------------------- + * Set the exception vector to something sane. + * --------------------------------------------- + */ + adr x0, early_exceptions + msr vbar_el1, x0 + isb + + /* --------------------------------------------- + * Enable the SError interrupt now that the + * exception vectors have been setup. + * --------------------------------------------- + */ + msr daifclr, #DAIF_ABT_BIT + + /* --------------------------------------------- + * Enable the instruction cache, stack pointer + * and data access alignment checks and disable + * speculative loads. + * --------------------------------------------- + */ + mov x1, #(SCTLR_I_BIT | SCTLR_A_BIT | SCTLR_SA_BIT) + mrs x0, sctlr_el1 + orr x0, x0, x1 + bic x0, x0, #SCTLR_DSSBS_BIT + msr sctlr_el1, x0 + isb + + /* --------------------------------------------- + * Invalidate the RW memory used by the BL2 + * image. This includes the data and NOBITS + * sections. This is done to safeguard against + * possible corruption of this memory by dirty + * cache lines in a system cache as a result of + * use by an earlier boot loader stage. + * --------------------------------------------- + */ + adr x0, __RW_START__ + adr x1, __RW_END__ + sub x1, x1, x0 + bl inv_dcache_range + + /* --------------------------------------------- + * Zero out NOBITS sections. There are 2 of them: + * - the .bss section; + * - the coherent memory section. + * --------------------------------------------- + */ + adrp x0, __BSS_START__ + add x0, x0, :lo12:__BSS_START__ + adrp x1, __BSS_END__ + add x1, x1, :lo12:__BSS_END__ + sub x1, x1, x0 + bl zeromem + +#if USE_COHERENT_MEM + adrp x0, __COHERENT_RAM_START__ + add x0, x0, :lo12:__COHERENT_RAM_START__ + adrp x1, __COHERENT_RAM_END_UNALIGNED__ + add x1, x1, :lo12:__COHERENT_RAM_END_UNALIGNED__ + sub x1, x1, x0 + bl zeromem +#endif + + /* -------------------------------------------- + * Allocate a stack whose memory will be marked + * as Normal-IS-WBWA when the MMU is enabled. + * There is no risk of reading stale stack + * memory after enabling the MMU as only the + * primary cpu is running at the moment. + * -------------------------------------------- + */ + bl plat_set_my_stack + + /* --------------------------------------------- + * Initialize the stack protector canary before + * any C code is called. + * --------------------------------------------- + */ +#if STACK_PROTECTOR_ENABLED + bl update_stack_protector_canary +#endif + + /* --------------------------------------------- + * Perform BL2 setup + * --------------------------------------------- + */ + mov x0, x20 + mov x1, x21 + mov x2, x22 + mov x3, x23 + bl bl2_setup + +#if ENABLE_PAUTH + /* --------------------------------------------- + * Program APIAKey_EL1 + * and enable pointer authentication. + * --------------------------------------------- + */ + bl pauth_init_enable_el1 +#endif /* ENABLE_PAUTH */ + + /* --------------------------------------------- + * Jump to main function. + * --------------------------------------------- + */ + bl bl2_main + + /* --------------------------------------------- + * Should never reach this point. + * --------------------------------------------- + */ + no_ret plat_panic_handler + +endfunc bl2_entrypoint diff --git a/drivers/rz/ipl/rza/bl2/bl2.ld.S b/drivers/rz/ipl/rza/bl2/bl2.ld.S new file mode 100644 index 00000000..37849c31 --- /dev/null +++ b/drivers/rz/ipl/rza/bl2/bl2.ld.S @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +OUTPUT_FORMAT(PLATFORM_LINKER_FORMAT) +OUTPUT_ARCH(PLATFORM_LINKER_ARCH) +ENTRY(bl2_entrypoint) + +MEMORY { + RAM (rwx): ORIGIN = BL2_BASE, LENGTH = BL2_LIMIT - BL2_BASE +} + + +SECTIONS +{ + . = BL2_BASE; + ASSERT(. == ALIGN(PAGE_SIZE), + "BL2_BASE address is not aligned on a page boundary.") + +#if SEPARATE_CODE_AND_RODATA + .text . : { + __TEXT_START__ = .; + *bl2_entrypoint.o(.text*) + *(SORT_BY_ALIGNMENT(.text*)) + *(.vectors) + . = ALIGN(PAGE_SIZE); + __TEXT_END__ = .; + } >RAM + + /* .ARM.extab and .ARM.exidx are only added because Clang need them */ + .ARM.extab . : { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } >RAM + + .ARM.exidx . : { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } >RAM + + .rodata . : { + __RODATA_START__ = .; + *(SORT_BY_ALIGNMENT(.rodata*)) + + RODATA_COMMON + + . = ALIGN(PAGE_SIZE); + __RODATA_END__ = .; + } >RAM +#else + ro . : { + __RO_START__ = .; + *bl2_entrypoint.o(.text*) + *(SORT_BY_ALIGNMENT(.text*)) + *(SORT_BY_ALIGNMENT(.rodata*)) + + RODATA_COMMON + + *(.vectors) + __RO_END_UNALIGNED__ = .; + /* + * Memory page(s) mapped to this section will be marked as + * read-only, executable. No RW data from the next section must + * creep in. Ensure the rest of the current memory page is unused. + */ + . = ALIGN(PAGE_SIZE); + __RO_END__ = .; + } >RAM +#endif + + /* + * Define a linker symbol to mark start of the RW memory area for this + * image. + */ + __RW_START__ = . ; + + DATA_SECTION >RAM + STACK_SECTION >RAM + BSS_SECTION >RAM + XLAT_TABLE_SECTION >RAM + +#if USE_COHERENT_MEM + /* + * The base address of the coherent memory section must be page-aligned (4K) + * to guarantee that the coherent data are stored on their own pages and + * are not mixed with normal data. This is required to set up the correct + * memory attributes for the coherent data page tables. + */ + coherent_ram (NOLOAD) : ALIGN(PAGE_SIZE) { + __COHERENT_RAM_START__ = .; + *(tzfw_coherent_mem) + __COHERENT_RAM_END_UNALIGNED__ = .; + /* + * Memory page(s) mapped to this section will be marked + * as device memory. No other unexpected data must creep in. + * Ensure the rest of the current memory page is unused. + */ + . = ALIGN(PAGE_SIZE); + __COHERENT_RAM_END__ = .; + } >RAM +#endif + + /* + * Define a linker symbol to mark end of the RW memory area for this + * image. + */ + __RW_END__ = .; + __BL2_END__ = .; + + __BSS_SIZE__ = SIZEOF(.bss); + +#if USE_COHERENT_MEM + __COHERENT_RAM_UNALIGNED_SIZE__ = + __COHERENT_RAM_END_UNALIGNED__ - __COHERENT_RAM_START__; +#endif + + ASSERT(. <= BL2_LIMIT, "BL2 image has exceeded its limit.") +} diff --git a/drivers/rz/ipl/rza/bl2/bl2.mk b/drivers/rz/ipl/rza/bl2/bl2.mk new file mode 100644 index 00000000..735e7e04 --- /dev/null +++ b/drivers/rz/ipl/rza/bl2/bl2.mk @@ -0,0 +1,37 @@ +# +# Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +BL2_SOURCES += bl2/bl2_image_load_v2.c \ + bl2/bl2_main.c \ + bl2/${ARCH}/bl2_arch_setup.c \ + lib/locks/exclusive/${ARCH}/spinlock.S \ + plat/common/${ARCH}/platform_up_stack.S \ + ${MBEDTLS_SOURCES} + +ifeq (${ARCH},aarch64) +BL2_SOURCES += common/aarch64/early_exceptions.S +endif + +ifeq (${BL2_AT_EL3},0) +BL2_SOURCES += bl2/${ARCH}/bl2_entrypoint.S +BL2_LINKERFILE := bl2/bl2.ld.S + +else +BL2_SOURCES += bl2/${ARCH}/bl2_el3_entrypoint.S \ + bl2/${ARCH}/bl2_el3_exceptions.S \ + lib/cpus/${ARCH}/cpu_helpers.S \ + lib/cpus/errata_report.c + +ifeq (${DISABLE_MTPMU},1) +BL2_SOURCES += lib/extensions/mtpmu/${ARCH}/mtpmu.S +endif + +ifeq (${ARCH},aarch64) +BL2_SOURCES += lib/cpus/aarch64/dsu_helpers.S +endif + +BL2_LINKERFILE := bl2/bl2_el3.ld.S +endif diff --git a/drivers/rz/ipl/rza/bl2/bl2_el3.ld.S b/drivers/rz/ipl/rza/bl2/bl2_el3.ld.S new file mode 100644 index 00000000..bc1794c0 --- /dev/null +++ b/drivers/rz/ipl/rza/bl2/bl2_el3.ld.S @@ -0,0 +1,173 @@ +/* + * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +OUTPUT_FORMAT(PLATFORM_LINKER_FORMAT) +OUTPUT_ARCH(PLATFORM_LINKER_ARCH) +ENTRY(bl2_entrypoint) + +MEMORY { +#if BL2_IN_XIP_MEM + ROM (rx): ORIGIN = BL2_RO_BASE, LENGTH = BL2_RO_LIMIT - BL2_RO_BASE + RAM (rwx): ORIGIN = BL2_RW_BASE, LENGTH = BL2_RW_LIMIT - BL2_RW_BASE +#else + RAM (rwx): ORIGIN = BL2_BASE, LENGTH = BL2_LIMIT - BL2_BASE +#endif +} + +#if !BL2_IN_XIP_MEM +#define ROM RAM +#endif + +SECTIONS +{ +#if BL2_IN_XIP_MEM + . = BL2_RO_BASE; + ASSERT(. == ALIGN(PAGE_SIZE), + "BL2_RO_BASE address is not aligned on a page boundary.") +#else + . = BL2_BASE; + ASSERT(. == ALIGN(PAGE_SIZE), + "BL2_BASE address is not aligned on a page boundary.") +#endif + +#if SEPARATE_CODE_AND_RODATA + .text . : { + __TEXT_START__ = .; + __TEXT_RESIDENT_START__ = .; + *bl2_el3_entrypoint.o(.text*) + *(.text.asm.*) + __TEXT_RESIDENT_END__ = .; + *(SORT_BY_ALIGNMENT(.text*)) + *(.vectors) + . = ALIGN(PAGE_SIZE); + __TEXT_END__ = .; + } >ROM + + .rodata . : { + __RODATA_START__ = .; + *(SORT_BY_ALIGNMENT(.rodata*)) + + RODATA_COMMON + + . = ALIGN(PAGE_SIZE); + __RODATA_END__ = .; + } >ROM + + ASSERT(__TEXT_RESIDENT_END__ - __TEXT_RESIDENT_START__ <= PAGE_SIZE, + "Resident part of BL2 has exceeded its limit.") +#else + ro . : { + __RO_START__ = .; + __TEXT_RESIDENT_START__ = .; + *bl2_el3_entrypoint.o(.text*) + *(.text.asm.*) + __TEXT_RESIDENT_END__ = .; + *(SORT_BY_ALIGNMENT(.text*)) + *(SORT_BY_ALIGNMENT(.rodata*)) + + RODATA_COMMON + + *(.vectors) + __RO_END_UNALIGNED__ = .; + /* + * Memory page(s) mapped to this section will be marked as + * read-only, executable. No RW data from the next section must + * creep in. Ensure the rest of the current memory page is unused. + */ + . = ALIGN(PAGE_SIZE); + + __RO_END__ = .; + } >ROM +#endif + + ASSERT(__CPU_OPS_END__ > __CPU_OPS_START__, + "cpu_ops not defined for this platform.") + +#if BL2_IN_XIP_MEM + . = BL2_RW_BASE; + ASSERT(BL2_RW_BASE == ALIGN(PAGE_SIZE), + "BL2_RW_BASE address is not aligned on a page boundary.") +#endif + + /* + * Define a linker symbol to mark start of the RW memory area for this + * image. + */ + __RW_START__ = . ; + + DATA_SECTION >RAM AT>ROM + __DATA_RAM_START__ = __DATA_START__; + __DATA_RAM_END__ = __DATA_END__; + + RELA_SECTION >RAM + STACK_SECTION >RAM + BSS_SECTION >RAM + XLAT_TABLE_SECTION >RAM + +#if USE_COHERENT_MEM + /* + * The base address of the coherent memory section must be page-aligned (4K) + * to guarantee that the coherent data are stored on their own pages and + * are not mixed with normal data. This is required to set up the correct + * memory attributes for the coherent data page tables. + */ + coherent_ram (NOLOAD) : ALIGN(PAGE_SIZE) { + __COHERENT_RAM_START__ = .; + *(tzfw_coherent_mem) + __COHERENT_RAM_END_UNALIGNED__ = .; + /* + * Memory page(s) mapped to this section will be marked + * as device memory. No other unexpected data must creep in. + * Ensure the rest of the current memory page is unused. + */ + . = ALIGN(PAGE_SIZE); + __COHERENT_RAM_END__ = .; + } >RAM +#endif + + /* + * Define a linker symbol to mark end of the RW memory area for this + * image. + */ + __RW_END__ = .; + __BL2_END__ = .; + + /DISCARD/ : { + *(.dynsym .dynstr .hash .gnu.hash) + } + +#if BL2_IN_XIP_MEM + __BL2_RAM_START__ = ADDR(.data); + __BL2_RAM_END__ = .; + + __DATA_ROM_START__ = LOADADDR(.data); + __DATA_SIZE__ = SIZEOF(.data); + + /* + * The .data section is the last PROGBITS section so its end marks the end + * of BL2's RO content in XIP memory.. + */ + __BL2_ROM_END__ = __DATA_ROM_START__ + __DATA_SIZE__; + ASSERT(__BL2_ROM_END__ <= BL2_RO_LIMIT, + "BL2's RO content has exceeded its limit.") +#endif + __BSS_SIZE__ = SIZEOF(.bss); + + +#if USE_COHERENT_MEM + __COHERENT_RAM_UNALIGNED_SIZE__ = + __COHERENT_RAM_END_UNALIGNED__ - __COHERENT_RAM_START__; +#endif + +#if BL2_IN_XIP_MEM + ASSERT(. <= BL2_RW_LIMIT, "BL2's RW content has exceeded its limit.") +#else + ASSERT(. <= BL2_LIMIT, "BL2 image has exceeded its limit.") +#endif +} diff --git a/drivers/rz/ipl/rza/bl2/bl2_image_load_v2.c b/drivers/rz/ipl/rza/bl2/bl2_image_load_v2.c new file mode 100644 index 00000000..48c9beca --- /dev/null +++ b/drivers/rz/ipl/rza/bl2/bl2_image_load_v2.c @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "bl2_private.h" + +/******************************************************************************* + * This function loads SCP_BL2/BL3x images and returns the ep_info for + * the next executable image. + ******************************************************************************/ +struct entry_point_info *bl2_load_images(void) +{ + bl_params_t *bl2_to_next_bl_params; + bl_load_info_t *bl2_load_info; + const bl_load_info_node_t *bl2_node_info; + int plat_setup_done = 0; + int err; + + /* + * Get information about the images to load. + */ + bl2_load_info = plat_get_bl_image_load_info(); + assert(bl2_load_info != NULL); + assert(bl2_load_info->head != NULL); + assert(bl2_load_info->h.type == PARAM_BL_LOAD_INFO); + assert(bl2_load_info->h.version >= VERSION_2); + bl2_node_info = bl2_load_info->head; + + while (bl2_node_info != NULL) { + /* + * Perform platform setup before loading the image, + * if indicated in the image attributes AND if NOT + * already done before. + */ + if ((bl2_node_info->image_info->h.attr & + IMAGE_ATTRIB_PLAT_SETUP) != 0U) { + if (plat_setup_done != 0) { + WARN("BL2: Platform setup already done!!\n"); + } else { + INFO("BL2: Doing platform setup\n"); + bl2_platform_setup(); + plat_setup_done = 1; + } + } + + err = bl2_plat_handle_pre_image_load(bl2_node_info->image_id); + if (err != 0) { + ERROR("BL2: Failure in pre image load handling (%i)\n", err); + plat_error_handler(err); + } + + if ((bl2_node_info->image_info->h.attr & + IMAGE_ATTRIB_SKIP_LOADING) == 0U) { + INFO("BL2: Loading image id %d\n", bl2_node_info->image_id); + err = load_auth_image(bl2_node_info->image_id, + bl2_node_info->image_info); + if (err != 0) { + ERROR("BL2: Failed to load image id %d (%i)\n", + bl2_node_info->image_id, err); + plat_error_handler(err); + } + } else { + INFO("BL2: Skip loading image id %d\n", bl2_node_info->image_id); + } + + /* Allow platform to handle image information. */ + err = bl2_plat_handle_post_image_load(bl2_node_info->image_id); + if (err != 0) { + ERROR("BL2: Failure in post image load handling (%i)\n", err); + plat_error_handler(err); + } + + /* Go to next image */ + bl2_node_info = bl2_node_info->next_load_info; + } + + /* + * Get information to pass to the next image. + */ + bl2_to_next_bl_params = plat_get_next_bl_params(); + assert(bl2_to_next_bl_params != NULL); + assert(bl2_to_next_bl_params->head != NULL); + assert(bl2_to_next_bl_params->h.type == PARAM_BL_PARAMS); + assert(bl2_to_next_bl_params->h.version >= VERSION_2); + assert(bl2_to_next_bl_params->head->ep_info != NULL); + + /* Populate arg0 for the next BL image if not already provided */ + if (bl2_to_next_bl_params->head->ep_info->args.arg0 == (u_register_t)0) + bl2_to_next_bl_params->head->ep_info->args.arg0 = + (u_register_t)bl2_to_next_bl_params; + + /* Flush the parameters to be passed to next image */ + plat_flush_next_bl_params(); + + return bl2_to_next_bl_params->head->ep_info; +} diff --git a/drivers/rz/ipl/rza/bl2/bl2_main.c b/drivers/rz/ipl/rza/bl2/bl2_main.c new file mode 100644 index 00000000..203e1d4b --- /dev/null +++ b/drivers/rz/ipl/rza/bl2/bl2_main.c @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#if MEASURED_BOOT +#include +#endif +#include +#include + +#include "bl2_private.h" + +#ifdef __aarch64__ +#define NEXT_IMAGE "BL31" +#else +#define NEXT_IMAGE "BL32" +#endif + +#if !BL2_AT_EL3 +/******************************************************************************* + * Setup function for BL2. + ******************************************************************************/ +void bl2_setup(u_register_t arg0, u_register_t arg1, u_register_t arg2, + u_register_t arg3) +{ + /* Perform early platform-specific setup */ + bl2_early_platform_setup2(arg0, arg1, arg2, arg3); + + /* Perform late platform-specific setup */ + bl2_plat_arch_setup(); + +#if CTX_INCLUDE_PAUTH_REGS + /* + * Assert that the ARMv8.3-PAuth registers are present or an access + * fault will be triggered when they are being saved or restored. + */ + assert(is_armv8_3_pauth_present()); +#endif /* CTX_INCLUDE_PAUTH_REGS */ +} + +#else /* if BL2_AT_EL3 */ +/******************************************************************************* + * Setup function for BL2 when BL2_AT_EL3=1. + ******************************************************************************/ +void bl2_el3_setup(u_register_t arg0, u_register_t arg1, u_register_t arg2, + u_register_t arg3) +{ + /* Perform early platform-specific setup */ + bl2_el3_early_platform_setup(arg0, arg1, arg2, arg3); + + /* Perform late platform-specific setup */ + bl2_el3_plat_arch_setup(); + +#if CTX_INCLUDE_PAUTH_REGS + /* + * Assert that the ARMv8.3-PAuth registers are present or an access + * fault will be triggered when they are being saved or restored. + */ + assert(is_armv8_3_pauth_present()); +#endif /* CTX_INCLUDE_PAUTH_REGS */ +} +#endif /* BL2_AT_EL3 */ + +/******************************************************************************* + * The only thing to do in BL2 is to load further images and pass control to + * next BL. The memory occupied by BL2 will be reclaimed by BL3x stages. BL2 + * runs entirely in S-EL1. + ******************************************************************************/ +void bl2_main(void) +{ + entry_point_info_t *next_bl_ep_info; + + NOTICE("BL2: %s\n", version_string); + NOTICE("BL2: %s\n", build_message); + + /* Perform remaining generic architectural setup in S-EL1 */ + bl2_arch_setup(); + +#if TRUSTED_BOARD_BOOT + /* Initialize authentication module */ + auth_mod_init(); + +#if MEASURED_BOOT + /* Initialize measured boot module */ + measured_boot_init(); + +#endif /* MEASURED_BOOT */ +#endif /* TRUSTED_BOARD_BOOT */ + + /* Initialize boot source */ + bl2_plat_preload_setup(); + + /* Load the subsequent bootloader images. */ + next_bl_ep_info = bl2_load_images(); + +#if MEASURED_BOOT + /* Finalize measured boot */ + measured_boot_finish(); +#endif /* MEASURED_BOOT */ + +#if !BL2_AT_EL3 +#ifndef __aarch64__ + /* + * For AArch32 state BL1 and BL2 share the MMU setup. + * Given that BL2 does not map BL1 regions, MMU needs + * to be disabled in order to go back to BL1. + */ + disable_mmu_icache_secure(); +#endif /* !__aarch64__ */ + + console_flush(); + +#if ENABLE_PAUTH + /* + * Disable pointer authentication before running next boot image + */ + pauth_disable_el1(); +#endif /* ENABLE_PAUTH */ + + /* + * Run next BL image via an SMC to BL1. Information on how to pass + * control to the BL32 (if present) and BL33 software images will + * be passed to next BL image as an argument. + */ + smc(BL1_SMC_RUN_IMAGE, (unsigned long)next_bl_ep_info, 0, 0, 0, 0, 0, 0); +#else /* if BL2_AT_EL3 */ + NOTICE("BL2: Booting " NEXT_IMAGE "\n"); + print_entry_point_info(next_bl_ep_info); + console_flush(); + +#if ENABLE_PAUTH + /* + * Disable pointer authentication before running next boot image + */ + pauth_disable_el3(); +#endif /* ENABLE_PAUTH */ + + bl2_run_next_image(next_bl_ep_info); +#endif /* BL2_AT_EL3 */ +} diff --git a/drivers/rz/ipl/rza/bl2/bl2_private.h b/drivers/rz/ipl/rza/bl2/bl2_private.h new file mode 100644 index 00000000..b1704d28 --- /dev/null +++ b/drivers/rz/ipl/rza/bl2/bl2_private.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef BL2_PRIVATE_H +#define BL2_PRIVATE_H + +#include + +/****************************************** + * Forward declarations + *****************************************/ +struct entry_point_info; + +/****************************************** + * Function prototypes + *****************************************/ +void bl2_arch_setup(void); +struct entry_point_info *bl2_load_images(void); +void bl2_run_next_image(const struct entry_point_info *bl_ep_info); + +#endif /* BL2_PRIVATE_H */ diff --git a/drivers/rz/ipl/rza/common/aarch64/debug.S b/drivers/rz/ipl/rza/common/aarch64/debug.S new file mode 100644 index 00000000..d105d087 --- /dev/null +++ b/drivers/rz/ipl/rza/common/aarch64/debug.S @@ -0,0 +1,221 @@ +/* + * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + + .globl asm_print_str + .globl asm_print_hex + .globl asm_print_hex_bits + .globl asm_print_newline + .globl asm_assert + .globl do_panic + +/* Since the max decimal input number is 65536 */ +#define MAX_DEC_DIVISOR 10000 +/* The offset to add to get ascii for numerals '0 - 9' */ +#define ASCII_OFFSET_NUM 0x30 + +#if ENABLE_ASSERTIONS +.section .rodata.assert_str, "aS" +assert_msg1: + .asciz "ASSERT: File " +assert_msg2: + .asciz " Line " + + /* + * This macro is intended to be used to print the + * line number in decimal. Used by asm_assert macro. + * The max number expected is 65536. + * In: x4 = the decimal to print. + * Clobber: x30, x0, x1, x2, x5, x6 + */ + .macro asm_print_line_dec + mov x6, #10 /* Divide by 10 after every loop iteration */ + mov x5, #MAX_DEC_DIVISOR +dec_print_loop: + udiv x0, x4, x5 /* Get the quotient */ + msub x4, x0, x5, x4 /* Find the remainder */ + add x0, x0, #ASCII_OFFSET_NUM /* Convert to ascii */ + bl plat_crash_console_putc + udiv x5, x5, x6 /* Reduce divisor */ + cbnz x5, dec_print_loop + .endm + + +/* --------------------------------------------------------------------------- + * Assertion support in assembly. + * The below function helps to support assertions in assembly where we do not + * have a C runtime stack. Arguments to the function are : + * x0 - File name + * x1 - Line no + * Clobber list : x30, x0, x1, x2, x3, x4, x5, x6. + * --------------------------------------------------------------------------- + */ +func asm_assert +#if LOG_LEVEL >= LOG_LEVEL_INFO + /* + * Only print the output if LOG_LEVEL is higher or equal to + * LOG_LEVEL_INFO, which is the default value for builds with DEBUG=1. + */ + mov x5, x0 + mov x6, x1 + + /* Ensure the console is initialized */ + bl plat_crash_console_init + + /* Check if the console is initialized */ + cbz x0, _assert_loop + + /* The console is initialized */ + adr x4, assert_msg1 + bl asm_print_str + mov x4, x5 + bl asm_print_str + adr x4, assert_msg2 + bl asm_print_str + + /* Check if line number higher than max permitted */ + tst x6, #~0xffff + b.ne _assert_loop + mov x4, x6 + asm_print_line_dec + bl plat_crash_console_flush +_assert_loop: +#endif /* LOG_LEVEL >= LOG_LEVEL_INFO */ + no_ret plat_panic_handler +endfunc asm_assert +#endif /* ENABLE_ASSERTIONS */ + +/* + * This function prints a string from address in x4. + * In: x4 = pointer to string. + * Clobber: x30, x0, x1, x2, x3 + */ +func asm_print_str + mov x3, x30 +1: + ldrb w0, [x4], #0x1 + cbz x0, 2f + bl plat_crash_console_putc + b 1b +2: + ret x3 +endfunc asm_print_str + +/* + * This function prints a hexadecimal number in x4. + * In: x4 = the hexadecimal to print. + * Clobber: x30, x0 - x3, x5 + */ +func asm_print_hex + mov x5, #64 /* No of bits to convert to ascii */ + + /* Convert to ascii number of bits in x5 */ +asm_print_hex_bits: + mov x3, x30 +1: + sub x5, x5, #4 + lsrv x0, x4, x5 + and x0, x0, #0xf + cmp x0, #0xA + b.lo 2f + /* Add by 0x27 in addition to ASCII_OFFSET_NUM + * to get ascii for characters 'a - f'. + */ + add x0, x0, #0x27 +2: + add x0, x0, #ASCII_OFFSET_NUM + bl plat_crash_console_putc + cbnz x5, 1b + ret x3 +endfunc asm_print_hex + +/* + * Helper function to print newline to console + * Clobber: x0 + */ +func asm_print_newline + mov x0, '\n' + b plat_crash_console_putc +endfunc asm_print_newline + + /*********************************************************** + * The common implementation of do_panic for all BL stages + ***********************************************************/ + +.section .rodata.panic_str, "aS" + panic_msg: .asciz "PANIC at PC : 0x" + +/* --------------------------------------------------------------------------- + * do_panic assumes that it is invoked from a C Runtime Environment ie a + * valid stack exists. This call will not return. + * Clobber list : if CRASH_REPORTING is not enabled then x30, x0 - x6 + * --------------------------------------------------------------------------- + */ + +/* This is for the non el3 BL stages to compile through */ + .weak el3_panic + .weak elx_panic + +func do_panic +#if CRASH_REPORTING + str x0, [sp, #-0x10]! + mrs x0, currentel + ubfx x0, x0, #MODE_EL_SHIFT, #MODE_EL_WIDTH + cmp x0, #MODE_EL3 +#if !HANDLE_EA_EL3_FIRST + ldr x0, [sp], #0x10 + b.eq el3_panic +#else + b.ne to_panic_common + + /* Check EL the exception taken from */ + mrs x0, spsr_el3 + ubfx x0, x0, #SPSR_EL_SHIFT, #SPSR_EL_WIDTH + cmp x0, #MODE_EL3 + b.ne elx_panic + ldr x0, [sp], #0x10 + b el3_panic + +to_panic_common: + ldr x0, [sp], #0x10 +#endif /* HANDLE_EA_EL3_FIRST */ +#endif /* CRASH_REPORTING */ + +panic_common: +/* + * el3_panic will be redefined by the BL31 + * crash reporting mechanism (if enabled) + */ +el3_panic: + mov x6, x30 + bl plat_crash_console_init + + /* Check if the console is initialized */ + cbz x0, _panic_handler + + /* The console is initialized */ + adr x4, panic_msg + bl asm_print_str + mov x4, x6 + + /* The panic location is lr -4 */ + sub x4, x4, #4 + bl asm_print_hex + + /* Print new line */ + bl asm_print_newline + + bl plat_crash_console_flush + +_panic_handler: + /* Pass to plat_panic_handler the address from where el3_panic was + * called, not the address of the call from el3_panic. */ + mov x30, x6 + b plat_panic_handler +endfunc do_panic diff --git a/drivers/rz/ipl/rza/common/aarch64/early_exceptions.S b/drivers/rz/ipl/rza/common/aarch64/early_exceptions.S new file mode 100644 index 00000000..36a87246 --- /dev/null +++ b/drivers/rz/ipl/rza/common/aarch64/early_exceptions.S @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +/* ----------------------------------------------------------------------------- + * Very simple stackless exception handlers used by BL2 and BL31 stages. + * BL31 uses them before stacks are setup. BL2 uses them throughout. + * ----------------------------------------------------------------------------- + */ + .globl early_exceptions + +vector_base early_exceptions + + /* ----------------------------------------------------- + * Current EL with SP0 : 0x0 - 0x200 + * ----------------------------------------------------- + */ +vector_entry SynchronousExceptionSP0 + mov x0, #SYNC_EXCEPTION_SP_EL0 + bl plat_report_exception + no_ret plat_panic_handler +end_vector_entry SynchronousExceptionSP0 + +vector_entry IrqSP0 + mov x0, #IRQ_SP_EL0 + bl plat_report_exception + no_ret plat_panic_handler +end_vector_entry IrqSP0 + +vector_entry FiqSP0 + mov x0, #FIQ_SP_EL0 + bl plat_report_exception + no_ret plat_panic_handler +end_vector_entry FiqSP0 + +vector_entry SErrorSP0 + mov x0, #SERROR_SP_EL0 + bl plat_report_exception + no_ret plat_panic_handler +end_vector_entry SErrorSP0 + + /* ----------------------------------------------------- + * Current EL with SPx: 0x200 - 0x400 + * ----------------------------------------------------- + */ +vector_entry SynchronousExceptionSPx + mov x0, #SYNC_EXCEPTION_SP_ELX + bl plat_report_exception + no_ret plat_panic_handler +end_vector_entry SynchronousExceptionSPx + +vector_entry IrqSPx + mov x0, #IRQ_SP_ELX + bl plat_report_exception + no_ret plat_panic_handler +end_vector_entry IrqSPx + +vector_entry FiqSPx + mov x0, #FIQ_SP_ELX + bl plat_report_exception + no_ret plat_panic_handler +end_vector_entry FiqSPx + +vector_entry SErrorSPx + mov x0, #SERROR_SP_ELX + bl plat_report_exception + no_ret plat_panic_handler +end_vector_entry SErrorSPx + + /* ----------------------------------------------------- + * Lower EL using AArch64 : 0x400 - 0x600 + * ----------------------------------------------------- + */ +vector_entry SynchronousExceptionA64 + mov x0, #SYNC_EXCEPTION_AARCH64 + bl plat_report_exception + no_ret plat_panic_handler +end_vector_entry SynchronousExceptionA64 + +vector_entry IrqA64 + mov x0, #IRQ_AARCH64 + bl plat_report_exception + no_ret plat_panic_handler +end_vector_entry IrqA64 + +vector_entry FiqA64 + mov x0, #FIQ_AARCH64 + bl plat_report_exception + no_ret plat_panic_handler +end_vector_entry FiqA64 + +vector_entry SErrorA64 + mov x0, #SERROR_AARCH64 + bl plat_report_exception + no_ret plat_panic_handler +end_vector_entry SErrorA64 + + /* ----------------------------------------------------- + * Lower EL using AArch32 : 0x600 - 0x800 + * ----------------------------------------------------- + */ +vector_entry SynchronousExceptionA32 + mov x0, #SYNC_EXCEPTION_AARCH32 + bl plat_report_exception + no_ret plat_panic_handler +end_vector_entry SynchronousExceptionA32 + +vector_entry IrqA32 + mov x0, #IRQ_AARCH32 + bl plat_report_exception + no_ret plat_panic_handler +end_vector_entry IrqA32 + +vector_entry FiqA32 + mov x0, #FIQ_AARCH32 + bl plat_report_exception + no_ret plat_panic_handler +end_vector_entry FiqA32 + +vector_entry SErrorA32 + mov x0, #SERROR_AARCH32 + bl plat_report_exception + no_ret plat_panic_handler +end_vector_entry SErrorA32 diff --git a/drivers/rz/ipl/rza/common/backtrace/backtrace.c b/drivers/rz/ipl/rza/common/backtrace/backtrace.c new file mode 100644 index 00000000..25e2c707 --- /dev/null +++ b/drivers/rz/ipl/rza/common/backtrace/backtrace.c @@ -0,0 +1,273 @@ +/* + * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include + +/* Maximum number of entries in the backtrace to display */ +#define UNWIND_LIMIT 20U + +/* + * If -fno-omit-frame-pointer is used: + * + * - AArch64: The AAPCS defines the format of the frame records and mandates the + * usage of r29 as frame pointer. + * + * - AArch32: The format of the frame records is not defined in the AAPCS. + * However, at least GCC and Clang use the same format. When they are forced + * to only generate A32 code (with -marm), they use r11 as frame pointer and a + * similar format as in AArch64. If interworking with T32 is enabled, the + * frame pointer is r7 and the format is different. This is not supported by + * this implementation of backtrace, so it is needed to use -marm. + */ + +/* Frame records form a linked list in the stack */ +struct frame_record { + /* Previous frame record in the list */ + struct frame_record *parent; + /* Return address of the function at this level */ + uintptr_t return_addr; +}; + +const char *get_el_str(unsigned int el) +{ + if (el == 3U) { + return "EL3"; + } else if (el == 2U) { + return "EL2"; + } else { + return "S-EL1"; + } +} + +/* + * Returns true if the address points to a virtual address that can be read at + * the current EL, false otherwise. + */ +#ifdef __aarch64__ +static bool is_address_readable(uintptr_t addr) +{ + unsigned int el = get_current_el(); + +#if ENABLE_PAUTH + /* + * When pointer authentication is enabled, the LR value saved on the + * stack contains a PAC. It must be stripped to retrieve the return + * address. + */ + xpaci(addr); +#endif + if (el == 3U) { + ats1e3r(addr); + } else if (el == 2U) { + ats1e2r(addr); + } else { + AT(ats1e1r, addr); + } + + isb(); + + /* If PAR.F == 1 the address translation was aborted. */ + if ((read_par_el1() & PAR_F_MASK) != 0U) + return false; + + return true; +} +#else /* !__aarch64__ */ +static bool is_address_readable(uintptr_t addr) +{ + unsigned int el = get_current_el(); + + if (el == 3U) { + write_ats1cpr(addr); + } else if (el == 2U) { + write_ats1hr(addr); + } else { + write_ats1cpr(addr); + } + + isb(); + + /* If PAR.F == 1 the address translation was aborted. */ + if ((read64_par() & PAR_F_MASK) != 0U) + return false; + + return true; +} +#endif /* __aarch64__ */ + +/* + * Returns true if all the bytes in a given object are in mapped memory and an + * LDR using this pointer would succeed, false otherwise. + */ +static bool is_valid_object(uintptr_t addr, size_t size) +{ + assert(size > 0U); + + if (addr == 0U) + return false; + + /* Detect overflows */ + if ((addr + size) < addr) + return false; + + /* A pointer not aligned properly could trigger an alignment fault. */ + if ((addr & (sizeof(uintptr_t) - 1U)) != 0U) + return false; + + /* Check that all the object is readable */ + for (size_t i = 0; i < size; i++) { + if (!is_address_readable(addr + i)) + return false; + } + + return true; +} + +/* + * Returns true if the specified address is correctly aligned and points to a + * valid memory region. + */ +static bool is_valid_jump_address(uintptr_t addr) +{ + if (addr == 0U) + return false; + + /* Check alignment. Both A64 and A32 use 32-bit opcodes */ + if ((addr & (sizeof(uint32_t) - 1U)) != 0U) + return false; + + if (!is_address_readable(addr)) + return false; + + return true; +} + +/* + * Returns true if the pointer points at a valid frame record, false otherwise. + */ +static bool is_valid_frame_record(struct frame_record *fr) +{ + return is_valid_object((uintptr_t)fr, sizeof(struct frame_record)); +} + +/* + * Adjust the frame-pointer-register value by 4 bytes on AArch32 to have the + * same layout as AArch64. + */ +static struct frame_record *adjust_frame_record(struct frame_record *fr) +{ +#ifdef __aarch64__ + return fr; +#else + return (struct frame_record *)((uintptr_t)fr - 4U); +#endif +} + +static void unwind_stack(struct frame_record *fr, uintptr_t current_pc, + uintptr_t link_register) +{ + uintptr_t call_site; + static const char *backtrace_str = "%u: %s: 0x%lx\n"; + const char *el_str = get_el_str(get_current_el()); + + if (!is_valid_frame_record(fr)) { + printf("ERROR: Corrupted frame pointer (frame record address = %p)\n", + fr); + return; + } + + if (fr->return_addr != link_register) { + printf("ERROR: Corrupted stack (frame record address = %p)\n", + fr); + return; + } + + /* The level 0 of the backtrace is the current backtrace function */ + printf(backtrace_str, 0U, el_str, current_pc); + + /* + * The last frame record pointer in the linked list at the beginning of + * the stack should be NULL unless stack is corrupted. + */ + for (unsigned int i = 1U; i < UNWIND_LIMIT; i++) { + /* If an invalid frame record is found, exit. */ + if (!is_valid_frame_record(fr)) + return; + /* + * A32 and A64 are fixed length so the address from where the + * call was made is the instruction before the return address, + * which is always 4 bytes before it. + */ + call_site = fr->return_addr - 4U; + +#if ENABLE_PAUTH + /* + * When pointer authentication is enabled, the LR value saved on + * the stack contains a PAC. It must be stripped to retrieve the + * return address. + */ + xpaci(call_site); +#endif + /* + * If the address is invalid it means that the frame record is + * probably corrupted. + */ + if (!is_valid_jump_address(call_site)) + return; + + printf(backtrace_str, i, el_str, call_site); + + fr = adjust_frame_record(fr->parent); + } + + printf("ERROR: Max backtrace depth reached\n"); +} + +/* + * Display a backtrace. The cookie string parameter is displayed along the + * trace to help filter the log messages. + * + * Many things can prevent displaying the expected backtrace. For example, + * compiler optimizations can use a branch instead of branch with link when it + * detects a tail call. The backtrace level for this caller will not be + * displayed, as it does not appear in the call stack anymore. Also, assembly + * functions will not be displayed unless they setup AAPCS compliant frame + * records on AArch64 and compliant with GCC-specific frame record format on + * AArch32. + * + * Usage of the trace: addr2line can be used to map the addresses to function + * and source code location when given the ELF file compiled with debug + * information. The "-i" flag is highly recommended to improve display of + * inlined function. The *.dump files generated when building each image can + * also be used. + * + * WARNING: In case of corrupted stack, this function could display security + * sensitive information past the beginning of the stack so it must not be used + * in production build. This function is only compiled in when ENABLE_BACKTRACE + * is set to 1. + */ +void backtrace(const char *cookie) +{ + uintptr_t return_address = (uintptr_t)__builtin_return_address(0U); + struct frame_record *fr = __builtin_frame_address(0U); + + /* Printing the backtrace may crash the system, flush before starting */ + console_flush(); + + fr = adjust_frame_record(fr); + + printf("BACKTRACE: START: %s\n", cookie); + + unwind_stack(fr, (uintptr_t)&backtrace, return_address); + + printf("BACKTRACE: END: %s\n", cookie); +} diff --git a/drivers/rz/ipl/rza/common/backtrace/backtrace.mk b/drivers/rz/ipl/rza/common/backtrace/backtrace.mk new file mode 100644 index 00000000..e669331c --- /dev/null +++ b/drivers/rz/ipl/rza/common/backtrace/backtrace.mk @@ -0,0 +1,31 @@ +# +# Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# Enable backtrace by default in DEBUG AArch64 builds +ifeq (${ARCH},aarch32) + ENABLE_BACKTRACE := 0 +else + ENABLE_BACKTRACE := ${DEBUG} +endif + +ifeq (${ENABLE_BACKTRACE},1) + # Force the compiler to include the frame pointer + TF_CFLAGS += -fno-omit-frame-pointer + + BL_COMMON_SOURCES += common/backtrace/backtrace.c +endif + +ifeq (${ARCH},aarch32) + ifeq (${ENABLE_BACKTRACE},1) + ifneq (${AARCH32_INSTRUCTION_SET},A32) + $(error Error: AARCH32_INSTRUCTION_SET=A32 is needed \ + for ENABLE_BACKTRACE when compiling for AArch32.) + endif + endif +endif + +$(eval $(call assert_boolean,ENABLE_BACKTRACE)) +$(eval $(call add_define,ENABLE_BACKTRACE)) diff --git a/drivers/rz/ipl/rza/common/bl_common.c b/drivers/rz/ipl/rza/common/bl_common.c new file mode 100644 index 00000000..f17afcb1 --- /dev/null +++ b/drivers/rz/ipl/rza/common/bl_common.c @@ -0,0 +1,272 @@ +/* + * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if TRUSTED_BOARD_BOOT +# ifdef DYN_DISABLE_AUTH +static int disable_auth; + +/****************************************************************************** + * API to dynamically disable authentication. Only meant for development + * systems. This is only invoked if DYN_DISABLE_AUTH is defined. + *****************************************************************************/ +void dyn_disable_auth(void) +{ + INFO("Disabling authentication of images dynamically\n"); + disable_auth = 1; +} +# endif /* DYN_DISABLE_AUTH */ + +/****************************************************************************** + * Function to determine whether the authentication is disabled dynamically. + *****************************************************************************/ +static int dyn_is_auth_disabled(void) +{ +# ifdef DYN_DISABLE_AUTH + return disable_auth; +# else + return 0; +# endif +} +#endif /* TRUSTED_BOARD_BOOT */ + +uintptr_t page_align(uintptr_t value, unsigned dir) +{ + /* Round up the limit to the next page boundary */ + if ((value & PAGE_SIZE_MASK) != 0U) { + value &= ~PAGE_SIZE_MASK; + if (dir == UP) + value += PAGE_SIZE; + } + + return value; +} + +/******************************************************************************* + * Internal function to load an image at a specific address given + * an image ID and extents of free memory. + * + * If the load is successful then the image information is updated. + * + * Returns 0 on success, a negative error code otherwise. + ******************************************************************************/ +static int load_image(unsigned int image_id, image_info_t *image_data) +{ + uintptr_t dev_handle; + uintptr_t image_handle; + uintptr_t image_spec; + uintptr_t image_base; + size_t image_size; + size_t bytes_read; + int io_result; + + assert(image_data != NULL); + assert(image_data->h.version >= VERSION_2); + + image_base = image_data->image_base; + + /* Obtain a reference to the image by querying the platform layer */ + io_result = plat_get_image_source(image_id, &dev_handle, &image_spec); + if (io_result != 0) { + WARN("Failed to obtain reference to image id=%u (%i)\n", + image_id, io_result); + return io_result; + } + + /* Attempt to access the image */ + io_result = io_open(dev_handle, image_spec, &image_handle); + if (io_result != 0) { + WARN("Failed to access image id=%u (%i)\n", + image_id, io_result); + return io_result; + } + + INFO("Loading image id=%u at address 0x%lx\n", image_id, image_base); + + /* Find the size of the image */ + io_result = io_size(image_handle, &image_size); + if ((io_result != 0) || (image_size == 0U)) { + WARN("Failed to determine the size of the image id=%u (%i)\n", + image_id, io_result); + goto exit; + } + + /* Check that the image size to load is within limit */ + if (image_size > image_data->image_max_size) { + WARN("Image id=%u size out of bounds\n", image_id); + io_result = -EFBIG; + goto exit; + } + + /* + * image_data->image_max_size is a uint32_t so image_size will always + * fit in image_data->image_size. + */ + image_data->image_size = (uint32_t)image_size; + + /* We have enough space so load the image now */ + /* TODO: Consider whether to try to recover/retry a partially successful read */ + io_result = io_read(image_handle, image_base, image_size, &bytes_read); + if ((io_result != 0) || (bytes_read < image_size)) { + WARN("Failed to load image id=%u (%i)\n", image_id, io_result); + goto exit; + } + + INFO("Image id=%u loaded: 0x%lx - 0x%lx\n", image_id, image_base, + (uintptr_t)(image_base + image_size)); + +exit: + (void)io_close(image_handle); + /* Ignore improbable/unrecoverable error in 'close' */ + + /* TODO: Consider maintaining open device connection from this bootloader stage */ + (void)io_dev_close(dev_handle); + /* Ignore improbable/unrecoverable error in 'dev_close' */ + + return io_result; +} + +/* + * Load an image and flush it out to main memory so that it can be executed + * later by any CPU, regardless of cache and MMU state. + */ +static int load_image_flush(unsigned int image_id, + image_info_t *image_data) +{ + int rc; + + rc = load_image(image_id, image_data); + if (rc == 0) { + flush_dcache_range(image_data->image_base, + image_data->image_size); + } + + return rc; +} + + +#if TRUSTED_BOARD_BOOT +/* + * This function uses recursion to authenticate the parent images up to the root + * of trust. + */ +static int load_auth_image_recursive(unsigned int image_id, + image_info_t *image_data, + int is_parent_image) +{ + int rc; + unsigned int parent_id; + + /* Use recursion to authenticate parent images */ + rc = auth_mod_get_parent_id(image_id, &parent_id); + if (rc == 0) { + rc = load_auth_image_recursive(parent_id, image_data, 1); + if (rc != 0) { + return rc; + } + } + + /* Load the image */ + rc = load_image(image_id, image_data); + if (rc != 0) { + return rc; + } + + /* Authenticate it */ + rc = auth_mod_verify_img(image_id, + (void *)image_data->image_base, + image_data->image_size); + if (rc != 0) { + /* Authentication error, zero memory and flush it right away. */ + zero_normalmem((void *)image_data->image_base, + image_data->image_size); + flush_dcache_range(image_data->image_base, + image_data->image_size); + return -EAUTH; + } + + /* + * Flush the image to main memory so that it can be executed later by + * any CPU, regardless of cache and MMU state. This is only needed for + * child images, not for the parents (certificates). + */ + if (is_parent_image == 0) { + flush_dcache_range(image_data->image_base, + image_data->image_size); + } + + return 0; +} +#endif /* TRUSTED_BOARD_BOOT */ + +static int load_auth_image_internal(unsigned int image_id, + image_info_t *image_data) +{ +#if TRUSTED_BOARD_BOOT + if (dyn_is_auth_disabled() == 0) { + return load_auth_image_recursive(image_id, image_data, 0); + } +#endif + + return load_image_flush(image_id, image_data); +} + +/******************************************************************************* + * Generic function to load and authenticate an image. The image is actually + * loaded by calling the 'load_image()' function. Therefore, it returns the + * same error codes if the loading operation failed, or -EAUTH if the + * authentication failed. In addition, this function uses recursion to + * authenticate the parent images up to the root of trust (if TBB is enabled). + ******************************************************************************/ +int load_auth_image(unsigned int image_id, image_info_t *image_data) +{ + int err; + + do { + err = load_auth_image_internal(image_id, image_data); + } while ((err != 0) && (plat_try_next_boot_source() != 0)); + + return err; +} + +/******************************************************************************* + * Print the content of an entry_point_info_t structure. + ******************************************************************************/ +void print_entry_point_info(const entry_point_info_t *ep_info) +{ + INFO("Entry point address = 0x%lx\n", ep_info->pc); + INFO("SPSR = 0x%x\n", ep_info->spsr); + +#define PRINT_IMAGE_ARG(n) \ + VERBOSE("Argument #" #n " = 0x%llx\n", \ + (unsigned long long) ep_info->args.arg##n) + + PRINT_IMAGE_ARG(0); + PRINT_IMAGE_ARG(1); + PRINT_IMAGE_ARG(2); + PRINT_IMAGE_ARG(3); +#ifdef __aarch64__ + PRINT_IMAGE_ARG(4); + PRINT_IMAGE_ARG(5); + PRINT_IMAGE_ARG(6); + PRINT_IMAGE_ARG(7); +#endif +#undef PRINT_IMAGE_ARG +} diff --git a/drivers/rz/ipl/rza/common/desc_image_load.c b/drivers/rz/ipl/rza/common/desc_image_load.c new file mode 100644 index 00000000..30b97e05 --- /dev/null +++ b/drivers/rz/ipl/rza/common/desc_image_load.c @@ -0,0 +1,351 @@ +/* + * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include + +static bl_load_info_t bl_load_info; +static bl_params_t next_bl_params; + + +/******************************************************************************* + * This function flushes the data structures so that they are visible + * in memory for the next BL image. + ******************************************************************************/ +void flush_bl_params_desc(void) +{ + flush_bl_params_desc_args(bl_mem_params_desc_ptr, + bl_mem_params_desc_num, + &next_bl_params); +} + +/******************************************************************************* + * This function flushes the data structures specified as arguments so that they + * are visible in memory for the next BL image. + ******************************************************************************/ +void flush_bl_params_desc_args(bl_mem_params_node_t *mem_params_desc_ptr, + unsigned int mem_params_desc_num, + bl_params_t *next_bl_params_ptr) +{ + assert(mem_params_desc_ptr != NULL); + assert(mem_params_desc_num != 0U); + assert(next_bl_params_ptr != NULL); + + flush_dcache_range((uintptr_t)mem_params_desc_ptr, + sizeof(*mem_params_desc_ptr) * mem_params_desc_num); + + flush_dcache_range((uintptr_t)next_bl_params_ptr, + sizeof(*next_bl_params_ptr)); +} + +/******************************************************************************* + * This function returns the index for given image_id, within the + * image descriptor array provided by bl_image_info_descs_ptr, if the + * image is found else it returns -1. + ******************************************************************************/ +int get_bl_params_node_index(unsigned int image_id) +{ + unsigned int index; + assert(image_id != INVALID_IMAGE_ID); + + for (index = 0U; index < bl_mem_params_desc_num; index++) { + if (bl_mem_params_desc_ptr[index].image_id == image_id) + return (int)index; + } + + return -1; +} + +/******************************************************************************* + * This function returns the pointer to `bl_mem_params_node_t` object for + * given image_id, within the image descriptor array provided by + * bl_mem_params_desc_ptr, if the image is found else it returns NULL. + ******************************************************************************/ +bl_mem_params_node_t *get_bl_mem_params_node(unsigned int image_id) +{ + int index; + assert(image_id != INVALID_IMAGE_ID); + + index = get_bl_params_node_index(image_id); + if (index >= 0) + return &bl_mem_params_desc_ptr[index]; + else + return NULL; +} + +/******************************************************************************* + * This function creates the list of loadable images, by populating and + * linking each `bl_load_info_node_t` type node, using the internal array + * of image descriptor provided by bl_mem_params_desc_ptr. It also populates + * and returns `bl_load_info_t` type structure that contains head of the list + * of loadable images. + ******************************************************************************/ +bl_load_info_t *get_bl_load_info_from_mem_params_desc(void) +{ + unsigned int index = 0; + + /* If there is no image to start with, return NULL */ + if (bl_mem_params_desc_num == 0U) + return NULL; + + /* Assign initial data structures */ + bl_load_info_node_t *bl_node_info = + &bl_mem_params_desc_ptr[index].load_node_mem; + bl_load_info.head = bl_node_info; + SET_PARAM_HEAD(&bl_load_info, PARAM_BL_LOAD_INFO, VERSION_2, 0U); + + /* Go through the image descriptor array and create the list */ + for (; index < bl_mem_params_desc_num; index++) { + + /* Populate the image information */ + bl_node_info->image_id = bl_mem_params_desc_ptr[index].image_id; + bl_node_info->image_info = &bl_mem_params_desc_ptr[index].image_info; + + /* Link next image if present */ + if ((index + 1U) < bl_mem_params_desc_num) { + /* Get the memory and link the next node */ + bl_node_info->next_load_info = + &bl_mem_params_desc_ptr[index + 1U].load_node_mem; + bl_node_info = bl_node_info->next_load_info; + } + } + + return &bl_load_info; +} + +/******************************************************************************* + * This function creates the list of executable images, by populating and + * linking each `bl_params_node_t` type node, using the internal array of + * image descriptor provided by bl_mem_params_desc_ptr. It also populates + * and returns `bl_params_t` type structure that contains head of the list + * of executable images. + ******************************************************************************/ +bl_params_t *get_next_bl_params_from_mem_params_desc(void) +{ + unsigned int count; + unsigned int img_id = 0U; + unsigned int link_index = 0U; + bl_params_node_t *bl_current_exec_node = NULL; + bl_params_node_t *bl_last_exec_node = NULL; + bl_mem_params_node_t *desc_ptr; + + /* If there is no image to start with, return NULL */ + if (bl_mem_params_desc_num == 0U) + return NULL; + + /* Get the list HEAD */ + for (count = 0U; count < bl_mem_params_desc_num; count++) { + + desc_ptr = &bl_mem_params_desc_ptr[count]; + + if ((EP_GET_EXE(desc_ptr->ep_info.h.attr) == EXECUTABLE) && + (EP_GET_FIRST_EXE(desc_ptr->ep_info.h.attr) == EP_FIRST_EXE)) { + next_bl_params.head = &desc_ptr->params_node_mem; + link_index = count; + break; + } + } + + /* Make sure we have a HEAD node */ + assert(next_bl_params.head != NULL); + + /* Populate the HEAD information */ + SET_PARAM_HEAD(&next_bl_params, PARAM_BL_PARAMS, VERSION_2, 0U); + + /* + * Go through the image descriptor array and create the list. + * This bounded loop is to make sure that we are not looping forever. + */ + for (count = 0U; count < bl_mem_params_desc_num; count++) { + + desc_ptr = &bl_mem_params_desc_ptr[link_index]; + + /* Make sure the image is executable */ + assert(EP_GET_EXE(desc_ptr->ep_info.h.attr) == EXECUTABLE); + + /* Get the memory for current node */ + bl_current_exec_node = &desc_ptr->params_node_mem; + + /* Populate the image information */ + bl_current_exec_node->image_id = desc_ptr->image_id; + bl_current_exec_node->image_info = &desc_ptr->image_info; + bl_current_exec_node->ep_info = &desc_ptr->ep_info; + + if (bl_last_exec_node != NULL) { + /* Assert if loop detected */ + assert(bl_last_exec_node->next_params_info == NULL); + + /* Link the previous node to the current one */ + bl_last_exec_node->next_params_info = bl_current_exec_node; + } + + /* Update the last node */ + bl_last_exec_node = bl_current_exec_node; + + /* If no next hand-off image then break out */ + img_id = desc_ptr->next_handoff_image_id; + if (img_id == INVALID_IMAGE_ID) + break; + + /* Get the index for the next hand-off image */ + link_index = get_bl_params_node_index(img_id); + assert((link_index > 0U) && + (link_index < bl_mem_params_desc_num)); + } + + /* Invalid image is expected to terminate the loop */ + assert(img_id == INVALID_IMAGE_ID); + + return &next_bl_params; +} + +/******************************************************************************* + * This function populates the entry point information with the corresponding + * config file for all executable BL images described in bl_params. + ******************************************************************************/ +void populate_next_bl_params_config(bl_params_t *bl2_to_next_bl_params) +{ + bl_params_node_t *params_node; + unsigned int fw_config_id; + uintptr_t fw_config_base; + bl_mem_params_node_t *mem_params; + uintptr_t hw_config_base = 0; + + assert(bl2_to_next_bl_params != NULL); + + /* + * Get the `bl_mem_params_node_t` corresponding to HW_CONFIG + * if available. + */ + mem_params = get_bl_mem_params_node(HW_CONFIG_ID); + + if (mem_params != NULL) + hw_config_base = mem_params->image_info.image_base; + + for (params_node = bl2_to_next_bl_params->head; params_node != NULL; + params_node = params_node->next_params_info) { + + fw_config_base = 0; + + switch (params_node->image_id) { + case BL31_IMAGE_ID: + fw_config_id = SOC_FW_CONFIG_ID; + break; + case BL32_IMAGE_ID: + /* + * At the moment, OPTEE cannot accept a DTB in secure memory, + * so fall back and use NT_FW_CONFIG instead. + * This MUST be fixed as soon as OPTEE has support to + * receive DTBs in secure memory. + */ +#ifndef SPD_opteed + fw_config_id = TOS_FW_CONFIG_ID; + break; +#endif + case BL33_IMAGE_ID: + fw_config_id = NT_FW_CONFIG_ID; + break; + default: + fw_config_id = INVALID_IMAGE_ID; + break; + } + + if (fw_config_id != INVALID_IMAGE_ID) { + mem_params = get_bl_mem_params_node(fw_config_id); + if (mem_params != NULL) { + fw_config_base = mem_params->image_info.image_base; + } + } + +#ifdef SPD_opteed + /* + * If SPD_opteed is enabled, arg[0,2] are populated by + * parse_optee_header(), which is called by + * arm_bl2_handle_post_image_load(). The meaning of the + * arguments are: + * arg0 <-- MODE_RW + * arg1 <-- Paged image base + * arg2 <-- Paged image size + */ + if (params_node->image_id == BL32_IMAGE_ID) { + params_node->ep_info->args.arg3 = fw_config_base; + } else { +#endif + /* + * Pass hw and tb_fw config addresses to next images. + * NOTE - for EL3 runtime images (BL31 for AArch64 + * and BL32 for AArch32), arg0 is already used by + * generic code. Take care of not overwriting the + * previous initialisations. + */ + if (params_node == bl2_to_next_bl_params->head) { + if (params_node->ep_info->args.arg1 == 0U) + params_node->ep_info->args.arg1 = + fw_config_base; + if (params_node->ep_info->args.arg2 == 0U) + params_node->ep_info->args.arg2 = + hw_config_base; + } else { + if (params_node->ep_info->args.arg0 == 0U) + params_node->ep_info->args.arg0 = + fw_config_base; + if (params_node->ep_info->args.arg1 == 0U) + params_node->ep_info->args.arg1 = + hw_config_base; + } +#ifdef SPD_opteed + } +#endif + } +} + +/******************************************************************************* + * Helper to extract BL32/BL33 entry point info from arg0 passed to BL31, for + * platforms that are only interested in those. Platforms that need to extract + * more information can parse the structures themselves. + ******************************************************************************/ + +void bl31_params_parse_helper(u_register_t param, + entry_point_info_t *bl32_ep_info_out, + entry_point_info_t *bl33_ep_info_out) +{ + bl_params_node_t *node; + bl_params_t *v2 = (void *)(uintptr_t)param; + +#if !ERROR_DEPRECATED + if (v2->h.version == PARAM_VERSION_1) { + struct { /* Deprecated version 1 parameter structure. */ + param_header_t h; + image_info_t *bl31_image_info; + entry_point_info_t *bl32_ep_info; + image_info_t *bl32_image_info; + entry_point_info_t *bl33_ep_info; + image_info_t *bl33_image_info; + } *v1 = (void *)(uintptr_t)param; + assert(v1->h.type == PARAM_BL31); + if (bl32_ep_info_out != NULL) + *bl32_ep_info_out = *v1->bl32_ep_info; + if (bl33_ep_info_out != NULL) + *bl33_ep_info_out = *v1->bl33_ep_info; + return; + } +#endif /* !ERROR_DEPRECATED */ + + assert(v2->h.version == PARAM_VERSION_2); + assert(v2->h.type == PARAM_BL_PARAMS); + for (node = v2->head; node != NULL; node = node->next_params_info) { + if (node->image_id == BL32_IMAGE_ID) + if (bl32_ep_info_out != NULL) + *bl32_ep_info_out = *node->ep_info; + if (node->image_id == BL33_IMAGE_ID) + if (bl33_ep_info_out != NULL) + *bl33_ep_info_out = *node->ep_info; + } +} diff --git a/drivers/rz/ipl/rza/common/tf_log.c b/drivers/rz/ipl/rza/common/tf_log.c new file mode 100644 index 00000000..08d3cf48 --- /dev/null +++ b/drivers/rz/ipl/rza/common/tf_log.c @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2017-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include + +/* Set the default maximum log level to the `LOG_LEVEL` build flag */ +static unsigned int max_log_level = LOG_LEVEL; + +/* + * The common log function which is invoked by TF-A code. + * This function should not be directly invoked and is meant to be + * only used by the log macros defined in debug.h. The function + * expects the first character in the format string to be one of the + * LOG_MARKER_* macros defined in debug.h. + */ +void tf_log(const char *fmt, ...) +{ + unsigned int log_level; + va_list args; + const char *prefix_str; + + /* We expect the LOG_MARKER_* macro as the first character */ + log_level = fmt[0]; + + /* Verify that log_level is one of LOG_MARKER_* macro defined in debug.h */ + assert((log_level > 0U) && (log_level <= LOG_LEVEL_VERBOSE)); + assert((log_level % 10U) == 0U); + + if (log_level > max_log_level) + return; + + prefix_str = plat_log_get_prefix(log_level); + + while (*prefix_str != '\0') { + (void)putchar(*prefix_str); + prefix_str++; + } + + va_start(args, fmt); + (void)vprintf(fmt + 1, args); + va_end(args); +} + +/* + * The helper function to set the log level dynamically by platform. The + * maximum log level is determined by `LOG_LEVEL` build flag at compile time + * and this helper can set a lower (or equal) log level than the one at compile. + */ +void tf_log_set_max_level(unsigned int log_level) +{ + assert(log_level <= LOG_LEVEL_VERBOSE); + assert((log_level % 10U) == 0U); + + /* Cap log_level to the compile time maximum. */ + if (log_level <= (unsigned int)LOG_LEVEL) + max_log_level = log_level; +} diff --git a/drivers/rz/ipl/rza/drivers/arm/gic/common/gic_common.c b/drivers/rz/ipl/rza/drivers/arm/gic/common/gic_common.c new file mode 100644 index 00000000..bf6405f7 --- /dev/null +++ b/drivers/rz/ipl/rza/drivers/arm/gic/common/gic_common.c @@ -0,0 +1,342 @@ +/* + * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#pragma message __FILE__ " is deprecated, use gicv2.mk instead" + +#include + +#include +#include + +#include "gic_common_private.h" + +/******************************************************************************* + * GIC Distributor interface accessors for reading entire registers + ******************************************************************************/ +/* + * Accessor to read the GIC Distributor IGROUPR corresponding to the interrupt + * `id`, 32 interrupt ids at a time. + */ +unsigned int gicd_read_igroupr(uintptr_t base, unsigned int id) +{ + unsigned int n = id >> IGROUPR_SHIFT; + + return mmio_read_32(base + GICD_IGROUPR + (n << 2)); +} + +/* + * Accessor to read the GIC Distributor ISENABLER corresponding to the + * interrupt `id`, 32 interrupt ids at a time. + */ +unsigned int gicd_read_isenabler(uintptr_t base, unsigned int id) +{ + unsigned int n = id >> ISENABLER_SHIFT; + + return mmio_read_32(base + GICD_ISENABLER + (n << 2)); +} + +/* + * Accessor to read the GIC Distributor ICENABLER corresponding to the + * interrupt `id`, 32 interrupt IDs at a time. + */ +unsigned int gicd_read_icenabler(uintptr_t base, unsigned int id) +{ + unsigned int n = id >> ICENABLER_SHIFT; + + return mmio_read_32(base + GICD_ICENABLER + (n << 2)); +} + +/* + * Accessor to read the GIC Distributor ISPENDR corresponding to the + * interrupt `id`, 32 interrupt IDs at a time. + */ +unsigned int gicd_read_ispendr(uintptr_t base, unsigned int id) +{ + unsigned int n = id >> ISPENDR_SHIFT; + + return mmio_read_32(base + GICD_ISPENDR + (n << 2)); +} + +/* + * Accessor to read the GIC Distributor ICPENDR corresponding to the + * interrupt `id`, 32 interrupt IDs at a time. + */ +unsigned int gicd_read_icpendr(uintptr_t base, unsigned int id) +{ + unsigned int n = id >> ICPENDR_SHIFT; + + return mmio_read_32(base + GICD_ICPENDR + (n << 2)); +} + +/* + * Accessor to read the GIC Distributor ISACTIVER corresponding to the + * interrupt `id`, 32 interrupt IDs at a time. + */ +unsigned int gicd_read_isactiver(uintptr_t base, unsigned int id) +{ + unsigned int n = id >> ISACTIVER_SHIFT; + + return mmio_read_32(base + GICD_ISACTIVER + (n << 2)); +} + +/* + * Accessor to read the GIC Distributor ICACTIVER corresponding to the + * interrupt `id`, 32 interrupt IDs at a time. + */ +unsigned int gicd_read_icactiver(uintptr_t base, unsigned int id) +{ + unsigned int n = id >> ICACTIVER_SHIFT; + + return mmio_read_32(base + GICD_ICACTIVER + (n << 2)); +} + +/* + * Accessor to read the GIC Distributor IPRIORITYR corresponding to the + * interrupt `id`, 4 interrupt IDs at a time. + */ +unsigned int gicd_read_ipriorityr(uintptr_t base, unsigned int id) +{ + unsigned int n = id >> IPRIORITYR_SHIFT; + + return mmio_read_32(base + GICD_IPRIORITYR + (n << 2)); +} + +/* + * Accessor to read the GIC Distributor ICGFR corresponding to the + * interrupt `id`, 16 interrupt IDs at a time. + */ +unsigned int gicd_read_icfgr(uintptr_t base, unsigned int id) +{ + unsigned int n = id >> ICFGR_SHIFT; + + return mmio_read_32(base + GICD_ICFGR + (n << 2)); +} + +/* + * Accessor to read the GIC Distributor NSACR corresponding to the + * interrupt `id`, 16 interrupt IDs at a time. + */ +unsigned int gicd_read_nsacr(uintptr_t base, unsigned int id) +{ + unsigned int n = id >> NSACR_SHIFT; + + return mmio_read_32(base + GICD_NSACR + (n << 2)); +} + +/******************************************************************************* + * GIC Distributor interface accessors for writing entire registers + ******************************************************************************/ +/* + * Accessor to write the GIC Distributor IGROUPR corresponding to the + * interrupt `id`, 32 interrupt IDs at a time. + */ +void gicd_write_igroupr(uintptr_t base, unsigned int id, unsigned int val) +{ + unsigned int n = id >> IGROUPR_SHIFT; + + mmio_write_32(base + GICD_IGROUPR + (n << 2), val); +} + +/* + * Accessor to write the GIC Distributor ISENABLER corresponding to the + * interrupt `id`, 32 interrupt IDs at a time. + */ +void gicd_write_isenabler(uintptr_t base, unsigned int id, unsigned int val) +{ + unsigned int n = id >> ISENABLER_SHIFT; + + mmio_write_32(base + GICD_ISENABLER + (n << 2), val); +} + +/* + * Accessor to write the GIC Distributor ICENABLER corresponding to the + * interrupt `id`, 32 interrupt IDs at a time. + */ +void gicd_write_icenabler(uintptr_t base, unsigned int id, unsigned int val) +{ + unsigned int n = id >> ICENABLER_SHIFT; + + mmio_write_32(base + GICD_ICENABLER + (n << 2), val); +} + +/* + * Accessor to write the GIC Distributor ISPENDR corresponding to the + * interrupt `id`, 32 interrupt IDs at a time. + */ +void gicd_write_ispendr(uintptr_t base, unsigned int id, unsigned int val) +{ + unsigned int n = id >> ISPENDR_SHIFT; + + mmio_write_32(base + GICD_ISPENDR + (n << 2), val); +} + +/* + * Accessor to write the GIC Distributor ICPENDR corresponding to the + * interrupt `id`, 32 interrupt IDs at a time. + */ +void gicd_write_icpendr(uintptr_t base, unsigned int id, unsigned int val) +{ + unsigned int n = id >> ICPENDR_SHIFT; + + mmio_write_32(base + GICD_ICPENDR + (n << 2), val); +} + +/* + * Accessor to write the GIC Distributor ISACTIVER corresponding to the + * interrupt `id`, 32 interrupt IDs at a time. + */ +void gicd_write_isactiver(uintptr_t base, unsigned int id, unsigned int val) +{ + unsigned int n = id >> ISACTIVER_SHIFT; + + mmio_write_32(base + GICD_ISACTIVER + (n << 2), val); +} + +/* + * Accessor to write the GIC Distributor ICACTIVER corresponding to the + * interrupt `id`, 32 interrupt IDs at a time. + */ +void gicd_write_icactiver(uintptr_t base, unsigned int id, unsigned int val) +{ + unsigned int n = id >> ICACTIVER_SHIFT; + + mmio_write_32(base + GICD_ICACTIVER + (n << 2), val); +} + +/* + * Accessor to write the GIC Distributor IPRIORITYR corresponding to the + * interrupt `id`, 4 interrupt IDs at a time. + */ +void gicd_write_ipriorityr(uintptr_t base, unsigned int id, unsigned int val) +{ + unsigned int n = id >> IPRIORITYR_SHIFT; + + mmio_write_32(base + GICD_IPRIORITYR + (n << 2), val); +} + +/* + * Accessor to write the GIC Distributor ICFGR corresponding to the + * interrupt `id`, 16 interrupt IDs at a time. + */ +void gicd_write_icfgr(uintptr_t base, unsigned int id, unsigned int val) +{ + unsigned int n = id >> ICFGR_SHIFT; + + mmio_write_32(base + GICD_ICFGR + (n << 2), val); +} + +/* + * Accessor to write the GIC Distributor NSACR corresponding to the + * interrupt `id`, 16 interrupt IDs at a time. + */ +void gicd_write_nsacr(uintptr_t base, unsigned int id, unsigned int val) +{ + unsigned int n = id >> NSACR_SHIFT; + + mmio_write_32(base + GICD_NSACR + (n << 2), val); +} + +/******************************************************************************* + * GIC Distributor functions for accessing the GIC registers + * corresponding to a single interrupt ID. These functions use bitwise + * operations or appropriate register accesses to modify or return + * the bit-field corresponding the single interrupt ID. + ******************************************************************************/ +unsigned int gicd_get_igroupr(uintptr_t base, unsigned int id) +{ + unsigned int bit_num = id & ((1U << IGROUPR_SHIFT) - 1U); + unsigned int reg_val = gicd_read_igroupr(base, id); + + return (reg_val >> bit_num) & 0x1U; +} + +void gicd_set_igroupr(uintptr_t base, unsigned int id) +{ + unsigned int bit_num = id & ((1U << IGROUPR_SHIFT) - 1U); + unsigned int reg_val = gicd_read_igroupr(base, id); + + gicd_write_igroupr(base, id, reg_val | (1U << bit_num)); +} + +void gicd_clr_igroupr(uintptr_t base, unsigned int id) +{ + unsigned int bit_num = id & ((1U << IGROUPR_SHIFT) - 1U); + unsigned int reg_val = gicd_read_igroupr(base, id); + + gicd_write_igroupr(base, id, reg_val & ~(1U << bit_num)); +} + +void gicd_set_isenabler(uintptr_t base, unsigned int id) +{ + unsigned int bit_num = id & ((1U << ISENABLER_SHIFT) - 1U); + + gicd_write_isenabler(base, id, (1U << bit_num)); +} + +void gicd_set_icenabler(uintptr_t base, unsigned int id) +{ + unsigned int bit_num = id & ((1U << ICENABLER_SHIFT) - 1U); + + gicd_write_icenabler(base, id, (1U << bit_num)); +} + +void gicd_set_ispendr(uintptr_t base, unsigned int id) +{ + unsigned int bit_num = id & ((1U << ISPENDR_SHIFT) - 1U); + + gicd_write_ispendr(base, id, (1U << bit_num)); +} + +void gicd_set_icpendr(uintptr_t base, unsigned int id) +{ + unsigned int bit_num = id & ((1U << ICPENDR_SHIFT) - 1U); + + gicd_write_icpendr(base, id, (1U << bit_num)); +} + +unsigned int gicd_get_isactiver(uintptr_t base, unsigned int id) +{ + unsigned int bit_num = id & ((1U << ISACTIVER_SHIFT) - 1U); + unsigned int reg_val = gicd_read_isactiver(base, id); + + return (reg_val >> bit_num) & 0x1U; +} + +void gicd_set_isactiver(uintptr_t base, unsigned int id) +{ + unsigned int bit_num = id & ((1U << ISACTIVER_SHIFT) - 1U); + + gicd_write_isactiver(base, id, (1U << bit_num)); +} + +void gicd_set_icactiver(uintptr_t base, unsigned int id) +{ + unsigned int bit_num = id & ((1U << ICACTIVER_SHIFT) - 1U); + + gicd_write_icactiver(base, id, (1U << bit_num)); +} + +void gicd_set_ipriorityr(uintptr_t base, unsigned int id, unsigned int pri) +{ + uint8_t val = pri & GIC_PRI_MASK; + + mmio_write_8(base + GICD_IPRIORITYR + id, val); +} + +void gicd_set_icfgr(uintptr_t base, unsigned int id, unsigned int cfg) +{ + /* Interrupt configuration is a 2-bit field */ + unsigned int bit_num = id & ((1U << ICFGR_SHIFT) - 1U); + unsigned int bit_shift = bit_num << 1; + + uint32_t reg_val = gicd_read_icfgr(base, id); + + /* Clear the field, and insert required configuration */ + reg_val &= ~(GIC_CFG_MASK << bit_shift); + reg_val |= ((cfg & GIC_CFG_MASK) << bit_shift); + + gicd_write_icfgr(base, id, reg_val); +} diff --git a/drivers/rz/ipl/rza/drivers/arm/gic/common/gic_common_private.h b/drivers/rz/ipl/rza/drivers/arm/gic/common/gic_common_private.h new file mode 100644 index 00000000..1ab1bdbe --- /dev/null +++ b/drivers/rz/ipl/rza/drivers/arm/gic/common/gic_common_private.h @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef GIC_COMMON_PRIVATE_H +#define GIC_COMMON_PRIVATE_H + +#include + +#include +#include + +/******************************************************************************* + * GIC Distributor interface register accessors that are common to GICv3 & GICv2 + ******************************************************************************/ +static inline unsigned int gicd_read_ctlr(uintptr_t base) +{ + return mmio_read_32(base + GICD_CTLR); +} + +static inline unsigned int gicd_read_typer(uintptr_t base) +{ + return mmio_read_32(base + GICD_TYPER); +} + +static inline unsigned int gicd_read_iidr(uintptr_t base) +{ + return mmio_read_32(base + GICD_IIDR); +} + +static inline void gicd_write_ctlr(uintptr_t base, unsigned int val) +{ + mmio_write_32(base + GICD_CTLR, val); +} + +/******************************************************************************* + * GIC Distributor function prototypes for accessing entire registers. + * Note: The raw register values correspond to multiple interrupt IDs and + * the number of interrupt IDs involved depends on the register accessed. + ******************************************************************************/ +unsigned int gicd_read_igroupr(uintptr_t base, unsigned int id); +unsigned int gicd_read_isenabler(uintptr_t base, unsigned int id); +unsigned int gicd_read_icenabler(uintptr_t base, unsigned int id); +unsigned int gicd_read_ispendr(uintptr_t base, unsigned int id); +unsigned int gicd_read_icpendr(uintptr_t base, unsigned int id); +unsigned int gicd_read_isactiver(uintptr_t base, unsigned int id); +unsigned int gicd_read_icactiver(uintptr_t base, unsigned int id); +unsigned int gicd_read_ipriorityr(uintptr_t base, unsigned int id); +unsigned int gicd_read_icfgr(uintptr_t base, unsigned int id); +unsigned int gicd_read_nsacr(uintptr_t base, unsigned int id); +unsigned int gicd_read_spendsgir(uintptr_t base, unsigned int id); +unsigned int gicd_read_cpendsgir(uintptr_t base, unsigned int id); +unsigned int gicd_read_itargetsr(uintptr_t base, unsigned int id); +void gicd_write_igroupr(uintptr_t base, unsigned int id, unsigned int val); +void gicd_write_isenabler(uintptr_t base, unsigned int id, unsigned int val); +void gicd_write_icenabler(uintptr_t base, unsigned int id, unsigned int val); +void gicd_write_ispendr(uintptr_t base, unsigned int id, unsigned int val); +void gicd_write_icpendr(uintptr_t base, unsigned int id, unsigned int val); +void gicd_write_isactiver(uintptr_t base, unsigned int id, unsigned int val); +void gicd_write_icactiver(uintptr_t base, unsigned int id, unsigned int val); +void gicd_write_ipriorityr(uintptr_t base, unsigned int id, unsigned int val); +void gicd_write_icfgr(uintptr_t base, unsigned int id, unsigned int val); +void gicd_write_nsacr(uintptr_t base, unsigned int id, unsigned int val); +void gicd_write_spendsgir(uintptr_t base, unsigned int id, unsigned int val); +void gicd_write_cpendsgir(uintptr_t base, unsigned int id, unsigned int val); +void gicd_write_itargetsr(uintptr_t base, unsigned int id, unsigned int val); + +/******************************************************************************* + * GIC Distributor function prototypes for accessing the GIC registers + * corresponding to a single interrupt ID. These functions use bitwise + * operations or appropriate register accesses to modify or return + * the bit-field corresponding the single interrupt ID. + ******************************************************************************/ +unsigned int gicd_get_igroupr(uintptr_t base, unsigned int id); +void gicd_set_igroupr(uintptr_t base, unsigned int id); +void gicd_clr_igroupr(uintptr_t base, unsigned int id); +void gicd_set_isenabler(uintptr_t base, unsigned int id); +void gicd_set_icenabler(uintptr_t base, unsigned int id); +void gicd_set_ispendr(uintptr_t base, unsigned int id); +void gicd_set_icpendr(uintptr_t base, unsigned int id); +unsigned int gicd_get_isactiver(uintptr_t base, unsigned int id); +void gicd_set_isactiver(uintptr_t base, unsigned int id); +void gicd_set_icactiver(uintptr_t base, unsigned int id); +void gicd_set_ipriorityr(uintptr_t base, unsigned int id, unsigned int pri); +void gicd_set_icfgr(uintptr_t base, unsigned int id, unsigned int cfg); + +#endif /* GIC_COMMON_PRIVATE_H */ diff --git a/drivers/rz/ipl/rza/drivers/arm/gic/v3/arm_gicv3_common.c b/drivers/rz/ipl/rza/drivers/arm/gic/v3/arm_gicv3_common.c new file mode 100644 index 00000000..44898928 --- /dev/null +++ b/drivers/rz/ipl/rza/drivers/arm/gic/v3/arm_gicv3_common.c @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * Driver for implementation defined features that are identical in ARM GICv3 +* implementations (GIC-500 and GIC-600 for now). This driver only overrides +* APIs that are different to those generic ones in GICv3 driver. + */ + +#include + +#include +#include +#include + +#include "gicv3_private.h" + +/* + * Flush the internal GIC cache of the LPIs pending tables to memory before + * saving the state of the Redistributor. This is required before powering off + * the GIC when the pending status must be preserved. + * `rdist_proc_num` is the processor number corresponding to the Redistributor of the + * current CPU. + */ +void arm_gicv3_distif_pre_save(unsigned int rdist_proc_num) +{ + uintptr_t gicr_base = 0; + + assert(gicv3_driver_data); + assert(gicv3_driver_data->rdistif_base_addrs); + + /* + * The GICR_WAKER.Sleep bit should be set only when both + * GICR_WAKER.ChildrenAsleep and GICR_WAKER.ProcessorSleep are set on + * all the Redistributors. + */ + for (unsigned int i = 0; i < gicv3_driver_data->rdistif_num; i++) { + gicr_base = gicv3_driver_data->rdistif_base_addrs[i]; + assert(gicr_base); + assert(gicr_read_waker(gicr_base) & WAKER_CA_BIT); + assert(gicr_read_waker(gicr_base) & WAKER_PS_BIT); + } + + gicr_base = gicv3_driver_data->rdistif_base_addrs[rdist_proc_num]; + /* + * According to the TRM, there is only one instance of the + * GICR_WAKER.Sleep and GICR_WAKER.Quiescent bits that can be accessed + * through any of the Redistributor. + */ + + /* + * Set GICR_WAKER.Sleep + * After this point, the system must be configured so that the + * wake_request signals for the right cores are asserted when a wakeup + * interrupt is detected. The GIC will not be able to do that anymore + * when the GICR_WAKER.Sleep bit is set to 1. + */ + gicr_write_waker(gicr_base, gicr_read_waker(gicr_base) | WAKER_SL_BIT); + + /* Wait until the GICR_WAKER.Quiescent bit is set */ + while (!(gicr_read_waker(gicr_base) & WAKER_QSC_BIT)) + ; +} + +/* + * Allow the LPIs pending state to be read back from the tables in memory after + * having restored the state of the GIC Redistributor. + */ +void arm_gicv3_distif_post_restore(unsigned int rdist_proc_num) +{ + uintptr_t gicr_base; + + assert(gicv3_driver_data); + assert(gicv3_driver_data->rdistif_base_addrs); + + /* + * According to the TRM, there is only one instance of the + * GICR_WAKER.Sleep and GICR_WAKER.Quiescent bits that can be accessed + * through any of the Redistributor. + */ + gicr_base = gicv3_driver_data->rdistif_base_addrs[rdist_proc_num]; + assert(gicr_base); + + /* + * If the GIC had power removed, the GICR_WAKER state will be reset. + * Since the GICR_WAKER.Sleep and GICR_WAKER.Quiescent bits are cleared, + * we can exit early. This also prevents the following assert from + * erroneously triggering. + */ + if (!(gicr_read_waker(gicr_base) & WAKER_SL_BIT)) + return; + + /* + * Writes to GICR_WAKER.Sleep bit are ignored if GICR_WAKER.Quiescent + * bit is not set. We should be alright on power on path, therefore + * coming out of sleep and Quiescent should be set, but we assert in + * case. + */ + assert(gicr_read_waker(gicr_base) & WAKER_QSC_BIT); + + /* Clear GICR_WAKER.Sleep */ + gicr_write_waker(gicr_base, gicr_read_waker(gicr_base) & ~WAKER_SL_BIT); + + /* + * We don't know if the effects of setting GICR_WAKER.Sleep bit is + * instantaneous, so we wait until the interface is not Quiescent + * anymore. + */ + while (gicr_read_waker(gicr_base) & WAKER_QSC_BIT) + ; +} + diff --git a/drivers/rz/ipl/rza/drivers/arm/gic/v3/gic-x00.c b/drivers/rz/ipl/rza/drivers/arm/gic/v3/gic-x00.c new file mode 100644 index 00000000..6e106bab --- /dev/null +++ b/drivers/rz/ipl/rza/drivers/arm/gic/v3/gic-x00.c @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2020, NVIDIA Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * Driver for GIC-500 and GIC-600 specific features. This driver only + * overrides APIs that are different to those generic ones in GICv3 + * driver. + * + * GIC-600 supports independently power-gating redistributor interface. + */ + +#include + +#include +#include + +#include "gicv3_private.h" + +/* GIC-600 specific register offsets */ +#define GICR_PWRR 0x24U +#define IIDR_MODEL_ARM_GIC_600 U(0x0200043b) +#define IIDR_MODEL_ARM_GIC_600AE U(0x0300043b) +#define IIDR_MODEL_ARM_GIC_CLAYTON U(0x0400043b) + +/* GICR_PWRR fields */ +#define PWRR_RDPD_SHIFT 0 +#define PWRR_RDAG_SHIFT 1 +#define PWRR_RDGPD_SHIFT 2 +#define PWRR_RDGPO_SHIFT 3 + +#define PWRR_RDPD (1U << PWRR_RDPD_SHIFT) +#define PWRR_RDAG (1U << PWRR_RDAG_SHIFT) +#define PWRR_RDGPD (1U << PWRR_RDGPD_SHIFT) +#define PWRR_RDGPO (1U << PWRR_RDGPO_SHIFT) + +/* + * Values to write to GICR_PWRR register to power redistributor + * for operating through the core (GICR_PWRR.RDAG = 0) + */ +#define PWRR_ON (0U << PWRR_RDPD_SHIFT) +#define PWRR_OFF (1U << PWRR_RDPD_SHIFT) + +#if GICV3_SUPPORT_GIC600 + +/* GIC-600/Clayton specific accessor functions */ +static void gicr_write_pwrr(uintptr_t base, unsigned int val) +{ + mmio_write_32(base + GICR_PWRR, val); +} + +static uint32_t gicr_read_pwrr(uintptr_t base) +{ + return mmio_read_32(base + GICR_PWRR); +} + +static void gicr_wait_group_not_in_transit(uintptr_t base) +{ + uint32_t pwrr; + + do { + pwrr = gicr_read_pwrr(base); + + /* Check group not transitioning: RDGPD == RDGPO */ + } while (((pwrr & PWRR_RDGPD) >> PWRR_RDGPD_SHIFT) != + ((pwrr & PWRR_RDGPO) >> PWRR_RDGPO_SHIFT)); +} + +static void gic600_pwr_on(uintptr_t base) +{ + do { /* Wait until group not transitioning */ + gicr_wait_group_not_in_transit(base); + + /* Power on redistributor */ + gicr_write_pwrr(base, PWRR_ON); + + /* + * Wait until the power on state is reflected. + * If RDPD == 0 then powered on. + */ + } while ((gicr_read_pwrr(base) & PWRR_RDPD) != PWRR_ON); +} + +static void gic600_pwr_off(uintptr_t base) +{ + /* Wait until group not transitioning */ + gicr_wait_group_not_in_transit(base); + + /* Power off redistributor */ + gicr_write_pwrr(base, PWRR_OFF); + + /* + * If this is the last man, turning this redistributor frame off will + * result in the group itself being powered off and RDGPD = 1. + * In that case, wait as long as it's in transition, or has aborted + * the transition altogether for any reason. + */ + if ((gicr_read_pwrr(base) & PWRR_RDGPD) != 0U) { + /* Wait until group not transitioning */ + gicr_wait_group_not_in_transit(base); + } +} + +static uintptr_t get_gicr_base(unsigned int proc_num) +{ + uintptr_t gicr_base; + + assert(gicv3_driver_data != NULL); + assert(proc_num < gicv3_driver_data->rdistif_num); + assert(gicv3_driver_data->rdistif_base_addrs != NULL); + + gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num]; + assert(gicr_base != 0UL); + + return gicr_base; +} + +static bool gicv3_redists_need_power_mgmt(uintptr_t gicr_base) +{ + uint32_t reg = mmio_read_32(gicr_base + GICR_IIDR); + + /* + * The Arm GIC-600 and GIC-Clayton models have their redistributors + * powered down at reset. + */ + return (((reg & IIDR_MODEL_MASK) == IIDR_MODEL_ARM_GIC_600) || + ((reg & IIDR_MODEL_MASK) == IIDR_MODEL_ARM_GIC_600AE) || + ((reg & IIDR_MODEL_MASK) == IIDR_MODEL_ARM_GIC_CLAYTON)); +} + +#endif /* GICV3_SUPPORT_GIC600 */ + +void gicv3_distif_pre_save(unsigned int proc_num) +{ + arm_gicv3_distif_pre_save(proc_num); +} + +void gicv3_distif_post_restore(unsigned int proc_num) +{ + arm_gicv3_distif_post_restore(proc_num); +} + +/* + * Power off GIC-600 redistributor (if configured and detected) + */ +void gicv3_rdistif_off(unsigned int proc_num) +{ +#if GICV3_SUPPORT_GIC600 + uintptr_t gicr_base = get_gicr_base(proc_num); + + /* Attempt to power redistributor off */ + if (gicv3_redists_need_power_mgmt(gicr_base)) { + gic600_pwr_off(gicr_base); + } +#endif +} + +/* + * Power on GIC-600 redistributor (if configured and detected) + */ +void gicv3_rdistif_on(unsigned int proc_num) +{ +#if GICV3_SUPPORT_GIC600 + uintptr_t gicr_base = get_gicr_base(proc_num); + + /* Power redistributor on */ + if (gicv3_redists_need_power_mgmt(gicr_base)) { + gic600_pwr_on(gicr_base); + } +#endif +} diff --git a/drivers/rz/ipl/rza/drivers/arm/gic/v3/gic600_multichip.c b/drivers/rz/ipl/rza/drivers/arm/gic/v3/gic600_multichip.c new file mode 100644 index 00000000..ca7c43bf --- /dev/null +++ b/drivers/rz/ipl/rza/drivers/arm/gic/v3/gic600_multichip.c @@ -0,0 +1,240 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * GIC-600 driver extension for multichip setup + */ + +#include + +#include +#include +#include + +#include "../common/gic_common_private.h" +#include "gic600_multichip_private.h" + +#warning "GIC-600 Multichip driver is currently experimental and the API may change in future." + +/******************************************************************************* + * GIC-600 multichip operation related helper functions + ******************************************************************************/ +static void gicd_dchipr_wait_for_power_update_progress(uintptr_t base) +{ + unsigned int retry = GICD_PUP_UPDATE_RETRIES; + + while ((read_gicd_dchipr(base) & GICD_DCHIPR_PUP_BIT) != 0U) { + if (retry-- == 0) { + ERROR("GIC-600 connection to Routing Table Owner timed " + "out\n"); + panic(); + } + } +} + +/******************************************************************************* + * Sets up the routing table owner. + ******************************************************************************/ +static void set_gicd_dchipr_rt_owner(uintptr_t base, unsigned int rt_owner) +{ + /* + * Ensure that Group enables in GICD_CTLR are disabled and no pending + * register writes to GICD_CTLR. + */ + if ((gicd_read_ctlr(base) & + (CTLR_ENABLE_G0_BIT | CTLR_ENABLE_G1S_BIT | + CTLR_ENABLE_G1NS_BIT | GICD_CTLR_RWP_BIT)) != 0) { + ERROR("GICD_CTLR group interrupts are either enabled or have " + "pending writes. Cannot set RT owner.\n"); + panic(); + } + + /* Poll till PUP is zero before intiating write */ + gicd_dchipr_wait_for_power_update_progress(base); + + write_gicd_dchipr(base, read_gicd_dchipr(base) | + (rt_owner << GICD_DCHIPR_RT_OWNER_SHIFT)); + + /* Poll till PUP is zero to ensure write is complete */ + gicd_dchipr_wait_for_power_update_progress(base); +} + +/******************************************************************************* + * Configures the Chip Register to make connections to GICDs on + * a multichip platform. + ******************************************************************************/ +static void set_gicd_chipr_n(uintptr_t base, + unsigned int chip_id, + uint64_t chip_addr, + unsigned int spi_id_min, + unsigned int spi_id_max) +{ + unsigned int spi_block_min, spi_blocks; + uint64_t chipr_n_val; + + /* + * Ensure that group enables in GICD_CTLR are disabled and no pending + * register writes to GICD_CTLR. + */ + if ((gicd_read_ctlr(base) & + (CTLR_ENABLE_G0_BIT | CTLR_ENABLE_G1S_BIT | + CTLR_ENABLE_G1NS_BIT | GICD_CTLR_RWP_BIT)) != 0) { + ERROR("GICD_CTLR group interrupts are either enabled or have " + "pending writes. Cannot set CHIPR register.\n"); + panic(); + } + + /* + * spi_id_min and spi_id_max of value 0 is used to intidicate that the + * chip doesn't own any SPI block. Re-assign min and max values as SPI + * id starts from 32. + */ + if (spi_id_min == 0 && spi_id_max == 0) { + spi_id_min = GIC600_SPI_ID_MIN; + spi_id_max = GIC600_SPI_ID_MIN; + } + + spi_block_min = SPI_BLOCK_MIN_VALUE(spi_id_min); + spi_blocks = SPI_BLOCKS_VALUE(spi_id_min, spi_id_max); + + chipr_n_val = (GICD_CHIPR_VALUE(chip_addr, spi_block_min, spi_blocks)) | + GICD_CHIPRx_SOCKET_STATE; + + /* + * Wait for DCHIPR.PUP to be zero before commencing writes to + * GICD_CHIPRx. + */ + gicd_dchipr_wait_for_power_update_progress(base); + + /* + * Assign chip addr, spi min block, number of spi blocks and bring chip + * online by setting SocketState. + */ + write_gicd_chipr_n(base, chip_id, chipr_n_val); + + /* + * Poll until DCHIP.PUP is zero to verify connection to rt_owner chip + * is complete. + */ + gicd_dchipr_wait_for_power_update_progress(base); + + /* + * Ensure that write to GICD_CHIPRx is successful and the chip_n came + * online. + */ + if (read_gicd_chipr_n(base, chip_id) != chipr_n_val) { + ERROR("GICD_CHIPR%u write failed\n", chip_id); + panic(); + } + + /* Ensure that chip is in consistent state */ + if (((read_gicd_chipsr(base) & GICD_CHIPSR_RTS_MASK) >> + GICD_CHIPSR_RTS_SHIFT) != + GICD_CHIPSR_RTS_STATE_CONSISTENT) { + ERROR("Chip %u routing table is not in consistent state\n", + chip_id); + panic(); + } +} + +/******************************************************************************* + * Validates the GIC-600 Multichip data structure passed by the platform. + ******************************************************************************/ +static void gic600_multichip_validate_data( + struct gic600_multichip_data *multichip_data) +{ + unsigned int i, spi_id_min, spi_id_max, blocks_of_32; + unsigned int multichip_spi_blocks = 0; + + assert(multichip_data != NULL); + + if (multichip_data->chip_count > GIC600_MAX_MULTICHIP) { + ERROR("GIC-600 Multichip count should not exceed %d\n", + GIC600_MAX_MULTICHIP); + panic(); + } + + for (i = 0; i < multichip_data->chip_count; i++) { + spi_id_min = multichip_data->spi_ids[i][SPI_MIN_INDEX]; + spi_id_max = multichip_data->spi_ids[i][SPI_MAX_INDEX]; + + if ((spi_id_min != 0) || (spi_id_max != 0)) { + + /* SPI IDs range check */ + if (!(spi_id_min >= GIC600_SPI_ID_MIN) || + !(spi_id_max < GIC600_SPI_ID_MAX) || + !(spi_id_min <= spi_id_max) || + !((spi_id_max - spi_id_min + 1) % 32 == 0)) { + ERROR("Invalid SPI IDs {%u, %u} passed for " + "Chip %u\n", spi_id_min, + spi_id_max, i); + panic(); + } + + /* SPI IDs overlap check */ + blocks_of_32 = BLOCKS_OF_32(spi_id_min, spi_id_max); + if ((multichip_spi_blocks & blocks_of_32) != 0) { + ERROR("SPI IDs of Chip %u overlapping\n", i); + panic(); + } + multichip_spi_blocks |= blocks_of_32; + } + } +} + +/******************************************************************************* + * Intialize GIC-600 Multichip operation. + ******************************************************************************/ +void gic600_multichip_init(struct gic600_multichip_data *multichip_data) +{ + unsigned int i; + + gic600_multichip_validate_data(multichip_data); + + INFO("GIC-600 Multichip driver is experimental\n"); + + /* + * Ensure that G0/G1S/G1NS interrupts are disabled. This also ensures + * that GIC-600 Multichip configuration is done first. + */ + if ((gicd_read_ctlr(multichip_data->rt_owner_base) & + (CTLR_ENABLE_G0_BIT | CTLR_ENABLE_G1S_BIT | + CTLR_ENABLE_G1NS_BIT | GICD_CTLR_RWP_BIT)) != 0) { + ERROR("GICD_CTLR group interrupts are either enabled or have " + "pending writes.\n"); + panic(); + } + + /* Ensure that the routing table owner is in disconnected state */ + if (((read_gicd_chipsr(multichip_data->rt_owner_base) & + GICD_CHIPSR_RTS_MASK) >> GICD_CHIPSR_RTS_SHIFT) != + GICD_CHIPSR_RTS_STATE_DISCONNECTED) { + ERROR("GIC-600 routing table owner is not in disconnected " + "state to begin multichip configuration\n"); + panic(); + } + + /* Initialize the GICD which is marked as routing table owner first */ + set_gicd_dchipr_rt_owner(multichip_data->rt_owner_base, + multichip_data->rt_owner); + + set_gicd_chipr_n(multichip_data->rt_owner_base, multichip_data->rt_owner, + multichip_data->chip_addrs[multichip_data->rt_owner], + multichip_data-> + spi_ids[multichip_data->rt_owner][SPI_MIN_INDEX], + multichip_data-> + spi_ids[multichip_data->rt_owner][SPI_MAX_INDEX]); + + for (i = 0; i < multichip_data->chip_count; i++) { + if (i == multichip_data->rt_owner) + continue; + + set_gicd_chipr_n(multichip_data->rt_owner_base, i, + multichip_data->chip_addrs[i], + multichip_data->spi_ids[i][SPI_MIN_INDEX], + multichip_data->spi_ids[i][SPI_MAX_INDEX]); + } +} diff --git a/drivers/rz/ipl/rza/drivers/arm/gic/v3/gic600_multichip_private.h b/drivers/rz/ipl/rza/drivers/arm/gic/v3/gic600_multichip_private.h new file mode 100644 index 00000000..fe4134cb --- /dev/null +++ b/drivers/rz/ipl/rza/drivers/arm/gic/v3/gic600_multichip_private.h @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2019, ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef GIC600_MULTICHIP_PRIVATE_H +#define GIC600_MULTICHIP_PRIVATE_H + +#include + +#include "gicv3_private.h" + +/* GIC600 GICD multichip related offsets */ +#define GICD_CHIPSR U(0xC000) +#define GICD_DCHIPR U(0xC004) +#define GICD_CHIPR U(0xC008) + +/* GIC600 GICD multichip related masks */ +#define GICD_CHIPRx_PUP_BIT BIT_64(1) +#define GICD_CHIPRx_SOCKET_STATE BIT_64(0) +#define GICD_DCHIPR_PUP_BIT BIT_32(0) +#define GICD_CHIPSR_RTS_MASK (BIT_32(4) | BIT_32(5)) + +/* GIC600 GICD multichip related shifts */ +#define GICD_CHIPRx_ADDR_SHIFT 16 +#define GICD_CHIPSR_RTS_SHIFT 4 +#define GICD_DCHIPR_RT_OWNER_SHIFT 4 + +/* + * If GIC v4 extension is enabled, then use SPI macros specific to GIC-Clayton. + * Other shifts and mask remains same between GIC-600 and GIC-Clayton. + */ +#if GIC_ENABLE_V4_EXTN +#define GICD_CHIPRx_SPI_BLOCK_MIN_SHIFT 9 +#define GICD_CHIPRx_SPI_BLOCKS_SHIFT 3 +#else +#define GICD_CHIPRx_SPI_BLOCK_MIN_SHIFT 10 +#define GICD_CHIPRx_SPI_BLOCKS_SHIFT 5 +#endif + +#define GICD_CHIPSR_RTS_STATE_DISCONNECTED U(0) +#define GICD_CHIPSR_RTS_STATE_UPDATING U(1) +#define GICD_CHIPSR_RTS_STATE_CONSISTENT U(2) + +/* SPI interrupt id minimum and maximum range */ +#define GIC600_SPI_ID_MIN 32 +#define GIC600_SPI_ID_MAX 960 + +/* Number of retries for PUP update */ +#define GICD_PUP_UPDATE_RETRIES 10000 + +#define SPI_MIN_INDEX 0 +#define SPI_MAX_INDEX 1 + +#define SPI_BLOCK_MIN_VALUE(spi_id_min) \ + (((spi_id_min) - GIC600_SPI_ID_MIN) / \ + GIC600_SPI_ID_MIN) +#define SPI_BLOCKS_VALUE(spi_id_min, spi_id_max) \ + (((spi_id_max) - (spi_id_min) + 1) / \ + GIC600_SPI_ID_MIN) +#define GICD_CHIPR_VALUE(chip_addr, spi_block_min, spi_blocks) \ + (((chip_addr) << GICD_CHIPRx_ADDR_SHIFT) | \ + ((spi_block_min) << GICD_CHIPRx_SPI_BLOCK_MIN_SHIFT) | \ + ((spi_blocks) << GICD_CHIPRx_SPI_BLOCKS_SHIFT)) + +/* + * Multichip data assertion macros + */ +/* Set bits from 0 to ((spi_id_max + 1) / 32) */ +#define SPI_BLOCKS_TILL_MAX(spi_id_max) ((1 << (((spi_id_max) + 1) >> 5)) - 1) +/* Set bits from 0 to (spi_id_min / 32) */ +#define SPI_BLOCKS_TILL_MIN(spi_id_min) ((1 << ((spi_id_min) >> 5)) - 1) +/* Set bits from (spi_id_min / 32) to ((spi_id_max + 1) / 32) */ +#define BLOCKS_OF_32(spi_id_min, spi_id_max) \ + SPI_BLOCKS_TILL_MAX(spi_id_max) ^ \ + SPI_BLOCKS_TILL_MIN(spi_id_min) + +/******************************************************************************* + * GIC-600 multichip operation related helper functions + ******************************************************************************/ +static inline uint32_t read_gicd_dchipr(uintptr_t base) +{ + return mmio_read_32(base + GICD_DCHIPR); +} + +static inline uint64_t read_gicd_chipr_n(uintptr_t base, uint8_t n) +{ + return mmio_read_64(base + (GICD_CHIPR + (8U * n))); +} + +static inline uint32_t read_gicd_chipsr(uintptr_t base) +{ + return mmio_read_32(base + GICD_CHIPSR); +} + +static inline void write_gicd_dchipr(uintptr_t base, uint32_t val) +{ + mmio_write_32(base + GICD_DCHIPR, val); +} + +static inline void write_gicd_chipr_n(uintptr_t base, uint8_t n, uint64_t val) +{ + mmio_write_64(base + (GICD_CHIPR + (8U * n)), val); +} + +#endif /* GIC600_MULTICHIP_PRIVATE_H */ diff --git a/drivers/rz/ipl/rza/drivers/arm/gic/v3/gicdv3_helpers.c b/drivers/rz/ipl/rza/drivers/arm/gic/v3/gicdv3_helpers.c new file mode 100644 index 00000000..987be69e --- /dev/null +++ b/drivers/rz/ipl/rza/drivers/arm/gic/v3/gicdv3_helpers.c @@ -0,0 +1,244 @@ +/* + * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include "gicv3_private.h" + +/******************************************************************************* + * GIC Distributor functions for accessing the GIC registers + * corresponding to a single interrupt ID. These functions use bitwise + * operations or appropriate register accesses to modify or return + * the bit-field corresponding the single interrupt ID. + ******************************************************************************/ + +/* + * Accessors to set the bits corresponding to interrupt ID + * in GIC Distributor ICFGR and ICFGRE. + */ +void gicd_set_icfgr(uintptr_t base, unsigned int id, unsigned int cfg) +{ + /* Interrupt configuration is a 2-bit field */ + unsigned int bit_shift = BIT_NUM(ICFG, id) << 1U; + + /* Clear the field, and insert required configuration */ + mmio_clrsetbits_32(base + GICD_OFFSET(ICFG, id), + (uint32_t)GIC_CFG_MASK << bit_shift, + (cfg & GIC_CFG_MASK) << bit_shift); +} + +/* + * Accessors to get/set/clear the bit corresponding to interrupt ID + * in GIC Distributor IGROUPR and IGROUPRE. + */ +unsigned int gicd_get_igroupr(uintptr_t base, unsigned int id) +{ + return GICD_GET_BIT(IGROUP, base, id); +} + +void gicd_set_igroupr(uintptr_t base, unsigned int id) +{ + GICD_SET_BIT(IGROUP, base, id); +} + +void gicd_clr_igroupr(uintptr_t base, unsigned int id) +{ + GICD_CLR_BIT(IGROUP, base, id); +} + +/* + * Accessors to get/set/clear the bit corresponding to interrupt ID + * in GIC Distributor IGRPMODR and IGRPMODRE. + */ +unsigned int gicd_get_igrpmodr(uintptr_t base, unsigned int id) +{ + return GICD_GET_BIT(IGRPMOD, base, id); +} + +void gicd_set_igrpmodr(uintptr_t base, unsigned int id) +{ + GICD_SET_BIT(IGRPMOD, base, id); +} + +void gicd_clr_igrpmodr(uintptr_t base, unsigned int id) +{ + GICD_CLR_BIT(IGRPMOD, base, id); +} + +/* + * Accessors to set the bit corresponding to interrupt ID + * in GIC Distributor ICENABLER and ICENABLERE. + */ +void gicd_set_icenabler(uintptr_t base, unsigned int id) +{ + GICD_WRITE_BIT(ICENABLE, base, id); +} + +/* + * Accessors to set the bit corresponding to interrupt ID + * in GIC Distributor ICPENDR and ICPENDRE. + */ +void gicd_set_icpendr(uintptr_t base, unsigned int id) +{ + GICD_WRITE_BIT(ICPEND, base, id); +} + +/* + * Accessors to get/set the bit corresponding to interrupt ID + * in GIC Distributor ISACTIVER and ISACTIVERE. + */ +unsigned int gicd_get_isactiver(uintptr_t base, unsigned int id) +{ + return GICD_GET_BIT(ISACTIVE, base, id); +} + +void gicd_set_isactiver(uintptr_t base, unsigned int id) +{ + GICD_WRITE_BIT(ISACTIVE, base, id); +} + +/* + * Accessors to set the bit corresponding to interrupt ID + * in GIC Distributor ISENABLER and ISENABLERE. + */ +void gicd_set_isenabler(uintptr_t base, unsigned int id) +{ + GICD_WRITE_BIT(ISENABLE, base, id); +} + +/* + * Accessors to set the bit corresponding to interrupt ID + * in GIC Distributor ISPENDR and ISPENDRE. + */ +void gicd_set_ispendr(uintptr_t base, unsigned int id) +{ + GICD_WRITE_BIT(ISPEND, base, id); +} + +/* + * Accessors to set the bit corresponding to interrupt ID + * in GIC Distributor IPRIORITYR and IPRIORITYRE. + */ +void gicd_set_ipriorityr(uintptr_t base, unsigned int id, unsigned int pri) +{ + GICD_WRITE_8(IPRIORITY, base, id, (uint8_t)(pri & GIC_PRI_MASK)); +} + +/******************************************************************************* + * GIC Distributor interface accessors for reading/writing entire registers + ******************************************************************************/ + +/* + * Accessors to read/write the GIC Distributor ICGFR and ICGFRE + * corresponding to the interrupt ID, 16 interrupt IDs at a time. + */ +unsigned int gicd_read_icfgr(uintptr_t base, unsigned int id) +{ + return GICD_READ(ICFG, base, id); +} + +void gicd_write_icfgr(uintptr_t base, unsigned int id, unsigned int val) +{ + GICD_WRITE(ICFG, base, id, val); +} + +/* + * Accessors to read/write the GIC Distributor IGROUPR and IGROUPRE + * corresponding to the interrupt ID, 32 interrupt IDs at a time. + */ +unsigned int gicd_read_igroupr(uintptr_t base, unsigned int id) +{ + return GICD_READ(IGROUP, base, id); +} + +void gicd_write_igroupr(uintptr_t base, unsigned int id, unsigned int val) +{ + GICD_WRITE(IGROUP, base, id, val); +} + +/* + * Accessors to read/write the GIC Distributor IGRPMODR and IGRPMODRE + * corresponding to the interrupt ID, 32 interrupt IDs at a time. + */ +unsigned int gicd_read_igrpmodr(uintptr_t base, unsigned int id) +{ + return GICD_READ(IGRPMOD, base, id); +} + +void gicd_write_igrpmodr(uintptr_t base, unsigned int id, unsigned int val) +{ + GICD_WRITE(IGRPMOD, base, id, val); +} + +/* + * Accessors to read/write the GIC Distributor IPRIORITYR and IPRIORITYRE + * corresponding to the interrupt ID, 4 interrupt IDs at a time. + */ +unsigned int gicd_read_ipriorityr(uintptr_t base, unsigned int id) +{ + return GICD_READ(IPRIORITY, base, id); +} + +void gicd_write_ipriorityr(uintptr_t base, unsigned int id, unsigned int val) +{ + GICD_WRITE(IPRIORITY, base, id, val); +} + +/* + * Accessors to read/write the GIC Distributor ISACTIVER and ISACTIVERE + * corresponding to the interrupt ID, 32 interrupt IDs at a time. + */ +unsigned int gicd_read_isactiver(uintptr_t base, unsigned int id) +{ + return GICD_READ(ISACTIVE, base, id); +} + +void gicd_write_isactiver(uintptr_t base, unsigned int id, unsigned int val) +{ + GICD_WRITE(ISACTIVE, base, id, val); +} + +/* + * Accessors to read/write the GIC Distributor ISENABLER and ISENABLERE + * corresponding to the interrupt ID, 32 interrupt IDs at a time. + */ +unsigned int gicd_read_isenabler(uintptr_t base, unsigned int id) +{ + return GICD_READ(ISENABLE, base, id); +} + +void gicd_write_isenabler(uintptr_t base, unsigned int id, unsigned int val) +{ + GICD_WRITE(ISENABLE, base, id, val); +} + +/* + * Accessors to read/write the GIC Distributor ISPENDR and ISPENDRE + * corresponding to the interrupt ID, 32 interrupt IDs at a time. + */ +unsigned int gicd_read_ispendr(uintptr_t base, unsigned int id) +{ + return GICD_READ(ISPEND, base, id); +} + +void gicd_write_ispendr(uintptr_t base, unsigned int id, unsigned int val) +{ + GICD_WRITE(ISPEND, base, id, val); +} + +/* + * Accessors to read/write the GIC Distributor NSACR and NSACRE + * corresponding to the interrupt ID, 16 interrupt IDs at a time. + */ +unsigned int gicd_read_nsacr(uintptr_t base, unsigned int id) +{ + return GICD_READ(NSAC, base, id); +} + +void gicd_write_nsacr(uintptr_t base, unsigned int id, unsigned int val) +{ + GICD_WRITE(NSAC, base, id, val); +} diff --git a/drivers/rz/ipl/rza/drivers/arm/gic/v3/gicrv3_helpers.c b/drivers/rz/ipl/rza/drivers/arm/gic/v3/gicrv3_helpers.c new file mode 100644 index 00000000..3004054e --- /dev/null +++ b/drivers/rz/ipl/rza/drivers/arm/gic/v3/gicrv3_helpers.c @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2015-2020, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include "gicv3_private.h" + +/******************************************************************************* + * GIC Redistributor functions + * Note: The raw register values correspond to multiple interrupt `id`s and + * the number of interrupt `id`s involved depends on the register accessed. + ******************************************************************************/ + +/* + * Accessors to read/write the GIC Redistributor IPRIORITYR and IPRIORITYRE + * register corresponding to the interrupt `id`, 4 interrupts IDs at a time. + */ +unsigned int gicr_read_ipriorityr(uintptr_t base, unsigned int id) +{ + return GICR_READ(IPRIORITY, base, id); +} + +void gicr_write_ipriorityr(uintptr_t base, unsigned int id, unsigned int val) +{ + GICR_WRITE(IPRIORITY, base, id, val); +} + +/* + * Accessor to set the byte corresponding to interrupt `id` + * in GIC Redistributor IPRIORITYR and IPRIORITYRE. + */ +void gicr_set_ipriorityr(uintptr_t base, unsigned int id, unsigned int pri) +{ + GICR_WRITE_8(IPRIORITY, base, id, (uint8_t)(pri & GIC_PRI_MASK)); +} + +/* + * Accessors to get/set/clear the bit corresponding to interrupt `id` + * from GIC Redistributor IGROUPR0 and IGROUPRE + */ +unsigned int gicr_get_igroupr(uintptr_t base, unsigned int id) +{ + return GICR_GET_BIT(IGROUP, base, id); +} + +void gicr_set_igroupr(uintptr_t base, unsigned int id) +{ + GICR_SET_BIT(IGROUP, base, id); +} + +void gicr_clr_igroupr(uintptr_t base, unsigned int id) +{ + GICR_CLR_BIT(IGROUP, base, id); +} + +/* + * Accessors to get/set/clear the bit corresponding to interrupt `id` + * from GIC Redistributor IGRPMODR0 and IGRPMODRE + */ +unsigned int gicr_get_igrpmodr(uintptr_t base, unsigned int id) +{ + return GICR_GET_BIT(IGRPMOD, base, id); +} + +void gicr_set_igrpmodr(uintptr_t base, unsigned int id) +{ + GICR_SET_BIT(IGRPMOD, base, id); +} + +void gicr_clr_igrpmodr(uintptr_t base, unsigned int id) +{ + GICR_CLR_BIT(IGRPMOD, base, id); +} + +/* + * Accessor to write the bit corresponding to interrupt `id` + * in GIC Redistributor ISENABLER0 and ISENABLERE + */ +void gicr_set_isenabler(uintptr_t base, unsigned int id) +{ + GICR_WRITE_BIT(ISENABLE, base, id); +} + +/* + * Accessor to write the bit corresponding to interrupt `id` + * in GIC Redistributor ICENABLER0 and ICENABLERE + */ +void gicr_set_icenabler(uintptr_t base, unsigned int id) +{ + GICR_WRITE_BIT(ICENABLE, base, id); +} + +/* + * Accessor to get the bit corresponding to interrupt `id` + * in GIC Redistributor ISACTIVER0 and ISACTIVERE + */ +unsigned int gicr_get_isactiver(uintptr_t base, unsigned int id) +{ + return GICR_GET_BIT(ISACTIVE, base, id); +} + +/* + * Accessor to clear the bit corresponding to interrupt `id` + * in GIC Redistributor ICPENDR0 and ICPENDRE + */ +void gicr_set_icpendr(uintptr_t base, unsigned int id) +{ + GICR_WRITE_BIT(ICPEND, base, id); +} + +/* + * Accessor to write the bit corresponding to interrupt `id` + * in GIC Redistributor ISPENDR0 and ISPENDRE + */ +void gicr_set_ispendr(uintptr_t base, unsigned int id) +{ + GICR_WRITE_BIT(ISPEND, base, id); +} + +/* + * Accessor to set the bit fields corresponding to interrupt `id` + * in GIC Redistributor ICFGR0, ICFGR1 and ICFGRE + */ +void gicr_set_icfgr(uintptr_t base, unsigned int id, unsigned int cfg) +{ + /* Interrupt configuration is a 2-bit field */ + unsigned int bit_shift = BIT_NUM(ICFG, id) << 1U; + + /* Clear the field, and insert required configuration */ + mmio_clrsetbits_32(base + GICR_OFFSET(ICFG, id), + (uint32_t)GIC_CFG_MASK << bit_shift, + (cfg & GIC_CFG_MASK) << bit_shift); +} diff --git a/drivers/rz/ipl/rza/drivers/arm/gic/v3/gicv3.mk b/drivers/rz/ipl/rza/drivers/arm/gic/v3/gicv3.mk new file mode 100644 index 00000000..a2fc16f9 --- /dev/null +++ b/drivers/rz/ipl/rza/drivers/arm/gic/v3/gicv3.mk @@ -0,0 +1,38 @@ +# +# Copyright (c) 2013-2020, Arm Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# Default configuration values +GICV3_SUPPORT_GIC600 ?= 0 +GICV3_IMPL_GIC600_MULTICHIP ?= 0 +GICV3_OVERRIDE_DISTIF_PWR_OPS ?= 0 +GIC_ENABLE_V4_EXTN ?= 0 +GIC_EXT_INTID ?= 0 + +GICV3_SOURCES += drivers/arm/gic/v3/gicv3_main.c \ + drivers/arm/gic/v3/gicv3_helpers.c \ + drivers/arm/gic/v3/gicdv3_helpers.c \ + drivers/arm/gic/v3/gicrv3_helpers.c + +ifeq (${GICV3_OVERRIDE_DISTIF_PWR_OPS}, 0) +GICV3_SOURCES += drivers/arm/gic/v3/arm_gicv3_common.c +endif + +GICV3_SOURCES += drivers/arm/gic/v3/gic-x00.c +ifeq (${GICV3_IMPL_GIC600_MULTICHIP}, 1) +GICV3_SOURCES += drivers/arm/gic/v3/gic600_multichip.c +endif + +# Set GIC-600 support +$(eval $(call assert_boolean,GICV3_SUPPORT_GIC600)) +$(eval $(call add_define,GICV3_SUPPORT_GIC600)) + +# Set GICv4 extension +$(eval $(call assert_boolean,GIC_ENABLE_V4_EXTN)) +$(eval $(call add_define,GIC_ENABLE_V4_EXTN)) + +# Set support for extended PPI and SPI range +$(eval $(call assert_boolean,GIC_EXT_INTID)) +$(eval $(call add_define,GIC_EXT_INTID)) diff --git a/drivers/rz/ipl/rza/drivers/arm/gic/v3/gicv3_helpers.c b/drivers/rz/ipl/rza/drivers/arm/gic/v3/gicv3_helpers.c new file mode 100644 index 00000000..6bb66a02 --- /dev/null +++ b/drivers/rz/ipl/rza/drivers/arm/gic/v3/gicv3_helpers.c @@ -0,0 +1,370 @@ +/* + * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include + +#include "../common/gic_common_private.h" +#include "gicv3_private.h" + +/****************************************************************************** + * This function marks the core as awake in the re-distributor and + * ensures that the interface is active. + *****************************************************************************/ +void gicv3_rdistif_mark_core_awake(uintptr_t gicr_base) +{ + /* + * The WAKER_PS_BIT should be changed to 0 + * only when WAKER_CA_BIT is 1. + */ + assert((gicr_read_waker(gicr_base) & WAKER_CA_BIT) != 0U); + + /* Mark the connected core as awake */ + gicr_write_waker(gicr_base, gicr_read_waker(gicr_base) & ~WAKER_PS_BIT); + + /* Wait till the WAKER_CA_BIT changes to 0 */ + while ((gicr_read_waker(gicr_base) & WAKER_CA_BIT) != 0U) { + } +} + +/****************************************************************************** + * This function marks the core as asleep in the re-distributor and ensures + * that the interface is quiescent. + *****************************************************************************/ +void gicv3_rdistif_mark_core_asleep(uintptr_t gicr_base) +{ + /* Mark the connected core as asleep */ + gicr_write_waker(gicr_base, gicr_read_waker(gicr_base) | WAKER_PS_BIT); + + /* Wait till the WAKER_CA_BIT changes to 1 */ + while ((gicr_read_waker(gicr_base) & WAKER_CA_BIT) == 0U) { + } +} + +/******************************************************************************* + * This function probes the Redistributor frames when the driver is initialised + * and saves their base addresses. These base addresses are used later to + * initialise each Redistributor interface. + ******************************************************************************/ +void gicv3_rdistif_base_addrs_probe(uintptr_t *rdistif_base_addrs, + unsigned int rdistif_num, + uintptr_t gicr_base, + mpidr_hash_fn mpidr_to_core_pos) +{ + u_register_t mpidr; + unsigned int proc_num; + uint64_t typer_val; + uintptr_t rdistif_base = gicr_base; + + assert(rdistif_base_addrs != NULL); + + /* + * Iterate over the Redistributor frames. Store the base address of each + * frame in the platform provided array. Use the "Processor Number" + * field to index into the array if the platform has not provided a hash + * function to convert an MPIDR (obtained from the "Affinity Value" + * field into a linear index. + */ + do { + typer_val = gicr_read_typer(rdistif_base); + if (mpidr_to_core_pos != NULL) { + mpidr = mpidr_from_gicr_typer(typer_val); + proc_num = mpidr_to_core_pos(mpidr); + } else { + proc_num = (typer_val >> TYPER_PROC_NUM_SHIFT) & + TYPER_PROC_NUM_MASK; + } + + if (proc_num < rdistif_num) { + rdistif_base_addrs[proc_num] = rdistif_base; + } + + rdistif_base += (1U << GICR_PCPUBASE_SHIFT); + } while ((typer_val & TYPER_LAST_BIT) == 0U); +} + +/******************************************************************************* + * Helper function to configure the default attributes of (E)SPIs. + ******************************************************************************/ +void gicv3_spis_config_defaults(uintptr_t gicd_base) +{ + unsigned int i, num_ints; +#if GIC_EXT_INTID + unsigned int num_eints; +#endif + unsigned int typer_reg = gicd_read_typer(gicd_base); + + /* Maximum SPI INTID is 32 * (GICD_TYPER.ITLinesNumber + 1) - 1 */ + num_ints = ((typer_reg & TYPER_IT_LINES_NO_MASK) + 1U) << 5; + + /* + * The GICv3 architecture allows GICD_TYPER.ITLinesNumber to be 31, so + * the maximum possible value for num_ints is 1024. Limit the value to + * MAX_SPI_ID + 1 to avoid getting wrong address in GICD_OFFSET() macro. + */ + if (num_ints > MAX_SPI_ID + 1U) { + num_ints = MAX_SPI_ID + 1U; + } + INFO("Maximum SPI INTID supported: %u\n", num_ints - 1); + + /* Treat all (E)SPIs as G1NS by default. We do 32 at a time. */ + for (i = MIN_SPI_ID; i < num_ints; i += (1U << IGROUPR_SHIFT)) { + gicd_write_igroupr(gicd_base, i, ~0U); + } + +#if GIC_EXT_INTID + /* Check if extended SPI range is implemented */ + if ((typer_reg & TYPER_ESPI) != 0U) { + /* + * Maximum ESPI INTID is 32 * (GICD_TYPER.ESPI_range + 1) + 4095 + */ + num_eints = ((((typer_reg >> TYPER_ESPI_RANGE_SHIFT) & + TYPER_ESPI_RANGE_MASK) + 1U) << 5) + MIN_ESPI_ID; + INFO("Maximum ESPI INTID supported: %u\n", num_eints - 1); + + for (i = MIN_ESPI_ID; i < num_eints; + i += (1U << IGROUPR_SHIFT)) { + gicd_write_igroupr(gicd_base, i, ~0U); + } + } else { + num_eints = 0U; + INFO("ESPI range is not implemented.\n"); + } +#endif + + /* Setup the default (E)SPI priorities doing four at a time */ + for (i = MIN_SPI_ID; i < num_ints; i += (1U << IPRIORITYR_SHIFT)) { + gicd_write_ipriorityr(gicd_base, i, GICD_IPRIORITYR_DEF_VAL); + } + +#if GIC_EXT_INTID + for (i = MIN_ESPI_ID; i < num_eints; + i += (1U << IPRIORITYR_SHIFT)) { + gicd_write_ipriorityr(gicd_base, i, GICD_IPRIORITYR_DEF_VAL); + } +#endif + /* + * Treat all (E)SPIs as level triggered by default, write 16 at a time + */ + for (i = MIN_SPI_ID; i < num_ints; i += (1U << ICFGR_SHIFT)) { + gicd_write_icfgr(gicd_base, i, 0U); + } + +#if GIC_EXT_INTID + for (i = MIN_ESPI_ID; i < num_eints; i += (1U << ICFGR_SHIFT)) { + gicd_write_icfgr(gicd_base, i, 0U); + } +#endif +} + +/******************************************************************************* + * Helper function to configure properties of secure (E)SPIs + ******************************************************************************/ +unsigned int gicv3_secure_spis_config_props(uintptr_t gicd_base, + const interrupt_prop_t *interrupt_props, + unsigned int interrupt_props_num) +{ + unsigned int i; + const interrupt_prop_t *current_prop; + unsigned long long gic_affinity_val; + unsigned int ctlr_enable = 0U; + + /* Make sure there's a valid property array */ + if (interrupt_props_num > 0U) { + assert(interrupt_props != NULL); + } + + for (i = 0U; i < interrupt_props_num; i++) { + current_prop = &interrupt_props[i]; + + unsigned int intr_num = current_prop->intr_num; + + /* Skip SGI, (E)PPI and LPI interrupts */ + if (!IS_SPI(intr_num)) { + continue; + } + + /* Configure this interrupt as a secure interrupt */ + gicd_clr_igroupr(gicd_base, intr_num); + + /* Configure this interrupt as G0 or a G1S interrupt */ + assert((current_prop->intr_grp == INTR_GROUP0) || + (current_prop->intr_grp == INTR_GROUP1S)); + + if (current_prop->intr_grp == INTR_GROUP1S) { + gicd_set_igrpmodr(gicd_base, intr_num); + ctlr_enable |= CTLR_ENABLE_G1S_BIT; + } else { + gicd_clr_igrpmodr(gicd_base, intr_num); + ctlr_enable |= CTLR_ENABLE_G0_BIT; + } + + /* Set interrupt configuration */ + gicd_set_icfgr(gicd_base, intr_num, current_prop->intr_cfg); + + /* Set the priority of this interrupt */ + gicd_set_ipriorityr(gicd_base, intr_num, + current_prop->intr_pri); + + /* Target (E)SPIs to the primary CPU */ + gic_affinity_val = + gicd_irouter_val_from_mpidr(read_mpidr(), 0U); + gicd_write_irouter(gicd_base, intr_num, + gic_affinity_val); + + /* Enable this interrupt */ + gicd_set_isenabler(gicd_base, intr_num); + } + + return ctlr_enable; +} + +/******************************************************************************* + * Helper function to configure the default attributes of (E)SPIs + ******************************************************************************/ +void gicv3_ppi_sgi_config_defaults(uintptr_t gicr_base) +{ + unsigned int i, ppi_regs_num, regs_num; + +#if GIC_EXT_INTID + /* Calculate number of PPI registers */ + ppi_regs_num = (unsigned int)((gicr_read_typer(gicr_base) >> + TYPER_PPI_NUM_SHIFT) & TYPER_PPI_NUM_MASK) + 1; + /* All other values except PPInum [0-2] are reserved */ + if (ppi_regs_num > 3U) { + ppi_regs_num = 1U; + } +#else + ppi_regs_num = 1U; +#endif + /* + * Disable all SGIs (imp. def.)/(E)PPIs before configuring them. + * This is a more scalable approach as it avoids clearing + * the enable bits in the GICD_CTLR. + */ + for (i = 0U; i < ppi_regs_num; ++i) { + gicr_write_icenabler(gicr_base, i, ~0U); + } + + /* Wait for pending writes to GICR_ICENABLER */ + gicr_wait_for_pending_write(gicr_base); + + /* 32 interrupt IDs per GICR_IGROUPR register */ + for (i = 0U; i < ppi_regs_num; ++i) { + /* Treat all SGIs/(E)PPIs as G1NS by default */ + gicr_write_igroupr(gicr_base, i, ~0U); + } + + /* 4 interrupt IDs per GICR_IPRIORITYR register */ + regs_num = ppi_regs_num << 3; + for (i = 0U; i < regs_num; ++i) { + /* Setup the default (E)PPI/SGI priorities doing 4 at a time */ + gicr_write_ipriorityr(gicr_base, i, GICD_IPRIORITYR_DEF_VAL); + } + + /* 16 interrupt IDs per GICR_ICFGR register */ + regs_num = ppi_regs_num << 1; + for (i = (MIN_PPI_ID >> ICFGR_SHIFT); i < regs_num; ++i) { + /* Configure all (E)PPIs as level triggered by default */ + gicr_write_icfgr(gicr_base, i, 0U); + } +} + +/******************************************************************************* + * Helper function to configure properties of secure G0 and G1S (E)PPIs and SGIs + ******************************************************************************/ +unsigned int gicv3_secure_ppi_sgi_config_props(uintptr_t gicr_base, + const interrupt_prop_t *interrupt_props, + unsigned int interrupt_props_num) +{ + unsigned int i; + const interrupt_prop_t *current_prop; + unsigned int ctlr_enable = 0U; + + /* Make sure there's a valid property array */ + if (interrupt_props_num > 0U) { + assert(interrupt_props != NULL); + } + + for (i = 0U; i < interrupt_props_num; i++) { + current_prop = &interrupt_props[i]; + + unsigned int intr_num = current_prop->intr_num; + + /* Skip (E)SPI interrupt */ + if (!IS_SGI_PPI(intr_num)) { + continue; + } + + /* Configure this interrupt as a secure interrupt */ + gicr_clr_igroupr(gicr_base, intr_num); + + /* Configure this interrupt as G0 or a G1S interrupt */ + assert((current_prop->intr_grp == INTR_GROUP0) || + (current_prop->intr_grp == INTR_GROUP1S)); + + if (current_prop->intr_grp == INTR_GROUP1S) { + gicr_set_igrpmodr(gicr_base, intr_num); + ctlr_enable |= CTLR_ENABLE_G1S_BIT; + } else { + gicr_clr_igrpmodr(gicr_base, intr_num); + ctlr_enable |= CTLR_ENABLE_G0_BIT; + } + + /* Set the priority of this interrupt */ + gicr_set_ipriorityr(gicr_base, intr_num, + current_prop->intr_pri); + + /* + * Set interrupt configuration for (E)PPIs. + * Configurations for SGIs 0-15 are ignored. + */ + if (intr_num >= MIN_PPI_ID) { + gicr_set_icfgr(gicr_base, intr_num, + current_prop->intr_cfg); + } + + /* Enable this interrupt */ + gicr_set_isenabler(gicr_base, intr_num); + } + + return ctlr_enable; +} + +/** + * gicv3_rdistif_get_number_frames() - determine size of GICv3 GICR region + * @gicr_frame: base address of the GICR region to check + * + * This iterates over the GICR_TYPER registers of multiple GICR frames in + * a GICR region, to find the instance which has the LAST bit set. For most + * systems this corresponds to the number of cores handled by a redistributor, + * but there could be disabled cores among them. + * It assumes that each GICR region is fully accessible (till the LAST bit + * marks the end of the region). + * If a platform has multiple GICR regions, this function would need to be + * called multiple times, providing the respective GICR base address each time. + * + * Return: number of valid GICR frames (at least 1, up to PLATFORM_CORE_COUNT) + ******************************************************************************/ +unsigned int gicv3_rdistif_get_number_frames(const uintptr_t gicr_frame) +{ + uintptr_t rdistif_base = gicr_frame; + unsigned int count; + + for (count = 1; count < PLATFORM_CORE_COUNT; count++) { + if ((gicr_read_typer(rdistif_base) & TYPER_LAST_BIT) != 0U) { + break; + } + rdistif_base += (1U << GICR_PCPUBASE_SHIFT); + } + + return count; +} diff --git a/drivers/rz/ipl/rza/drivers/arm/gic/v3/gicv3_main.c b/drivers/rz/ipl/rza/drivers/arm/gic/v3/gicv3_main.c new file mode 100644 index 00000000..5a49b4f5 --- /dev/null +++ b/drivers/rz/ipl/rza/drivers/arm/gic/v3/gicv3_main.c @@ -0,0 +1,1383 @@ +/* + * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include +#include + +#include "gicv3_private.h" + +const gicv3_driver_data_t *gicv3_driver_data; + +/* + * Spinlock to guard registers needing read-modify-write. APIs protected by this + * spinlock are used either at boot time (when only a single CPU is active), or + * when the system is fully coherent. + */ +static spinlock_t gic_lock; + +/* + * Redistributor power operations are weakly bound so that they can be + * overridden + */ +#pragma weak gicv3_rdistif_off +#pragma weak gicv3_rdistif_on + +/* Check interrupt ID for SGI/(E)PPI and (E)SPIs */ +static bool is_sgi_ppi(unsigned int id); + +/* + * Helper macros to save and restore GICR and GICD registers + * corresponding to their numbers to and from the context + */ +#define RESTORE_GICR_REG(base, ctx, name, i) \ + gicr_write_##name((base), (i), (ctx)->gicr_##name[(i)]) + +#define SAVE_GICR_REG(base, ctx, name, i) \ + (ctx)->gicr_##name[(i)] = gicr_read_##name((base), (i)) + +/* Helper macros to save and restore GICD registers to and from the context */ +#define RESTORE_GICD_REGS(base, ctx, intr_num, reg, REG) \ + do { \ + for (unsigned int int_id = MIN_SPI_ID; int_id < (intr_num);\ + int_id += (1U << REG##R_SHIFT)) { \ + gicd_write_##reg((base), int_id, \ + (ctx)->gicd_##reg[(int_id - MIN_SPI_ID) >> \ + REG##R_SHIFT]); \ + } \ + } while (false) + +#define SAVE_GICD_REGS(base, ctx, intr_num, reg, REG) \ + do { \ + for (unsigned int int_id = MIN_SPI_ID; int_id < (intr_num);\ + int_id += (1U << REG##R_SHIFT)) { \ + (ctx)->gicd_##reg[(int_id - MIN_SPI_ID) >> \ + REG##R_SHIFT] = gicd_read_##reg((base), int_id); \ + } \ + } while (false) + +#if GIC_EXT_INTID +#define RESTORE_GICD_EREGS(base, ctx, intr_num, reg, REG) \ + do { \ + for (unsigned int int_id = MIN_ESPI_ID; int_id < (intr_num);\ + int_id += (1U << REG##R_SHIFT)) { \ + gicd_write_##reg((base), int_id, \ + (ctx)->gicd_##reg[(int_id - (MIN_ESPI_ID - \ + round_up(TOTAL_SPI_INTR_NUM, 1U << REG##R_SHIFT)))\ + >> REG##R_SHIFT]); \ + } \ + } while (false) + +#define SAVE_GICD_EREGS(base, ctx, intr_num, reg, REG) \ + do { \ + for (unsigned int int_id = MIN_ESPI_ID; int_id < (intr_num);\ + int_id += (1U << REG##R_SHIFT)) { \ + (ctx)->gicd_##reg[(int_id - (MIN_ESPI_ID - \ + round_up(TOTAL_SPI_INTR_NUM, 1U << REG##R_SHIFT)))\ + >> REG##R_SHIFT] = gicd_read_##reg((base), int_id);\ + } \ + } while (false) +#else +#define SAVE_GICD_EREGS(base, ctx, intr_num, reg, REG) +#define RESTORE_GICD_EREGS(base, ctx, intr_num, reg, REG) +#endif /* GIC_EXT_INTID */ + +/******************************************************************************* + * This function initialises the ARM GICv3 driver in EL3 with provided platform + * inputs. + ******************************************************************************/ +void __init gicv3_driver_init(const gicv3_driver_data_t *plat_driver_data) +{ + unsigned int gic_version; + unsigned int gicv2_compat; + + assert(plat_driver_data != NULL); + assert(plat_driver_data->gicd_base != 0U); + assert(plat_driver_data->rdistif_num != 0U); + assert(plat_driver_data->rdistif_base_addrs != NULL); + + assert(IS_IN_EL3()); + + assert((plat_driver_data->interrupt_props_num != 0U) ? + (plat_driver_data->interrupt_props != NULL) : 1); + + /* Check for system register support */ +#ifndef __aarch64__ + assert((read_id_pfr1() & + (ID_PFR1_GIC_MASK << ID_PFR1_GIC_SHIFT)) != 0U); +#else + assert((read_id_aa64pfr0_el1() & + (ID_AA64PFR0_GIC_MASK << ID_AA64PFR0_GIC_SHIFT)) != 0U); +#endif /* !__aarch64__ */ + + gic_version = gicd_read_pidr2(plat_driver_data->gicd_base); + gic_version >>= PIDR2_ARCH_REV_SHIFT; + gic_version &= PIDR2_ARCH_REV_MASK; + + /* Check GIC version */ +#if GIC_ENABLE_V4_EXTN + assert(gic_version == ARCH_REV_GICV4); + + /* GICv4 supports Direct Virtual LPI injection */ + assert((gicd_read_typer(plat_driver_data->gicd_base) + & TYPER_DVIS) != 0); +#else + assert(gic_version == ARCH_REV_GICV3); +#endif + /* + * Find out whether the GIC supports the GICv2 compatibility mode. + * The ARE_S bit resets to 0 if supported + */ + gicv2_compat = gicd_read_ctlr(plat_driver_data->gicd_base); + gicv2_compat >>= CTLR_ARE_S_SHIFT; + gicv2_compat = gicv2_compat & CTLR_ARE_S_MASK; + + if (plat_driver_data->gicr_base != 0U) { + /* + * Find the base address of each implemented Redistributor interface. + * The number of interfaces should be equal to the number of CPUs in the + * system. The memory for saving these addresses has to be allocated by + * the platform port + */ + gicv3_rdistif_base_addrs_probe(plat_driver_data->rdistif_base_addrs, + plat_driver_data->rdistif_num, + plat_driver_data->gicr_base, + plat_driver_data->mpidr_to_core_pos); +#if !HW_ASSISTED_COHERENCY + /* + * Flush the rdistif_base_addrs[] contents linked to the GICv3 driver. + */ + flush_dcache_range((uintptr_t)(plat_driver_data->rdistif_base_addrs), + plat_driver_data->rdistif_num * + sizeof(*(plat_driver_data->rdistif_base_addrs))); +#endif + } + gicv3_driver_data = plat_driver_data; + + /* + * The GIC driver data is initialized by the primary CPU with caches + * enabled. When the secondary CPU boots up, it initializes the + * GICC/GICR interface with the caches disabled. Hence flush the + * driver data to ensure coherency. This is not required if the + * platform has HW_ASSISTED_COHERENCY enabled. + */ +#if !HW_ASSISTED_COHERENCY + flush_dcache_range((uintptr_t)&gicv3_driver_data, + sizeof(gicv3_driver_data)); + flush_dcache_range((uintptr_t)gicv3_driver_data, + sizeof(*gicv3_driver_data)); +#endif + INFO("GICv%u with%s legacy support detected.\n", gic_version, + (gicv2_compat == 0U) ? "" : "out"); + INFO("ARM GICv%u driver initialized in EL3\n", gic_version); +} + +/******************************************************************************* + * This function initialises the GIC distributor interface based upon the data + * provided by the platform while initialising the driver. + ******************************************************************************/ +void __init gicv3_distif_init(void) +{ + unsigned int bitmap; + + assert(gicv3_driver_data != NULL); + assert(gicv3_driver_data->gicd_base != 0U); + + assert(IS_IN_EL3()); + + /* + * Clear the "enable" bits for G0/G1S/G1NS interrupts before configuring + * the ARE_S bit. The Distributor might generate a system error + * otherwise. + */ + gicd_clr_ctlr(gicv3_driver_data->gicd_base, + CTLR_ENABLE_G0_BIT | + CTLR_ENABLE_G1S_BIT | + CTLR_ENABLE_G1NS_BIT, + RWP_TRUE); + + /* Set the ARE_S and ARE_NS bit now that interrupts have been disabled */ + gicd_set_ctlr(gicv3_driver_data->gicd_base, + CTLR_ARE_S_BIT | CTLR_ARE_NS_BIT, RWP_TRUE); + + /* Set the default attribute of all (E)SPIs */ + gicv3_spis_config_defaults(gicv3_driver_data->gicd_base); + + bitmap = gicv3_secure_spis_config_props( + gicv3_driver_data->gicd_base, + gicv3_driver_data->interrupt_props, + gicv3_driver_data->interrupt_props_num); + + /* Enable the secure (E)SPIs now that they have been configured */ + gicd_set_ctlr(gicv3_driver_data->gicd_base, bitmap, RWP_TRUE); +} + +/******************************************************************************* + * This function initialises the GIC Redistributor interface of the calling CPU + * (identified by the 'proc_num' parameter) based upon the data provided by the + * platform while initialising the driver. + ******************************************************************************/ +void gicv3_rdistif_init(unsigned int proc_num) +{ + uintptr_t gicr_base; + unsigned int bitmap; + uint32_t ctlr; + + assert(gicv3_driver_data != NULL); + assert(proc_num < gicv3_driver_data->rdistif_num); + assert(gicv3_driver_data->rdistif_base_addrs != NULL); + assert(gicv3_driver_data->gicd_base != 0U); + + ctlr = gicd_read_ctlr(gicv3_driver_data->gicd_base); + assert((ctlr & CTLR_ARE_S_BIT) != 0U); + + assert(IS_IN_EL3()); + + /* Power on redistributor */ + gicv3_rdistif_on(proc_num); + + gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num]; + assert(gicr_base != 0U); + + /* Set the default attribute of all SGIs and (E)PPIs */ + gicv3_ppi_sgi_config_defaults(gicr_base); + + bitmap = gicv3_secure_ppi_sgi_config_props(gicr_base, + gicv3_driver_data->interrupt_props, + gicv3_driver_data->interrupt_props_num); + + /* Enable interrupt groups as required, if not already */ + if ((ctlr & bitmap) != bitmap) { + gicd_set_ctlr(gicv3_driver_data->gicd_base, bitmap, RWP_TRUE); + } +} + +/******************************************************************************* + * Functions to perform power operations on GIC Redistributor + ******************************************************************************/ +void gicv3_rdistif_off(unsigned int proc_num) +{ +} + +void gicv3_rdistif_on(unsigned int proc_num) +{ +} + +/******************************************************************************* + * This function enables the GIC CPU interface of the calling CPU using only + * system register accesses. + ******************************************************************************/ +void gicv3_cpuif_enable(unsigned int proc_num) +{ + uintptr_t gicr_base; + u_register_t scr_el3; + unsigned int icc_sre_el3; + + assert(gicv3_driver_data != NULL); + assert(proc_num < gicv3_driver_data->rdistif_num); + assert(gicv3_driver_data->rdistif_base_addrs != NULL); + assert(IS_IN_EL3()); + + /* Mark the connected core as awake */ + gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num]; + gicv3_rdistif_mark_core_awake(gicr_base); + + /* Disable the legacy interrupt bypass */ + icc_sre_el3 = ICC_SRE_DIB_BIT | ICC_SRE_DFB_BIT; + + /* + * Enable system register access for EL3 and allow lower exception + * levels to configure the same for themselves. If the legacy mode is + * not supported, the SRE bit is RAO/WI + */ + icc_sre_el3 |= (ICC_SRE_EN_BIT | ICC_SRE_SRE_BIT); + write_icc_sre_el3(read_icc_sre_el3() | icc_sre_el3); + + scr_el3 = read_scr_el3(); + + /* + * Switch to NS state to write Non secure ICC_SRE_EL1 and + * ICC_SRE_EL2 registers. + */ + write_scr_el3(scr_el3 | SCR_NS_BIT); + isb(); + + write_icc_sre_el2(read_icc_sre_el2() | icc_sre_el3); + write_icc_sre_el1(ICC_SRE_SRE_BIT); + isb(); + + /* Switch to secure state. */ + write_scr_el3(scr_el3 & (~SCR_NS_BIT)); + isb(); + + /* Write the secure ICC_SRE_EL1 register */ + write_icc_sre_el1(ICC_SRE_SRE_BIT); + isb(); + + /* Program the idle priority in the PMR */ + write_icc_pmr_el1(GIC_PRI_MASK); + + /* Enable Group0 interrupts */ + write_icc_igrpen0_el1(IGRPEN1_EL1_ENABLE_G0_BIT); + + /* Enable Group1 Secure interrupts */ + write_icc_igrpen1_el3(read_icc_igrpen1_el3() | + IGRPEN1_EL3_ENABLE_G1S_BIT); + isb(); +} + +/******************************************************************************* + * This function disables the GIC CPU interface of the calling CPU using + * only system register accesses. + ******************************************************************************/ +void gicv3_cpuif_disable(unsigned int proc_num) +{ + uintptr_t gicr_base; + + assert(gicv3_driver_data != NULL); + assert(proc_num < gicv3_driver_data->rdistif_num); + assert(gicv3_driver_data->rdistif_base_addrs != NULL); + + assert(IS_IN_EL3()); + + /* Disable legacy interrupt bypass */ + write_icc_sre_el3(read_icc_sre_el3() | + (ICC_SRE_DIB_BIT | ICC_SRE_DFB_BIT)); + + /* Disable Group0 interrupts */ + write_icc_igrpen0_el1(read_icc_igrpen0_el1() & + ~IGRPEN1_EL1_ENABLE_G0_BIT); + + /* Disable Group1 Secure and Non-Secure interrupts */ + write_icc_igrpen1_el3(read_icc_igrpen1_el3() & + ~(IGRPEN1_EL3_ENABLE_G1NS_BIT | + IGRPEN1_EL3_ENABLE_G1S_BIT)); + + /* Synchronise accesses to group enable registers */ + isb(); + + /* Mark the connected core as asleep */ + gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num]; + assert(gicr_base != 0U); + gicv3_rdistif_mark_core_asleep(gicr_base); +} + +/******************************************************************************* + * This function returns the id of the highest priority pending interrupt at + * the GIC cpu interface. + ******************************************************************************/ +unsigned int gicv3_get_pending_interrupt_id(void) +{ + unsigned int id; + + assert(IS_IN_EL3()); + id = (uint32_t)read_icc_hppir0_el1() & HPPIR0_EL1_INTID_MASK; + + /* + * If the ID is special identifier corresponding to G1S or G1NS + * interrupt, then read the highest pending group 1 interrupt. + */ + if ((id == PENDING_G1S_INTID) || (id == PENDING_G1NS_INTID)) { + return (uint32_t)read_icc_hppir1_el1() & HPPIR1_EL1_INTID_MASK; + } + + return id; +} + +/******************************************************************************* + * This function returns the type of the highest priority pending interrupt at + * the GIC cpu interface. The return values can be one of the following : + * PENDING_G1S_INTID : The interrupt type is secure Group 1. + * PENDING_G1NS_INTID : The interrupt type is non secure Group 1. + * 0 - 1019 : The interrupt type is secure Group 0. + * GIC_SPURIOUS_INTERRUPT : there is no pending interrupt with + * sufficient priority to be signaled + ******************************************************************************/ +unsigned int gicv3_get_pending_interrupt_type(void) +{ + assert(IS_IN_EL3()); + return (uint32_t)read_icc_hppir0_el1() & HPPIR0_EL1_INTID_MASK; +} + +/******************************************************************************* + * This function returns the type of the interrupt id depending upon the group + * this interrupt has been configured under by the interrupt controller i.e. + * group0 or group1 Secure / Non Secure. The return value can be one of the + * following : + * INTR_GROUP0 : The interrupt type is a Secure Group 0 interrupt + * INTR_GROUP1S : The interrupt type is a Secure Group 1 secure interrupt + * INTR_GROUP1NS: The interrupt type is a Secure Group 1 non secure + * interrupt. + ******************************************************************************/ +unsigned int gicv3_get_interrupt_type(unsigned int id, unsigned int proc_num) +{ + unsigned int igroup, grpmodr; + uintptr_t gicr_base; + + assert(IS_IN_EL3()); + assert(gicv3_driver_data != NULL); + + /* Ensure the parameters are valid */ + assert((id < PENDING_G1S_INTID) || (id >= MIN_LPI_ID)); + assert(proc_num < gicv3_driver_data->rdistif_num); + + /* All LPI interrupts are Group 1 non secure */ + if (id >= MIN_LPI_ID) { + return INTR_GROUP1NS; + } + + /* Check interrupt ID */ + if (is_sgi_ppi(id)) { + /* SGIs: 0-15, PPIs: 16-31, EPPIs: 1056-1119 */ + assert(gicv3_driver_data->rdistif_base_addrs != NULL); + gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num]; + igroup = gicr_get_igroupr(gicr_base, id); + grpmodr = gicr_get_igrpmodr(gicr_base, id); + } else { + /* SPIs: 32-1019, ESPIs: 4096-5119 */ + assert(gicv3_driver_data->gicd_base != 0U); + igroup = gicd_get_igroupr(gicv3_driver_data->gicd_base, id); + grpmodr = gicd_get_igrpmodr(gicv3_driver_data->gicd_base, id); + } + + /* + * If the IGROUP bit is set, then it is a Group 1 Non secure + * interrupt + */ + if (igroup != 0U) { + return INTR_GROUP1NS; + } + + /* If the GRPMOD bit is set, then it is a Group 1 Secure interrupt */ + if (grpmodr != 0U) { + return INTR_GROUP1S; + } + + /* Else it is a Group 0 Secure interrupt */ + return INTR_GROUP0; +} + +/***************************************************************************** + * Function to save and disable the GIC ITS register context. The power + * management of GIC ITS is implementation-defined and this function doesn't + * save any memory structures required to support ITS. As the sequence to save + * this state is implementation defined, it should be executed in platform + * specific code. Calling this function alone and then powering down the GIC and + * ITS without implementing the aforementioned platform specific code will + * corrupt the ITS state. + * + * This function must be invoked after the GIC CPU interface is disabled. + *****************************************************************************/ +void gicv3_its_save_disable(uintptr_t gits_base, + gicv3_its_ctx_t * const its_ctx) +{ + unsigned int i; + + assert(gicv3_driver_data != NULL); + assert(IS_IN_EL3()); + assert(its_ctx != NULL); + assert(gits_base != 0U); + + its_ctx->gits_ctlr = gits_read_ctlr(gits_base); + + /* Disable the ITS */ + gits_write_ctlr(gits_base, its_ctx->gits_ctlr & ~GITS_CTLR_ENABLED_BIT); + + /* Wait for quiescent state */ + gits_wait_for_quiescent_bit(gits_base); + + its_ctx->gits_cbaser = gits_read_cbaser(gits_base); + its_ctx->gits_cwriter = gits_read_cwriter(gits_base); + + for (i = 0U; i < ARRAY_SIZE(its_ctx->gits_baser); i++) { + its_ctx->gits_baser[i] = gits_read_baser(gits_base, i); + } +} + +/***************************************************************************** + * Function to restore the GIC ITS register context. The power + * management of GIC ITS is implementation defined and this function doesn't + * restore any memory structures required to support ITS. The assumption is + * that these structures are in memory and are retained during system suspend. + * + * This must be invoked before the GIC CPU interface is enabled. + *****************************************************************************/ +void gicv3_its_restore(uintptr_t gits_base, + const gicv3_its_ctx_t * const its_ctx) +{ + unsigned int i; + + assert(gicv3_driver_data != NULL); + assert(IS_IN_EL3()); + assert(its_ctx != NULL); + assert(gits_base != 0U); + + /* Assert that the GITS is disabled and quiescent */ + assert((gits_read_ctlr(gits_base) & GITS_CTLR_ENABLED_BIT) == 0U); + assert((gits_read_ctlr(gits_base) & GITS_CTLR_QUIESCENT_BIT) != 0U); + + gits_write_cbaser(gits_base, its_ctx->gits_cbaser); + gits_write_cwriter(gits_base, its_ctx->gits_cwriter); + + for (i = 0U; i < ARRAY_SIZE(its_ctx->gits_baser); i++) { + gits_write_baser(gits_base, i, its_ctx->gits_baser[i]); + } + + /* Restore the ITS CTLR but leave the ITS disabled */ + gits_write_ctlr(gits_base, its_ctx->gits_ctlr & ~GITS_CTLR_ENABLED_BIT); +} + +/***************************************************************************** + * Function to save the GIC Redistributor register context. This function + * must be invoked after CPU interface disable and prior to Distributor save. + *****************************************************************************/ +void gicv3_rdistif_save(unsigned int proc_num, + gicv3_redist_ctx_t * const rdist_ctx) +{ + uintptr_t gicr_base; + unsigned int i, ppi_regs_num, regs_num; + + assert(gicv3_driver_data != NULL); + assert(proc_num < gicv3_driver_data->rdistif_num); + assert(gicv3_driver_data->rdistif_base_addrs != NULL); + assert(IS_IN_EL3()); + assert(rdist_ctx != NULL); + + gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num]; + +#if GIC_EXT_INTID + /* Calculate number of PPI registers */ + ppi_regs_num = (unsigned int)((gicr_read_typer(gicr_base) >> + TYPER_PPI_NUM_SHIFT) & TYPER_PPI_NUM_MASK) + 1; + /* All other values except PPInum [0-2] are reserved */ + if (ppi_regs_num > 3U) { + ppi_regs_num = 1U; + } +#else + ppi_regs_num = 1U; +#endif + /* + * Wait for any write to GICR_CTLR to complete before trying to save any + * state. + */ + gicr_wait_for_pending_write(gicr_base); + + rdist_ctx->gicr_ctlr = gicr_read_ctlr(gicr_base); + + rdist_ctx->gicr_propbaser = gicr_read_propbaser(gicr_base); + rdist_ctx->gicr_pendbaser = gicr_read_pendbaser(gicr_base); + + /* 32 interrupt IDs per register */ + for (i = 0U; i < ppi_regs_num; ++i) { + SAVE_GICR_REG(gicr_base, rdist_ctx, igroupr, i); + SAVE_GICR_REG(gicr_base, rdist_ctx, isenabler, i); + SAVE_GICR_REG(gicr_base, rdist_ctx, ispendr, i); + SAVE_GICR_REG(gicr_base, rdist_ctx, isactiver, i); + SAVE_GICR_REG(gicr_base, rdist_ctx, igrpmodr, i); + } + + /* 16 interrupt IDs per GICR_ICFGR register */ + regs_num = ppi_regs_num << 1; + for (i = 0U; i < regs_num; ++i) { + SAVE_GICR_REG(gicr_base, rdist_ctx, icfgr, i); + } + + rdist_ctx->gicr_nsacr = gicr_read_nsacr(gicr_base); + + /* 4 interrupt IDs per GICR_IPRIORITYR register */ + regs_num = ppi_regs_num << 3; + for (i = 0U; i < regs_num; ++i) { + rdist_ctx->gicr_ipriorityr[i] = + gicr_ipriorityr_read(gicr_base, i); + } + + /* + * Call the pre-save hook that implements the IMP DEF sequence that may + * be required on some GIC implementations. As this may need to access + * the Redistributor registers, we pass it proc_num. + */ + gicv3_distif_pre_save(proc_num); +} + +/***************************************************************************** + * Function to restore the GIC Redistributor register context. We disable + * LPI and per-cpu interrupts before we start restore of the Redistributor. + * This function must be invoked after Distributor restore but prior to + * CPU interface enable. The pending and active interrupts are restored + * after the interrupts are fully configured and enabled. + *****************************************************************************/ +void gicv3_rdistif_init_restore(unsigned int proc_num, + const gicv3_redist_ctx_t * const rdist_ctx) +{ + uintptr_t gicr_base; + unsigned int i, ppi_regs_num, regs_num; + + assert(gicv3_driver_data != NULL); + assert(proc_num < gicv3_driver_data->rdistif_num); + assert(gicv3_driver_data->rdistif_base_addrs != NULL); + assert(IS_IN_EL3()); + assert(rdist_ctx != NULL); + + gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num]; + +#if GIC_EXT_INTID + /* Calculate number of PPI registers */ + ppi_regs_num = (unsigned int)((gicr_read_typer(gicr_base) >> + TYPER_PPI_NUM_SHIFT) & TYPER_PPI_NUM_MASK) + 1; + /* All other values except PPInum [0-2] are reserved */ + if (ppi_regs_num > 3U) { + ppi_regs_num = 1U; + } +#else + ppi_regs_num = 1U; +#endif + /* Power on redistributor */ + gicv3_rdistif_on(proc_num); + + /* + * Call the post-restore hook that implements the IMP DEF sequence that + * may be required on some GIC implementations. As this may need to + * access the Redistributor registers, we pass it proc_num. + */ + gicv3_distif_post_restore(proc_num); + + /* + * Disable all SGIs (imp. def.)/(E)PPIs before configuring them. + * This is a more scalable approach as it avoids clearing the enable + * bits in the GICD_CTLR. + */ + for (i = 0U; i < ppi_regs_num; ++i) { + gicr_write_icenabler(gicr_base, i, ~0U); + } + + /* Wait for pending writes to GICR_ICENABLER */ + gicr_wait_for_pending_write(gicr_base); + + /* + * Disable the LPIs to avoid unpredictable behavior when writing to + * GICR_PROPBASER and GICR_PENDBASER. + */ + gicr_write_ctlr(gicr_base, + rdist_ctx->gicr_ctlr & ~(GICR_CTLR_EN_LPIS_BIT)); + + /* Restore registers' content */ + gicr_write_propbaser(gicr_base, rdist_ctx->gicr_propbaser); + gicr_write_pendbaser(gicr_base, rdist_ctx->gicr_pendbaser); + + /* 32 interrupt IDs per register */ + for (i = 0U; i < ppi_regs_num; ++i) { + RESTORE_GICR_REG(gicr_base, rdist_ctx, igroupr, i); + RESTORE_GICR_REG(gicr_base, rdist_ctx, igrpmodr, i); + } + + /* 4 interrupt IDs per GICR_IPRIORITYR register */ + regs_num = ppi_regs_num << 3; + for (i = 0U; i < regs_num; ++i) { + gicr_ipriorityr_write(gicr_base, i, + rdist_ctx->gicr_ipriorityr[i]); + } + + /* 16 interrupt IDs per GICR_ICFGR register */ + regs_num = ppi_regs_num << 1; + for (i = 0U; i < regs_num; ++i) { + RESTORE_GICR_REG(gicr_base, rdist_ctx, icfgr, i); + } + + gicr_write_nsacr(gicr_base, rdist_ctx->gicr_nsacr); + + /* Restore after group and priorities are set. + * 32 interrupt IDs per register + */ + for (i = 0U; i < ppi_regs_num; ++i) { + RESTORE_GICR_REG(gicr_base, rdist_ctx, ispendr, i); + RESTORE_GICR_REG(gicr_base, rdist_ctx, isactiver, i); + } + + /* + * Wait for all writes to the Distributor to complete before enabling + * the SGI and (E)PPIs. + */ + gicr_wait_for_upstream_pending_write(gicr_base); + + /* 32 interrupt IDs per GICR_ISENABLER register */ + for (i = 0U; i < ppi_regs_num; ++i) { + RESTORE_GICR_REG(gicr_base, rdist_ctx, isenabler, i); + } + + /* + * Restore GICR_CTLR.Enable_LPIs bit and wait for pending writes in case + * the first write to GICR_CTLR was still in flight (this write only + * restores GICR_CTLR.Enable_LPIs and no waiting is required for this + * bit). + */ + gicr_write_ctlr(gicr_base, rdist_ctx->gicr_ctlr); + gicr_wait_for_pending_write(gicr_base); +} + +/***************************************************************************** + * Function to save the GIC Distributor register context. This function + * must be invoked after CPU interface disable and Redistributor save. + *****************************************************************************/ +void gicv3_distif_save(gicv3_dist_ctx_t * const dist_ctx) +{ + unsigned int typer_reg, num_ints; +#if GIC_EXT_INTID + unsigned int num_eints; +#endif + + assert(gicv3_driver_data != NULL); + assert(gicv3_driver_data->gicd_base != 0U); + assert(IS_IN_EL3()); + assert(dist_ctx != NULL); + + uintptr_t gicd_base = gicv3_driver_data->gicd_base; + + typer_reg = gicd_read_typer(gicd_base); + + /* Maximum SPI INTID is 32 * (GICD_TYPER.ITLinesNumber + 1) - 1 */ + num_ints = ((typer_reg & TYPER_IT_LINES_NO_MASK) + 1U) << 5; + + /* Filter out special INTIDs 1020-1023 */ + if (num_ints > (MAX_SPI_ID + 1U)) { + num_ints = MAX_SPI_ID + 1U; + } + +#if GIC_EXT_INTID + /* Check if extended SPI range is implemented */ + if ((typer_reg & TYPER_ESPI) != 0U) { + /* + * Maximum ESPI INTID is 32 * (GICD_TYPER.ESPI_range + 1) + 4095 + */ + num_eints = ((((typer_reg >> TYPER_ESPI_RANGE_SHIFT) & + TYPER_ESPI_RANGE_MASK) + 1U) << 5) + MIN_ESPI_ID; + } else { + num_eints = 0U; + } +#endif + /* Wait for pending write to complete */ + gicd_wait_for_pending_write(gicd_base); + + /* Save the GICD_CTLR */ + dist_ctx->gicd_ctlr = gicd_read_ctlr(gicd_base); + + /* Save GICD_IGROUPR for INTIDs 32 - 1019 */ + SAVE_GICD_REGS(gicd_base, dist_ctx, num_ints, igroupr, IGROUP); + + /* Save GICD_IGROUPRE for INTIDs 4096 - 5119 */ + SAVE_GICD_EREGS(gicd_base, dist_ctx, num_eints, igroupr, IGROUP); + + /* Save GICD_ISENABLER for INT_IDs 32 - 1019 */ + SAVE_GICD_REGS(gicd_base, dist_ctx, num_ints, isenabler, ISENABLE); + + /* Save GICD_ISENABLERE for INT_IDs 4096 - 5119 */ + SAVE_GICD_EREGS(gicd_base, dist_ctx, num_eints, isenabler, ISENABLE); + + /* Save GICD_ISPENDR for INTIDs 32 - 1019 */ + SAVE_GICD_REGS(gicd_base, dist_ctx, num_ints, ispendr, ISPEND); + + /* Save GICD_ISPENDRE for INTIDs 4096 - 5119 */ + SAVE_GICD_EREGS(gicd_base, dist_ctx, num_eints, ispendr, ISPEND); + + /* Save GICD_ISACTIVER for INTIDs 32 - 1019 */ + SAVE_GICD_REGS(gicd_base, dist_ctx, num_ints, isactiver, ISACTIVE); + + /* Save GICD_ISACTIVERE for INTIDs 4096 - 5119 */ + SAVE_GICD_EREGS(gicd_base, dist_ctx, num_eints, isactiver, ISACTIVE); + + /* Save GICD_IPRIORITYR for INTIDs 32 - 1019 */ + SAVE_GICD_REGS(gicd_base, dist_ctx, num_ints, ipriorityr, IPRIORITY); + + /* Save GICD_IPRIORITYRE for INTIDs 4096 - 5119 */ + SAVE_GICD_EREGS(gicd_base, dist_ctx, num_eints, ipriorityr, IPRIORITY); + + /* Save GICD_ICFGR for INTIDs 32 - 1019 */ + SAVE_GICD_REGS(gicd_base, dist_ctx, num_ints, icfgr, ICFG); + + /* Save GICD_ICFGRE for INTIDs 4096 - 5119 */ + SAVE_GICD_EREGS(gicd_base, dist_ctx, num_eints, icfgr, ICFG); + + /* Save GICD_IGRPMODR for INTIDs 32 - 1019 */ + SAVE_GICD_REGS(gicd_base, dist_ctx, num_ints, igrpmodr, IGRPMOD); + + /* Save GICD_IGRPMODRE for INTIDs 4096 - 5119 */ + SAVE_GICD_EREGS(gicd_base, dist_ctx, num_eints, igrpmodr, IGRPMOD); + + /* Save GICD_NSACR for INTIDs 32 - 1019 */ + SAVE_GICD_REGS(gicd_base, dist_ctx, num_ints, nsacr, NSAC); + + /* Save GICD_NSACRE for INTIDs 4096 - 5119 */ + SAVE_GICD_EREGS(gicd_base, dist_ctx, num_eints, nsacr, NSAC); + + /* Save GICD_IROUTER for INTIDs 32 - 1019 */ + SAVE_GICD_REGS(gicd_base, dist_ctx, num_ints, irouter, IROUTE); + + /* Save GICD_IROUTERE for INTIDs 4096 - 5119 */ + SAVE_GICD_EREGS(gicd_base, dist_ctx, num_eints, irouter, IROUTE); + + /* + * GICD_ITARGETSR and GICD_SPENDSGIR are RAZ/WI when + * GICD_CTLR.ARE_(S|NS) bits are set which is the case for our GICv3 + * driver. + */ +} + +/***************************************************************************** + * Function to restore the GIC Distributor register context. We disable G0, G1S + * and G1NS interrupt groups before we start restore of the Distributor. This + * function must be invoked prior to Redistributor restore and CPU interface + * enable. The pending and active interrupts are restored after the interrupts + * are fully configured and enabled. + *****************************************************************************/ +void gicv3_distif_init_restore(const gicv3_dist_ctx_t * const dist_ctx) +{ + unsigned int typer_reg, num_ints; +#if GIC_EXT_INTID + unsigned int num_eints; +#endif + + assert(gicv3_driver_data != NULL); + assert(gicv3_driver_data->gicd_base != 0U); + assert(IS_IN_EL3()); + assert(dist_ctx != NULL); + + uintptr_t gicd_base = gicv3_driver_data->gicd_base; + + /* + * Clear the "enable" bits for G0/G1S/G1NS interrupts before configuring + * the ARE_S bit. The Distributor might generate a system error + * otherwise. + */ + gicd_clr_ctlr(gicd_base, + CTLR_ENABLE_G0_BIT | + CTLR_ENABLE_G1S_BIT | + CTLR_ENABLE_G1NS_BIT, + RWP_TRUE); + + /* Set the ARE_S and ARE_NS bit now that interrupts have been disabled */ + gicd_set_ctlr(gicd_base, CTLR_ARE_S_BIT | CTLR_ARE_NS_BIT, RWP_TRUE); + + typer_reg = gicd_read_typer(gicd_base); + + /* Maximum SPI INTID is 32 * (GICD_TYPER.ITLinesNumber + 1) - 1 */ + num_ints = ((typer_reg & TYPER_IT_LINES_NO_MASK) + 1U) << 5; + + /* Filter out special INTIDs 1020-1023 */ + if (num_ints > (MAX_SPI_ID + 1U)) { + num_ints = MAX_SPI_ID + 1U; + } + +#if GIC_EXT_INTID + /* Check if extended SPI range is implemented */ + if ((typer_reg & TYPER_ESPI) != 0U) { + /* + * Maximum ESPI INTID is 32 * (GICD_TYPER.ESPI_range + 1) + 4095 + */ + num_eints = ((((typer_reg >> TYPER_ESPI_RANGE_SHIFT) & + TYPER_ESPI_RANGE_MASK) + 1U) << 5) + MIN_ESPI_ID; + } else { + num_eints = 0U; + } +#endif + /* Restore GICD_IGROUPR for INTIDs 32 - 1019 */ + RESTORE_GICD_REGS(gicd_base, dist_ctx, num_ints, igroupr, IGROUP); + + /* Restore GICD_IGROUPRE for INTIDs 4096 - 5119 */ + RESTORE_GICD_EREGS(gicd_base, dist_ctx, num_eints, igroupr, IGROUP); + + /* Restore GICD_IPRIORITYR for INTIDs 32 - 1019 */ + RESTORE_GICD_REGS(gicd_base, dist_ctx, num_ints, ipriorityr, IPRIORITY); + + /* Restore GICD_IPRIORITYRE for INTIDs 4096 - 5119 */ + RESTORE_GICD_EREGS(gicd_base, dist_ctx, num_eints, ipriorityr, IPRIORITY); + + /* Restore GICD_ICFGR for INTIDs 32 - 1019 */ + RESTORE_GICD_REGS(gicd_base, dist_ctx, num_ints, icfgr, ICFG); + + /* Restore GICD_ICFGRE for INTIDs 4096 - 5119 */ + RESTORE_GICD_EREGS(gicd_base, dist_ctx, num_eints, icfgr, ICFG); + + /* Restore GICD_IGRPMODR for INTIDs 32 - 1019 */ + RESTORE_GICD_REGS(gicd_base, dist_ctx, num_ints, igrpmodr, IGRPMOD); + + /* Restore GICD_IGRPMODRE for INTIDs 4096 - 5119 */ + RESTORE_GICD_EREGS(gicd_base, dist_ctx, num_eints, igrpmodr, IGRPMOD); + + /* Restore GICD_NSACR for INTIDs 32 - 1019 */ + RESTORE_GICD_REGS(gicd_base, dist_ctx, num_ints, nsacr, NSAC); + + /* Restore GICD_NSACRE for INTIDs 4096 - 5119 */ + RESTORE_GICD_EREGS(gicd_base, dist_ctx, num_eints, nsacr, NSAC); + + /* Restore GICD_IROUTER for INTIDs 32 - 1019 */ + RESTORE_GICD_REGS(gicd_base, dist_ctx, num_ints, irouter, IROUTE); + + /* Restore GICD_IROUTERE for INTIDs 4096 - 5119 */ + RESTORE_GICD_EREGS(gicd_base, dist_ctx, num_eints, irouter, IROUTE); + + /* + * Restore ISENABLER(E), ISPENDR(E) and ISACTIVER(E) after + * the interrupts are configured. + */ + + /* Restore GICD_ISENABLER for INT_IDs 32 - 1019 */ + RESTORE_GICD_REGS(gicd_base, dist_ctx, num_ints, isenabler, ISENABLE); + + /* Restore GICD_ISENABLERE for INT_IDs 4096 - 5119 */ + RESTORE_GICD_EREGS(gicd_base, dist_ctx, num_eints, isenabler, ISENABLE); + + /* Restore GICD_ISPENDR for INTIDs 32 - 1019 */ + RESTORE_GICD_REGS(gicd_base, dist_ctx, num_ints, ispendr, ISPEND); + + /* Restore GICD_ISPENDRE for INTIDs 4096 - 5119 */ + RESTORE_GICD_EREGS(gicd_base, dist_ctx, num_eints, ispendr, ISPEND); + + /* Restore GICD_ISACTIVER for INTIDs 32 - 1019 */ + RESTORE_GICD_REGS(gicd_base, dist_ctx, num_ints, isactiver, ISACTIVE); + + /* Restore GICD_ISACTIVERE for INTIDs 4096 - 5119 */ + RESTORE_GICD_EREGS(gicd_base, dist_ctx, num_eints, isactiver, ISACTIVE); + + /* Restore the GICD_CTLR */ + gicd_write_ctlr(gicd_base, dist_ctx->gicd_ctlr); + gicd_wait_for_pending_write(gicd_base); +} + +/******************************************************************************* + * This function gets the priority of the interrupt the processor is currently + * servicing. + ******************************************************************************/ +unsigned int gicv3_get_running_priority(void) +{ + return (unsigned int)read_icc_rpr_el1(); +} + +/******************************************************************************* + * This function checks if the interrupt identified by id is active (whether the + * state is either active, or active and pending). The proc_num is used if the + * interrupt is SGI or (E)PPI and programs the corresponding Redistributor + * interface. + ******************************************************************************/ +unsigned int gicv3_get_interrupt_active(unsigned int id, unsigned int proc_num) +{ + assert(gicv3_driver_data != NULL); + assert(gicv3_driver_data->gicd_base != 0U); + assert(proc_num < gicv3_driver_data->rdistif_num); + assert(gicv3_driver_data->rdistif_base_addrs != NULL); + + /* Check interrupt ID */ + if (is_sgi_ppi(id)) { + /* For SGIs: 0-15, PPIs: 16-31 and EPPIs: 1056-1119 */ + return gicr_get_isactiver( + gicv3_driver_data->rdistif_base_addrs[proc_num], id); + } + + /* For SPIs: 32-1019 and ESPIs: 4096-5119 */ + return gicd_get_isactiver(gicv3_driver_data->gicd_base, id); +} + +/******************************************************************************* + * This function enables the interrupt identified by id. The proc_num + * is used if the interrupt is SGI or PPI, and programs the corresponding + * Redistributor interface. + ******************************************************************************/ +void gicv3_enable_interrupt(unsigned int id, unsigned int proc_num) +{ + assert(gicv3_driver_data != NULL); + assert(gicv3_driver_data->gicd_base != 0U); + assert(proc_num < gicv3_driver_data->rdistif_num); + assert(gicv3_driver_data->rdistif_base_addrs != NULL); + + /* + * Ensure that any shared variable updates depending on out of band + * interrupt trigger are observed before enabling interrupt. + */ + dsbishst(); + + /* Check interrupt ID */ + if (is_sgi_ppi(id)) { + /* For SGIs: 0-15, PPIs: 16-31 and EPPIs: 1056-1119 */ + gicr_set_isenabler( + gicv3_driver_data->rdistif_base_addrs[proc_num], id); + } else { + /* For SPIs: 32-1019 and ESPIs: 4096-5119 */ + gicd_set_isenabler(gicv3_driver_data->gicd_base, id); + } +} + +/******************************************************************************* + * This function disables the interrupt identified by id. The proc_num + * is used if the interrupt is SGI or PPI, and programs the corresponding + * Redistributor interface. + ******************************************************************************/ +void gicv3_disable_interrupt(unsigned int id, unsigned int proc_num) +{ + assert(gicv3_driver_data != NULL); + assert(gicv3_driver_data->gicd_base != 0U); + assert(proc_num < gicv3_driver_data->rdistif_num); + assert(gicv3_driver_data->rdistif_base_addrs != NULL); + + /* + * Disable interrupt, and ensure that any shared variable updates + * depending on out of band interrupt trigger are observed afterwards. + */ + + /* Check interrupt ID */ + if (is_sgi_ppi(id)) { + /* For SGIs: 0-15, PPIs: 16-31 and EPPIs: 1056-1119 */ + gicr_set_icenabler( + gicv3_driver_data->rdistif_base_addrs[proc_num], id); + + /* Write to clear enable requires waiting for pending writes */ + gicr_wait_for_pending_write( + gicv3_driver_data->rdistif_base_addrs[proc_num]); + } else { + /* For SPIs: 32-1019 and ESPIs: 4096-5119 */ + gicd_set_icenabler(gicv3_driver_data->gicd_base, id); + + /* Write to clear enable requires waiting for pending writes */ + gicd_wait_for_pending_write(gicv3_driver_data->gicd_base); + } + + dsbishst(); +} + +/******************************************************************************* + * This function sets the interrupt priority as supplied for the given interrupt + * id. + ******************************************************************************/ +void gicv3_set_interrupt_priority(unsigned int id, unsigned int proc_num, + unsigned int priority) +{ + uintptr_t gicr_base; + + assert(gicv3_driver_data != NULL); + assert(gicv3_driver_data->gicd_base != 0U); + assert(proc_num < gicv3_driver_data->rdistif_num); + assert(gicv3_driver_data->rdistif_base_addrs != NULL); + + /* Check interrupt ID */ + if (is_sgi_ppi(id)) { + /* For SGIs: 0-15, PPIs: 16-31 and EPPIs: 1056-1119 */ + gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num]; + gicr_set_ipriorityr(gicr_base, id, priority); + } else { + /* For SPIs: 32-1019 and ESPIs: 4096-5119 */ + gicd_set_ipriorityr(gicv3_driver_data->gicd_base, id, priority); + } +} + +/******************************************************************************* + * This function assigns group for the interrupt identified by id. The proc_num + * is used if the interrupt is SGI or (E)PPI, and programs the corresponding + * Redistributor interface. The group can be any of GICV3_INTR_GROUP* + ******************************************************************************/ +void gicv3_set_interrupt_type(unsigned int id, unsigned int proc_num, + unsigned int type) +{ + bool igroup = false, grpmod = false; + uintptr_t gicr_base; + + assert(gicv3_driver_data != NULL); + assert(gicv3_driver_data->gicd_base != 0U); + assert(proc_num < gicv3_driver_data->rdistif_num); + assert(gicv3_driver_data->rdistif_base_addrs != NULL); + + switch (type) { + case INTR_GROUP1S: + igroup = false; + grpmod = true; + break; + case INTR_GROUP0: + igroup = false; + grpmod = false; + break; + case INTR_GROUP1NS: + igroup = true; + grpmod = false; + break; + default: + assert(false); + break; + } + + /* Check interrupt ID */ + if (is_sgi_ppi(id)) { + /* For SGIs: 0-15, PPIs: 16-31 and EPPIs: 1056-1119 */ + gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num]; + + igroup ? gicr_set_igroupr(gicr_base, id) : + gicr_clr_igroupr(gicr_base, id); + grpmod ? gicr_set_igrpmodr(gicr_base, id) : + gicr_clr_igrpmodr(gicr_base, id); + } else { + /* For SPIs: 32-1019 and ESPIs: 4096-5119 */ + + /* Serialize read-modify-write to Distributor registers */ + spin_lock(&gic_lock); + + igroup ? gicd_set_igroupr(gicv3_driver_data->gicd_base, id) : + gicd_clr_igroupr(gicv3_driver_data->gicd_base, id); + grpmod ? gicd_set_igrpmodr(gicv3_driver_data->gicd_base, id) : + gicd_clr_igrpmodr(gicv3_driver_data->gicd_base, id); + + spin_unlock(&gic_lock); + } +} + +/******************************************************************************* + * This function raises the specified Secure Group 0 SGI. + * + * The target parameter must be a valid MPIDR in the system. + ******************************************************************************/ +void gicv3_raise_secure_g0_sgi(unsigned int sgi_num, u_register_t target) +{ + unsigned int tgt, aff3, aff2, aff1, aff0; + uint64_t sgi_val; + + /* Verify interrupt number is in the SGI range */ + assert((sgi_num >= MIN_SGI_ID) && (sgi_num < MIN_PPI_ID)); + + /* Extract affinity fields from target */ + aff0 = MPIDR_AFFLVL0_VAL(target); + aff1 = MPIDR_AFFLVL1_VAL(target); + aff2 = MPIDR_AFFLVL2_VAL(target); + aff3 = MPIDR_AFFLVL3_VAL(target); + + /* + * Make target list from affinity 0, and ensure GICv3 SGI can target + * this PE. + */ + assert(aff0 < GICV3_MAX_SGI_TARGETS); + tgt = BIT_32(aff0); + + /* Raise SGI to PE specified by its affinity */ + sgi_val = GICV3_SGIR_VALUE(aff3, aff2, aff1, sgi_num, SGIR_IRM_TO_AFF, + tgt); + + /* + * Ensure that any shared variable updates depending on out of band + * interrupt trigger are observed before raising SGI. + */ + dsbishst(); + write_icc_sgi0r_el1(sgi_val); + isb(); +} + +/******************************************************************************* + * This function sets the interrupt routing for the given (E)SPI interrupt id. + * The interrupt routing is specified in routing mode and mpidr. + * + * The routing mode can be either of: + * - GICV3_IRM_ANY + * - GICV3_IRM_PE + * + * The mpidr is the affinity of the PE to which the interrupt will be routed, + * and is ignored for routing mode GICV3_IRM_ANY. + ******************************************************************************/ +void gicv3_set_spi_routing(unsigned int id, unsigned int irm, u_register_t mpidr) +{ + unsigned long long aff; + uint64_t router; + + assert(gicv3_driver_data != NULL); + assert(gicv3_driver_data->gicd_base != 0U); + + assert((irm == GICV3_IRM_ANY) || (irm == GICV3_IRM_PE)); + + assert(IS_SPI(id)); + + aff = gicd_irouter_val_from_mpidr(mpidr, irm); + gicd_write_irouter(gicv3_driver_data->gicd_base, id, aff); + + /* + * In implementations that do not require 1 of N distribution of SPIs, + * IRM might be RAZ/WI. Read back and verify IRM bit. + */ + if (irm == GICV3_IRM_ANY) { + router = gicd_read_irouter(gicv3_driver_data->gicd_base, id); + if (((router >> IROUTER_IRM_SHIFT) & IROUTER_IRM_MASK) == 0U) { + ERROR("GICv3 implementation doesn't support routing ANY\n"); + panic(); + } + } +} + +/******************************************************************************* + * This function clears the pending status of an interrupt identified by id. + * The proc_num is used if the interrupt is SGI or (E)PPI, and programs the + * corresponding Redistributor interface. + ******************************************************************************/ +void gicv3_clear_interrupt_pending(unsigned int id, unsigned int proc_num) +{ + assert(gicv3_driver_data != NULL); + assert(gicv3_driver_data->gicd_base != 0U); + assert(proc_num < gicv3_driver_data->rdistif_num); + assert(gicv3_driver_data->rdistif_base_addrs != NULL); + + /* + * Clear pending interrupt, and ensure that any shared variable updates + * depending on out of band interrupt trigger are observed afterwards. + */ + + /* Check interrupt ID */ + if (is_sgi_ppi(id)) { + /* For SGIs: 0-15, PPIs: 16-31 and EPPIs: 1056-1119 */ + gicr_set_icpendr( + gicv3_driver_data->rdistif_base_addrs[proc_num], id); + } else { + /* For SPIs: 32-1019 and ESPIs: 4096-5119 */ + gicd_set_icpendr(gicv3_driver_data->gicd_base, id); + } + + dsbishst(); +} + +/******************************************************************************* + * This function sets the pending status of an interrupt identified by id. + * The proc_num is used if the interrupt is SGI or PPI and programs the + * corresponding Redistributor interface. + ******************************************************************************/ +void gicv3_set_interrupt_pending(unsigned int id, unsigned int proc_num) +{ + assert(gicv3_driver_data != NULL); + assert(gicv3_driver_data->gicd_base != 0U); + assert(proc_num < gicv3_driver_data->rdistif_num); + assert(gicv3_driver_data->rdistif_base_addrs != NULL); + + /* + * Ensure that any shared variable updates depending on out of band + * interrupt trigger are observed before setting interrupt pending. + */ + dsbishst(); + + /* Check interrupt ID */ + if (is_sgi_ppi(id)) { + /* For SGIs: 0-15, PPIs: 16-31 and EPPIs: 1056-1119 */ + gicr_set_ispendr( + gicv3_driver_data->rdistif_base_addrs[proc_num], id); + } else { + /* For SPIs: 32-1019 and ESPIs: 4096-5119 */ + gicd_set_ispendr(gicv3_driver_data->gicd_base, id); + } +} + +/******************************************************************************* + * This function sets the PMR register with the supplied value. Returns the + * original PMR. + ******************************************************************************/ +unsigned int gicv3_set_pmr(unsigned int mask) +{ + unsigned int old_mask; + + old_mask = (unsigned int)read_icc_pmr_el1(); + + /* + * Order memory updates w.r.t. PMR write, and ensure they're visible + * before potential out of band interrupt trigger because of PMR update. + * PMR system register writes are self-synchronizing, so no ISB required + * thereafter. + */ + dsbishst(); + write_icc_pmr_el1(mask); + + return old_mask; +} + +/******************************************************************************* + * This function delegates the responsibility of discovering the corresponding + * Redistributor frames to each CPU itself. It is a modified version of + * gicv3_rdistif_base_addrs_probe() and is executed by each CPU in the platform + * unlike the previous way in which only the Primary CPU did the discovery of + * all the Redistributor frames for every CPU. It also handles the scenario in + * which the frames of various CPUs are not contiguous in physical memory. + ******************************************************************************/ +int gicv3_rdistif_probe(const uintptr_t gicr_frame) +{ + u_register_t mpidr, mpidr_self; + unsigned int proc_num; + uint64_t typer_val; + uintptr_t rdistif_base; + bool gicr_frame_found = false; + + assert(gicv3_driver_data->gicr_base == 0U); + + /* Ensure this function is called with Data Cache enabled */ +#ifndef __aarch64__ + assert((read_sctlr() & SCTLR_C_BIT) != 0U); +#else + assert((read_sctlr_el3() & SCTLR_C_BIT) != 0U); +#endif /* !__aarch64__ */ + + mpidr_self = read_mpidr_el1() & MPIDR_AFFINITY_MASK; + rdistif_base = gicr_frame; + do { + typer_val = gicr_read_typer(rdistif_base); + mpidr = mpidr_from_gicr_typer(typer_val); + if (gicv3_driver_data->mpidr_to_core_pos != NULL) { + proc_num = gicv3_driver_data->mpidr_to_core_pos(mpidr); + } else { + proc_num = (unsigned int)(typer_val >> + TYPER_PROC_NUM_SHIFT) & TYPER_PROC_NUM_MASK; + } + if (mpidr == mpidr_self) { + /* The base address doesn't need to be initialized on + * every warm boot. + */ + if (gicv3_driver_data->rdistif_base_addrs[proc_num] + != 0U) { + return 0; + } + gicv3_driver_data->rdistif_base_addrs[proc_num] = + rdistif_base; + gicr_frame_found = true; + break; + } + rdistif_base += (uintptr_t)(ULL(1) << GICR_PCPUBASE_SHIFT); + } while ((typer_val & TYPER_LAST_BIT) == 0U); + + if (!gicr_frame_found) { + return -1; + } + + /* + * Flush the driver data to ensure coherency. This is + * not required if platform has HW_ASSISTED_COHERENCY + * enabled. + */ +#if !HW_ASSISTED_COHERENCY + /* + * Flush the rdistif_base_addrs[] contents linked to the GICv3 driver. + */ + flush_dcache_range((uintptr_t)&(gicv3_driver_data->rdistif_base_addrs[proc_num]), + sizeof(*(gicv3_driver_data->rdistif_base_addrs))); +#endif + return 0; /* Found matching GICR frame */ +} + +/****************************************************************************** + * This function checks the interrupt ID and returns true for SGIs and (E)PPIs + * and false for (E)SPIs IDs. + *****************************************************************************/ +static bool is_sgi_ppi(unsigned int id) +{ + /* SGIs: 0-15, PPIs: 16-31, EPPIs: 1056-1119 */ + if (IS_SGI_PPI(id)) { + return true; + } + + /* SPIs: 32-1019, ESPIs: 4096-5119 */ + if (IS_SPI(id)) { + return false; + } + + assert(false); + panic(); +} diff --git a/drivers/rz/ipl/rza/drivers/arm/gic/v3/gicv3_private.h b/drivers/rz/ipl/rza/drivers/arm/gic/v3/gicv3_private.h new file mode 100644 index 00000000..416cdd01 --- /dev/null +++ b/drivers/rz/ipl/rza/drivers/arm/gic/v3/gicv3_private.h @@ -0,0 +1,705 @@ +/* + * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef GICV3_PRIVATE_H +#define GICV3_PRIVATE_H + +#include +#include + +#include +#include +#include + +#include "../common/gic_common_private.h" + +/******************************************************************************* + * GICv3 private macro definitions + ******************************************************************************/ + +/* Constants to indicate the status of the RWP bit */ +#define RWP_TRUE U(1) +#define RWP_FALSE U(0) + +/* Calculate GIC register bit number corresponding to its interrupt ID */ +#define BIT_NUM(REG, id) \ + ((id) & ((1U << REG##R_SHIFT) - 1U)) + +/* + * Calculate 8, 32 and 64-bit GICD register offset + * corresponding to its interrupt ID + */ +#if GIC_EXT_INTID + /* GICv3.1 */ +#define GICD_OFFSET_8(REG, id) \ + (((id) <= MAX_SPI_ID) ? \ + GICD_##REG##R + (uintptr_t)(id) : \ + GICD_##REG##RE + (uintptr_t)(id) - MIN_ESPI_ID) + +#define GICD_OFFSET(REG, id) \ + (((id) <= MAX_SPI_ID) ? \ + GICD_##REG##R + (((uintptr_t)(id) >> REG##R_SHIFT) << 2) : \ + GICD_##REG##RE + ((((uintptr_t)(id) - MIN_ESPI_ID) >> \ + REG##R_SHIFT) << 2)) + +#define GICD_OFFSET_64(REG, id) \ + (((id) <= MAX_SPI_ID) ? \ + GICD_##REG##R + (((uintptr_t)(id) >> REG##R_SHIFT) << 3) : \ + GICD_##REG##RE + ((((uintptr_t)(id) - MIN_ESPI_ID) >> \ + REG##R_SHIFT) << 3)) + +#else /* GICv3 */ +#define GICD_OFFSET_8(REG, id) \ + (GICD_##REG##R + (uintptr_t)(id)) + +#define GICD_OFFSET(REG, id) \ + (GICD_##REG##R + (((uintptr_t)(id) >> REG##R_SHIFT) << 2)) + +#define GICD_OFFSET_64(REG, id) \ + (GICD_##REG##R + (((uintptr_t)(id) >> REG##R_SHIFT) << 3)) +#endif /* GIC_EXT_INTID */ + +/* + * Read/Write 8, 32 and 64-bit GIC Distributor register + * corresponding to its interrupt ID + */ +#define GICD_READ(REG, base, id) \ + mmio_read_32((base) + GICD_OFFSET(REG, (id))) + +#define GICD_READ_64(REG, base, id) \ + mmio_read_64((base) + GICD_OFFSET_64(REG, (id))) + +#define GICD_WRITE_8(REG, base, id, val) \ + mmio_write_8((base) + GICD_OFFSET_8(REG, (id)), (val)) + +#define GICD_WRITE(REG, base, id, val) \ + mmio_write_32((base) + GICD_OFFSET(REG, (id)), (val)) + +#define GICD_WRITE_64(REG, base, id, val) \ + mmio_write_64((base) + GICD_OFFSET_64(REG, (id)), (val)) + +/* + * Bit operations on GIC Distributor register corresponding + * to its interrupt ID + */ +/* Get bit in GIC Distributor register */ +#define GICD_GET_BIT(REG, base, id) \ + ((mmio_read_32((base) + GICD_OFFSET(REG, (id))) >> \ + BIT_NUM(REG, (id))) & 1U) + +/* Set bit in GIC Distributor register */ +#define GICD_SET_BIT(REG, base, id) \ + mmio_setbits_32((base) + GICD_OFFSET(REG, (id)), \ + ((uint32_t)1 << BIT_NUM(REG, (id)))) + +/* Clear bit in GIC Distributor register */ +#define GICD_CLR_BIT(REG, base, id) \ + mmio_clrbits_32((base) + GICD_OFFSET(REG, (id)), \ + ((uint32_t)1 << BIT_NUM(REG, (id)))) + +/* Write bit in GIC Distributor register */ +#define GICD_WRITE_BIT(REG, base, id) \ + mmio_write_32((base) + GICD_OFFSET(REG, (id)), \ + ((uint32_t)1 << BIT_NUM(REG, (id)))) + +/* + * Calculate 8 and 32-bit GICR register offset + * corresponding to its interrupt ID + */ +#if GIC_EXT_INTID + /* GICv3.1 */ +#define GICR_OFFSET_8(REG, id) \ + (((id) <= MAX_PPI_ID) ? \ + GICR_##REG##R + (uintptr_t)(id) : \ + GICR_##REG##R + (uintptr_t)(id) - (MIN_EPPI_ID - MIN_SPI_ID)) + +#define GICR_OFFSET(REG, id) \ + (((id) <= MAX_PPI_ID) ? \ + GICR_##REG##R + (((uintptr_t)(id) >> REG##R_SHIFT) << 2) : \ + GICR_##REG##R + ((((uintptr_t)(id) - (MIN_EPPI_ID - MIN_SPI_ID))\ + >> REG##R_SHIFT) << 2)) +#else /* GICv3 */ +#define GICR_OFFSET_8(REG, id) \ + (GICR_##REG##R + (uintptr_t)(id)) + +#define GICR_OFFSET(REG, id) \ + (GICR_##REG##R + (((uintptr_t)(id) >> REG##R_SHIFT) << 2)) +#endif /* GIC_EXT_INTID */ + +/* Read/Write GIC Redistributor register corresponding to its interrupt ID */ +#define GICR_READ(REG, base, id) \ + mmio_read_32((base) + GICR_OFFSET(REG, (id))) + +#define GICR_WRITE_8(REG, base, id, val) \ + mmio_write_8((base) + GICR_OFFSET_8(REG, (id)), (val)) + +#define GICR_WRITE(REG, base, id, val) \ + mmio_write_32((base) + GICR_OFFSET(REG, (id)), (val)) + +/* + * Bit operations on GIC Redistributor register + * corresponding to its interrupt ID + */ +/* Get bit in GIC Redistributor register */ +#define GICR_GET_BIT(REG, base, id) \ + ((mmio_read_32((base) + GICR_OFFSET(REG, (id))) >> \ + BIT_NUM(REG, (id))) & 1U) + +/* Write bit in GIC Redistributor register */ +#define GICR_WRITE_BIT(REG, base, id) \ + mmio_write_32((base) + GICR_OFFSET(REG, (id)), \ + ((uint32_t)1 << BIT_NUM(REG, (id)))) + +/* Set bit in GIC Redistributor register */ +#define GICR_SET_BIT(REG, base, id) \ + mmio_setbits_32((base) + GICR_OFFSET(REG, (id)), \ + ((uint32_t)1 << BIT_NUM(REG, (id)))) + +/* Clear bit in GIC Redistributor register */ +#define GICR_CLR_BIT(REG, base, id) \ + mmio_clrbits_32((base) + GICR_OFFSET(REG, (id)), \ + ((uint32_t)1 << BIT_NUM(REG, (id)))) + +/* + * Macro to convert an mpidr to a value suitable for programming into a + * GICD_IROUTER. Bits[31:24] in the MPIDR are cleared as they are not relevant + * to GICv3. + */ +static inline u_register_t gicd_irouter_val_from_mpidr(u_register_t mpidr, + unsigned int irm) +{ + return (mpidr & ~(U(0xff) << 24)) | + ((irm & IROUTER_IRM_MASK) << IROUTER_IRM_SHIFT); +} + +/* + * Macro to convert a GICR_TYPER affinity value into a MPIDR value. Bits[31:24] + * are zeroes. + */ +#ifdef __aarch64__ +static inline u_register_t mpidr_from_gicr_typer(uint64_t typer_val) +{ + return (((typer_val >> 56) & MPIDR_AFFLVL_MASK) << MPIDR_AFF3_SHIFT) | + ((typer_val >> 32) & U(0xffffff)); +} +#else +static inline u_register_t mpidr_from_gicr_typer(uint64_t typer_val) +{ + return (((typer_val) >> 32) & U(0xffffff)); +} +#endif + +/******************************************************************************* + * GICv3 private global variables declarations + ******************************************************************************/ +extern const gicv3_driver_data_t *gicv3_driver_data; + +/******************************************************************************* + * Private GICv3 function prototypes for accessing entire registers. + * Note: The raw register values correspond to multiple interrupt IDs and + * the number of interrupt IDs involved depends on the register accessed. + ******************************************************************************/ +unsigned int gicd_read_igrpmodr(uintptr_t base, unsigned int id); +unsigned int gicr_read_ipriorityr(uintptr_t base, unsigned int id); +void gicd_write_igrpmodr(uintptr_t base, unsigned int id, unsigned int val); +void gicr_write_ipriorityr(uintptr_t base, unsigned int id, unsigned int val); + +/******************************************************************************* + * Private GICv3 function prototypes for accessing the GIC registers + * corresponding to a single interrupt ID. These functions use bitwise + * operations or appropriate register accesses to modify or return + * the bit-field corresponding the single interrupt ID. + ******************************************************************************/ +unsigned int gicd_get_igrpmodr(uintptr_t base, unsigned int id); +unsigned int gicr_get_igrpmodr(uintptr_t base, unsigned int id); +unsigned int gicr_get_igroupr(uintptr_t base, unsigned int id); +unsigned int gicr_get_isactiver(uintptr_t base, unsigned int id); +void gicd_set_igrpmodr(uintptr_t base, unsigned int id); +void gicr_set_igrpmodr(uintptr_t base, unsigned int id); +void gicr_set_isenabler(uintptr_t base, unsigned int id); +void gicr_set_icenabler(uintptr_t base, unsigned int id); +void gicr_set_ispendr(uintptr_t base, unsigned int id); +void gicr_set_icpendr(uintptr_t base, unsigned int id); +void gicr_set_igroupr(uintptr_t base, unsigned int id); +void gicd_clr_igrpmodr(uintptr_t base, unsigned int id); +void gicr_clr_igrpmodr(uintptr_t base, unsigned int id); +void gicr_clr_igroupr(uintptr_t base, unsigned int id); +void gicr_set_ipriorityr(uintptr_t base, unsigned int id, unsigned int pri); +void gicr_set_icfgr(uintptr_t base, unsigned int id, unsigned int cfg); + +/******************************************************************************* + * Private GICv3 helper function prototypes + ******************************************************************************/ +void gicv3_spis_config_defaults(uintptr_t gicd_base); +void gicv3_ppi_sgi_config_defaults(uintptr_t gicr_base); +unsigned int gicv3_secure_ppi_sgi_config_props(uintptr_t gicr_base, + const interrupt_prop_t *interrupt_props, + unsigned int interrupt_props_num); +unsigned int gicv3_secure_spis_config_props(uintptr_t gicd_base, + const interrupt_prop_t *interrupt_props, + unsigned int interrupt_props_num); +void gicv3_rdistif_base_addrs_probe(uintptr_t *rdistif_base_addrs, + unsigned int rdistif_num, + uintptr_t gicr_base, + mpidr_hash_fn mpidr_to_core_pos); +void gicv3_rdistif_mark_core_awake(uintptr_t gicr_base); +void gicv3_rdistif_mark_core_asleep(uintptr_t gicr_base); + +/******************************************************************************* + * GIC Distributor interface accessors + ******************************************************************************/ +/* + * Wait for updates to: + * GICD_CTLR[2:0] - the Group Enables + * GICD_CTLR[7:4] - the ARE bits, E1NWF bit and DS bit + * GICD_ICENABLER - the clearing of enable state for SPIs + */ +static inline void gicd_wait_for_pending_write(uintptr_t gicd_base) +{ + while ((gicd_read_ctlr(gicd_base) & GICD_CTLR_RWP_BIT) != 0U) { + } +} + +static inline uint32_t gicd_read_pidr2(uintptr_t base) +{ + return mmio_read_32(base + GICD_PIDR2_GICV3); +} + +static inline uint64_t gicd_read_irouter(uintptr_t base, unsigned int id) +{ + assert(id >= MIN_SPI_ID); + return GICD_READ_64(IROUTE, base, id); +} + +static inline void gicd_write_irouter(uintptr_t base, + unsigned int id, + uint64_t affinity) +{ + assert(id >= MIN_SPI_ID); + GICD_WRITE_64(IROUTE, base, id, affinity); +} + +static inline void gicd_clr_ctlr(uintptr_t base, + unsigned int bitmap, + unsigned int rwp) +{ + gicd_write_ctlr(base, gicd_read_ctlr(base) & ~bitmap); + if (rwp != 0U) { + gicd_wait_for_pending_write(base); + } +} + +static inline void gicd_set_ctlr(uintptr_t base, + unsigned int bitmap, + unsigned int rwp) +{ + gicd_write_ctlr(base, gicd_read_ctlr(base) | bitmap); + if (rwp != 0U) { + gicd_wait_for_pending_write(base); + } +} + +/******************************************************************************* + * GIC Redistributor interface accessors + ******************************************************************************/ +static inline uint32_t gicr_read_ctlr(uintptr_t base) +{ + return mmio_read_32(base + GICR_CTLR); +} + +static inline void gicr_write_ctlr(uintptr_t base, uint32_t val) +{ + mmio_write_32(base + GICR_CTLR, val); +} + +static inline uint64_t gicr_read_typer(uintptr_t base) +{ + return mmio_read_64(base + GICR_TYPER); +} + +static inline uint32_t gicr_read_waker(uintptr_t base) +{ + return mmio_read_32(base + GICR_WAKER); +} + +static inline void gicr_write_waker(uintptr_t base, uint32_t val) +{ + mmio_write_32(base + GICR_WAKER, val); +} + +/* + * Wait for updates to: + * GICR_ICENABLER0 + * GICR_CTLR.DPG1S + * GICR_CTLR.DPG1NS + * GICR_CTLR.DPG0 + * GICR_CTLR, which clears EnableLPIs from 1 to 0 + */ +static inline void gicr_wait_for_pending_write(uintptr_t gicr_base) +{ + while ((gicr_read_ctlr(gicr_base) & GICR_CTLR_RWP_BIT) != 0U) { + } +} + +static inline void gicr_wait_for_upstream_pending_write(uintptr_t gicr_base) +{ + while ((gicr_read_ctlr(gicr_base) & GICR_CTLR_UWP_BIT) != 0U) { + } +} + +/* Private implementation of Distributor power control hooks */ +void arm_gicv3_distif_pre_save(unsigned int rdist_proc_num); +void arm_gicv3_distif_post_restore(unsigned int rdist_proc_num); + +/******************************************************************************* + * GIC Redistributor functions for accessing entire registers. + * Note: The raw register values correspond to multiple interrupt IDs and + * the number of interrupt IDs involved depends on the register accessed. + ******************************************************************************/ + +/* + * Accessors to read/write GIC Redistributor ICENABLER0 register + */ +static inline unsigned int gicr_read_icenabler0(uintptr_t base) +{ + return mmio_read_32(base + GICR_ICENABLER0); +} + +static inline void gicr_write_icenabler0(uintptr_t base, unsigned int val) +{ + mmio_write_32(base + GICR_ICENABLER0, val); +} + +/* + * Accessors to read/write GIC Redistributor ICENABLER0 and ICENABLERE + * register corresponding to its number + */ +static inline unsigned int gicr_read_icenabler(uintptr_t base, + unsigned int reg_num) +{ + return mmio_read_32(base + GICR_ICENABLER + (reg_num << 2)); +} + +static inline void gicr_write_icenabler(uintptr_t base, unsigned int reg_num, + unsigned int val) +{ + mmio_write_32(base + GICR_ICENABLER + (reg_num << 2), val); +} + +/* + * Accessors to read/write GIC Redistributor ICFGR0, ICFGR1 registers + */ +static inline unsigned int gicr_read_icfgr0(uintptr_t base) +{ + return mmio_read_32(base + GICR_ICFGR0); +} + +static inline unsigned int gicr_read_icfgr1(uintptr_t base) +{ + return mmio_read_32(base + GICR_ICFGR1); +} + +static inline void gicr_write_icfgr0(uintptr_t base, unsigned int val) +{ + mmio_write_32(base + GICR_ICFGR0, val); +} + +static inline void gicr_write_icfgr1(uintptr_t base, unsigned int val) +{ + mmio_write_32(base + GICR_ICFGR1, val); +} + +/* + * Accessors to read/write GIC Redistributor ICFGR0, ICFGR1 and ICFGRE + * register corresponding to its number + */ +static inline unsigned int gicr_read_icfgr(uintptr_t base, unsigned int reg_num) +{ + return mmio_read_32(base + GICR_ICFGR + (reg_num << 2)); +} + +static inline void gicr_write_icfgr(uintptr_t base, unsigned int reg_num, + unsigned int val) +{ + mmio_write_32(base + GICR_ICFGR + (reg_num << 2), val); +} + +/* + * Accessor to write GIC Redistributor ICPENDR0 register + */ +static inline void gicr_write_icpendr0(uintptr_t base, unsigned int val) +{ + mmio_write_32(base + GICR_ICPENDR0, val); +} + +/* + * Accessor to write GIC Redistributor ICPENDR0 and ICPENDRE + * register corresponding to its number + */ +static inline void gicr_write_icpendr(uintptr_t base, unsigned int reg_num, + unsigned int val) +{ + mmio_write_32(base + GICR_ICPENDR + (reg_num << 2), val); +} + +/* + * Accessors to read/write GIC Redistributor IGROUPR0 register + */ +static inline unsigned int gicr_read_igroupr0(uintptr_t base) +{ + return mmio_read_32(base + GICR_IGROUPR0); +} + +static inline void gicr_write_igroupr0(uintptr_t base, unsigned int val) +{ + mmio_write_32(base + GICR_IGROUPR0, val); +} + +/* + * Accessors to read/write GIC Redistributor IGROUPR0 and IGROUPRE + * register corresponding to its number + */ +static inline unsigned int gicr_read_igroupr(uintptr_t base, + unsigned int reg_num) +{ + return mmio_read_32(base + GICR_IGROUPR + (reg_num << 2)); +} + +static inline void gicr_write_igroupr(uintptr_t base, unsigned int reg_num, + unsigned int val) +{ + mmio_write_32(base + GICR_IGROUPR + (reg_num << 2), val); +} + +/* + * Accessors to read/write GIC Redistributor IGRPMODR0 register + */ +static inline unsigned int gicr_read_igrpmodr0(uintptr_t base) +{ + return mmio_read_32(base + GICR_IGRPMODR0); +} + +static inline void gicr_write_igrpmodr0(uintptr_t base, unsigned int val) +{ + mmio_write_32(base + GICR_IGRPMODR0, val); +} + +/* + * Accessors to read/write GIC Redistributor IGRPMODR0 and IGRPMODRE + * register corresponding to its number + */ +static inline unsigned int gicr_read_igrpmodr(uintptr_t base, + unsigned int reg_num) +{ + return mmio_read_32(base + GICR_IGRPMODR + (reg_num << 2)); +} + +static inline void gicr_write_igrpmodr(uintptr_t base, unsigned int reg_num, + unsigned int val) +{ + mmio_write_32(base + GICR_IGRPMODR + (reg_num << 2), val); +} + +/* + * Accessors to read/write the GIC Redistributor IPRIORITYR(E) register + * corresponding to its number, 4 interrupts IDs at a time. + */ +static inline unsigned int gicr_ipriorityr_read(uintptr_t base, + unsigned int reg_num) +{ + return mmio_read_32(base + GICR_IPRIORITYR + (reg_num << 2)); +} + +static inline void gicr_ipriorityr_write(uintptr_t base, unsigned int reg_num, + unsigned int val) +{ + mmio_write_32(base + GICR_IPRIORITYR + (reg_num << 2), val); +} + +/* + * Accessors to read/write GIC Redistributor ISACTIVER0 register + */ +static inline unsigned int gicr_read_isactiver0(uintptr_t base) +{ + return mmio_read_32(base + GICR_ISACTIVER0); +} + +static inline void gicr_write_isactiver0(uintptr_t base, unsigned int val) +{ + mmio_write_32(base + GICR_ISACTIVER0, val); +} + +/* + * Accessors to read/write GIC Redistributor ISACTIVER0 and ISACTIVERE + * register corresponding to its number + */ +static inline unsigned int gicr_read_isactiver(uintptr_t base, + unsigned int reg_num) +{ + return mmio_read_32(base + GICR_ISACTIVER + (reg_num << 2)); +} + +static inline void gicr_write_isactiver(uintptr_t base, unsigned int reg_num, + unsigned int val) +{ + mmio_write_32(base + GICR_ISACTIVER + (reg_num << 2), val); +} + +/* + * Accessors to read/write GIC Redistributor ISENABLER0 register + */ +static inline unsigned int gicr_read_isenabler0(uintptr_t base) +{ + return mmio_read_32(base + GICR_ISENABLER0); +} + +static inline void gicr_write_isenabler0(uintptr_t base, unsigned int val) +{ + mmio_write_32(base + GICR_ISENABLER0, val); +} + +/* + * Accessors to read/write GIC Redistributor ISENABLER0 and ISENABLERE + * register corresponding to its number + */ +static inline unsigned int gicr_read_isenabler(uintptr_t base, + unsigned int reg_num) +{ + return mmio_read_32(base + GICR_ISENABLER + (reg_num << 2)); +} + +static inline void gicr_write_isenabler(uintptr_t base, unsigned int reg_num, + unsigned int val) +{ + mmio_write_32(base + GICR_ISENABLER + (reg_num << 2), val); +} + +/* + * Accessors to read/write GIC Redistributor ISPENDR0 register + */ +static inline unsigned int gicr_read_ispendr0(uintptr_t base) +{ + return mmio_read_32(base + GICR_ISPENDR0); +} + +static inline void gicr_write_ispendr0(uintptr_t base, unsigned int val) +{ + mmio_write_32(base + GICR_ISPENDR0, val); +} + +/* + * Accessors to read/write GIC Redistributor ISPENDR0 and ISPENDRE + * register corresponding to its number + */ +static inline unsigned int gicr_read_ispendr(uintptr_t base, + unsigned int reg_num) +{ + return mmio_read_32(base + GICR_ISPENDR + (reg_num << 2)); +} + +static inline void gicr_write_ispendr(uintptr_t base, unsigned int reg_num, + unsigned int val) +{ + mmio_write_32(base + GICR_ISPENDR + (reg_num << 2), val); +} + +/* + * Accessors to read/write GIC Redistributor NSACR register + */ +static inline unsigned int gicr_read_nsacr(uintptr_t base) +{ + return mmio_read_32(base + GICR_NSACR); +} + +static inline void gicr_write_nsacr(uintptr_t base, unsigned int val) +{ + mmio_write_32(base + GICR_NSACR, val); +} + +/* + * Accessors to read/write GIC Redistributor PROPBASER register + */ +static inline uint64_t gicr_read_propbaser(uintptr_t base) +{ + return mmio_read_64(base + GICR_PROPBASER); +} + +static inline void gicr_write_propbaser(uintptr_t base, uint64_t val) +{ + mmio_write_64(base + GICR_PROPBASER, val); +} + +/* + * Accessors to read/write GIC Redistributor PENDBASER register + */ +static inline uint64_t gicr_read_pendbaser(uintptr_t base) +{ + return mmio_read_64(base + GICR_PENDBASER); +} + +static inline void gicr_write_pendbaser(uintptr_t base, uint64_t val) +{ + mmio_write_64(base + GICR_PENDBASER, val); +} + +/******************************************************************************* + * GIC ITS functions to read and write entire ITS registers. + ******************************************************************************/ +static inline uint32_t gits_read_ctlr(uintptr_t base) +{ + return mmio_read_32(base + GITS_CTLR); +} + +static inline void gits_write_ctlr(uintptr_t base, uint32_t val) +{ + mmio_write_32(base + GITS_CTLR, val); +} + +static inline uint64_t gits_read_cbaser(uintptr_t base) +{ + return mmio_read_64(base + GITS_CBASER); +} + +static inline void gits_write_cbaser(uintptr_t base, uint64_t val) +{ + mmio_write_64(base + GITS_CBASER, val); +} + +static inline uint64_t gits_read_cwriter(uintptr_t base) +{ + return mmio_read_64(base + GITS_CWRITER); +} + +static inline void gits_write_cwriter(uintptr_t base, uint64_t val) +{ + mmio_write_64(base + GITS_CWRITER, val); +} + +static inline uint64_t gits_read_baser(uintptr_t base, + unsigned int its_table_id) +{ + assert(its_table_id < 8U); + return mmio_read_64(base + GITS_BASER + (8U * its_table_id)); +} + +static inline void gits_write_baser(uintptr_t base, unsigned int its_table_id, + uint64_t val) +{ + assert(its_table_id < 8U); + mmio_write_64(base + GITS_BASER + (8U * its_table_id), val); +} + +/* + * Wait for Quiescent bit when GIC ITS is disabled + */ +static inline void gits_wait_for_quiescent_bit(uintptr_t gits_base) +{ + assert((gits_read_ctlr(gits_base) & GITS_CTLR_ENABLED_BIT) == 0U); + while ((gits_read_ctlr(gits_base) & GITS_CTLR_QUIESCENT_BIT) == 0U) { + } +} + +#endif /* GICV3_PRIVATE_H */ diff --git a/drivers/rz/ipl/rza/drivers/arm/tzc/tzc400.c b/drivers/rz/ipl/rza/drivers/arm/tzc/tzc400.c new file mode 100644 index 00000000..9fc1578a --- /dev/null +++ b/drivers/rz/ipl/rza/drivers/arm/tzc/tzc400.c @@ -0,0 +1,342 @@ +/* + * Copyright (c) 2016-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include + +#include "tzc_common_private.h" + +/* + * Macros which will be used by common core functions. + */ +#define TZC_400_REGION_BASE_LOW_0_OFFSET U(0x100) +#define TZC_400_REGION_BASE_HIGH_0_OFFSET U(0x104) +#define TZC_400_REGION_TOP_LOW_0_OFFSET U(0x108) +#define TZC_400_REGION_TOP_HIGH_0_OFFSET U(0x10c) +#define TZC_400_REGION_ATTR_0_OFFSET U(0x110) +#define TZC_400_REGION_ID_ACCESS_0_OFFSET U(0x114) + +/* + * Implementation defined values used to validate inputs later. + * Filters : max of 4 ; 0 to 3 + * Regions : max of 9 ; 0 to 8 + * Address width : Values between 32 to 64 + */ +typedef struct tzc400_instance { + uintptr_t base; + uint8_t addr_width; + uint8_t num_filters; + uint8_t num_regions; +} tzc400_instance_t; + +static tzc400_instance_t tzc400; + +static inline unsigned int _tzc400_read_build_config(uintptr_t base) +{ + return mmio_read_32(base + BUILD_CONFIG_OFF); +} + +static inline unsigned int _tzc400_read_gate_keeper(uintptr_t base) +{ + return mmio_read_32(base + GATE_KEEPER_OFF); +} + +static inline void _tzc400_write_gate_keeper(uintptr_t base, unsigned int val) +{ + mmio_write_32(base + GATE_KEEPER_OFF, val); +} + +/* + * Get the open status information for all filter units. + */ +#define get_gate_keeper_os(_base) ((_tzc400_read_gate_keeper(_base) >> \ + GATE_KEEPER_OS_SHIFT) & \ + GATE_KEEPER_OS_MASK) + + +/* Define common core functions used across different TZC peripherals. */ +DEFINE_TZC_COMMON_WRITE_ACTION(400, 400) +DEFINE_TZC_COMMON_WRITE_REGION_BASE(400, 400) +DEFINE_TZC_COMMON_WRITE_REGION_TOP(400, 400) +DEFINE_TZC_COMMON_WRITE_REGION_ATTRIBUTES(400, 400) +DEFINE_TZC_COMMON_WRITE_REGION_ID_ACCESS(400, 400) +DEFINE_TZC_COMMON_CONFIGURE_REGION0(400) +DEFINE_TZC_COMMON_CONFIGURE_REGION(400) + +static void _tzc400_clear_it(uintptr_t base, uint32_t filter) +{ + mmio_write_32(base + INT_CLEAR, BIT_32(filter)); +} + +static uint32_t _tzc400_get_int_by_filter(uintptr_t base, uint32_t filter) +{ + return mmio_read_32(base + INT_STATUS) & BIT_32(filter); +} + +#if DEBUG +static unsigned long _tzc400_get_fail_address(uintptr_t base, uint32_t filter) +{ + unsigned long fail_address; + + fail_address = mmio_read_32(base + FAIL_ADDRESS_LOW_OFF + + (filter * FILTER_OFFSET)); +#ifdef __aarch64__ + fail_address += (unsigned long)mmio_read_32(base + FAIL_ADDRESS_HIGH_OFF + + (filter * FILTER_OFFSET)) << 32; +#endif + + return fail_address; +} + +static uint32_t _tzc400_get_fail_id(uintptr_t base, uint32_t filter) +{ + return mmio_read_32(base + FAIL_ID + (filter * FILTER_OFFSET)); +} + +static uint32_t _tzc400_get_fail_control(uintptr_t base, uint32_t filter) +{ + return mmio_read_32(base + FAIL_CONTROL_OFF + (filter * FILTER_OFFSET)); +} + +static void _tzc400_dump_fail_filter(uintptr_t base, uint32_t filter) +{ + uint32_t control_fail; + uint32_t fail_id; + unsigned long address_fail; + + address_fail = _tzc400_get_fail_address(base, filter); + ERROR("Illegal access to 0x%lx:\n", address_fail); + + fail_id = _tzc400_get_fail_id(base, filter); + ERROR("\tFAIL_ID = 0x%x\n", fail_id); + + control_fail = _tzc400_get_fail_control(base, filter); + if (((control_fail & BIT_32(FAIL_CONTROL_NS_SHIFT)) >> FAIL_CONTROL_NS_SHIFT) == + FAIL_CONTROL_NS_NONSECURE) { + ERROR("\tNon-Secure\n"); + } else { + ERROR("\tSecure\n"); + } + + if (((control_fail & BIT_32(FAIL_CONTROL_PRIV_SHIFT)) >> FAIL_CONTROL_PRIV_SHIFT) == + FAIL_CONTROL_PRIV_PRIV) { + ERROR("\tPrivilege\n"); + } else { + ERROR("\tUnprivilege\n"); + } + + if (((control_fail & BIT_32(FAIL_CONTROL_DIR_SHIFT)) >> FAIL_CONTROL_DIR_SHIFT) == + FAIL_CONTROL_DIR_WRITE) { + ERROR("\tWrite\n"); + } else { + ERROR("\tRead\n"); + } +} +#endif /* DEBUG */ + +static unsigned int _tzc400_get_gate_keeper(uintptr_t base, + unsigned int filter) +{ + unsigned int open_status; + + open_status = get_gate_keeper_os(base); + + return (open_status >> filter) & GATE_KEEPER_FILTER_MASK; +} + +/* This function is not MP safe. */ +static void _tzc400_set_gate_keeper(uintptr_t base, + unsigned int filter, + int val) +{ + unsigned int open_status; + + /* Upper half is current state. Lower half is requested state. */ + open_status = get_gate_keeper_os(base); + + if (val != 0) + open_status |= (1UL << filter); + else + open_status &= ~(1UL << filter); + + _tzc400_write_gate_keeper(base, (open_status & GATE_KEEPER_OR_MASK) << + GATE_KEEPER_OR_SHIFT); + + /* Wait here until we see the change reflected in the TZC status. */ + while ((get_gate_keeper_os(base)) != open_status) + ; +} + +void tzc400_set_action(unsigned int action) +{ + assert(tzc400.base != 0U); + assert(action <= TZC_ACTION_ERR_INT); + + _tzc400_write_action(tzc400.base, action); +} + +void tzc400_init(uintptr_t base) +{ +#if DEBUG + unsigned int tzc400_id; +#endif + unsigned int tzc400_build; + + assert(base != 0U); + tzc400.base = base; + +#if DEBUG + tzc400_id = _tzc_read_peripheral_id(base); + if (tzc400_id != TZC_400_PERIPHERAL_ID) { + ERROR("TZC-400 : Wrong device ID (0x%x).\n", tzc400_id); + panic(); + } +#endif + + /* Save values we will use later. */ + tzc400_build = _tzc400_read_build_config(tzc400.base); + tzc400.num_filters = (uint8_t)((tzc400_build >> BUILD_CONFIG_NF_SHIFT) & + BUILD_CONFIG_NF_MASK) + 1U; + tzc400.addr_width = (uint8_t)((tzc400_build >> BUILD_CONFIG_AW_SHIFT) & + BUILD_CONFIG_AW_MASK) + 1U; + tzc400.num_regions = (uint8_t)((tzc400_build >> BUILD_CONFIG_NR_SHIFT) & + BUILD_CONFIG_NR_MASK) + 1U; +} + +/* + * `tzc400_configure_region0` is used to program region 0 into the TrustZone + * controller. Region 0 covers the whole address space that is not mapped + * to any other region, and is enabled on all filters; this cannot be + * changed. This function only changes the access permissions. + */ +void tzc400_configure_region0(unsigned int sec_attr, + unsigned int ns_device_access) +{ + assert(tzc400.base != 0U); + assert(sec_attr <= TZC_REGION_S_RDWR); + + _tzc400_configure_region0(tzc400.base, sec_attr, ns_device_access); +} + +/* + * `tzc400_configure_region` is used to program regions into the TrustZone + * controller. A region can be associated with more than one filter. The + * associated filters are passed in as a bitmap (bit0 = filter0), except that + * the value TZC_400_REGION_ATTR_FILTER_BIT_ALL selects all filters, based on + * the value of tzc400.num_filters. + * NOTE: + * Region 0 is special; it is preferable to use tzc400_configure_region0 + * for this region (see comment for that function). + */ +void tzc400_configure_region(unsigned int filters, + unsigned int region, + unsigned long long region_base, + unsigned long long region_top, + unsigned int sec_attr, + unsigned int nsaid_permissions) +{ + assert(tzc400.base != 0U); + + /* Adjust filter mask by real filter number */ + if (filters == TZC_400_REGION_ATTR_FILTER_BIT_ALL) { + filters = (1U << tzc400.num_filters) - 1U; + } + + /* Do range checks on filters and regions. */ + assert(((filters >> tzc400.num_filters) == 0U) && + (region < tzc400.num_regions)); + + /* + * Do address range check based on TZC configuration. A 64bit address is + * the max and expected case. + */ + assert((region_top <= (UINT64_MAX >> (64U - tzc400.addr_width))) && + (region_base < region_top)); + + /* region_base and (region_top + 1) must be 4KB aligned */ + assert(((region_base | (region_top + 1U)) & (4096U - 1U)) == 0U); + + assert(sec_attr <= TZC_REGION_S_RDWR); + + _tzc400_configure_region(tzc400.base, filters, region, region_base, + region_top, + sec_attr, nsaid_permissions); +} + +void tzc400_enable_filters(void) +{ + unsigned int state; + unsigned int filter; + + assert(tzc400.base != 0U); + + for (filter = 0U; filter < tzc400.num_filters; filter++) { + state = _tzc400_get_gate_keeper(tzc400.base, filter); + if (state != 0U) { + /* + * The TZC filter is already configured. Changing the + * programmer's view in an active system can cause + * unpredictable behavior therefore panic for now rather + * than try to determine whether this is safe in this + * instance. + * + * See the 'ARM (R) CoreLink TM TZC-400 TrustZone (R) + * Address Space Controller' Technical Reference Manual. + */ + ERROR("TZC-400 : Filter %d Gatekeeper already" + " enabled.\n", filter); + panic(); + } + _tzc400_set_gate_keeper(tzc400.base, filter, 1); + } +} + +void tzc400_disable_filters(void) +{ + unsigned int filter; + + assert(tzc400.base != 0U); + + /* + * We don't do the same state check as above as the Gatekeepers are + * disabled after reset. + */ + for (filter = 0; filter < tzc400.num_filters; filter++) + _tzc400_set_gate_keeper(tzc400.base, filter, 0); +} + +int tzc400_it_handler(void) +{ + uint32_t filter; + uint32_t filter_it_pending = tzc400.num_filters; + + assert(tzc400.base != 0U); + + for (filter = 0U; filter < tzc400.num_filters; filter++) { + if (_tzc400_get_int_by_filter(tzc400.base, filter) != 0U) { + filter_it_pending = filter; + break; + } + } + + if (filter_it_pending == tzc400.num_filters) { + ERROR("TZC-400: No interrupt pending!\n"); + return -1; + } + +#if DEBUG + _tzc400_dump_fail_filter(tzc400.base, filter_it_pending); +#endif + + _tzc400_clear_it(tzc400.base, filter_it_pending); + + return 0; +} diff --git a/drivers/rz/ipl/rza/drivers/arm/tzc/tzc_common_private.h b/drivers/rz/ipl/rza/drivers/arm/tzc/tzc_common_private.h new file mode 100644 index 00000000..1d99077a --- /dev/null +++ b/drivers/rz/ipl/rza/drivers/arm/tzc/tzc_common_private.h @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TZC_COMMON_PRIVATE_H +#define TZC_COMMON_PRIVATE_H + +#include +#include +#include +#include + +#define DEFINE_TZC_COMMON_WRITE_ACTION(fn_name, macro_name) \ + static inline void _tzc##fn_name##_write_action( \ + uintptr_t base, \ + unsigned int action) \ + { \ + mmio_write_32(base + TZC_##macro_name##_ACTION_OFF, \ + action); \ + } + +#define DEFINE_TZC_COMMON_WRITE_REGION_BASE(fn_name, macro_name) \ + static inline void _tzc##fn_name##_write_region_base( \ + uintptr_t base, \ + unsigned int region_no, \ + unsigned long long region_base) \ + { \ + mmio_write_32(base + \ + TZC_REGION_OFFSET( \ + TZC_##macro_name##_REGION_SIZE, \ + (u_register_t)region_no) + \ + TZC_##macro_name##_REGION_BASE_LOW_0_OFFSET, \ + (uint32_t)region_base); \ + mmio_write_32(base + \ + TZC_REGION_OFFSET( \ + TZC_##macro_name##_REGION_SIZE, \ + (u_register_t)region_no) + \ + TZC_##macro_name##_REGION_BASE_HIGH_0_OFFSET, \ + (uint32_t)(region_base >> 32)); \ + } + +#define DEFINE_TZC_COMMON_WRITE_REGION_TOP(fn_name, macro_name) \ + static inline void _tzc##fn_name##_write_region_top( \ + uintptr_t base, \ + unsigned int region_no, \ + unsigned long long region_top) \ + { \ + mmio_write_32(base + \ + TZC_REGION_OFFSET( \ + TZC_##macro_name##_REGION_SIZE, \ + (u_register_t)region_no) + \ + TZC_##macro_name##_REGION_TOP_LOW_0_OFFSET, \ + (uint32_t)region_top); \ + mmio_write_32(base + \ + TZC_REGION_OFFSET( \ + TZC_##macro_name##_REGION_SIZE, \ + (u_register_t)region_no) + \ + TZC_##macro_name##_REGION_TOP_HIGH_0_OFFSET, \ + (uint32_t)(region_top >> 32)); \ + } + +#define DEFINE_TZC_COMMON_WRITE_REGION_ATTRIBUTES(fn_name, macro_name) \ + static inline void _tzc##fn_name##_write_region_attributes( \ + uintptr_t base, \ + unsigned int region_no, \ + unsigned int attr) \ + { \ + mmio_write_32(base + \ + TZC_REGION_OFFSET( \ + TZC_##macro_name##_REGION_SIZE, \ + (u_register_t)region_no) + \ + TZC_##macro_name##_REGION_ATTR_0_OFFSET, \ + attr); \ + } + +#define DEFINE_TZC_COMMON_WRITE_REGION_ID_ACCESS(fn_name, macro_name) \ + static inline void _tzc##fn_name##_write_region_id_access( \ + uintptr_t base, \ + unsigned int region_no, \ + unsigned int val) \ + { \ + mmio_write_32(base + \ + TZC_REGION_OFFSET( \ + TZC_##macro_name##_REGION_SIZE, \ + (u_register_t)region_no) + \ + TZC_##macro_name##_REGION_ID_ACCESS_0_OFFSET, \ + val); \ + } + +/* + * It is used to program region 0 ATTRIBUTES and ACCESS register. + */ +#define DEFINE_TZC_COMMON_CONFIGURE_REGION0(fn_name) \ + static void _tzc##fn_name##_configure_region0(uintptr_t base, \ + unsigned int sec_attr, \ + unsigned int ns_device_access) \ + { \ + assert(base != 0U); \ + VERBOSE("TrustZone : Configuring region 0 " \ + "(TZC Interface Base=0x%lx sec_attr=0x%x," \ + " ns_devs=0x%x)\n", base, \ + sec_attr, ns_device_access); \ + \ + /* Set secure attributes on region 0 */ \ + _tzc##fn_name##_write_region_attributes(base, 0, \ + sec_attr << TZC_REGION_ATTR_SEC_SHIFT); \ + \ + /***************************************************/ \ + /* Specify which non-secure devices have permission*/ \ + /* to access region 0. */ \ + /***************************************************/ \ + _tzc##fn_name##_write_region_id_access(base, \ + 0, \ + ns_device_access); \ + } + +/* + * It is used to program a region from 1 to 8 in the TrustZone controller. + * NOTE: + * Region 0 is special; it is preferable to use + * ##fn_name##_configure_region0 for this region (see comment for + * that function). + */ +#define DEFINE_TZC_COMMON_CONFIGURE_REGION(fn_name) \ + static void _tzc##fn_name##_configure_region(uintptr_t base, \ + unsigned int filters, \ + unsigned int region_no, \ + unsigned long long region_base, \ + unsigned long long region_top, \ + unsigned int sec_attr, \ + unsigned int nsaid_permissions) \ + { \ + assert(base != 0U); \ + VERBOSE("TrustZone : Configuring region " \ + "(TZC Interface Base: 0x%lx, region_no = %u)" \ + "...\n", base, region_no); \ + VERBOSE("TrustZone : ... base = %llx, top = %llx," \ + "\n", region_base, region_top); \ + VERBOSE("TrustZone : ... sec_attr = 0x%x," \ + " ns_devs = 0x%x)\n", \ + sec_attr, nsaid_permissions); \ + \ + /***************************************************/ \ + /* Inputs look ok, start programming registers. */ \ + /* All the address registers are 32 bits wide and */ \ + /* have a LOW and HIGH */ \ + /* component used to construct an address up to a */ \ + /* 64bit. */ \ + /***************************************************/ \ + _tzc##fn_name##_write_region_base(base, \ + region_no, region_base); \ + _tzc##fn_name##_write_region_top(base, \ + region_no, region_top); \ + \ + /* Enable filter to the region and set secure attributes */\ + _tzc##fn_name##_write_region_attributes(base, \ + region_no, \ + (sec_attr << TZC_REGION_ATTR_SEC_SHIFT) |\ + (filters << TZC_REGION_ATTR_F_EN_SHIFT));\ + \ + /***************************************************/ \ + /* Specify which non-secure devices have permission*/ \ + /* to access this region. */ \ + /***************************************************/ \ + _tzc##fn_name##_write_region_id_access(base, \ + region_no, \ + nsaid_permissions); \ + } + +static inline unsigned int _tzc_read_peripheral_id(uintptr_t base) +{ + unsigned int id; + + id = mmio_read_32(base + PID0_OFF); + /* Masks DESC part in PID1 */ + id |= ((mmio_read_32(base + PID1_OFF) & 0xFU) << 8U); + + return id; +} + +#endif /* TZC_COMMON_PRIVATE_H */ diff --git a/drivers/rz/ipl/rza/drivers/console/aarch64/skeleton_console.S b/drivers/rz/ipl/rza/drivers/console/aarch64/skeleton_console.S new file mode 100644 index 00000000..7ea2eec9 --- /dev/null +++ b/drivers/rz/ipl/rza/drivers/console/aarch64/skeleton_console.S @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include +#include + + /* + * This file contains a skeleton console driver that can be used as a + * basis for a real console driver. Console drivers in Trusted Firmware + * can be instantiated multiple times. Each instance is described by a + * separate console_t structure which must be registered with the common + * console framework via console_register(). Console drivers should + * define a console_xxx_register() function that initializes a new + * console_t structure passed in from the caller and registers it after + * initializing the console hardware. Drivers may define their own + * structures extending console_t to store private driver information. + * Console drivers *MUST* ensure that the console callbacks they + * implement only change registers allowed in the clobber lists defined + * in this file. (Note that in addition to the explicit clobber lists, + * any function may always clobber the intra-procedure-call registers + * X16 and X17, but may never depend on them retaining their values + * across any function call.) + */ + + .globl console_xxx_register + .globl console_xxx_putc + .globl console_xxx_getc + .globl console_xxx_flush + + /* ----------------------------------------------- + * int console_xxx_register(console_xxx_t *console, + * ...additional parameters as desired...) + * Function to initialize and register the console. + * The caller needs to pass an empty console_xxx_t + * structure in which *MUST* be allocated in + * persistent memory (e.g. a global or static local + * variable, *NOT* on the stack). + * In : x0 - pointer to empty console_t structure + * x1 through x7: additional parameters as desired + * Out: x0 - 1 on success, 0 on error + * Clobber list : x0 - x7 + * ----------------------------------------------- + */ +func console_xxx_register + /* + * Store parameters (e.g. hardware base address) in driver-specific + * console_xxx_t structure field if they will need to be retrieved + * by later console callback (e.g. putc). + * Example: + */ + str x1, [x0, #CONSOLE_T_BASE] + str x2, [x0, #CONSOLE_T_XXX_SOME_OTHER_VALUE] + + /* + * Initialize console hardware, using x1 - x7 parameters as needed. + * Keep console_t pointer in x0 for later. + */ + + /* + * Macro to finish up registration and return (needs valid x0 + x30). + * If any of the argument is unspecified, then the corresponding + * entry in console_t is set to 0. + */ + finish_console_register xxx putc=1, getc=1, flush=1 + + /* Jump here if hardware init fails or parameters are invalid. */ +register_fail: + mov w0, #0 + ret +endfunc console_xxx_register + + /* -------------------------------------------------------- + * int console_xxx_putc(int c, console_xxx_t *console) + * Function to output a character over the console. It + * returns the character printed on success or -1 on error. + * In : w0 - character to be printed + * x1 - pointer to console_t struct + * Out: w0 - printed character on success, < 0 on error. + * Clobber list : x0, x1, x2 + * -------------------------------------------------------- + */ +func console_xxx_putc + /* + * Retrieve values we need (e.g. hardware base address) from + * console_xxx_t structure pointed to by x1. + * Example: + */ + ldr x1, [x1, #CONSOLE_T_BASE] + + /* + * Write w0 to hardware. + */ + + ret + + /* Jump here if output fails for any reason. */ +putc_error: + mov w0, #-1 + ret +endfunc console_xxx_putc + + /* --------------------------------------------- + * int console_xxx_getc(console_xxx_t *console) + * Function to get a character from the console. + * Even though console_getc() is blocking, this + * callback has to be non-blocking and always + * return immediately to allow polling multiple + * drivers concurrently. + * Returns the character grabbed on success, + * ERROR_NO_PENDING_CHAR if no character was + * available at this time, or any value + * between -2 and -127 if there was an error. + * In : x0 - pointer to console_t struct + * Out: w0 - character on success, + * ERROR_NO_PENDING_CHAR if no char, + * < -1 on error + * Clobber list : x0, x1 + * --------------------------------------------- + */ +func console_xxx_getc + /* + * Retrieve values we need (e.g. hardware base address) from + * console_xxx_t structure pointed to by x0. + * Example: + */ + ldr x1, [x0, #CONSOLE_T_BASE] + + /* + * Try to read character into w0 from hardware. + */ + + ret + + /* Jump here if there is no character available at this time. */ +getc_no_char: + mov w0, #ERROR_NO_PENDING_CHAR + ret + + /* Jump here if there was any hardware error. */ +getc_error: + mov w0, #-2 /* may pick error codes between -2 and -127 */ + ret +endfunc console_xxx_getc + + /* --------------------------------------------- + * void console_xxx_flush(console_xxx_t *console) + * Function to force a write of all buffered + * data that hasn't been output. + * In : x0 - pointer to console_xxx_t struct + * Out: void + * Clobber list : x0, x1, x2, x3, x4, x5 + * --------------------------------------------- + */ +func console_xxx_flush + /* + * Retrieve values we need (e.g. hardware base address) from + * console_xxx_t structure pointed to by x0. + * Example: + */ + ldr x1, [x0, #CONSOLE_T_BASE] + + /* + * Flush all remaining output from hardware FIFOs. Do not return until + * all data has been flushed or there was an unrecoverable error. + */ + + ret +endfunc console_xxx_flush diff --git a/drivers/rz/ipl/rza/drivers/console/multi_console.c b/drivers/rz/ipl/rza/drivers/console/multi_console.c new file mode 100644 index 00000000..08b8e9fb --- /dev/null +++ b/drivers/rz/ipl/rza/drivers/console/multi_console.c @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +console_t *console_list; +uint8_t console_state = CONSOLE_FLAG_BOOT; + +IMPORT_SYM(console_t *, __STACKS_START__, stacks_start) +IMPORT_SYM(console_t *, __STACKS_END__, stacks_end) + +int console_register(console_t *console) +{ + /* Assert that the struct is not on the stack (common mistake). */ + assert((console < stacks_start) || (console >= stacks_end)); + + /* Check that we won't make a circle in the list. */ + if (console_is_registered(console) == 1) + return 1; + + console->next = console_list; + console_list = console; + + /* Return 1 for convenient tail-calling from console_xxx_register(). */ + return 1; +} + +console_t *console_unregister(console_t *to_be_deleted) +{ + console_t **ptr; + + assert(to_be_deleted != NULL); + + for (ptr = &console_list; *ptr != NULL; ptr = &(*ptr)->next) + if (*ptr == to_be_deleted) { + *ptr = (*ptr)->next; + return to_be_deleted; + } + + return NULL; +} + +int console_is_registered(console_t *to_find) +{ + console_t *console; + + assert(to_find != NULL); + + for (console = console_list; console != NULL; console = console->next) + if (console == to_find) + return 1; + + return 0; +} + +void console_switch_state(unsigned int new_state) +{ + console_state = new_state; +} + +void console_set_scope(console_t *console, unsigned int scope) +{ + assert(console != NULL); + + console->flags = (console->flags & ~CONSOLE_FLAG_SCOPE_MASK) | scope; +} + +static int do_putc(int c, console_t *console) +{ + int ret; + + if ((c == '\n') && + ((console->flags & CONSOLE_FLAG_TRANSLATE_CRLF) != 0)) { + ret = console->putc('\r', console); + if (ret < 0) + return ret; + } + + return console->putc(c, console); +} + +int console_putc(int c) +{ + int err = ERROR_NO_VALID_CONSOLE; + console_t *console; + + for (console = console_list; console != NULL; console = console->next) + if ((console->flags & console_state) && (console->putc != NULL)) { + int ret = do_putc(c, console); + if ((err == ERROR_NO_VALID_CONSOLE) || (ret < err)) + err = ret; + } + + return err; +} + +int console_getc(void) +{ + int err = ERROR_NO_VALID_CONSOLE; + console_t *console; + + do { /* Keep polling while at least one console works correctly. */ + for (console = console_list; console != NULL; + console = console->next) + if ((console->flags & console_state) && (console->getc != NULL)) { + int ret = console->getc(console); + if (ret >= 0) + return ret; + if (err != ERROR_NO_PENDING_CHAR) + err = ret; + } + } while (err == ERROR_NO_PENDING_CHAR); + + return err; +} + +void console_flush(void) +{ + console_t *console; + + for (console = console_list; console != NULL; console = console->next) + if ((console->flags & console_state) && (console->flush != NULL)) { + console->flush(console); + } +} diff --git a/drivers/rz/ipl/rza/drivers/delay_timer/delay_timer.c b/drivers/rz/ipl/rza/drivers/delay_timer/delay_timer.c new file mode 100644 index 00000000..a3fd7bfe --- /dev/null +++ b/drivers/rz/ipl/rza/drivers/delay_timer/delay_timer.c @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include +#include + +/*********************************************************** + * The delay timer implementation + ***********************************************************/ +static const timer_ops_t *timer_ops; + +/*********************************************************** + * Delay for the given number of microseconds. The driver must + * be initialized before calling this function. + ***********************************************************/ +void udelay(uint32_t usec) +{ + assert((timer_ops != NULL) && + (timer_ops->clk_mult != 0U) && + (timer_ops->clk_div != 0U) && + (timer_ops->get_timer_value != NULL)); + + uint32_t start, delta; + uint64_t total_delta; + + assert(usec < (UINT64_MAX / timer_ops->clk_div)); + + start = timer_ops->get_timer_value(); + + /* Add an extra tick to avoid delaying less than requested. */ + total_delta = + div_round_up((uint64_t)usec * timer_ops->clk_div, + timer_ops->clk_mult) + 1U; + /* + * Precaution for the total_delta ~ UINT32_MAX and the fact that we + * cannot catch every tick of the timer. + * For example 100MHz timer over 25MHz APB will miss at least 4 ticks. + * 1000U is an arbitrary big number which is believed to be sufficient. + */ + assert(total_delta < (UINT32_MAX - 1000U)); + + do { + /* + * If the timer value wraps around, the subtraction will + * overflow and it will still give the correct result. + * delta is decreasing counter + */ + delta = start - timer_ops->get_timer_value(); + + } while (delta < total_delta); +} + +/*********************************************************** + * Delay for the given number of milliseconds. The driver must + * be initialized before calling this function. + ***********************************************************/ +void mdelay(uint32_t msec) +{ + assert((msec * 1000UL) < UINT32_MAX); + udelay(msec * 1000U); +} + +/*********************************************************** + * Initialize the timer. The fields in the provided timer + * ops pointer must be valid. + ***********************************************************/ +void timer_init(const timer_ops_t *ops_ptr) +{ + assert((ops_ptr != NULL) && + (ops_ptr->clk_mult != 0U) && + (ops_ptr->clk_div != 0U) && + (ops_ptr->get_timer_value != NULL)); + + timer_ops = ops_ptr; +} diff --git a/drivers/rz/ipl/rza/drivers/delay_timer/generic_delay_timer.c b/drivers/rz/ipl/rza/drivers/delay_timer/generic_delay_timer.c new file mode 100644 index 00000000..ca522e05 --- /dev/null +++ b/drivers/rz/ipl/rza/drivers/delay_timer/generic_delay_timer.c @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2020, NVIDIA Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +static timer_ops_t ops; + +static uint32_t get_timer_value(void) +{ + /* + * Generic delay timer implementation expects the timer to be a down + * counter. We apply bitwise NOT operator to the tick values returned + * by read_cntpct_el0() to simulate the down counter. The value is + * clipped from 64 to 32 bits. + */ + return (uint32_t)(~read_cntpct_el0()); +} + +void generic_delay_timer_init_args(uint32_t mult, uint32_t div) +{ + ops.get_timer_value = get_timer_value; + ops.clk_mult = mult; + ops.clk_div = div; + + timer_init(&ops); + + VERBOSE("Generic delay timer configured with mult=%u and div=%u\n", + mult, div); +} + +void generic_delay_timer_init(void) +{ + assert(is_armv7_gentimer_present()); + + /* Value in ticks */ + unsigned int mult = MHZ_TICKS_PER_SEC; + + /* Value in ticks per second (Hz) */ + unsigned int div = plat_get_syscnt_freq2(); + + /* Reduce multiplier and divider by dividing them repeatedly by 10 */ + while (((mult % 10U) == 0U) && ((div % 10U) == 0U)) { + mult /= 10U; + div /= 10U; + } + + generic_delay_timer_init_args(mult, div); +} + diff --git a/drivers/rz/ipl/rza/drivers/io/io_block.c b/drivers/rz/ipl/rza/drivers/io/io_block.c new file mode 100644 index 00000000..5d45c2f1 --- /dev/null +++ b/drivers/rz/ipl/rza/drivers/io/io_block.c @@ -0,0 +1,551 @@ +/* + * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +typedef struct { + io_block_dev_spec_t *dev_spec; + uintptr_t base; + unsigned long long file_pos; + unsigned long long size; +} block_dev_state_t; + +#define is_power_of_2(x) (((x) != 0U) && (((x) & ((x) - 1U)) == 0U)) + +io_type_t device_type_block(void); + +static int block_open(io_dev_info_t *dev_info, const uintptr_t spec, + io_entity_t *entity); +static int block_seek(io_entity_t *entity, int mode, signed long long offset); +static int block_read(io_entity_t *entity, uintptr_t buffer, size_t length, + size_t *length_read); +static int block_write(io_entity_t *entity, const uintptr_t buffer, + size_t length, size_t *length_written); +static int block_close(io_entity_t *entity); +static int block_dev_open(const uintptr_t dev_spec, io_dev_info_t **dev_info); +static int block_dev_close(io_dev_info_t *dev_info); + +static const io_dev_connector_t block_dev_connector = { + .dev_open = block_dev_open +}; + +static const io_dev_funcs_t block_dev_funcs = { + .type = device_type_block, + .open = block_open, + .seek = block_seek, + .size = NULL, + .read = block_read, + .write = block_write, + .close = block_close, + .dev_init = NULL, + .dev_close = block_dev_close, +}; + +static block_dev_state_t state_pool[MAX_IO_BLOCK_DEVICES]; +static io_dev_info_t dev_info_pool[MAX_IO_BLOCK_DEVICES]; + +/* Track number of allocated block state */ +static unsigned int block_dev_count; + +io_type_t device_type_block(void) +{ + return IO_TYPE_BLOCK; +} + +/* Locate a block state in the pool, specified by address */ +static int find_first_block_state(const io_block_dev_spec_t *dev_spec, + unsigned int *index_out) +{ + unsigned int index; + int result = -ENOENT; + + for (index = 0U; index < MAX_IO_BLOCK_DEVICES; ++index) { + /* dev_spec is used as identifier since it's unique */ + if (state_pool[index].dev_spec == dev_spec) { + result = 0; + *index_out = index; + break; + } + } + return result; +} + +/* Allocate a device info from the pool and return a pointer to it */ +static int allocate_dev_info(io_dev_info_t **dev_info) +{ + int result = -ENOMEM; + assert(dev_info != NULL); + + if (block_dev_count < MAX_IO_BLOCK_DEVICES) { + unsigned int index = 0; + result = find_first_block_state(NULL, &index); + assert(result == 0); + /* initialize dev_info */ + dev_info_pool[index].funcs = &block_dev_funcs; + dev_info_pool[index].info = (uintptr_t)&state_pool[index]; + *dev_info = &dev_info_pool[index]; + ++block_dev_count; + } + + return result; +} + + +/* Release a device info to the pool */ +static int free_dev_info(io_dev_info_t *dev_info) +{ + int result; + unsigned int index = 0; + block_dev_state_t *state; + assert(dev_info != NULL); + + state = (block_dev_state_t *)dev_info->info; + result = find_first_block_state(state->dev_spec, &index); + if (result == 0) { + /* free if device info is valid */ + zeromem(state, sizeof(block_dev_state_t)); + zeromem(dev_info, sizeof(io_dev_info_t)); + --block_dev_count; + } + + return result; +} + +static int block_open(io_dev_info_t *dev_info, const uintptr_t spec, + io_entity_t *entity) +{ + block_dev_state_t *cur; + io_block_spec_t *region; + + assert((dev_info->info != (uintptr_t)NULL) && + (spec != (uintptr_t)NULL) && + (entity->info == (uintptr_t)NULL)); + + region = (io_block_spec_t *)spec; + cur = (block_dev_state_t *)dev_info->info; + assert(((region->offset % cur->dev_spec->block_size) == 0) && + ((region->length % cur->dev_spec->block_size) == 0)); + + cur->base = region->offset; + cur->size = region->length; + cur->file_pos = 0; + + entity->info = (uintptr_t)cur; + return 0; +} + +/* parameter offset is relative address at here */ +static int block_seek(io_entity_t *entity, int mode, signed long long offset) +{ + block_dev_state_t *cur; + + assert(entity->info != (uintptr_t)NULL); + + cur = (block_dev_state_t *)entity->info; + assert((offset >= 0) && ((unsigned long long)offset < cur->size)); + + switch (mode) { + case IO_SEEK_SET: + cur->file_pos = (unsigned long long)offset; + break; + case IO_SEEK_CUR: + cur->file_pos += (unsigned long long)offset; + break; + default: + return -EINVAL; + } + assert(cur->file_pos < cur->size); + return 0; +} + +/* + * This function allows the caller to read any number of bytes + * from any position. It hides from the caller that the low level + * driver only can read aligned blocks of data. For this reason + * we need to handle the use case where the first byte to be read is not + * aligned to start of the block, the last byte to be read is also not + * aligned to the end of a block, and there are zero or more blocks-worth + * of data in between. + * + * In such a case we need to read more bytes than requested (i.e. full + * blocks) and strip-out the leading bytes (aka skip) and the trailing + * bytes (aka padding). See diagram below + * + * cur->file_pos ------------ + * | + * cur->base | + * | | + * v v<---- length ----> + * -------------------------------------------------------------- + * | | block#1 | | block#n | + * | block#0 | + | ... | + | + * | | <- skip -> + | | + <- padding ->| + * ------------------------+----------------------+-------------- + * ^ ^ + * | | + * v iteration#1 iteration#n v + * -------------------------------------------------- + * | | | | + * |<---- request ---->| ... |<----- request ---->| + * | | | | + * -------------------------------------------------- + * / / | | + * / / | | + * / / | | + * / / | | + * / / | | + * / / | | + * / / | | + * / / | | + * / / | | + * / / | | + * <---- request ------> <------ request -----> + * --------------------- ----------------------- + * | | | | | | + * |<-skip->|<-nbytes->| -------->|<-nbytes->|<-padding->| + * | | | | | | | + * --------------------- | ----------------------- + * ^ \ \ | | | + * | \ \ | | | + * | \ \ | | | + * buf->offset \ \ buf->offset | | + * \ \ | | + * \ \ | | + * \ \ | | + * \ \ | | + * \ \ | | + * \ \ | | + * \ \ | | + * -------------------------------- + * | | | | + * buffer-------------->| | ... | | + * | | | | + * -------------------------------- + * <-count#1->| | + * <---------- count#n --------> + * <---------- length ----------> + * + * Additionally, the IO driver has an underlying buffer that is at least + * one block-size and may be big enough to allow. + */ +static int block_read(io_entity_t *entity, uintptr_t buffer, size_t length, + size_t *length_read) +{ + block_dev_state_t *cur; + io_block_spec_t *buf; + io_block_ops_t *ops; + int lba; + size_t block_size, left; + size_t nbytes; /* number of bytes read in one iteration */ + size_t request; /* number of requested bytes in one iteration */ + size_t count; /* number of bytes already read */ + /* + * number of leading bytes from start of the block + * to the first byte to be read + */ + size_t skip; + + /* + * number of trailing bytes between the last byte + * to be read and the end of the block + */ + size_t padding; + + assert(entity->info != (uintptr_t)NULL); + cur = (block_dev_state_t *)entity->info; + ops = &(cur->dev_spec->ops); + buf = &(cur->dev_spec->buffer); + block_size = cur->dev_spec->block_size; + assert((length <= cur->size) && + (length > 0U) && + (ops->read != 0)); + + /* + * We don't know the number of bytes that we are going + * to read in every iteration, because it will depend + * on the low level driver. + */ + count = 0; + for (left = length; left > 0U; left -= nbytes) { + /* + * We must only request operations aligned to the block + * size. Therefore if file_pos is not block-aligned, + * we have to request the operation to start at the + * previous block boundary and skip the leading bytes. And + * similarly, the number of bytes requested must be a + * block size multiple + */ + skip = cur->file_pos & (block_size - 1U); + + /* + * Calculate the block number containing file_pos + * - e.g. block 3. + */ + lba = (cur->file_pos + cur->base) / block_size; + + if ((skip + left) > buf->length) { + /* + * The underlying read buffer is too small to + * read all the required data - limit to just + * fill the buffer, and then read again. + */ + request = buf->length; + } else { + /* + * The underlying read buffer is big enough to + * read all the required data. Calculate the + * number of bytes to read to align with the + * block size. + */ + request = skip + left; + request = (request + (block_size - 1U)) & + ~(block_size - 1U); + } + request = ops->read(lba, buf->offset, request); + + if (request <= skip) { + /* + * We couldn't read enough bytes to jump over + * the skip bytes, so we should have to read + * again the same block, thus generating + * the same error. + */ + return -EIO; + } + + /* + * Need to remove skip and padding bytes,if any, from + * the read data when copying to the user buffer. + */ + nbytes = request - skip; + padding = (nbytes > left) ? nbytes - left : 0U; + nbytes -= padding; + + memcpy((void *)(buffer + count), + (void *)(buf->offset + skip), + nbytes); + + cur->file_pos += nbytes; + count += nbytes; + } + assert(count == length); + *length_read = count; + + return 0; +} + +/* + * This function allows the caller to write any number of bytes + * from any position. It hides from the caller that the low level + * driver only can write aligned blocks of data. + * See comments for block_read for more details. + */ +static int block_write(io_entity_t *entity, const uintptr_t buffer, + size_t length, size_t *length_written) +{ + block_dev_state_t *cur; + io_block_spec_t *buf; + io_block_ops_t *ops; + int lba; + size_t block_size, left; + size_t nbytes; /* number of bytes read in one iteration */ + size_t request; /* number of requested bytes in one iteration */ + size_t count; /* number of bytes already read */ + /* + * number of leading bytes from start of the block + * to the first byte to be read + */ + size_t skip; + + /* + * number of trailing bytes between the last byte + * to be read and the end of the block + */ + size_t padding; + + assert(entity->info != (uintptr_t)NULL); + cur = (block_dev_state_t *)entity->info; + ops = &(cur->dev_spec->ops); + buf = &(cur->dev_spec->buffer); + block_size = cur->dev_spec->block_size; + assert((length <= cur->size) && + (length > 0U) && + (ops->read != 0) && + (ops->write != 0)); + + /* + * We don't know the number of bytes that we are going + * to write in every iteration, because it will depend + * on the low level driver. + */ + count = 0; + for (left = length; left > 0U; left -= nbytes) { + /* + * We must only request operations aligned to the block + * size. Therefore if file_pos is not block-aligned, + * we have to request the operation to start at the + * previous block boundary and skip the leading bytes. And + * similarly, the number of bytes requested must be a + * block size multiple + */ + skip = cur->file_pos & (block_size - 1U); + + /* + * Calculate the block number containing file_pos + * - e.g. block 3. + */ + lba = (cur->file_pos + cur->base) / block_size; + + if ((skip + left) > buf->length) { + /* + * The underlying read buffer is too small to + * read all the required data - limit to just + * fill the buffer, and then read again. + */ + request = buf->length; + } else { + /* + * The underlying read buffer is big enough to + * read all the required data. Calculate the + * number of bytes to read to align with the + * block size. + */ + request = skip + left; + request = (request + (block_size - 1U)) & + ~(block_size - 1U); + } + + /* + * The number of bytes that we are going to write + * from the user buffer will depend of the size + * of the current request. + */ + nbytes = request - skip; + padding = (nbytes > left) ? nbytes - left : 0U; + nbytes -= padding; + + /* + * If we have skip or padding bytes then we have to preserve + * some content and it means that we have to read before + * writing + */ + if ((skip > 0U) || (padding > 0U)) { + request = ops->read(lba, buf->offset, request); + /* + * The read may return size less than + * requested. Round down to the nearest block + * boundary + */ + request &= ~(block_size - 1U); + if (request <= skip) { + /* + * We couldn't read enough bytes to jump over + * the skip bytes, so we should have to read + * again the same block, thus generating + * the same error. + */ + return -EIO; + } + nbytes = request - skip; + padding = (nbytes > left) ? nbytes - left : 0U; + nbytes -= padding; + } + + memcpy((void *)(buf->offset + skip), + (void *)(buffer + count), + nbytes); + + request = ops->write(lba, buf->offset, request); + if (request <= skip) + return -EIO; + + /* + * And the previous write operation may modify the size + * of the request, so again, we have to calculate the + * number of bytes that we consumed from the user + * buffer + */ + nbytes = request - skip; + padding = (nbytes > left) ? nbytes - left : 0U; + nbytes -= padding; + + cur->file_pos += nbytes; + count += nbytes; + } + assert(count == length); + *length_written = count; + + return 0; +} + +static int block_close(io_entity_t *entity) +{ + entity->info = (uintptr_t)NULL; + return 0; +} + +static int block_dev_open(const uintptr_t dev_spec, io_dev_info_t **dev_info) +{ + block_dev_state_t *cur; + io_block_spec_t *buffer; + io_dev_info_t *info; + size_t block_size; + int result; + + assert(dev_info != NULL); + result = allocate_dev_info(&info); + if (result != 0) + return -ENOENT; + + cur = (block_dev_state_t *)info->info; + /* dev_spec is type of io_block_dev_spec_t. */ + cur->dev_spec = (io_block_dev_spec_t *)dev_spec; + buffer = &(cur->dev_spec->buffer); + block_size = cur->dev_spec->block_size; + assert((block_size > 0U) && + (is_power_of_2(block_size) != 0U) && + ((buffer->offset % block_size) == 0U) && + ((buffer->length % block_size) == 0U)); + + *dev_info = info; /* cast away const */ + (void)block_size; + (void)buffer; + return 0; +} + +static int block_dev_close(io_dev_info_t *dev_info) +{ + return free_dev_info(dev_info); +} + +/* Exported functions */ + +/* Register the Block driver with the IO abstraction */ +int register_io_dev_block(const io_dev_connector_t **dev_con) +{ + int result; + + assert(dev_con != NULL); + + /* + * Since dev_info isn't really used in io_register_device, always + * use the same device info at here instead. + */ + result = io_register_device(&dev_info_pool[0]); + if (result == 0) + *dev_con = &block_dev_connector; + return result; +} diff --git a/drivers/rz/ipl/rza/drivers/io/io_dummy.c b/drivers/rz/ipl/rza/drivers/io/io_dummy.c new file mode 100644 index 00000000..4f0cda6d --- /dev/null +++ b/drivers/rz/ipl/rza/drivers/io/io_dummy.c @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include + +struct file_state { + int in_use; + size_t size; +}; + +static struct file_state current_file = {0}; + +/* Identify the device type as dummy */ +static io_type_t device_type_dummy(void) +{ + return IO_TYPE_DUMMY; +} + +/* Dummy device functions */ +static int dummy_dev_open(const uintptr_t dev_spec, io_dev_info_t **dev_info); +static int dummy_block_open(io_dev_info_t *dev_info, const uintptr_t spec, + io_entity_t *entity); +static int dummy_block_len(io_entity_t *entity, size_t *length); +static int dummy_block_read(io_entity_t *entity, uintptr_t buffer, + size_t length, size_t *length_read); +static int dummy_block_close(io_entity_t *entity); +static int dummy_dev_close(io_dev_info_t *dev_info); + + +static const io_dev_connector_t dummy_dev_connector = { + .dev_open = dummy_dev_open +}; + + +static const io_dev_funcs_t dummy_dev_funcs = { + .type = device_type_dummy, + .open = dummy_block_open, + .seek = NULL, + .size = dummy_block_len, + .read = dummy_block_read, + .write = NULL, + .close = dummy_block_close, + .dev_init = NULL, + .dev_close = dummy_dev_close, +}; + + +static const io_dev_info_t dummy_dev_info = { + .funcs = &dummy_dev_funcs, + .info = (uintptr_t)NULL +}; + + +/* Open a connection to the dummy device */ +static int dummy_dev_open(const uintptr_t dev_spec __attribute__((unused)), + io_dev_info_t **dev_info) +{ + assert(dev_info != NULL); + *dev_info = (io_dev_info_t *)&dummy_dev_info; + + return 0; +} + + +/* Close a connection to the dummy device */ +static int dummy_dev_close(io_dev_info_t *dev_info) +{ + return 0; +} + + +/* Open a file on the dummy device */ +static int dummy_block_open(io_dev_info_t *dev_info, const uintptr_t spec, + io_entity_t *entity) +{ + int result; + const io_block_spec_t *block_spec = (io_block_spec_t *)spec; + + if (current_file.in_use == 0) { + assert(block_spec != NULL); + assert(entity != NULL); + + current_file.in_use = 1; + current_file.size = block_spec->length; + entity->info = (uintptr_t)¤t_file; + result = 0; + } else { + WARN("A Dummy device is already active. Close first.\n"); + result = -ENOMEM; + } + + return result; +} + + +/* Return the size of a file on the dummy device */ +static int dummy_block_len(io_entity_t *entity, size_t *length) +{ + assert(entity != NULL); + assert(length != NULL); + + *length = ((struct file_state *)entity->info)->size; + + return 0; +} + + +/* Read data from a file on the dummy device */ +static int dummy_block_read(io_entity_t *entity, uintptr_t buffer, + size_t length, size_t *length_read) +{ + assert(length_read != NULL); + + *length_read = length; + + return 0; +} + + +/* Close a file on the dummy device */ +static int dummy_block_close(io_entity_t *entity) +{ + assert(entity != NULL); + + entity->info = 0; + current_file.in_use = 0; + + return 0; +} + + +/* Exported functions */ + +/* Register the dummy driver with the IO abstraction */ +int register_io_dev_dummy(const io_dev_connector_t **dev_con) +{ + int result; + + assert(dev_con != NULL); + + result = io_register_device(&dummy_dev_info); + if (result == 0) + *dev_con = &dummy_dev_connector; + + return result; +} diff --git a/drivers/rz/ipl/rza/drivers/io/io_encrypted.c b/drivers/rz/ipl/rza/drivers/io/io_encrypted.c new file mode 100644 index 00000000..744ca835 --- /dev/null +++ b/drivers/rz/ipl/rza/drivers/io/io_encrypted.c @@ -0,0 +1,244 @@ +/* + * Copyright (c) 2020, Linaro Limited. All rights reserved. + * Author: Sumit Garg + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static uintptr_t backend_dev_handle; +static uintptr_t backend_dev_spec; +static uintptr_t backend_handle; +static uintptr_t backend_image_spec; + +static io_dev_info_t enc_dev_info; + +/* Encrypted firmware driver functions */ +static int enc_dev_open(const uintptr_t dev_spec, io_dev_info_t **dev_info); +static int enc_file_open(io_dev_info_t *dev_info, const uintptr_t spec, + io_entity_t *entity); +static int enc_file_len(io_entity_t *entity, size_t *length); +static int enc_file_read(io_entity_t *entity, uintptr_t buffer, size_t length, + size_t *length_read); +static int enc_file_close(io_entity_t *entity); +static int enc_dev_init(io_dev_info_t *dev_info, const uintptr_t init_params); +static int enc_dev_close(io_dev_info_t *dev_info); + +static inline int is_valid_header(struct fw_enc_hdr *header) +{ + if (header->magic == ENC_HEADER_MAGIC) + return 1; + else + return 0; +} + +static io_type_t device_type_enc(void) +{ + return IO_TYPE_ENCRYPTED; +} + +static const io_dev_connector_t enc_dev_connector = { + .dev_open = enc_dev_open +}; + +static const io_dev_funcs_t enc_dev_funcs = { + .type = device_type_enc, + .open = enc_file_open, + .seek = NULL, + .size = enc_file_len, + .read = enc_file_read, + .write = NULL, + .close = enc_file_close, + .dev_init = enc_dev_init, + .dev_close = enc_dev_close, +}; + +static int enc_dev_open(const uintptr_t dev_spec, io_dev_info_t **dev_info) +{ + assert(dev_info != NULL); + + enc_dev_info.funcs = &enc_dev_funcs; + *dev_info = &enc_dev_info; + + return 0; +} + +static int enc_dev_init(io_dev_info_t *dev_info, const uintptr_t init_params) +{ + int result; + unsigned int image_id = (unsigned int)init_params; + + /* Obtain a reference to the image by querying the platform layer */ + result = plat_get_image_source(image_id, &backend_dev_handle, + &backend_dev_spec); + if (result != 0) { + WARN("Failed to obtain reference to image id=%u (%i)\n", + image_id, result); + return -ENOENT; + } + + return result; +} + +static int enc_dev_close(io_dev_info_t *dev_info) +{ + backend_dev_handle = (uintptr_t)NULL; + backend_dev_spec = (uintptr_t)NULL; + + return 0; +} + +static int enc_file_open(io_dev_info_t *dev_info, const uintptr_t spec, + io_entity_t *entity) +{ + int result; + + assert(spec != 0); + assert(entity != NULL); + + backend_image_spec = spec; + + result = io_open(backend_dev_handle, backend_image_spec, + &backend_handle); + if (result != 0) { + WARN("Failed to open backend device (%i)\n", result); + result = -ENOENT; + } + + return result; +} + +static int enc_file_len(io_entity_t *entity, size_t *length) +{ + int result; + + assert(entity != NULL); + assert(length != NULL); + + result = io_size(backend_handle, length); + if (result != 0) { + WARN("Failed to read blob length (%i)\n", result); + return -ENOENT; + } + + /* + * Encryption header is attached at the beginning of the encrypted file + * and is not considered a part of the payload. + */ + if (*length < sizeof(struct fw_enc_hdr)) + return -EIO; + + *length -= sizeof(struct fw_enc_hdr); + + return result; +} + +static int enc_file_read(io_entity_t *entity, uintptr_t buffer, size_t length, + size_t *length_read) +{ + int result; + struct fw_enc_hdr header; + enum fw_enc_status_t fw_enc_status; + size_t bytes_read; + uint8_t key[ENC_MAX_KEY_SIZE]; + size_t key_len = sizeof(key); + unsigned int key_flags = 0; + const io_uuid_spec_t *uuid_spec = (io_uuid_spec_t *)backend_image_spec; + + assert(entity != NULL); + assert(length_read != NULL); + + result = io_read(backend_handle, (uintptr_t)&header, sizeof(header), + &bytes_read); + if (result != 0) { + WARN("Failed to read encryption header (%i)\n", result); + return -ENOENT; + } + + if (!is_valid_header(&header)) { + WARN("Encryption header check failed.\n"); + return -ENOENT; + } + + VERBOSE("Encryption header looks OK.\n"); + fw_enc_status = header.flags & FW_ENC_STATUS_FLAG_MASK; + + if ((header.iv_len > ENC_MAX_IV_SIZE) || + (header.tag_len > ENC_MAX_TAG_SIZE)) { + WARN("Incorrect IV or tag length\n"); + return -ENOENT; + } + + result = io_read(backend_handle, buffer, length, &bytes_read); + if (result != 0) { + WARN("Failed to read encrypted payload (%i)\n", result); + return -ENOENT; + } + + *length_read = bytes_read; + + result = plat_get_enc_key_info(fw_enc_status, key, &key_len, &key_flags, + (uint8_t *)&uuid_spec->uuid, + sizeof(uuid_t)); + if (result != 0) { + WARN("Failed to obtain encryption key (%i)\n", result); + return -ENOENT; + } + + result = crypto_mod_auth_decrypt(header.dec_algo, + (void *)buffer, *length_read, key, + key_len, key_flags, header.iv, + header.iv_len, header.tag, + header.tag_len); + memset(key, 0, key_len); + + if (result != 0) { + ERROR("File decryption failed (%i)\n", result); + return -ENOENT; + } + + return result; +} + +static int enc_file_close(io_entity_t *entity) +{ + io_close(backend_handle); + + backend_image_spec = (uintptr_t)NULL; + entity->info = 0; + + return 0; +} + +/* Exported functions */ + +/* Register the Encrypted Firmware driver with the IO abstraction */ +int register_io_dev_enc(const io_dev_connector_t **dev_con) +{ + int result; + + assert(dev_con != NULL); + + result = io_register_device(&enc_dev_info); + if (result == 0) + *dev_con = &enc_dev_connector; + + return result; +} diff --git a/drivers/rz/ipl/rza/drivers/io/io_fip.c b/drivers/rz/ipl/rza/drivers/io/io_fip.c new file mode 100644 index 00000000..6e152959 --- /dev/null +++ b/drivers/rz/ipl/rza/drivers/io/io_fip.c @@ -0,0 +1,481 @@ +/* + * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef MAX_FIP_DEVICES +#define MAX_FIP_DEVICES 1 +#endif + +/* Useful for printing UUIDs when debugging.*/ +#define PRINT_UUID2(x) \ + "%08x-%04hx-%04hx-%02hhx%02hhx-%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx", \ + x.time_low, x.time_mid, x.time_hi_and_version, \ + x.clock_seq_hi_and_reserved, x.clock_seq_low, \ + x.node[0], x.node[1], x.node[2], x.node[3], \ + x.node[4], x.node[5] + +typedef struct { + unsigned int file_pos; + fip_toc_entry_t entry; +} fip_file_state_t; + +/* + * Maintain dev_spec per FIP Device + * TODO - Add backend handles and file state + * per FIP device here once backends like io_memmap + * can support multiple open files + */ +typedef struct { + uintptr_t dev_spec; + uint16_t plat_toc_flag; +} fip_dev_state_t; + +/* + * Only one file can be open across all FIP device + * as backends like io_memmap don't support + * multiple open files. The file state and + * backend handle should be maintained per FIP device + * if the same support is available in the backend + */ +static fip_file_state_t current_fip_file = {0}; +static uintptr_t backend_dev_handle; +static uintptr_t backend_image_spec; + +static fip_dev_state_t state_pool[MAX_FIP_DEVICES]; +static io_dev_info_t dev_info_pool[MAX_FIP_DEVICES]; + +/* Track number of allocated fip devices */ +static unsigned int fip_dev_count; + +/* Firmware Image Package driver functions */ +static int fip_dev_open(const uintptr_t dev_spec, io_dev_info_t **dev_info); +static int fip_file_open(io_dev_info_t *dev_info, const uintptr_t spec, + io_entity_t *entity); +static int fip_file_len(io_entity_t *entity, size_t *length); +static int fip_file_read(io_entity_t *entity, uintptr_t buffer, size_t length, + size_t *length_read); +static int fip_file_close(io_entity_t *entity); +static int fip_dev_init(io_dev_info_t *dev_info, const uintptr_t init_params); +static int fip_dev_close(io_dev_info_t *dev_info); + + +/* Return 0 for equal uuids. */ +static inline int compare_uuids(const uuid_t *uuid1, const uuid_t *uuid2) +{ + return memcmp(uuid1, uuid2, sizeof(uuid_t)); +} + + +static inline int is_valid_header(fip_toc_header_t *header) +{ + if ((header->name == TOC_HEADER_NAME) && (header->serial_number != 0)) { + return 1; + } else { + return 0; + } +} + + +/* Identify the device type as a virtual driver */ +static io_type_t device_type_fip(void) +{ + return IO_TYPE_FIRMWARE_IMAGE_PACKAGE; +} + + +static const io_dev_connector_t fip_dev_connector = { + .dev_open = fip_dev_open +}; + + +static const io_dev_funcs_t fip_dev_funcs = { + .type = device_type_fip, + .open = fip_file_open, + .seek = NULL, + .size = fip_file_len, + .read = fip_file_read, + .write = NULL, + .close = fip_file_close, + .dev_init = fip_dev_init, + .dev_close = fip_dev_close, +}; + +/* Locate a file state in the pool, specified by address */ +static int find_first_fip_state(const uintptr_t dev_spec, + unsigned int *index_out) +{ + int result = -ENOENT; + unsigned int index; + + for (index = 0; index < (unsigned int)MAX_FIP_DEVICES; ++index) { + /* dev_spec is used as identifier since it's unique */ + if (state_pool[index].dev_spec == dev_spec) { + result = 0; + *index_out = index; + break; + } + } + return result; +} + + +/* Allocate a device info from the pool and return a pointer to it */ +static int allocate_dev_info(io_dev_info_t **dev_info) +{ + int result = -ENOMEM; + + assert(dev_info != NULL); + + if (fip_dev_count < (unsigned int)MAX_FIP_DEVICES) { + unsigned int index = 0; + + result = find_first_fip_state(0, &index); + assert(result == 0); + /* initialize dev_info */ + dev_info_pool[index].funcs = &fip_dev_funcs; + dev_info_pool[index].info = + (uintptr_t)&state_pool[index]; + *dev_info = &dev_info_pool[index]; + ++fip_dev_count; + } + + return result; +} + +/* Release a device info to the pool */ +static int free_dev_info(io_dev_info_t *dev_info) +{ + int result; + unsigned int index = 0; + fip_dev_state_t *state; + + assert(dev_info != NULL); + + state = (fip_dev_state_t *)dev_info->info; + result = find_first_fip_state(state->dev_spec, &index); + if (result == 0) { + /* free if device info is valid */ + zeromem(state, sizeof(fip_dev_state_t)); + --fip_dev_count; + } + + return result; +} + +/* + * Multiple FIP devices can be opened depending on the value of + * MAX_FIP_DEVICES. Given that there is only one backend, only a + * single file can be open at a time by any FIP device. + */ +static int fip_dev_open(const uintptr_t dev_spec, + io_dev_info_t **dev_info) +{ + int result; + io_dev_info_t *info; + fip_dev_state_t *state; + + assert(dev_info != NULL); +#if MAX_FIP_DEVICES > 1 + assert(dev_spec != (uintptr_t)NULL); +#endif + + result = allocate_dev_info(&info); + if (result != 0) + return -ENOMEM; + + state = (fip_dev_state_t *)info->info; + + state->dev_spec = dev_spec; + + *dev_info = info; + + return 0; +} + + +/* Do some basic package checks. */ +static int fip_dev_init(io_dev_info_t *dev_info, const uintptr_t init_params) +{ + int result; + unsigned int image_id = (unsigned int)init_params; + uintptr_t backend_handle; + fip_toc_header_t header; + size_t bytes_read; + fip_dev_state_t *state; + + assert(dev_info != NULL); + + state = (fip_dev_state_t *)dev_info->info; + + /* Obtain a reference to the image by querying the platform layer */ + result = plat_get_image_source(image_id, &backend_dev_handle, + &backend_image_spec); + if (result != 0) { + WARN("Failed to obtain reference to image id=%u (%i)\n", + image_id, result); + result = -ENOENT; + goto fip_dev_init_exit; + } + + /* Attempt to access the FIP image */ + result = io_open(backend_dev_handle, backend_image_spec, + &backend_handle); + if (result != 0) { + WARN("Failed to access image id=%u (%i)\n", image_id, result); + result = -ENOENT; + goto fip_dev_init_exit; + } + + result = io_read(backend_handle, (uintptr_t)&header, sizeof(header), + &bytes_read); + if (result == 0) { + if (!is_valid_header(&header)) { + WARN("Firmware Image Package header check failed.\n"); + result = -ENOENT; + } else { + VERBOSE("FIP header looks OK.\n"); + /* + * Store 16-bit Platform ToC flags field which occupies + * bits [32-47] in fip header. + */ + state->plat_toc_flag = (header.flags >> 32) & 0xffff; + } + } + + io_close(backend_handle); + + fip_dev_init_exit: + return result; +} + +/* Close a connection to the FIP device */ +static int fip_dev_close(io_dev_info_t *dev_info) +{ + /* TODO: Consider tracking open files and cleaning them up here */ + + /* Clear the backend. */ + backend_dev_handle = (uintptr_t)NULL; + backend_image_spec = (uintptr_t)NULL; + + return free_dev_info(dev_info); +} + + +/* Open a file for access from package. */ +static int fip_file_open(io_dev_info_t *dev_info, const uintptr_t spec, + io_entity_t *entity) +{ + int result; + uintptr_t backend_handle; + const io_uuid_spec_t *uuid_spec = (io_uuid_spec_t *)spec; + static const uuid_t uuid_null = { {0} }; /* Double braces for clang */ + size_t bytes_read; + int found_file = 0; + + assert(uuid_spec != NULL); + assert(entity != NULL); + + /* Can only have one file open at a time for the moment. We need to + * track state like file cursor position. We know the header lives at + * offset zero, so this entry should never be zero for an active file. + * When the system supports dynamic memory allocation we can allow more + * than one open file at a time if needed. + */ + if (current_fip_file.entry.offset_address != 0U) { + WARN("fip_file_open : Only one open file at a time.\n"); + return -ENFILE; + } + + /* Attempt to access the FIP image */ + result = io_open(backend_dev_handle, backend_image_spec, + &backend_handle); + if (result != 0) { + WARN("Failed to open Firmware Image Package (%i)\n", result); + result = -ENOENT; + goto fip_file_open_exit; + } + + /* Seek past the FIP header into the Table of Contents */ + result = io_seek(backend_handle, IO_SEEK_SET, + (signed long long)sizeof(fip_toc_header_t)); + if (result != 0) { + WARN("fip_file_open: failed to seek\n"); + result = -ENOENT; + goto fip_file_open_close; + } + + found_file = 0; + do { + result = io_read(backend_handle, + (uintptr_t)¤t_fip_file.entry, + sizeof(current_fip_file.entry), + &bytes_read); + if (result == 0) { + if (compare_uuids(¤t_fip_file.entry.uuid, + &uuid_spec->uuid) == 0) { + found_file = 1; + } + } else { + WARN("Failed to read FIP (%i)\n", result); + goto fip_file_open_close; + } + } while ((found_file == 0) && + (compare_uuids(¤t_fip_file.entry.uuid, + &uuid_null) != 0)); + + if (found_file == 1) { + /* All fine. Update entity info with file state and return. Set + * the file position to 0. The 'current_fip_file.entry' holds + * the base and size of the file. + */ + current_fip_file.file_pos = 0; + entity->info = (uintptr_t)¤t_fip_file; + } else { + /* Did not find the file in the FIP. */ + current_fip_file.entry.offset_address = 0; + result = -ENOENT; + } + + fip_file_open_close: + io_close(backend_handle); + + fip_file_open_exit: + return result; +} + + +/* Return the size of a file in package */ +static int fip_file_len(io_entity_t *entity, size_t *length) +{ + assert(entity != NULL); + assert(length != NULL); + + *length = ((fip_file_state_t *)entity->info)->entry.size; + + return 0; +} + + +/* Read data from a file in package */ +static int fip_file_read(io_entity_t *entity, uintptr_t buffer, size_t length, + size_t *length_read) +{ + int result; + fip_file_state_t *fp; + size_t file_offset; + size_t bytes_read; + uintptr_t backend_handle; + + assert(entity != NULL); + assert(length_read != NULL); + assert(entity->info != (uintptr_t)NULL); + + /* Open the backend, attempt to access the blob image */ + result = io_open(backend_dev_handle, backend_image_spec, + &backend_handle); + if (result != 0) { + WARN("Failed to open FIP (%i)\n", result); + result = -ENOENT; + goto fip_file_read_exit; + } + + fp = (fip_file_state_t *)entity->info; + + /* Seek to the position in the FIP where the payload lives */ + file_offset = fp->entry.offset_address + fp->file_pos; + result = io_seek(backend_handle, IO_SEEK_SET, + (signed long long)file_offset); + if (result != 0) { + WARN("fip_file_read: failed to seek\n"); + result = -ENOENT; + goto fip_file_read_close; + } + + result = io_read(backend_handle, buffer, length, &bytes_read); + if (result != 0) { + /* We cannot read our data. Fail. */ + WARN("Failed to read payload (%i)\n", result); + result = -ENOENT; + goto fip_file_read_close; + } else { + /* Set caller length and new file position. */ + *length_read = bytes_read; + fp->file_pos += bytes_read; + } + +/* Close the backend. */ + fip_file_read_close: + io_close(backend_handle); + + fip_file_read_exit: + return result; +} + + +/* Close a file in package */ +static int fip_file_close(io_entity_t *entity) +{ + /* Clear our current file pointer. + * If we had malloc() we would free() here. + */ + if (current_fip_file.entry.offset_address != 0U) { + zeromem(¤t_fip_file, sizeof(current_fip_file)); + } + + /* Clear the Entity info. */ + entity->info = 0; + + return 0; +} + +/* Exported functions */ + +/* Register the Firmware Image Package driver with the IO abstraction */ +int register_io_dev_fip(const io_dev_connector_t **dev_con) +{ + int result; + assert(dev_con != NULL); + + /* + * Since dev_info isn't really used in io_register_device, always + * use the same device info at here instead. + */ + result = io_register_device(&dev_info_pool[0]); + if (result == 0) + *dev_con = &fip_dev_connector; + + return result; +} + +/* Function to retrieve plat_toc_flags, previously saved in FIP dev */ +int fip_dev_get_plat_toc_flag(io_dev_info_t *dev_info, uint16_t *plat_toc_flag) +{ + fip_dev_state_t *state; + + assert(dev_info != NULL); + + state = (fip_dev_state_t *)dev_info->info; + + *plat_toc_flag = state->plat_toc_flag; + + return 0; +} diff --git a/drivers/rz/ipl/rza/drivers/io/io_memmap.c b/drivers/rz/ipl/rza/drivers/io/io_memmap.c new file mode 100644 index 00000000..eb69163b --- /dev/null +++ b/drivers/rz/ipl/rza/drivers/io/io_memmap.c @@ -0,0 +1,251 @@ +/* + * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include + +#include +#include +#include +#include +#include + +/* As we need to be able to keep state for seek, only one file can be open + * at a time. Make this a structure and point to the entity->info. When we + * can malloc memory we can change this to support more open files. + */ +typedef struct { + /* Use the 'in_use' flag as any value for base and file_pos could be + * valid. + */ + int in_use; + uintptr_t base; + unsigned long long file_pos; + unsigned long long size; +} memmap_file_state_t; + +static memmap_file_state_t current_memmap_file = {0}; + +/* Identify the device type as memmap */ +static io_type_t device_type_memmap(void) +{ + return IO_TYPE_MEMMAP; +} + +/* Memmap device functions */ +static int memmap_dev_open(const uintptr_t dev_spec, io_dev_info_t **dev_info); +static int memmap_block_open(io_dev_info_t *dev_info, const uintptr_t spec, + io_entity_t *entity); +static int memmap_block_seek(io_entity_t *entity, int mode, + signed long long offset); +static int memmap_block_len(io_entity_t *entity, size_t *length); +static int memmap_block_read(io_entity_t *entity, uintptr_t buffer, + size_t length, size_t *length_read); +static int memmap_block_write(io_entity_t *entity, const uintptr_t buffer, + size_t length, size_t *length_written); +static int memmap_block_close(io_entity_t *entity); +static int memmap_dev_close(io_dev_info_t *dev_info); + + +static const io_dev_connector_t memmap_dev_connector = { + .dev_open = memmap_dev_open +}; + + +static const io_dev_funcs_t memmap_dev_funcs = { + .type = device_type_memmap, + .open = memmap_block_open, + .seek = memmap_block_seek, + .size = memmap_block_len, + .read = memmap_block_read, + .write = memmap_block_write, + .close = memmap_block_close, + .dev_init = NULL, + .dev_close = memmap_dev_close, +}; + + +/* No state associated with this device so structure can be const */ +static io_dev_info_t memmap_dev_info = { + .funcs = &memmap_dev_funcs, + .info = (uintptr_t)NULL +}; + + +/* Open a connection to the memmap device */ +static int memmap_dev_open(const uintptr_t dev_spec __unused, + io_dev_info_t **dev_info) +{ + assert(dev_info != NULL); + *dev_info = &memmap_dev_info; + return 0; +} + + + +/* Close a connection to the memmap device */ +static int memmap_dev_close(io_dev_info_t *dev_info) +{ + /* NOP */ + /* TODO: Consider tracking open files and cleaning them up here */ + return 0; +} + + +/* Open a file on the memmap device */ +static int memmap_block_open(io_dev_info_t *dev_info, const uintptr_t spec, + io_entity_t *entity) +{ + int result = -ENOMEM; + const io_block_spec_t *block_spec = (io_block_spec_t *)spec; + + /* Since we need to track open state for seek() we only allow one open + * spec at a time. When we have dynamic memory we can malloc and set + * entity->info. + */ + if (current_memmap_file.in_use == 0) { + assert(block_spec != NULL); + assert(entity != NULL); + + current_memmap_file.in_use = 1; + current_memmap_file.base = block_spec->offset; + /* File cursor offset for seek and incremental reads etc. */ + current_memmap_file.file_pos = 0; + current_memmap_file.size = block_spec->length; + entity->info = (uintptr_t)¤t_memmap_file; + result = 0; + } else { + WARN("A Memmap device is already active. Close first.\n"); + } + + return result; +} + + +/* Seek to a particular file offset on the memmap device */ +static int memmap_block_seek(io_entity_t *entity, int mode, + signed long long offset) +{ + int result = -ENOENT; + memmap_file_state_t *fp; + + /* We only support IO_SEEK_SET for the moment. */ + if (mode == IO_SEEK_SET) { + assert(entity != NULL); + + fp = (memmap_file_state_t *) entity->info; + + /* Assert that new file position is valid */ + assert((offset >= 0) && + ((unsigned long long)offset < fp->size)); + + /* Reset file position */ + fp->file_pos = (unsigned long long)offset; + result = 0; + } + + return result; +} + + +/* Return the size of a file on the memmap device */ +static int memmap_block_len(io_entity_t *entity, size_t *length) +{ + assert(entity != NULL); + assert(length != NULL); + + *length = (size_t)((memmap_file_state_t *)entity->info)->size; + + return 0; +} + + +/* Read data from a file on the memmap device */ +static int memmap_block_read(io_entity_t *entity, uintptr_t buffer, + size_t length, size_t *length_read) +{ + memmap_file_state_t *fp; + unsigned long long pos_after; + + assert(entity != NULL); + assert(length_read != NULL); + + fp = (memmap_file_state_t *) entity->info; + + /* Assert that file position is valid for this read operation */ + pos_after = fp->file_pos + length; + assert((pos_after >= fp->file_pos) && (pos_after <= fp->size)); + + memcpy((void *)buffer, + (void *)((uintptr_t)(fp->base + fp->file_pos)), length); + + *length_read = length; + + /* Set file position after read */ + fp->file_pos = pos_after; + + return 0; +} + + +/* Write data to a file on the memmap device */ +static int memmap_block_write(io_entity_t *entity, const uintptr_t buffer, + size_t length, size_t *length_written) +{ + memmap_file_state_t *fp; + unsigned long long pos_after; + + assert(entity != NULL); + assert(length_written != NULL); + + fp = (memmap_file_state_t *) entity->info; + + /* Assert that file position is valid for this write operation */ + pos_after = fp->file_pos + length; + assert((pos_after >= fp->file_pos) && (pos_after <= fp->size)); + + memcpy((void *)((uintptr_t)(fp->base + fp->file_pos)), + (void *)buffer, length); + + *length_written = length; + + /* Set file position after write */ + fp->file_pos = pos_after; + + return 0; +} + + +/* Close a file on the memmap device */ +static int memmap_block_close(io_entity_t *entity) +{ + assert(entity != NULL); + + entity->info = 0; + + /* This would be a mem free() if we had malloc.*/ + zeromem((void *)¤t_memmap_file, sizeof(current_memmap_file)); + + return 0; +} + + +/* Exported functions */ + +/* Register the memmap driver with the IO abstraction */ +int register_io_dev_memmap(const io_dev_connector_t **dev_con) +{ + int result; + assert(dev_con != NULL); + + result = io_register_device(&memmap_dev_info); + if (result == 0) + *dev_con = &memmap_dev_connector; + + return result; +} diff --git a/drivers/rz/ipl/rza/drivers/io/io_mtd.c b/drivers/rz/ipl/rza/drivers/io/io_mtd.c new file mode 100644 index 00000000..7575fa25 --- /dev/null +++ b/drivers/rz/ipl/rza/drivers/io/io_mtd.c @@ -0,0 +1,248 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include + +#include +#include +#include +#include + +typedef struct { + io_mtd_dev_spec_t *dev_spec; + uintptr_t base; + unsigned long long offset; /* Offset in bytes */ + unsigned long long size; /* Size of device in bytes */ +} mtd_dev_state_t; + +io_type_t device_type_mtd(void); + +static int mtd_open(io_dev_info_t *dev_info, const uintptr_t spec, + io_entity_t *entity); +static int mtd_seek(io_entity_t *entity, int mode, signed long long offset); +static int mtd_read(io_entity_t *entity, uintptr_t buffer, size_t length, + size_t *length_read); +static int mtd_close(io_entity_t *entity); +static int mtd_dev_open(const uintptr_t dev_spec, io_dev_info_t **dev_info); +static int mtd_dev_close(io_dev_info_t *dev_info); + +static const io_dev_connector_t mtd_dev_connector = { + .dev_open = mtd_dev_open +}; + +static const io_dev_funcs_t mtd_dev_funcs = { + .type = device_type_mtd, + .open = mtd_open, + .seek = mtd_seek, + .read = mtd_read, + .close = mtd_close, + .dev_close = mtd_dev_close, +}; + +static mtd_dev_state_t state_pool[MAX_IO_MTD_DEVICES]; +static io_dev_info_t dev_info_pool[MAX_IO_MTD_DEVICES]; + +io_type_t device_type_mtd(void) +{ + return IO_TYPE_MTD; +} + +/* Locate a MTD state in the pool, specified by address */ +static int find_first_mtd_state(const io_mtd_dev_spec_t *dev_spec, + unsigned int *index_out) +{ + unsigned int index; + int result = -ENOENT; + + for (index = 0U; index < MAX_IO_MTD_DEVICES; index++) { + /* dev_spec is used as identifier since it's unique */ + if (state_pool[index].dev_spec == dev_spec) { + result = 0; + *index_out = index; + break; + } + } + + return result; +} + +/* Allocate a device info from the pool */ +static int allocate_dev_info(io_dev_info_t **dev_info) +{ + unsigned int index = 0U; + int result; + + result = find_first_mtd_state(NULL, &index); + if (result != 0) { + return -ENOMEM; + } + + dev_info_pool[index].funcs = &mtd_dev_funcs; + dev_info_pool[index].info = (uintptr_t)&state_pool[index]; + *dev_info = &dev_info_pool[index]; + + return 0; +} + +/* Release a device info from the pool */ +static int free_dev_info(io_dev_info_t *dev_info) +{ + int result; + unsigned int index = 0U; + mtd_dev_state_t *state; + + state = (mtd_dev_state_t *)dev_info->info; + result = find_first_mtd_state(state->dev_spec, &index); + if (result != 0) { + return result; + } + + zeromem(state, sizeof(mtd_dev_state_t)); + zeromem(dev_info, sizeof(io_dev_info_t)); + + return 0; +} + +static int mtd_open(io_dev_info_t *dev_info, const uintptr_t spec, + io_entity_t *entity) +{ + mtd_dev_state_t *cur; + + assert((dev_info->info != 0UL) && (entity->info == 0UL)); + + cur = (mtd_dev_state_t *)dev_info->info; + entity->info = (uintptr_t)cur; + cur->offset = 0U; + + return 0; +} + +/* Seek to a specific position using offset */ +static int mtd_seek(io_entity_t *entity, int mode, signed long long offset) +{ + mtd_dev_state_t *cur; + + assert((entity->info != (uintptr_t)NULL) && (offset >= 0)); + + cur = (mtd_dev_state_t *)entity->info; + + switch (mode) { + case IO_SEEK_SET: + if ((offset >= 0) && + ((unsigned long long)offset >= cur->size)) { + return -EINVAL; + } + + cur->offset = offset; + break; + case IO_SEEK_CUR: + if (((cur->offset + (unsigned long long)offset) >= + cur->size) || + ((cur->offset + (unsigned long long)offset) < + cur->offset)) { + return -EINVAL; + } + + cur->offset += (unsigned long long)offset; + break; + default: + return -EINVAL; + } + + return 0; +} + +static int mtd_read(io_entity_t *entity, uintptr_t buffer, size_t length, + size_t *out_length) +{ + mtd_dev_state_t *cur; + io_mtd_ops_t *ops; + int ret; + + assert(entity->info != (uintptr_t)NULL); + assert((length > 0U) && (buffer != (uintptr_t)NULL)); + + cur = (mtd_dev_state_t *)entity->info; + ops = &cur->dev_spec->ops; + assert(ops->read != NULL); + + VERBOSE("Read at %llx into %lx, length %zi\n", + cur->offset, buffer, length); + if ((cur->offset + length) > cur->dev_spec->device_size) { + return -EINVAL; + } + + ret = ops->read(cur->offset, buffer, length, out_length); + if (ret < 0) { + return ret; + } + + assert(*out_length == length); + cur->offset += *out_length; + + return 0; +} + +static int mtd_close(io_entity_t *entity) +{ + entity->info = (uintptr_t)NULL; + + return 0; +} + +static int mtd_dev_open(const uintptr_t dev_spec, io_dev_info_t **dev_info) +{ + mtd_dev_state_t *cur; + io_dev_info_t *info; + io_mtd_ops_t *ops; + int result; + + result = allocate_dev_info(&info); + if (result != 0) { + return -ENOENT; + } + + cur = (mtd_dev_state_t *)info->info; + cur->dev_spec = (io_mtd_dev_spec_t *)dev_spec; + *dev_info = info; + ops = &(cur->dev_spec->ops); + if (ops->init != NULL) { + result = ops->init(&cur->dev_spec->device_size, + &cur->dev_spec->erase_size); + } + + if (result == 0) { + cur->size = cur->dev_spec->device_size; + } else { + cur->size = 0ULL; + } + + return result; +} + +static int mtd_dev_close(io_dev_info_t *dev_info) +{ + return free_dev_info(dev_info); +} + +/* Exported functions */ + +/* Register the MTD driver in the IO abstraction */ +int register_io_dev_mtd(const io_dev_connector_t **dev_con) +{ + int result; + + result = io_register_device(&dev_info_pool[0]); + if (result == 0) { + *dev_con = &mtd_dev_connector; + } + + return result; +} diff --git a/drivers/rz/ipl/rza/drivers/io/io_semihosting.c b/drivers/rz/ipl/rza/drivers/io/io_semihosting.c new file mode 100644 index 00000000..1c2f84d5 --- /dev/null +++ b/drivers/rz/ipl/rza/drivers/io/io_semihosting.c @@ -0,0 +1,201 @@ +/* + * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include +#include +#include +#include + +/* Identify the device type as semihosting */ +static io_type_t device_type_sh(void) +{ + return IO_TYPE_SEMIHOSTING; +} + + +/* Semi-hosting functions, device info and handle */ + +static int sh_dev_open(const uintptr_t dev_spec, io_dev_info_t **dev_info); +static int sh_file_open(io_dev_info_t *dev_info, const uintptr_t spec, + io_entity_t *entity); +static int sh_file_seek(io_entity_t *entity, int mode, signed long long offset); +static int sh_file_len(io_entity_t *entity, size_t *length); +static int sh_file_read(io_entity_t *entity, uintptr_t buffer, size_t length, + size_t *length_read); +static int sh_file_write(io_entity_t *entity, const uintptr_t buffer, + size_t length, size_t *length_written); +static int sh_file_close(io_entity_t *entity); + +static const io_dev_connector_t sh_dev_connector = { + .dev_open = sh_dev_open +}; + + +static const io_dev_funcs_t sh_dev_funcs = { + .type = device_type_sh, + .open = sh_file_open, + .seek = sh_file_seek, + .size = sh_file_len, + .read = sh_file_read, + .write = sh_file_write, + .close = sh_file_close, + .dev_init = NULL, /* NOP */ + .dev_close = NULL, /* NOP */ +}; + + +static io_dev_info_t sh_dev_info = { + .funcs = &sh_dev_funcs, + .info = (uintptr_t)NULL +}; + + +/* Open a connection to the semi-hosting device */ +static int sh_dev_open(const uintptr_t dev_spec __unused, + io_dev_info_t **dev_info) +{ + assert(dev_info != NULL); + *dev_info = &sh_dev_info; + return 0; +} + + +/* Open a file on the semi-hosting device */ +static int sh_file_open(io_dev_info_t *dev_info __unused, + const uintptr_t spec, io_entity_t *entity) +{ + int result = -ENOENT; + long sh_result; + const io_file_spec_t *file_spec = (const io_file_spec_t *)spec; + + assert(file_spec != NULL); + assert(entity != NULL); + + sh_result = semihosting_file_open(file_spec->path, file_spec->mode); + + if (sh_result > 0) { + entity->info = (uintptr_t)sh_result; + result = 0; + } + return result; +} + + +/* Seek to a particular file offset on the semi-hosting device */ +static int sh_file_seek(io_entity_t *entity, int mode, signed long long offset) +{ + long file_handle, sh_result; + + assert(entity != NULL); + + file_handle = (long)entity->info; + + sh_result = semihosting_file_seek(file_handle, (ssize_t)offset); + + return (sh_result == 0) ? 0 : -ENOENT; +} + + +/* Return the size of a file on the semi-hosting device */ +static int sh_file_len(io_entity_t *entity, size_t *length) +{ + int result = -ENOENT; + + assert(entity != NULL); + assert(length != NULL); + + long sh_handle = (long)entity->info; + long sh_result = semihosting_file_length(sh_handle); + + if (sh_result >= 0) { + result = 0; + *length = (size_t)sh_result; + } + + return result; +} + + +/* Read data from a file on the semi-hosting device */ +static int sh_file_read(io_entity_t *entity, uintptr_t buffer, size_t length, + size_t *length_read) +{ + int result = -ENOENT; + long sh_result; + size_t bytes = length; + long file_handle; + + assert(entity != NULL); + assert(length_read != NULL); + + file_handle = (long)entity->info; + + sh_result = semihosting_file_read(file_handle, &bytes, buffer); + + if (sh_result >= 0) { + *length_read = (bytes != length) ? bytes : length; + result = 0; + } + + return result; +} + + +/* Write data to a file on the semi-hosting device */ +static int sh_file_write(io_entity_t *entity, const uintptr_t buffer, + size_t length, size_t *length_written) +{ + long sh_result; + long file_handle; + size_t bytes = length; + + assert(entity != NULL); + assert(length_written != NULL); + + file_handle = (long)entity->info; + + sh_result = semihosting_file_write(file_handle, &bytes, buffer); + + *length_written = length - bytes; + + return (sh_result == 0) ? 0 : -ENOENT; +} + + +/* Close a file on the semi-hosting device */ +static int sh_file_close(io_entity_t *entity) +{ + long sh_result; + long file_handle; + + assert(entity != NULL); + + file_handle = (long)entity->info; + + sh_result = semihosting_file_close(file_handle); + + return (sh_result >= 0) ? 0 : -ENOENT; +} + + +/* Exported functions */ + +/* Register the semi-hosting driver with the IO abstraction */ +int register_io_dev_sh(const io_dev_connector_t **dev_con) +{ + int result; + assert(dev_con != NULL); + + result = io_register_device(&sh_dev_info); + if (result == 0) + *dev_con = &sh_dev_connector; + + return result; +} diff --git a/drivers/rz/ipl/rza/drivers/io/io_storage.c b/drivers/rz/ipl/rza/drivers/io/io_storage.c new file mode 100644 index 00000000..05342689 --- /dev/null +++ b/drivers/rz/ipl/rza/drivers/io/io_storage.c @@ -0,0 +1,328 @@ +/* + * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include + +#include +#include + +/* Storage for a fixed maximum number of IO entities, definable by platform */ +static io_entity_t entity_pool[MAX_IO_HANDLES]; + +/* Simple way of tracking used storage - each entry is NULL or a pointer to an + * entity */ +static io_entity_t *entity_map[MAX_IO_HANDLES]; + +/* Track number of allocated entities */ +static unsigned int entity_count; + +/* Array of fixed maximum of registered devices, definable by platform */ +static const io_dev_info_t *devices[MAX_IO_DEVICES]; + +/* Number of currently registered devices */ +static unsigned int dev_count; + +/* Extra validation functions only used when asserts are enabled */ +#if ENABLE_ASSERTIONS + +/* Return a boolean value indicating whether a device connector is valid */ +static bool is_valid_dev_connector(const io_dev_connector_t *dev_con) +{ + return (dev_con != NULL) && (dev_con->dev_open != NULL); +} + +/* Return a boolean value indicating whether a device handle is valid */ +static bool is_valid_dev(const uintptr_t dev_handle) +{ + const io_dev_info_t *dev = (io_dev_info_t *)dev_handle; + + return (dev != NULL) && (dev->funcs != NULL) && + (dev->funcs->type != NULL) && + (dev->funcs->type() < IO_TYPE_MAX); +} + + +/* Return a boolean value indicating whether an IO entity is valid */ +static bool is_valid_entity(const uintptr_t handle) +{ + const io_entity_t *entity = (io_entity_t *)handle; + + return (entity != NULL) && + (is_valid_dev((uintptr_t)entity->dev_handle)); +} + + +/* Return a boolean value indicating whether a seek mode is valid */ +static bool is_valid_seek_mode(io_seek_mode_t mode) +{ + return ((mode != IO_SEEK_INVALID) && (mode < IO_SEEK_MAX)); +} + +#endif /* ENABLE_ASSERTIONS */ +/* End of extra validation functions only used when asserts are enabled */ + + +/* Open a connection to a specific device */ +static int io_storage_dev_open(const io_dev_connector_t *dev_con, + const uintptr_t dev_spec, + io_dev_info_t **dev_info) +{ + assert(dev_info != NULL); + assert(is_valid_dev_connector(dev_con)); + + return dev_con->dev_open(dev_spec, dev_info); +} + + +/* Set a handle to track an entity */ +static void set_handle(uintptr_t *handle, io_entity_t *entity) +{ + assert(handle != NULL); + *handle = (uintptr_t)entity; +} + + +/* Locate an entity in the pool, specified by address */ +static int find_first_entity(const io_entity_t *entity, unsigned int *index_out) +{ + int result = -ENOENT; + for (unsigned int index = 0; index < MAX_IO_HANDLES; ++index) { + if (entity_map[index] == entity) { + result = 0; + *index_out = index; + break; + } + } + return result; +} + + +/* Allocate an entity from the pool and return a pointer to it */ +static int allocate_entity(io_entity_t **entity) +{ + int result = -ENOMEM; + assert(entity != NULL); + + if (entity_count < MAX_IO_HANDLES) { + unsigned int index = 0; + result = find_first_entity(NULL, &index); + assert(result == 0); + *entity = &entity_pool[index]; + entity_map[index] = &entity_pool[index]; + ++entity_count; + } + + return result; +} + + +/* Release an entity back to the pool */ +static int free_entity(const io_entity_t *entity) +{ + int result; + unsigned int index = 0; + assert(entity != NULL); + + result = find_first_entity(entity, &index); + if (result == 0) { + entity_map[index] = NULL; + --entity_count; + } + + return result; +} + + +/* Exported API */ + +/* Register a device driver */ +int io_register_device(const io_dev_info_t *dev_info) +{ + int result = -ENOMEM; + assert(dev_info != NULL); + + if (dev_count < MAX_IO_DEVICES) { + devices[dev_count] = dev_info; + dev_count++; + result = 0; + } + + return result; +} + + +/* Open a connection to an IO device */ +int io_dev_open(const io_dev_connector_t *dev_con, const uintptr_t dev_spec, + uintptr_t *handle) +{ + assert(handle != NULL); + return io_storage_dev_open(dev_con, dev_spec, (io_dev_info_t **)handle); +} + + +/* Initialise an IO device explicitly - to permit lazy initialisation or + * re-initialisation */ +int io_dev_init(uintptr_t dev_handle, const uintptr_t init_params) +{ + int result = 0; + assert(dev_handle != (uintptr_t)NULL); + assert(is_valid_dev(dev_handle)); + + io_dev_info_t *dev = (io_dev_info_t *)dev_handle; + + /* Absence of registered function implies NOP here */ + if (dev->funcs->dev_init != NULL) { + result = dev->funcs->dev_init(dev, init_params); + } + + return result; +} + +/* Close a connection to a device */ +int io_dev_close(uintptr_t dev_handle) +{ + int result = 0; + assert(dev_handle != (uintptr_t)NULL); + assert(is_valid_dev(dev_handle)); + + io_dev_info_t *dev = (io_dev_info_t *)dev_handle; + + /* Absence of registered function implies NOP here */ + if (dev->funcs->dev_close != NULL) { + result = dev->funcs->dev_close(dev); + } + + return result; +} + + +/* Synchronous operations */ + + +/* Open an IO entity */ +int io_open(uintptr_t dev_handle, const uintptr_t spec, uintptr_t *handle) +{ + int result; + assert((spec != (uintptr_t)NULL) && (handle != NULL)); + assert(is_valid_dev(dev_handle)); + + io_dev_info_t *dev = (io_dev_info_t *)dev_handle; + io_entity_t *entity; + + result = allocate_entity(&entity); + + if (result == 0) { + assert(dev->funcs->open != NULL); + result = dev->funcs->open(dev, spec, entity); + + if (result == 0) { + entity->dev_handle = dev; + set_handle(handle, entity); + } else + free_entity(entity); + } + return result; +} + + +/* Seek to a specific position in an IO entity */ +int io_seek(uintptr_t handle, io_seek_mode_t mode, signed long long offset) +{ + int result = -ENODEV; + assert(is_valid_entity(handle) && is_valid_seek_mode(mode)); + + io_entity_t *entity = (io_entity_t *)handle; + + io_dev_info_t *dev = entity->dev_handle; + + if (dev->funcs->seek != NULL) + result = dev->funcs->seek(entity, mode, offset); + + return result; +} + + +/* Determine the length of an IO entity */ +int io_size(uintptr_t handle, size_t *length) +{ + int result = -ENODEV; + assert(is_valid_entity(handle) && (length != NULL)); + + io_entity_t *entity = (io_entity_t *)handle; + + io_dev_info_t *dev = entity->dev_handle; + + if (dev->funcs->size != NULL) + result = dev->funcs->size(entity, length); + + return result; +} + + +/* Read data from an IO entity */ +int io_read(uintptr_t handle, + uintptr_t buffer, + size_t length, + size_t *length_read) +{ + int result = -ENODEV; + assert(is_valid_entity(handle)); + + io_entity_t *entity = (io_entity_t *)handle; + + io_dev_info_t *dev = entity->dev_handle; + + if (dev->funcs->read != NULL) + result = dev->funcs->read(entity, buffer, length, length_read); + + return result; +} + + +/* Write data to an IO entity */ +int io_write(uintptr_t handle, + const uintptr_t buffer, + size_t length, + size_t *length_written) +{ + int result = -ENODEV; + assert(is_valid_entity(handle)); + + io_entity_t *entity = (io_entity_t *)handle; + + io_dev_info_t *dev = entity->dev_handle; + + if (dev->funcs->write != NULL) { + result = dev->funcs->write(entity, buffer, length, + length_written); + } + + return result; +} + + +/* Close an IO entity */ +int io_close(uintptr_t handle) +{ + int result = 0; + assert(is_valid_entity(handle)); + + io_entity_t *entity = (io_entity_t *)handle; + + io_dev_info_t *dev = entity->dev_handle; + + /* Absence of registered function implies NOP here */ + if (dev->funcs->close != NULL) + result = dev->funcs->close(entity); + + /* Ignore improbable free_entity failure */ + (void)free_entity(entity); + + return result; +} diff --git a/drivers/rz/ipl/rza/drivers/renesas/common/io/io_common.h b/drivers/rz/ipl/rza/drivers/renesas/common/io/io_common.h new file mode 100644 index 00000000..6eb77777 --- /dev/null +++ b/drivers/rz/ipl/rza/drivers/renesas/common/io/io_common.h @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2015-2017, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef IO_COMMON_H +#define IO_COMMON_H + +typedef struct io_drv_spec { + size_t offset; + size_t length; + uint32_t partition; +} io_drv_spec_t; + +#endif /* IO_COMMON_H */ diff --git a/drivers/rz/ipl/rza/drivers/renesas/common/io/io_private.h b/drivers/rz/ipl/rza/drivers/renesas/common/io/io_private.h new file mode 100644 index 00000000..207523a7 --- /dev/null +++ b/drivers/rz/ipl/rza/drivers/renesas/common/io/io_private.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2015-2017, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef IO_PRIVATE_H +#define IO_PRIVATE_H + +/* + * Return codes reported by 'io_*' APIs + * The value of fail should not overlap with define of the errno. + * The errno is in "include/lib/stdlib/sys/errno.h". + */ +#define IO_SUCCESS (0) +#define IO_FAIL (-0x81) +#define IO_NOT_SUPPORTED (-0x82) +#define IO_RESOURCES_EXHAUSTED (-0x83) + +#endif /* IO_PRIVATE_H */ diff --git a/drivers/rz/ipl/rza/include/arch/aarch64/arch.h b/drivers/rz/ipl/rza/include/arch/aarch64/arch.h new file mode 100644 index 00000000..b86a13ed --- /dev/null +++ b/drivers/rz/ipl/rza/include/arch/aarch64/arch.h @@ -0,0 +1,1115 @@ +/* + * Copyright (c) 2013-2021, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2020, NVIDIA Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef ARCH_H +#define ARCH_H + +#include + +/******************************************************************************* + * MIDR bit definitions + ******************************************************************************/ +#define MIDR_IMPL_MASK U(0xff) +#define MIDR_IMPL_SHIFT U(0x18) +#define MIDR_VAR_SHIFT U(20) +#define MIDR_VAR_BITS U(4) +#define MIDR_VAR_MASK U(0xf) +#define MIDR_REV_SHIFT U(0) +#define MIDR_REV_BITS U(4) +#define MIDR_REV_MASK U(0xf) +#define MIDR_PN_MASK U(0xfff) +#define MIDR_PN_SHIFT U(0x4) + +/******************************************************************************* + * MPIDR macros + ******************************************************************************/ +#define MPIDR_MT_MASK (ULL(1) << 24) +#define MPIDR_CPU_MASK MPIDR_AFFLVL_MASK +#define MPIDR_CLUSTER_MASK (MPIDR_AFFLVL_MASK << MPIDR_AFFINITY_BITS) +#define MPIDR_AFFINITY_BITS U(8) +#define MPIDR_AFFLVL_MASK ULL(0xff) +#define MPIDR_AFF0_SHIFT U(0) +#define MPIDR_AFF1_SHIFT U(8) +#define MPIDR_AFF2_SHIFT U(16) +#define MPIDR_AFF3_SHIFT U(32) +#define MPIDR_AFF_SHIFT(_n) MPIDR_AFF##_n##_SHIFT +#define MPIDR_AFFINITY_MASK ULL(0xff00ffffff) +#define MPIDR_AFFLVL_SHIFT U(3) +#define MPIDR_AFFLVL0 ULL(0x0) +#define MPIDR_AFFLVL1 ULL(0x1) +#define MPIDR_AFFLVL2 ULL(0x2) +#define MPIDR_AFFLVL3 ULL(0x3) +#define MPIDR_AFFLVL(_n) MPIDR_AFFLVL##_n +#define MPIDR_AFFLVL0_VAL(mpidr) \ + (((mpidr) >> MPIDR_AFF0_SHIFT) & MPIDR_AFFLVL_MASK) +#define MPIDR_AFFLVL1_VAL(mpidr) \ + (((mpidr) >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK) +#define MPIDR_AFFLVL2_VAL(mpidr) \ + (((mpidr) >> MPIDR_AFF2_SHIFT) & MPIDR_AFFLVL_MASK) +#define MPIDR_AFFLVL3_VAL(mpidr) \ + (((mpidr) >> MPIDR_AFF3_SHIFT) & MPIDR_AFFLVL_MASK) +/* + * The MPIDR_MAX_AFFLVL count starts from 0. Take care to + * add one while using this macro to define array sizes. + * TODO: Support only the first 3 affinity levels for now. + */ +#define MPIDR_MAX_AFFLVL U(2) + +#define MPID_MASK (MPIDR_MT_MASK | \ + (MPIDR_AFFLVL_MASK << MPIDR_AFF3_SHIFT) | \ + (MPIDR_AFFLVL_MASK << MPIDR_AFF2_SHIFT) | \ + (MPIDR_AFFLVL_MASK << MPIDR_AFF1_SHIFT) | \ + (MPIDR_AFFLVL_MASK << MPIDR_AFF0_SHIFT)) + +#define MPIDR_AFF_ID(mpid, n) \ + (((mpid) >> MPIDR_AFF_SHIFT(n)) & MPIDR_AFFLVL_MASK) + +/* + * An invalid MPID. This value can be used by functions that return an MPID to + * indicate an error. + */ +#define INVALID_MPID U(0xFFFFFFFF) + +/******************************************************************************* + * Definitions for CPU system register interface to GICv3 + ******************************************************************************/ +#define ICC_IGRPEN1_EL1 S3_0_C12_C12_7 +#define ICC_SGI1R S3_0_C12_C11_5 +#define ICC_SRE_EL1 S3_0_C12_C12_5 +#define ICC_SRE_EL2 S3_4_C12_C9_5 +#define ICC_SRE_EL3 S3_6_C12_C12_5 +#define ICC_CTLR_EL1 S3_0_C12_C12_4 +#define ICC_CTLR_EL3 S3_6_C12_C12_4 +#define ICC_PMR_EL1 S3_0_C4_C6_0 +#define ICC_RPR_EL1 S3_0_C12_C11_3 +#define ICC_IGRPEN1_EL3 S3_6_c12_c12_7 +#define ICC_IGRPEN0_EL1 S3_0_c12_c12_6 +#define ICC_HPPIR0_EL1 S3_0_c12_c8_2 +#define ICC_HPPIR1_EL1 S3_0_c12_c12_2 +#define ICC_IAR0_EL1 S3_0_c12_c8_0 +#define ICC_IAR1_EL1 S3_0_c12_c12_0 +#define ICC_EOIR0_EL1 S3_0_c12_c8_1 +#define ICC_EOIR1_EL1 S3_0_c12_c12_1 +#define ICC_SGI0R_EL1 S3_0_c12_c11_7 + +/******************************************************************************* + * Definitions for EL2 system registers for save/restore routine + ******************************************************************************/ + +#define CNTPOFF_EL2 S3_4_C14_C0_6 +#define HAFGRTR_EL2 S3_4_C3_C1_6 +#define HDFGRTR_EL2 S3_4_C3_C1_4 +#define HDFGWTR_EL2 S3_4_C3_C1_5 +#define HFGITR_EL2 S3_4_C1_C1_6 +#define HFGRTR_EL2 S3_4_C1_C1_4 +#define HFGWTR_EL2 S3_4_C1_C1_5 +#define ICH_HCR_EL2 S3_4_C12_C11_0 +#define ICH_VMCR_EL2 S3_4_C12_C11_7 +#define MPAMVPM0_EL2 S3_4_C10_C5_0 +#define MPAMVPM1_EL2 S3_4_C10_C5_1 +#define MPAMVPM2_EL2 S3_4_C10_C5_2 +#define MPAMVPM3_EL2 S3_4_C10_C5_3 +#define MPAMVPM4_EL2 S3_4_C10_C5_4 +#define MPAMVPM5_EL2 S3_4_C10_C5_5 +#define MPAMVPM6_EL2 S3_4_C10_C5_6 +#define MPAMVPM7_EL2 S3_4_C10_C5_7 +#define MPAMVPMV_EL2 S3_4_C10_C4_1 +#define TRFCR_EL2 S3_4_C1_C2_1 +#define PMSCR_EL2 S3_4_C9_C9_0 +#define TFSR_EL2 S3_4_C5_C6_0 + +/******************************************************************************* + * Generic timer memory mapped registers & offsets + ******************************************************************************/ +#define CNTCR_OFF U(0x000) +#define CNTCV_OFF U(0x008) +#define CNTFID_OFF U(0x020) + +#define CNTCR_EN (U(1) << 0) +#define CNTCR_HDBG (U(1) << 1) +#define CNTCR_FCREQ(x) ((x) << 8) + +/******************************************************************************* + * System register bit definitions + ******************************************************************************/ +/* CLIDR definitions */ +#define LOUIS_SHIFT U(21) +#define LOC_SHIFT U(24) +#define CTYPE_SHIFT(n) U(3 * (n - 1)) +#define CLIDR_FIELD_WIDTH U(3) + +/* CSSELR definitions */ +#define LEVEL_SHIFT U(1) + +/* Data cache set/way op type defines */ +#define DCISW U(0x0) +#define DCCISW U(0x1) +#if ERRATA_A53_827319 +#define DCCSW DCCISW +#else +#define DCCSW U(0x2) +#endif + +/* ID_AA64PFR0_EL1 definitions */ +#define ID_AA64PFR0_EL0_SHIFT U(0) +#define ID_AA64PFR0_EL1_SHIFT U(4) +#define ID_AA64PFR0_EL2_SHIFT U(8) +#define ID_AA64PFR0_EL3_SHIFT U(12) +#define ID_AA64PFR0_AMU_SHIFT U(44) +#define ID_AA64PFR0_AMU_MASK ULL(0xf) +#define ID_AA64PFR0_AMU_NOT_SUPPORTED U(0x0) +#define ID_AA64PFR0_AMU_V1 U(0x1) +#define ID_AA64PFR0_AMU_V1P1 U(0x2) +#define ID_AA64PFR0_ELX_MASK ULL(0xf) +#define ID_AA64PFR0_GIC_SHIFT U(24) +#define ID_AA64PFR0_GIC_WIDTH U(4) +#define ID_AA64PFR0_GIC_MASK ULL(0xf) +#define ID_AA64PFR0_SVE_SHIFT U(32) +#define ID_AA64PFR0_SVE_MASK ULL(0xf) +#define ID_AA64PFR0_SEL2_SHIFT U(36) +#define ID_AA64PFR0_SEL2_MASK ULL(0xf) +#define ID_AA64PFR0_MPAM_SHIFT U(40) +#define ID_AA64PFR0_MPAM_MASK ULL(0xf) +#define ID_AA64PFR0_DIT_SHIFT U(48) +#define ID_AA64PFR0_DIT_MASK ULL(0xf) +#define ID_AA64PFR0_DIT_LENGTH U(4) +#define ID_AA64PFR0_DIT_SUPPORTED U(1) +#define ID_AA64PFR0_CSV2_SHIFT U(56) +#define ID_AA64PFR0_CSV2_MASK ULL(0xf) +#define ID_AA64PFR0_CSV2_LENGTH U(4) + +/* Exception level handling */ +#define EL_IMPL_NONE ULL(0) +#define EL_IMPL_A64ONLY ULL(1) +#define EL_IMPL_A64_A32 ULL(2) + +/* ID_AA64DFR0_EL1.PMS definitions (for ARMv8.2+) */ +#define ID_AA64DFR0_PMS_SHIFT U(32) +#define ID_AA64DFR0_PMS_MASK ULL(0xf) + +/* ID_AA64DFR0_EL1.MTPMU definitions (for ARMv8.6+) */ +#define ID_AA64DFR0_MTPMU_SHIFT U(48) +#define ID_AA64DFR0_MTPMU_MASK ULL(0xf) +#define ID_AA64DFR0_MTPMU_SUPPORTED ULL(1) + +/* ID_AA64ISAR0_EL1 definitions */ +#define ID_AA64ISAR0_RNDR_SHIFT U(60) +#define ID_AA64ISAR0_RNDR_MASK ULL(0xf) + +/* ID_AA64ISAR1_EL1 definitions */ +#define ID_AA64ISAR1_EL1 S3_0_C0_C6_1 +#define ID_AA64ISAR1_GPI_SHIFT U(28) +#define ID_AA64ISAR1_GPI_MASK ULL(0xf) +#define ID_AA64ISAR1_GPA_SHIFT U(24) +#define ID_AA64ISAR1_GPA_MASK ULL(0xf) +#define ID_AA64ISAR1_API_SHIFT U(8) +#define ID_AA64ISAR1_API_MASK ULL(0xf) +#define ID_AA64ISAR1_APA_SHIFT U(4) +#define ID_AA64ISAR1_APA_MASK ULL(0xf) + +/* ID_AA64MMFR0_EL1 definitions */ +#define ID_AA64MMFR0_EL1_PARANGE_SHIFT U(0) +#define ID_AA64MMFR0_EL1_PARANGE_MASK ULL(0xf) + +#define PARANGE_0000 U(32) +#define PARANGE_0001 U(36) +#define PARANGE_0010 U(40) +#define PARANGE_0011 U(42) +#define PARANGE_0100 U(44) +#define PARANGE_0101 U(48) +#define PARANGE_0110 U(52) + +#define ID_AA64MMFR0_EL1_ECV_SHIFT U(60) +#define ID_AA64MMFR0_EL1_ECV_MASK ULL(0xf) +#define ID_AA64MMFR0_EL1_ECV_NOT_SUPPORTED ULL(0x0) +#define ID_AA64MMFR0_EL1_ECV_SUPPORTED ULL(0x1) +#define ID_AA64MMFR0_EL1_ECV_SELF_SYNCH ULL(0x2) + +#define ID_AA64MMFR0_EL1_FGT_SHIFT U(56) +#define ID_AA64MMFR0_EL1_FGT_MASK ULL(0xf) +#define ID_AA64MMFR0_EL1_FGT_SUPPORTED ULL(0x1) +#define ID_AA64MMFR0_EL1_FGT_NOT_SUPPORTED ULL(0x0) + +#define ID_AA64MMFR0_EL1_TGRAN4_SHIFT U(28) +#define ID_AA64MMFR0_EL1_TGRAN4_MASK ULL(0xf) +#define ID_AA64MMFR0_EL1_TGRAN4_SUPPORTED ULL(0x0) +#define ID_AA64MMFR0_EL1_TGRAN4_NOT_SUPPORTED ULL(0xf) + +#define ID_AA64MMFR0_EL1_TGRAN64_SHIFT U(24) +#define ID_AA64MMFR0_EL1_TGRAN64_MASK ULL(0xf) +#define ID_AA64MMFR0_EL1_TGRAN64_SUPPORTED ULL(0x0) +#define ID_AA64MMFR0_EL1_TGRAN64_NOT_SUPPORTED ULL(0xf) + +#define ID_AA64MMFR0_EL1_TGRAN16_SHIFT U(20) +#define ID_AA64MMFR0_EL1_TGRAN16_MASK ULL(0xf) +#define ID_AA64MMFR0_EL1_TGRAN16_SUPPORTED ULL(0x1) +#define ID_AA64MMFR0_EL1_TGRAN16_NOT_SUPPORTED ULL(0x0) + +/* ID_AA64MMFR1_EL1 definitions */ +#define ID_AA64MMFR1_EL1_TWED_SHIFT U(32) +#define ID_AA64MMFR1_EL1_TWED_MASK ULL(0xf) +#define ID_AA64MMFR1_EL1_TWED_SUPPORTED ULL(0x1) +#define ID_AA64MMFR1_EL1_TWED_NOT_SUPPORTED ULL(0x0) + +#define ID_AA64MMFR1_EL1_PAN_SHIFT U(20) +#define ID_AA64MMFR1_EL1_PAN_MASK ULL(0xf) +#define ID_AA64MMFR1_EL1_PAN_NOT_SUPPORTED ULL(0x0) +#define ID_AA64MMFR1_EL1_PAN_SUPPORTED ULL(0x1) +#define ID_AA64MMFR1_EL1_PAN2_SUPPORTED ULL(0x2) +#define ID_AA64MMFR1_EL1_PAN3_SUPPORTED ULL(0x3) + +/* ID_AA64MMFR2_EL1 definitions */ +#define ID_AA64MMFR2_EL1 S3_0_C0_C7_2 + +#define ID_AA64MMFR2_EL1_ST_SHIFT U(28) +#define ID_AA64MMFR2_EL1_ST_MASK ULL(0xf) + +#define ID_AA64MMFR2_EL1_CNP_SHIFT U(0) +#define ID_AA64MMFR2_EL1_CNP_MASK ULL(0xf) + +/* ID_AA64PFR1_EL1 definitions */ +#define ID_AA64PFR1_EL1_SSBS_SHIFT U(4) +#define ID_AA64PFR1_EL1_SSBS_MASK ULL(0xf) + +#define SSBS_UNAVAILABLE ULL(0) /* No architectural SSBS support */ + +#define ID_AA64PFR1_EL1_BT_SHIFT U(0) +#define ID_AA64PFR1_EL1_BT_MASK ULL(0xf) + +#define BTI_IMPLEMENTED ULL(1) /* The BTI mechanism is implemented */ + +#define ID_AA64PFR1_EL1_MTE_SHIFT U(8) +#define ID_AA64PFR1_EL1_MTE_MASK ULL(0xf) + +/* Memory Tagging Extension is not implemented */ +#define MTE_UNIMPLEMENTED U(0) +/* FEAT_MTE: MTE instructions accessible at EL0 are implemented */ +#define MTE_IMPLEMENTED_EL0 U(1) +/* FEAT_MTE2: Full MTE is implemented */ +#define MTE_IMPLEMENTED_ELX U(2) +/* + * FEAT_MTE3: MTE is implemented with support for + * asymmetric Tag Check Fault handling + */ +#define MTE_IMPLEMENTED_ASY U(3) + +#define ID_AA64PFR1_MPAM_FRAC_SHIFT ULL(16) +#define ID_AA64PFR1_MPAM_FRAC_MASK ULL(0xf) + +/* ID_PFR1_EL1 definitions */ +#define ID_PFR1_VIRTEXT_SHIFT U(12) +#define ID_PFR1_VIRTEXT_MASK U(0xf) +#define GET_VIRT_EXT(id) (((id) >> ID_PFR1_VIRTEXT_SHIFT) \ + & ID_PFR1_VIRTEXT_MASK) + +/* SCTLR definitions */ +#define SCTLR_EL2_RES1 ((U(1) << 29) | (U(1) << 28) | (U(1) << 23) | \ + (U(1) << 22) | (U(1) << 18) | (U(1) << 16) | \ + (U(1) << 11) | (U(1) << 5) | (U(1) << 4)) + +#define SCTLR_EL1_RES1 ((UL(1) << 29) | (UL(1) << 28) | (UL(1) << 23) | \ + (UL(1) << 22) | (UL(1) << 20) | (UL(1) << 11)) + +#define SCTLR_AARCH32_EL1_RES1 \ + ((U(1) << 23) | (U(1) << 22) | (U(1) << 11) | \ + (U(1) << 4) | (U(1) << 3)) + +#define SCTLR_EL3_RES1 ((U(1) << 29) | (U(1) << 28) | (U(1) << 23) | \ + (U(1) << 22) | (U(1) << 18) | (U(1) << 16) | \ + (U(1) << 11) | (U(1) << 5) | (U(1) << 4)) + +#define SCTLR_M_BIT (ULL(1) << 0) +#define SCTLR_A_BIT (ULL(1) << 1) +#define SCTLR_C_BIT (ULL(1) << 2) +#define SCTLR_SA_BIT (ULL(1) << 3) +#define SCTLR_SA0_BIT (ULL(1) << 4) +#define SCTLR_CP15BEN_BIT (ULL(1) << 5) +#define SCTLR_nAA_BIT (ULL(1) << 6) +#define SCTLR_ITD_BIT (ULL(1) << 7) +#define SCTLR_SED_BIT (ULL(1) << 8) +#define SCTLR_UMA_BIT (ULL(1) << 9) +#define SCTLR_EnRCTX_BIT (ULL(1) << 10) +#define SCTLR_EOS_BIT (ULL(1) << 11) +#define SCTLR_I_BIT (ULL(1) << 12) +#define SCTLR_EnDB_BIT (ULL(1) << 13) +#define SCTLR_DZE_BIT (ULL(1) << 14) +#define SCTLR_UCT_BIT (ULL(1) << 15) +#define SCTLR_NTWI_BIT (ULL(1) << 16) +#define SCTLR_NTWE_BIT (ULL(1) << 18) +#define SCTLR_WXN_BIT (ULL(1) << 19) +#define SCTLR_TSCXT_BIT (ULL(1) << 20) +#define SCTLR_IESB_BIT (ULL(1) << 21) +#define SCTLR_EIS_BIT (ULL(1) << 22) +#define SCTLR_SPAN_BIT (ULL(1) << 23) +#define SCTLR_E0E_BIT (ULL(1) << 24) +#define SCTLR_EE_BIT (ULL(1) << 25) +#define SCTLR_UCI_BIT (ULL(1) << 26) +#define SCTLR_EnDA_BIT (ULL(1) << 27) +#define SCTLR_nTLSMD_BIT (ULL(1) << 28) +#define SCTLR_LSMAOE_BIT (ULL(1) << 29) +#define SCTLR_EnIB_BIT (ULL(1) << 30) +#define SCTLR_EnIA_BIT (ULL(1) << 31) +#define SCTLR_BT0_BIT (ULL(1) << 35) +#define SCTLR_BT1_BIT (ULL(1) << 36) +#define SCTLR_BT_BIT (ULL(1) << 36) +#define SCTLR_ITFSB_BIT (ULL(1) << 37) +#define SCTLR_TCF0_SHIFT U(38) +#define SCTLR_TCF0_MASK ULL(3) + +/* Tag Check Faults in EL0 have no effect on the PE */ +#define SCTLR_TCF0_NO_EFFECT U(0) +/* Tag Check Faults in EL0 cause a synchronous exception */ +#define SCTLR_TCF0_SYNC U(1) +/* Tag Check Faults in EL0 are asynchronously accumulated */ +#define SCTLR_TCF0_ASYNC U(2) +/* + * Tag Check Faults in EL0 cause a synchronous exception on reads, + * and are asynchronously accumulated on writes + */ +#define SCTLR_TCF0_SYNCR_ASYNCW U(3) + +#define SCTLR_TCF_SHIFT U(40) +#define SCTLR_TCF_MASK ULL(3) + +/* Tag Check Faults in EL1 have no effect on the PE */ +#define SCTLR_TCF_NO_EFFECT U(0) +/* Tag Check Faults in EL1 cause a synchronous exception */ +#define SCTLR_TCF_SYNC U(1) +/* Tag Check Faults in EL1 are asynchronously accumulated */ +#define SCTLR_TCF_ASYNC U(2) +/* + * Tag Check Faults in EL1 cause a synchronous exception on reads, + * and are asynchronously accumulated on writes + */ +#define SCTLR_TCF_SYNCR_ASYNCW U(3) + +#define SCTLR_ATA0_BIT (ULL(1) << 42) +#define SCTLR_ATA_BIT (ULL(1) << 43) +#define SCTLR_DSSBS_BIT (ULL(1) << 44) +#define SCTLR_TWEDEn_BIT (ULL(1) << 45) +#define SCTLR_TWEDEL_SHIFT U(46) +#define SCTLR_TWEDEL_MASK ULL(0xf) +#define SCTLR_EnASR_BIT (ULL(1) << 54) +#define SCTLR_EnAS0_BIT (ULL(1) << 55) +#define SCTLR_EnALS_BIT (ULL(1) << 56) +#define SCTLR_EPAN_BIT (ULL(1) << 57) +#define SCTLR_RESET_VAL SCTLR_EL3_RES1 + +/* CPACR_EL1 definitions */ +#define CPACR_EL1_FPEN(x) ((x) << 20) +#define CPACR_EL1_FP_TRAP_EL0 UL(0x1) +#define CPACR_EL1_FP_TRAP_ALL UL(0x2) +#define CPACR_EL1_FP_TRAP_NONE UL(0x3) + +/* SCR definitions */ +#define SCR_RES1_BITS ((U(1) << 4) | (U(1) << 5)) +#define SCR_TWEDEL_SHIFT U(30) +#define SCR_TWEDEL_MASK ULL(0xf) +#define SCR_AMVOFFEN_BIT (UL(1) << 35) +#define SCR_TWEDEn_BIT (UL(1) << 29) +#define SCR_ECVEN_BIT (UL(1) << 28) +#define SCR_FGTEN_BIT (UL(1) << 27) +#define SCR_ATA_BIT (UL(1) << 26) +#define SCR_FIEN_BIT (UL(1) << 21) +#define SCR_EEL2_BIT (UL(1) << 18) +#define SCR_API_BIT (UL(1) << 17) +#define SCR_APK_BIT (UL(1) << 16) +#define SCR_TERR_BIT (UL(1) << 15) +#define SCR_TWE_BIT (UL(1) << 13) +#define SCR_TWI_BIT (UL(1) << 12) +#define SCR_ST_BIT (UL(1) << 11) +#define SCR_RW_BIT (UL(1) << 10) +#define SCR_SIF_BIT (UL(1) << 9) +#define SCR_HCE_BIT (UL(1) << 8) +#define SCR_SMD_BIT (UL(1) << 7) +#define SCR_EA_BIT (UL(1) << 3) +#define SCR_FIQ_BIT (UL(1) << 2) +#define SCR_IRQ_BIT (UL(1) << 1) +#define SCR_NS_BIT (UL(1) << 0) +#define SCR_VALID_BIT_MASK U(0x2f8f) +#define SCR_RESET_VAL SCR_RES1_BITS + +/* MDCR_EL3 definitions */ +#define MDCR_MTPME_BIT (ULL(1) << 28) +#define MDCR_SCCD_BIT (ULL(1) << 23) +#define MDCR_SPME_BIT (ULL(1) << 17) +#define MDCR_SDD_BIT (ULL(1) << 16) +#define MDCR_SPD32(x) ((x) << 14) +#define MDCR_SPD32_LEGACY ULL(0x0) +#define MDCR_SPD32_DISABLE ULL(0x2) +#define MDCR_SPD32_ENABLE ULL(0x3) +#define MDCR_NSPB(x) ((x) << 12) +#define MDCR_NSPB_EL1 ULL(0x3) +#define MDCR_TDOSA_BIT (ULL(1) << 10) +#define MDCR_TDA_BIT (ULL(1) << 9) +#define MDCR_TPM_BIT (ULL(1) << 6) +#define MDCR_EL3_RESET_VAL ULL(0x0) + +/* MDCR_EL2 definitions */ +#define MDCR_EL2_MTPME (U(1) << 28) +#define MDCR_EL2_HLP (U(1) << 26) +#define MDCR_EL2_HCCD (U(1) << 23) +#define MDCR_EL2_TTRF (U(1) << 19) +#define MDCR_EL2_HPMD (U(1) << 17) +#define MDCR_EL2_TPMS (U(1) << 14) +#define MDCR_EL2_E2PB(x) ((x) << 12) +#define MDCR_EL2_E2PB_EL1 U(0x3) +#define MDCR_EL2_TDRA_BIT (U(1) << 11) +#define MDCR_EL2_TDOSA_BIT (U(1) << 10) +#define MDCR_EL2_TDA_BIT (U(1) << 9) +#define MDCR_EL2_TDE_BIT (U(1) << 8) +#define MDCR_EL2_HPME_BIT (U(1) << 7) +#define MDCR_EL2_TPM_BIT (U(1) << 6) +#define MDCR_EL2_TPMCR_BIT (U(1) << 5) +#define MDCR_EL2_RESET_VAL U(0x0) + +/* HSTR_EL2 definitions */ +#define HSTR_EL2_RESET_VAL U(0x0) +#define HSTR_EL2_T_MASK U(0xff) + +/* CNTHP_CTL_EL2 definitions */ +#define CNTHP_CTL_ENABLE_BIT (U(1) << 0) +#define CNTHP_CTL_RESET_VAL U(0x0) + +/* VTTBR_EL2 definitions */ +#define VTTBR_RESET_VAL ULL(0x0) +#define VTTBR_VMID_MASK ULL(0xff) +#define VTTBR_VMID_SHIFT U(48) +#define VTTBR_BADDR_MASK ULL(0xffffffffffff) +#define VTTBR_BADDR_SHIFT U(0) + +/* HCR definitions */ +#define HCR_AMVOFFEN_BIT (ULL(1) << 51) +#define HCR_API_BIT (ULL(1) << 41) +#define HCR_APK_BIT (ULL(1) << 40) +#define HCR_E2H_BIT (ULL(1) << 34) +#define HCR_TGE_BIT (ULL(1) << 27) +#define HCR_RW_SHIFT U(31) +#define HCR_RW_BIT (ULL(1) << HCR_RW_SHIFT) +#define HCR_AMO_BIT (ULL(1) << 5) +#define HCR_IMO_BIT (ULL(1) << 4) +#define HCR_FMO_BIT (ULL(1) << 3) + +/* ISR definitions */ +#define ISR_A_SHIFT U(8) +#define ISR_I_SHIFT U(7) +#define ISR_F_SHIFT U(6) + +/* CNTHCTL_EL2 definitions */ +#define CNTHCTL_RESET_VAL U(0x0) +#define EVNTEN_BIT (U(1) << 2) +#define EL1PCEN_BIT (U(1) << 1) +#define EL1PCTEN_BIT (U(1) << 0) + +/* CNTKCTL_EL1 definitions */ +#define EL0PTEN_BIT (U(1) << 9) +#define EL0VTEN_BIT (U(1) << 8) +#define EL0PCTEN_BIT (U(1) << 0) +#define EL0VCTEN_BIT (U(1) << 1) +#define EVNTEN_BIT (U(1) << 2) +#define EVNTDIR_BIT (U(1) << 3) +#define EVNTI_SHIFT U(4) +#define EVNTI_MASK U(0xf) + +/* CPTR_EL3 definitions */ +#define TCPAC_BIT (U(1) << 31) +#define TAM_BIT (U(1) << 30) +#define TTA_BIT (U(1) << 20) +#define TFP_BIT (U(1) << 10) +#define CPTR_EZ_BIT (U(1) << 8) +#define CPTR_EL3_RESET_VAL U(0x0) + +/* CPTR_EL2 definitions */ +#define CPTR_EL2_RES1 ((U(1) << 13) | (U(1) << 12) | (U(0x3ff))) +#define CPTR_EL2_TCPAC_BIT (U(1) << 31) +#define CPTR_EL2_TAM_BIT (U(1) << 30) +#define CPTR_EL2_TTA_BIT (U(1) << 20) +#define CPTR_EL2_TFP_BIT (U(1) << 10) +#define CPTR_EL2_TZ_BIT (U(1) << 8) +#define CPTR_EL2_RESET_VAL CPTR_EL2_RES1 + +/* CPSR/SPSR definitions */ +#define DAIF_FIQ_BIT (U(1) << 0) +#define DAIF_IRQ_BIT (U(1) << 1) +#define DAIF_ABT_BIT (U(1) << 2) +#define DAIF_DBG_BIT (U(1) << 3) +#define SPSR_DAIF_SHIFT U(6) +#define SPSR_DAIF_MASK U(0xf) + +#define SPSR_AIF_SHIFT U(6) +#define SPSR_AIF_MASK U(0x7) + +#define SPSR_E_SHIFT U(9) +#define SPSR_E_MASK U(0x1) +#define SPSR_E_LITTLE U(0x0) +#define SPSR_E_BIG U(0x1) + +#define SPSR_T_SHIFT U(5) +#define SPSR_T_MASK U(0x1) +#define SPSR_T_ARM U(0x0) +#define SPSR_T_THUMB U(0x1) + +#define SPSR_M_SHIFT U(4) +#define SPSR_M_MASK U(0x1) +#define SPSR_M_AARCH64 U(0x0) +#define SPSR_M_AARCH32 U(0x1) + +#define SPSR_EL_SHIFT U(2) +#define SPSR_EL_WIDTH U(2) + +#define SPSR_SSBS_BIT_AARCH64 BIT_64(12) +#define SPSR_SSBS_BIT_AARCH32 BIT_64(23) + +#define DISABLE_ALL_EXCEPTIONS \ + (DAIF_FIQ_BIT | DAIF_IRQ_BIT | DAIF_ABT_BIT | DAIF_DBG_BIT) + +#define DISABLE_INTERRUPTS (DAIF_FIQ_BIT | DAIF_IRQ_BIT) + +/* + * RMR_EL3 definitions + */ +#define RMR_EL3_RR_BIT (U(1) << 1) +#define RMR_EL3_AA64_BIT (U(1) << 0) + +/* + * HI-VECTOR address for AArch32 state + */ +#define HI_VECTOR_BASE U(0xFFFF0000) + +/* + * TCR defintions + */ +#define TCR_EL3_RES1 ((ULL(1) << 31) | (ULL(1) << 23)) +#define TCR_EL2_RES1 ((ULL(1) << 31) | (ULL(1) << 23)) +#define TCR_EL1_IPS_SHIFT U(32) +#define TCR_EL2_PS_SHIFT U(16) +#define TCR_EL3_PS_SHIFT U(16) + +#define TCR_TxSZ_MIN ULL(16) +#define TCR_TxSZ_MAX ULL(39) +#define TCR_TxSZ_MAX_TTST ULL(48) + +#define TCR_T0SZ_SHIFT U(0) +#define TCR_T1SZ_SHIFT U(16) + +/* (internal) physical address size bits in EL3/EL1 */ +#define TCR_PS_BITS_4GB ULL(0x0) +#define TCR_PS_BITS_64GB ULL(0x1) +#define TCR_PS_BITS_1TB ULL(0x2) +#define TCR_PS_BITS_4TB ULL(0x3) +#define TCR_PS_BITS_16TB ULL(0x4) +#define TCR_PS_BITS_256TB ULL(0x5) + +#define ADDR_MASK_48_TO_63 ULL(0xFFFF000000000000) +#define ADDR_MASK_44_TO_47 ULL(0x0000F00000000000) +#define ADDR_MASK_42_TO_43 ULL(0x00000C0000000000) +#define ADDR_MASK_40_TO_41 ULL(0x0000030000000000) +#define ADDR_MASK_36_TO_39 ULL(0x000000F000000000) +#define ADDR_MASK_32_TO_35 ULL(0x0000000F00000000) + +#define TCR_RGN_INNER_NC (ULL(0x0) << 8) +#define TCR_RGN_INNER_WBA (ULL(0x1) << 8) +#define TCR_RGN_INNER_WT (ULL(0x2) << 8) +#define TCR_RGN_INNER_WBNA (ULL(0x3) << 8) + +#define TCR_RGN_OUTER_NC (ULL(0x0) << 10) +#define TCR_RGN_OUTER_WBA (ULL(0x1) << 10) +#define TCR_RGN_OUTER_WT (ULL(0x2) << 10) +#define TCR_RGN_OUTER_WBNA (ULL(0x3) << 10) + +#define TCR_SH_NON_SHAREABLE (ULL(0x0) << 12) +#define TCR_SH_OUTER_SHAREABLE (ULL(0x2) << 12) +#define TCR_SH_INNER_SHAREABLE (ULL(0x3) << 12) + +#define TCR_RGN1_INNER_NC (ULL(0x0) << 24) +#define TCR_RGN1_INNER_WBA (ULL(0x1) << 24) +#define TCR_RGN1_INNER_WT (ULL(0x2) << 24) +#define TCR_RGN1_INNER_WBNA (ULL(0x3) << 24) + +#define TCR_RGN1_OUTER_NC (ULL(0x0) << 26) +#define TCR_RGN1_OUTER_WBA (ULL(0x1) << 26) +#define TCR_RGN1_OUTER_WT (ULL(0x2) << 26) +#define TCR_RGN1_OUTER_WBNA (ULL(0x3) << 26) + +#define TCR_SH1_NON_SHAREABLE (ULL(0x0) << 28) +#define TCR_SH1_OUTER_SHAREABLE (ULL(0x2) << 28) +#define TCR_SH1_INNER_SHAREABLE (ULL(0x3) << 28) + +#define TCR_TG0_SHIFT U(14) +#define TCR_TG0_MASK ULL(3) +#define TCR_TG0_4K (ULL(0) << TCR_TG0_SHIFT) +#define TCR_TG0_64K (ULL(1) << TCR_TG0_SHIFT) +#define TCR_TG0_16K (ULL(2) << TCR_TG0_SHIFT) + +#define TCR_TG1_SHIFT U(30) +#define TCR_TG1_MASK ULL(3) +#define TCR_TG1_16K (ULL(1) << TCR_TG1_SHIFT) +#define TCR_TG1_4K (ULL(2) << TCR_TG1_SHIFT) +#define TCR_TG1_64K (ULL(3) << TCR_TG1_SHIFT) + +#define TCR_EPD0_BIT (ULL(1) << 7) +#define TCR_EPD1_BIT (ULL(1) << 23) + +#define MODE_SP_SHIFT U(0x0) +#define MODE_SP_MASK U(0x1) +#define MODE_SP_EL0 U(0x0) +#define MODE_SP_ELX U(0x1) + +#define MODE_RW_SHIFT U(0x4) +#define MODE_RW_MASK U(0x1) +#define MODE_RW_64 U(0x0) +#define MODE_RW_32 U(0x1) + +#define MODE_EL_SHIFT U(0x2) +#define MODE_EL_MASK U(0x3) +#define MODE_EL_WIDTH U(0x2) +#define MODE_EL3 U(0x3) +#define MODE_EL2 U(0x2) +#define MODE_EL1 U(0x1) +#define MODE_EL0 U(0x0) + +#define MODE32_SHIFT U(0) +#define MODE32_MASK U(0xf) +#define MODE32_usr U(0x0) +#define MODE32_fiq U(0x1) +#define MODE32_irq U(0x2) +#define MODE32_svc U(0x3) +#define MODE32_mon U(0x6) +#define MODE32_abt U(0x7) +#define MODE32_hyp U(0xa) +#define MODE32_und U(0xb) +#define MODE32_sys U(0xf) + +#define GET_RW(mode) (((mode) >> MODE_RW_SHIFT) & MODE_RW_MASK) +#define GET_EL(mode) (((mode) >> MODE_EL_SHIFT) & MODE_EL_MASK) +#define GET_SP(mode) (((mode) >> MODE_SP_SHIFT) & MODE_SP_MASK) +#define GET_M32(mode) (((mode) >> MODE32_SHIFT) & MODE32_MASK) + +#define SPSR_64(el, sp, daif) \ + (((MODE_RW_64 << MODE_RW_SHIFT) | \ + (((el) & MODE_EL_MASK) << MODE_EL_SHIFT) | \ + (((sp) & MODE_SP_MASK) << MODE_SP_SHIFT) | \ + (((daif) & SPSR_DAIF_MASK) << SPSR_DAIF_SHIFT)) & \ + (~(SPSR_SSBS_BIT_AARCH64))) + +#define SPSR_MODE32(mode, isa, endian, aif) \ + (((MODE_RW_32 << MODE_RW_SHIFT) | \ + (((mode) & MODE32_MASK) << MODE32_SHIFT) | \ + (((isa) & SPSR_T_MASK) << SPSR_T_SHIFT) | \ + (((endian) & SPSR_E_MASK) << SPSR_E_SHIFT) | \ + (((aif) & SPSR_AIF_MASK) << SPSR_AIF_SHIFT)) & \ + (~(SPSR_SSBS_BIT_AARCH32))) + +/* + * TTBR Definitions + */ +#define TTBR_CNP_BIT ULL(0x1) + +/* + * CTR_EL0 definitions + */ +#define CTR_CWG_SHIFT U(24) +#define CTR_CWG_MASK U(0xf) +#define CTR_ERG_SHIFT U(20) +#define CTR_ERG_MASK U(0xf) +#define CTR_DMINLINE_SHIFT U(16) +#define CTR_DMINLINE_MASK U(0xf) +#define CTR_L1IP_SHIFT U(14) +#define CTR_L1IP_MASK U(0x3) +#define CTR_IMINLINE_SHIFT U(0) +#define CTR_IMINLINE_MASK U(0xf) + +#define MAX_CACHE_LINE_SIZE U(0x800) /* 2KB */ + +/* Physical timer control register bit fields shifts and masks */ +#define CNTP_CTL_ENABLE_SHIFT U(0) +#define CNTP_CTL_IMASK_SHIFT U(1) +#define CNTP_CTL_ISTATUS_SHIFT U(2) + +#define CNTP_CTL_ENABLE_MASK U(1) +#define CNTP_CTL_IMASK_MASK U(1) +#define CNTP_CTL_ISTATUS_MASK U(1) + +/* Physical timer control macros */ +#define CNTP_CTL_ENABLE_BIT (U(1) << CNTP_CTL_ENABLE_SHIFT) +#define CNTP_CTL_IMASK_BIT (U(1) << CNTP_CTL_IMASK_SHIFT) + +/* Exception Syndrome register bits and bobs */ +#define ESR_EC_SHIFT U(26) +#define ESR_EC_MASK U(0x3f) +#define ESR_EC_LENGTH U(6) +#define ESR_ISS_SHIFT U(0) +#define ESR_ISS_LENGTH U(25) +#define EC_UNKNOWN U(0x0) +#define EC_WFE_WFI U(0x1) +#define EC_AARCH32_CP15_MRC_MCR U(0x3) +#define EC_AARCH32_CP15_MRRC_MCRR U(0x4) +#define EC_AARCH32_CP14_MRC_MCR U(0x5) +#define EC_AARCH32_CP14_LDC_STC U(0x6) +#define EC_FP_SIMD U(0x7) +#define EC_AARCH32_CP10_MRC U(0x8) +#define EC_AARCH32_CP14_MRRC_MCRR U(0xc) +#define EC_ILLEGAL U(0xe) +#define EC_AARCH32_SVC U(0x11) +#define EC_AARCH32_HVC U(0x12) +#define EC_AARCH32_SMC U(0x13) +#define EC_AARCH64_SVC U(0x15) +#define EC_AARCH64_HVC U(0x16) +#define EC_AARCH64_SMC U(0x17) +#define EC_AARCH64_SYS U(0x18) +#define EC_IABORT_LOWER_EL U(0x20) +#define EC_IABORT_CUR_EL U(0x21) +#define EC_PC_ALIGN U(0x22) +#define EC_DABORT_LOWER_EL U(0x24) +#define EC_DABORT_CUR_EL U(0x25) +#define EC_SP_ALIGN U(0x26) +#define EC_AARCH32_FP U(0x28) +#define EC_AARCH64_FP U(0x2c) +#define EC_SERROR U(0x2f) +#define EC_BRK U(0x3c) + +/* + * External Abort bit in Instruction and Data Aborts synchronous exception + * syndromes. + */ +#define ESR_ISS_EABORT_EA_BIT U(9) + +#define EC_BITS(x) (((x) >> ESR_EC_SHIFT) & ESR_EC_MASK) + +/* Reset bit inside the Reset management register for EL3 (RMR_EL3) */ +#define RMR_RESET_REQUEST_SHIFT U(0x1) +#define RMR_WARM_RESET_CPU (U(1) << RMR_RESET_REQUEST_SHIFT) + +/******************************************************************************* + * Definitions of register offsets, fields and macros for CPU system + * instructions. + ******************************************************************************/ + +#define TLBI_ADDR_SHIFT U(12) +#define TLBI_ADDR_MASK ULL(0x00000FFFFFFFFFFF) +#define TLBI_ADDR(x) (((x) >> TLBI_ADDR_SHIFT) & TLBI_ADDR_MASK) + +/******************************************************************************* + * Definitions of register offsets and fields in the CNTCTLBase Frame of the + * system level implementation of the Generic Timer. + ******************************************************************************/ +#define CNTCTLBASE_CNTFRQ U(0x0) +#define CNTNSAR U(0x4) +#define CNTNSAR_NS_SHIFT(x) (x) + +#define CNTACR_BASE(x) (U(0x40) + ((x) << 2)) +#define CNTACR_RPCT_SHIFT U(0x0) +#define CNTACR_RVCT_SHIFT U(0x1) +#define CNTACR_RFRQ_SHIFT U(0x2) +#define CNTACR_RVOFF_SHIFT U(0x3) +#define CNTACR_RWVT_SHIFT U(0x4) +#define CNTACR_RWPT_SHIFT U(0x5) + +/******************************************************************************* + * Definitions of register offsets and fields in the CNTBaseN Frame of the + * system level implementation of the Generic Timer. + ******************************************************************************/ +/* Physical Count register. */ +#define CNTPCT_LO U(0x0) +/* Counter Frequency register. */ +#define CNTBASEN_CNTFRQ U(0x10) +/* Physical Timer CompareValue register. */ +#define CNTP_CVAL_LO U(0x20) +/* Physical Timer Control register. */ +#define CNTP_CTL U(0x2c) + +/* PMCR_EL0 definitions */ +#define PMCR_EL0_RESET_VAL U(0x0) +#define PMCR_EL0_N_SHIFT U(11) +#define PMCR_EL0_N_MASK U(0x1f) +#define PMCR_EL0_N_BITS (PMCR_EL0_N_MASK << PMCR_EL0_N_SHIFT) +#define PMCR_EL0_LP_BIT (U(1) << 7) +#define PMCR_EL0_LC_BIT (U(1) << 6) +#define PMCR_EL0_DP_BIT (U(1) << 5) +#define PMCR_EL0_X_BIT (U(1) << 4) +#define PMCR_EL0_D_BIT (U(1) << 3) +#define PMCR_EL0_C_BIT (U(1) << 2) +#define PMCR_EL0_P_BIT (U(1) << 1) +#define PMCR_EL0_E_BIT (U(1) << 0) + +/******************************************************************************* + * Definitions for system register interface to SVE + ******************************************************************************/ +#define ZCR_EL3 S3_6_C1_C2_0 +#define ZCR_EL2 S3_4_C1_C2_0 + +/* ZCR_EL3 definitions */ +#define ZCR_EL3_LEN_MASK U(0xf) + +/* ZCR_EL2 definitions */ +#define ZCR_EL2_LEN_MASK U(0xf) + +/******************************************************************************* + * Definitions of MAIR encodings for device and normal memory + ******************************************************************************/ +/* + * MAIR encodings for device memory attributes. + */ +#define MAIR_DEV_nGnRnE ULL(0x0) +#define MAIR_DEV_nGnRE ULL(0x4) +#define MAIR_DEV_nGRE ULL(0x8) +#define MAIR_DEV_GRE ULL(0xc) + +/* + * MAIR encodings for normal memory attributes. + * + * Cache Policy + * WT: Write Through + * WB: Write Back + * NC: Non-Cacheable + * + * Transient Hint + * NTR: Non-Transient + * TR: Transient + * + * Allocation Policy + * RA: Read Allocate + * WA: Write Allocate + * RWA: Read and Write Allocate + * NA: No Allocation + */ +#define MAIR_NORM_WT_TR_WA ULL(0x1) +#define MAIR_NORM_WT_TR_RA ULL(0x2) +#define MAIR_NORM_WT_TR_RWA ULL(0x3) +#define MAIR_NORM_NC ULL(0x4) +#define MAIR_NORM_WB_TR_WA ULL(0x5) +#define MAIR_NORM_WB_TR_RA ULL(0x6) +#define MAIR_NORM_WB_TR_RWA ULL(0x7) +#define MAIR_NORM_WT_NTR_NA ULL(0x8) +#define MAIR_NORM_WT_NTR_WA ULL(0x9) +#define MAIR_NORM_WT_NTR_RA ULL(0xa) +#define MAIR_NORM_WT_NTR_RWA ULL(0xb) +#define MAIR_NORM_WB_NTR_NA ULL(0xc) +#define MAIR_NORM_WB_NTR_WA ULL(0xd) +#define MAIR_NORM_WB_NTR_RA ULL(0xe) +#define MAIR_NORM_WB_NTR_RWA ULL(0xf) + +#define MAIR_NORM_OUTER_SHIFT U(4) + +#define MAKE_MAIR_NORMAL_MEMORY(inner, outer) \ + ((inner) | ((outer) << MAIR_NORM_OUTER_SHIFT)) + +/* PAR_EL1 fields */ +#define PAR_F_SHIFT U(0) +#define PAR_F_MASK ULL(0x1) +#define PAR_ADDR_SHIFT U(12) +#define PAR_ADDR_MASK (BIT(40) - ULL(1)) /* 40-bits-wide page address */ + +/******************************************************************************* + * Definitions for system register interface to SPE + ******************************************************************************/ +#define PMBLIMITR_EL1 S3_0_C9_C10_0 + +/******************************************************************************* + * Definitions for system register interface to MPAM + ******************************************************************************/ +#define MPAMIDR_EL1 S3_0_C10_C4_4 +#define MPAM2_EL2 S3_4_C10_C5_0 +#define MPAMHCR_EL2 S3_4_C10_C4_0 +#define MPAM3_EL3 S3_6_C10_C5_0 + +/******************************************************************************* + * Definitions for system register interface to AMU for FEAT_AMUv1 + ******************************************************************************/ +#define AMCR_EL0 S3_3_C13_C2_0 +#define AMCFGR_EL0 S3_3_C13_C2_1 +#define AMCGCR_EL0 S3_3_C13_C2_2 +#define AMUSERENR_EL0 S3_3_C13_C2_3 +#define AMCNTENCLR0_EL0 S3_3_C13_C2_4 +#define AMCNTENSET0_EL0 S3_3_C13_C2_5 +#define AMCNTENCLR1_EL0 S3_3_C13_C3_0 +#define AMCNTENSET1_EL0 S3_3_C13_C3_1 + +/* Activity Monitor Group 0 Event Counter Registers */ +#define AMEVCNTR00_EL0 S3_3_C13_C4_0 +#define AMEVCNTR01_EL0 S3_3_C13_C4_1 +#define AMEVCNTR02_EL0 S3_3_C13_C4_2 +#define AMEVCNTR03_EL0 S3_3_C13_C4_3 + +/* Activity Monitor Group 0 Event Type Registers */ +#define AMEVTYPER00_EL0 S3_3_C13_C6_0 +#define AMEVTYPER01_EL0 S3_3_C13_C6_1 +#define AMEVTYPER02_EL0 S3_3_C13_C6_2 +#define AMEVTYPER03_EL0 S3_3_C13_C6_3 + +/* Activity Monitor Group 1 Event Counter Registers */ +#define AMEVCNTR10_EL0 S3_3_C13_C12_0 +#define AMEVCNTR11_EL0 S3_3_C13_C12_1 +#define AMEVCNTR12_EL0 S3_3_C13_C12_2 +#define AMEVCNTR13_EL0 S3_3_C13_C12_3 +#define AMEVCNTR14_EL0 S3_3_C13_C12_4 +#define AMEVCNTR15_EL0 S3_3_C13_C12_5 +#define AMEVCNTR16_EL0 S3_3_C13_C12_6 +#define AMEVCNTR17_EL0 S3_3_C13_C12_7 +#define AMEVCNTR18_EL0 S3_3_C13_C13_0 +#define AMEVCNTR19_EL0 S3_3_C13_C13_1 +#define AMEVCNTR1A_EL0 S3_3_C13_C13_2 +#define AMEVCNTR1B_EL0 S3_3_C13_C13_3 +#define AMEVCNTR1C_EL0 S3_3_C13_C13_4 +#define AMEVCNTR1D_EL0 S3_3_C13_C13_5 +#define AMEVCNTR1E_EL0 S3_3_C13_C13_6 +#define AMEVCNTR1F_EL0 S3_3_C13_C13_7 + +/* Activity Monitor Group 1 Event Type Registers */ +#define AMEVTYPER10_EL0 S3_3_C13_C14_0 +#define AMEVTYPER11_EL0 S3_3_C13_C14_1 +#define AMEVTYPER12_EL0 S3_3_C13_C14_2 +#define AMEVTYPER13_EL0 S3_3_C13_C14_3 +#define AMEVTYPER14_EL0 S3_3_C13_C14_4 +#define AMEVTYPER15_EL0 S3_3_C13_C14_5 +#define AMEVTYPER16_EL0 S3_3_C13_C14_6 +#define AMEVTYPER17_EL0 S3_3_C13_C14_7 +#define AMEVTYPER18_EL0 S3_3_C13_C15_0 +#define AMEVTYPER19_EL0 S3_3_C13_C15_1 +#define AMEVTYPER1A_EL0 S3_3_C13_C15_2 +#define AMEVTYPER1B_EL0 S3_3_C13_C15_3 +#define AMEVTYPER1C_EL0 S3_3_C13_C15_4 +#define AMEVTYPER1D_EL0 S3_3_C13_C15_5 +#define AMEVTYPER1E_EL0 S3_3_C13_C15_6 +#define AMEVTYPER1F_EL0 S3_3_C13_C15_7 + +/* AMCFGR_EL0 definitions */ +#define AMCFGR_EL0_NCG_SHIFT U(28) +#define AMCFGR_EL0_NCG_MASK U(0xf) +#define AMCFGR_EL0_N_SHIFT U(0) +#define AMCFGR_EL0_N_MASK U(0xff) + +/* AMCGCR_EL0 definitions */ +#define AMCGCR_EL0_CG1NC_SHIFT U(8) +#define AMCGCR_EL0_CG1NC_MASK U(0xff) + +/* MPAM register definitions */ +#define MPAM3_EL3_MPAMEN_BIT (ULL(1) << 63) +#define MPAMHCR_EL2_TRAP_MPAMIDR_EL1 (ULL(1) << 31) + +#define MPAM2_EL2_TRAPMPAM0EL1 (ULL(1) << 49) +#define MPAM2_EL2_TRAPMPAM1EL1 (ULL(1) << 48) + +#define MPAMIDR_HAS_HCR_BIT (ULL(1) << 17) + +/******************************************************************************* + * Definitions for system register interface to AMU for FEAT_AMUv1p1 + ******************************************************************************/ + +/* Definition for register defining which virtual offsets are implemented. */ +#define AMCG1IDR_EL0 S3_3_C13_C2_6 +#define AMCG1IDR_CTR_MASK ULL(0xffff) +#define AMCG1IDR_CTR_SHIFT U(0) +#define AMCG1IDR_VOFF_MASK ULL(0xffff) +#define AMCG1IDR_VOFF_SHIFT U(16) + +/* New bit added to AMCR_EL0 */ +#define AMCR_CG1RZ_BIT (ULL(0x1) << 17) + +/* + * Definitions for virtual offset registers for architected activity monitor + * event counters. + * AMEVCNTVOFF01_EL2 intentionally left undefined, as it does not exist. + */ +#define AMEVCNTVOFF00_EL2 S3_4_C13_C8_0 +#define AMEVCNTVOFF02_EL2 S3_4_C13_C8_2 +#define AMEVCNTVOFF03_EL2 S3_4_C13_C8_3 + +/* + * Definitions for virtual offset registers for auxiliary activity monitor event + * counters. + */ +#define AMEVCNTVOFF10_EL2 S3_4_C13_C10_0 +#define AMEVCNTVOFF11_EL2 S3_4_C13_C10_1 +#define AMEVCNTVOFF12_EL2 S3_4_C13_C10_2 +#define AMEVCNTVOFF13_EL2 S3_4_C13_C10_3 +#define AMEVCNTVOFF14_EL2 S3_4_C13_C10_4 +#define AMEVCNTVOFF15_EL2 S3_4_C13_C10_5 +#define AMEVCNTVOFF16_EL2 S3_4_C13_C10_6 +#define AMEVCNTVOFF17_EL2 S3_4_C13_C10_7 +#define AMEVCNTVOFF18_EL2 S3_4_C13_C11_0 +#define AMEVCNTVOFF19_EL2 S3_4_C13_C11_1 +#define AMEVCNTVOFF1A_EL2 S3_4_C13_C11_2 +#define AMEVCNTVOFF1B_EL2 S3_4_C13_C11_3 +#define AMEVCNTVOFF1C_EL2 S3_4_C13_C11_4 +#define AMEVCNTVOFF1D_EL2 S3_4_C13_C11_5 +#define AMEVCNTVOFF1E_EL2 S3_4_C13_C11_6 +#define AMEVCNTVOFF1F_EL2 S3_4_C13_C11_7 + +/******************************************************************************* + * RAS system registers + ******************************************************************************/ +#define DISR_EL1 S3_0_C12_C1_1 +#define DISR_A_BIT U(31) + +#define ERRIDR_EL1 S3_0_C5_C3_0 +#define ERRIDR_MASK U(0xffff) + +#define ERRSELR_EL1 S3_0_C5_C3_1 + +/* System register access to Standard Error Record registers */ +#define ERXFR_EL1 S3_0_C5_C4_0 +#define ERXCTLR_EL1 S3_0_C5_C4_1 +#define ERXSTATUS_EL1 S3_0_C5_C4_2 +#define ERXADDR_EL1 S3_0_C5_C4_3 +#define ERXPFGF_EL1 S3_0_C5_C4_4 +#define ERXPFGCTL_EL1 S3_0_C5_C4_5 +#define ERXPFGCDN_EL1 S3_0_C5_C4_6 +#define ERXMISC0_EL1 S3_0_C5_C5_0 +#define ERXMISC1_EL1 S3_0_C5_C5_1 + +#define ERXCTLR_ED_BIT (U(1) << 0) +#define ERXCTLR_UE_BIT (U(1) << 4) + +#define ERXPFGCTL_UC_BIT (U(1) << 1) +#define ERXPFGCTL_UEU_BIT (U(1) << 2) +#define ERXPFGCTL_CDEN_BIT (U(1) << 31) + +/******************************************************************************* + * Armv8.3 Pointer Authentication Registers + ******************************************************************************/ +#define APIAKeyLo_EL1 S3_0_C2_C1_0 +#define APIAKeyHi_EL1 S3_0_C2_C1_1 +#define APIBKeyLo_EL1 S3_0_C2_C1_2 +#define APIBKeyHi_EL1 S3_0_C2_C1_3 +#define APDAKeyLo_EL1 S3_0_C2_C2_0 +#define APDAKeyHi_EL1 S3_0_C2_C2_1 +#define APDBKeyLo_EL1 S3_0_C2_C2_2 +#define APDBKeyHi_EL1 S3_0_C2_C2_3 +#define APGAKeyLo_EL1 S3_0_C2_C3_0 +#define APGAKeyHi_EL1 S3_0_C2_C3_1 + +/******************************************************************************* + * Armv8.4 Data Independent Timing Registers + ******************************************************************************/ +#define DIT S3_3_C4_C2_5 +#define DIT_BIT BIT(24) + +/******************************************************************************* + * Armv8.5 - new MSR encoding to directly access PSTATE.SSBS field + ******************************************************************************/ +#define SSBS S3_3_C4_C2_6 + +/******************************************************************************* + * Armv8.5 - Memory Tagging Extension Registers + ******************************************************************************/ +#define TFSRE0_EL1 S3_0_C5_C6_1 +#define TFSR_EL1 S3_0_C5_C6_0 +#define RGSR_EL1 S3_0_C1_C0_5 +#define GCR_EL1 S3_0_C1_C0_6 + +/******************************************************************************* + * Definitions for DynamicIQ Shared Unit registers + ******************************************************************************/ +#define CLUSTERPWRDN_EL1 S3_0_c15_c3_6 + +/* CLUSTERPWRDN_EL1 register definitions */ +#define DSU_CLUSTER_PWR_OFF 0 +#define DSU_CLUSTER_PWR_ON 1 +#define DSU_CLUSTER_PWR_MASK U(1) + +#endif /* ARCH_H */ diff --git a/drivers/rz/ipl/rza/include/arch/aarch64/arch_features.h b/drivers/rz/ipl/rza/include/arch/aarch64/arch_features.h new file mode 100644 index 00000000..47a797a1 --- /dev/null +++ b/drivers/rz/ipl/rza/include/arch/aarch64/arch_features.h @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2019-2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef ARCH_FEATURES_H +#define ARCH_FEATURES_H + +#include + +#include + +static inline bool is_armv7_gentimer_present(void) +{ + /* The Generic Timer is always present in an ARMv8-A implementation */ + return true; +} + +static inline bool is_armv8_2_ttcnp_present(void) +{ + return ((read_id_aa64mmfr2_el1() >> ID_AA64MMFR2_EL1_CNP_SHIFT) & + ID_AA64MMFR2_EL1_CNP_MASK) != 0U; +} + +static inline bool is_armv8_3_pauth_present(void) +{ + uint64_t mask = (ID_AA64ISAR1_GPI_MASK << ID_AA64ISAR1_GPI_SHIFT) | + (ID_AA64ISAR1_GPA_MASK << ID_AA64ISAR1_GPA_SHIFT) | + (ID_AA64ISAR1_API_MASK << ID_AA64ISAR1_API_SHIFT) | + (ID_AA64ISAR1_APA_MASK << ID_AA64ISAR1_APA_SHIFT); + + /* If any of the fields is not zero, PAuth is present */ + return (read_id_aa64isar1_el1() & mask) != 0U; +} + +static inline bool is_armv8_4_ttst_present(void) +{ + return ((read_id_aa64mmfr2_el1() >> ID_AA64MMFR2_EL1_ST_SHIFT) & + ID_AA64MMFR2_EL1_ST_MASK) == 1U; +} + +static inline bool is_armv8_5_bti_present(void) +{ + return ((read_id_aa64pfr1_el1() >> ID_AA64PFR1_EL1_BT_SHIFT) & + ID_AA64PFR1_EL1_BT_MASK) == BTI_IMPLEMENTED; +} + +static inline unsigned int get_armv8_5_mte_support(void) +{ + return ((read_id_aa64pfr1_el1() >> ID_AA64PFR1_EL1_MTE_SHIFT) & + ID_AA64PFR1_EL1_MTE_MASK); +} + +static inline bool is_armv8_4_sel2_present(void) +{ + return ((read_id_aa64pfr0_el1() >> ID_AA64PFR0_SEL2_SHIFT) & + ID_AA64PFR0_SEL2_MASK) == 1ULL; +} + +static inline bool is_armv8_6_twed_present(void) +{ + return (((read_id_aa64mmfr1_el1() >> ID_AA64MMFR1_EL1_TWED_SHIFT) & + ID_AA64MMFR1_EL1_TWED_MASK) == ID_AA64MMFR1_EL1_TWED_SUPPORTED); +} + +static inline bool is_armv8_6_fgt_present(void) +{ + return ((read_id_aa64mmfr0_el1() >> ID_AA64MMFR0_EL1_FGT_SHIFT) & + ID_AA64MMFR0_EL1_FGT_MASK) == ID_AA64MMFR0_EL1_FGT_SUPPORTED; +} + +static inline unsigned long int get_armv8_6_ecv_support(void) +{ + return ((read_id_aa64mmfr0_el1() >> ID_AA64MMFR0_EL1_ECV_SHIFT) & + ID_AA64MMFR0_EL1_ECV_MASK); +} + +static inline bool is_armv8_5_rng_present(void) +{ + return ((read_id_aa64isar0_el1() >> ID_AA64ISAR0_RNDR_SHIFT) & + ID_AA64ISAR0_RNDR_MASK); +} + +static inline bool is_armv8_6_feat_amuv1p1_present(void) +{ + return (((read_id_aa64pfr0_el1() >> ID_AA64PFR0_AMU_SHIFT) & + ID_AA64PFR0_AMU_MASK) >= ID_AA64PFR0_AMU_V1P1); +} + +/* + * Return MPAM version: + * + * 0x00: None Armv8.0 or later + * 0x01: v0.1 Armv8.4 or later + * 0x10: v1.0 Armv8.2 or later + * 0x11: v1.1 Armv8.4 or later + * + */ +static inline unsigned int get_mpam_version(void) +{ + return (unsigned int)((((read_id_aa64pfr0_el1() >> + ID_AA64PFR0_MPAM_SHIFT) & ID_AA64PFR0_MPAM_MASK) << 4) | + ((read_id_aa64pfr1_el1() >> + ID_AA64PFR1_MPAM_FRAC_SHIFT) & ID_AA64PFR1_MPAM_FRAC_MASK)); +} + +#endif /* ARCH_FEATURES_H */ diff --git a/drivers/rz/ipl/rza/include/arch/aarch64/arch_helpers.h b/drivers/rz/ipl/rza/include/arch/aarch64/arch_helpers.h new file mode 100644 index 00000000..a41b3258 --- /dev/null +++ b/drivers/rz/ipl/rza/include/arch/aarch64/arch_helpers.h @@ -0,0 +1,623 @@ +/* + * Copyright (c) 2013-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef ARCH_HELPERS_H +#define ARCH_HELPERS_H + +#include +#include +#include +#include + +#include + +/********************************************************************** + * Macros which create inline functions to read or write CPU system + * registers + *********************************************************************/ + +#define _DEFINE_SYSREG_READ_FUNC(_name, _reg_name) \ +static inline u_register_t read_ ## _name(void) \ +{ \ + u_register_t v; \ + __asm__ volatile ("mrs %0, " #_reg_name : "=r" (v)); \ + return v; \ +} + +#define _DEFINE_SYSREG_WRITE_FUNC(_name, _reg_name) \ +static inline void write_ ## _name(u_register_t v) \ +{ \ + __asm__ volatile ("msr " #_reg_name ", %0" : : "r" (v)); \ +} + +#define SYSREG_WRITE_CONST(reg_name, v) \ + __asm__ volatile ("msr " #reg_name ", %0" : : "i" (v)) + +/* Define read function for system register */ +#define DEFINE_SYSREG_READ_FUNC(_name) \ + _DEFINE_SYSREG_READ_FUNC(_name, _name) + +/* Define read & write function for system register */ +#define DEFINE_SYSREG_RW_FUNCS(_name) \ + _DEFINE_SYSREG_READ_FUNC(_name, _name) \ + _DEFINE_SYSREG_WRITE_FUNC(_name, _name) + +/* Define read & write function for renamed system register */ +#define DEFINE_RENAME_SYSREG_RW_FUNCS(_name, _reg_name) \ + _DEFINE_SYSREG_READ_FUNC(_name, _reg_name) \ + _DEFINE_SYSREG_WRITE_FUNC(_name, _reg_name) + +/* Define read function for renamed system register */ +#define DEFINE_RENAME_SYSREG_READ_FUNC(_name, _reg_name) \ + _DEFINE_SYSREG_READ_FUNC(_name, _reg_name) + +/* Define write function for renamed system register */ +#define DEFINE_RENAME_SYSREG_WRITE_FUNC(_name, _reg_name) \ + _DEFINE_SYSREG_WRITE_FUNC(_name, _reg_name) + +/********************************************************************** + * Macros to create inline functions for system instructions + *********************************************************************/ + +/* Define function for simple system instruction */ +#define DEFINE_SYSOP_FUNC(_op) \ +static inline void _op(void) \ +{ \ + __asm__ (#_op); \ +} + +/* Define function for system instruction with register parameter */ +#define DEFINE_SYSOP_PARAM_FUNC(_op) \ +static inline void _op(uint64_t v) \ +{ \ + __asm__ (#_op " %0" : : "r" (v)); \ +} + +/* Define function for system instruction with type specifier */ +#define DEFINE_SYSOP_TYPE_FUNC(_op, _type) \ +static inline void _op ## _type(void) \ +{ \ + __asm__ (#_op " " #_type : : : "memory"); \ +} + +/* Define function for system instruction with register parameter */ +#define DEFINE_SYSOP_TYPE_PARAM_FUNC(_op, _type) \ +static inline void _op ## _type(uint64_t v) \ +{ \ + __asm__ (#_op " " #_type ", %0" : : "r" (v)); \ +} + +/******************************************************************************* + * TLB maintenance accessor prototypes + ******************************************************************************/ + +#if ERRATA_A57_813419 || ERRATA_A76_1286807 +/* + * Define function for TLBI instruction with type specifier that implements + * the workaround for errata 813419 of Cortex-A57 or errata 1286807 of + * Cortex-A76. + */ +#define DEFINE_TLBIOP_ERRATA_TYPE_FUNC(_type)\ +static inline void tlbi ## _type(void) \ +{ \ + __asm__("tlbi " #_type "\n" \ + "dsb ish\n" \ + "tlbi " #_type); \ +} + +/* + * Define function for TLBI instruction with register parameter that implements + * the workaround for errata 813419 of Cortex-A57 or errata 1286807 of + * Cortex-A76. + */ +#define DEFINE_TLBIOP_ERRATA_TYPE_PARAM_FUNC(_type) \ +static inline void tlbi ## _type(uint64_t v) \ +{ \ + __asm__("tlbi " #_type ", %0\n" \ + "dsb ish\n" \ + "tlbi " #_type ", %0" : : "r" (v)); \ +} +#endif /* ERRATA_A57_813419 */ + +#if ERRATA_A53_819472 || ERRATA_A53_824069 || ERRATA_A53_827319 +/* + * Define function for DC instruction with register parameter that enables + * the workaround for errata 819472, 824069 and 827319 of Cortex-A53. + */ +#define DEFINE_DCOP_ERRATA_A53_TYPE_PARAM_FUNC(_name, _type) \ +static inline void dc ## _name(uint64_t v) \ +{ \ + __asm__("dc " #_type ", %0" : : "r" (v)); \ +} +#endif /* ERRATA_A53_819472 || ERRATA_A53_824069 || ERRATA_A53_827319 */ + +#if ERRATA_A57_813419 +DEFINE_SYSOP_TYPE_FUNC(tlbi, alle1) +DEFINE_SYSOP_TYPE_FUNC(tlbi, alle1is) +DEFINE_SYSOP_TYPE_FUNC(tlbi, alle2) +DEFINE_SYSOP_TYPE_FUNC(tlbi, alle2is) +DEFINE_TLBIOP_ERRATA_TYPE_FUNC(alle3) +DEFINE_TLBIOP_ERRATA_TYPE_FUNC(alle3is) +DEFINE_SYSOP_TYPE_FUNC(tlbi, vmalle1) +#elif ERRATA_A76_1286807 +DEFINE_TLBIOP_ERRATA_TYPE_FUNC(alle1) +DEFINE_TLBIOP_ERRATA_TYPE_FUNC(alle1is) +DEFINE_TLBIOP_ERRATA_TYPE_FUNC(alle2) +DEFINE_TLBIOP_ERRATA_TYPE_FUNC(alle2is) +DEFINE_TLBIOP_ERRATA_TYPE_FUNC(alle3) +DEFINE_TLBIOP_ERRATA_TYPE_FUNC(alle3is) +DEFINE_TLBIOP_ERRATA_TYPE_FUNC(vmalle1) +#else +DEFINE_SYSOP_TYPE_FUNC(tlbi, alle1) +DEFINE_SYSOP_TYPE_FUNC(tlbi, alle1is) +DEFINE_SYSOP_TYPE_FUNC(tlbi, alle2) +DEFINE_SYSOP_TYPE_FUNC(tlbi, alle2is) +DEFINE_SYSOP_TYPE_FUNC(tlbi, alle3) +DEFINE_SYSOP_TYPE_FUNC(tlbi, alle3is) +DEFINE_SYSOP_TYPE_FUNC(tlbi, vmalle1) +#endif + +#if ERRATA_A57_813419 +DEFINE_SYSOP_TYPE_PARAM_FUNC(tlbi, vaae1is) +DEFINE_SYSOP_TYPE_PARAM_FUNC(tlbi, vaale1is) +DEFINE_SYSOP_TYPE_PARAM_FUNC(tlbi, vae2is) +DEFINE_SYSOP_TYPE_PARAM_FUNC(tlbi, vale2is) +DEFINE_TLBIOP_ERRATA_TYPE_PARAM_FUNC(vae3is) +DEFINE_TLBIOP_ERRATA_TYPE_PARAM_FUNC(vale3is) +#elif ERRATA_A76_1286807 +DEFINE_TLBIOP_ERRATA_TYPE_PARAM_FUNC(vaae1is) +DEFINE_TLBIOP_ERRATA_TYPE_PARAM_FUNC(vaale1is) +DEFINE_TLBIOP_ERRATA_TYPE_PARAM_FUNC(vae2is) +DEFINE_TLBIOP_ERRATA_TYPE_PARAM_FUNC(vale2is) +DEFINE_TLBIOP_ERRATA_TYPE_PARAM_FUNC(vae3is) +DEFINE_TLBIOP_ERRATA_TYPE_PARAM_FUNC(vale3is) +#else +DEFINE_SYSOP_TYPE_PARAM_FUNC(tlbi, vaae1is) +DEFINE_SYSOP_TYPE_PARAM_FUNC(tlbi, vaale1is) +DEFINE_SYSOP_TYPE_PARAM_FUNC(tlbi, vae2is) +DEFINE_SYSOP_TYPE_PARAM_FUNC(tlbi, vale2is) +DEFINE_SYSOP_TYPE_PARAM_FUNC(tlbi, vae3is) +DEFINE_SYSOP_TYPE_PARAM_FUNC(tlbi, vale3is) +#endif + +/******************************************************************************* + * Cache maintenance accessor prototypes + ******************************************************************************/ +DEFINE_SYSOP_TYPE_PARAM_FUNC(dc, isw) +DEFINE_SYSOP_TYPE_PARAM_FUNC(dc, cisw) +#if ERRATA_A53_827319 +DEFINE_DCOP_ERRATA_A53_TYPE_PARAM_FUNC(csw, cisw) +#else +DEFINE_SYSOP_TYPE_PARAM_FUNC(dc, csw) +#endif +#if ERRATA_A53_819472 || ERRATA_A53_824069 || ERRATA_A53_827319 +DEFINE_DCOP_ERRATA_A53_TYPE_PARAM_FUNC(cvac, civac) +#else +DEFINE_SYSOP_TYPE_PARAM_FUNC(dc, cvac) +#endif +DEFINE_SYSOP_TYPE_PARAM_FUNC(dc, ivac) +DEFINE_SYSOP_TYPE_PARAM_FUNC(dc, civac) +#if ERRATA_A53_819472 || ERRATA_A53_824069 || ERRATA_A53_827319 +DEFINE_DCOP_ERRATA_A53_TYPE_PARAM_FUNC(cvau, civac) +#else +DEFINE_SYSOP_TYPE_PARAM_FUNC(dc, cvau) +#endif +DEFINE_SYSOP_TYPE_PARAM_FUNC(dc, zva) + +/******************************************************************************* + * Address translation accessor prototypes + ******************************************************************************/ +DEFINE_SYSOP_TYPE_PARAM_FUNC(at, s12e1r) +DEFINE_SYSOP_TYPE_PARAM_FUNC(at, s12e1w) +DEFINE_SYSOP_TYPE_PARAM_FUNC(at, s12e0r) +DEFINE_SYSOP_TYPE_PARAM_FUNC(at, s12e0w) +DEFINE_SYSOP_TYPE_PARAM_FUNC(at, s1e1r) +DEFINE_SYSOP_TYPE_PARAM_FUNC(at, s1e2r) +DEFINE_SYSOP_TYPE_PARAM_FUNC(at, s1e3r) + +/******************************************************************************* + * Strip Pointer Authentication Code + ******************************************************************************/ +DEFINE_SYSOP_PARAM_FUNC(xpaci) + +void flush_dcache_range(uintptr_t addr, size_t size); +void clean_dcache_range(uintptr_t addr, size_t size); +void inv_dcache_range(uintptr_t addr, size_t size); +bool is_dcache_enabled(void); + +void dcsw_op_louis(u_register_t op_type); +void dcsw_op_all(u_register_t op_type); + +void disable_mmu_el1(void); +void disable_mmu_el3(void); +void disable_mmu_icache_el1(void); +void disable_mmu_icache_el3(void); + +/******************************************************************************* + * Misc. accessor prototypes + ******************************************************************************/ + +#define write_daifclr(val) SYSREG_WRITE_CONST(daifclr, val) +#define write_daifset(val) SYSREG_WRITE_CONST(daifset, val) + +DEFINE_SYSREG_RW_FUNCS(par_el1) +DEFINE_SYSREG_READ_FUNC(id_pfr1_el1) +DEFINE_SYSREG_READ_FUNC(id_aa64isar0_el1) +DEFINE_SYSREG_READ_FUNC(id_aa64isar1_el1) +DEFINE_SYSREG_READ_FUNC(id_aa64pfr0_el1) +DEFINE_SYSREG_READ_FUNC(id_aa64pfr1_el1) +DEFINE_SYSREG_READ_FUNC(id_aa64dfr0_el1) +DEFINE_SYSREG_READ_FUNC(id_afr0_el1) +DEFINE_SYSREG_READ_FUNC(CurrentEl) +DEFINE_SYSREG_READ_FUNC(ctr_el0) +DEFINE_SYSREG_RW_FUNCS(daif) +DEFINE_SYSREG_RW_FUNCS(spsr_el1) +DEFINE_SYSREG_RW_FUNCS(spsr_el2) +DEFINE_SYSREG_RW_FUNCS(spsr_el3) +DEFINE_SYSREG_RW_FUNCS(elr_el1) +DEFINE_SYSREG_RW_FUNCS(elr_el2) +DEFINE_SYSREG_RW_FUNCS(elr_el3) +DEFINE_SYSREG_RW_FUNCS(mdccsr_el0) +DEFINE_SYSREG_RW_FUNCS(dbgdtrrx_el0) +DEFINE_SYSREG_RW_FUNCS(dbgdtrtx_el0) + +DEFINE_SYSOP_FUNC(wfi) +DEFINE_SYSOP_FUNC(wfe) +DEFINE_SYSOP_FUNC(sev) +DEFINE_SYSOP_TYPE_FUNC(dsb, sy) +DEFINE_SYSOP_TYPE_FUNC(dmb, sy) +DEFINE_SYSOP_TYPE_FUNC(dmb, st) +DEFINE_SYSOP_TYPE_FUNC(dmb, ld) +DEFINE_SYSOP_TYPE_FUNC(dsb, ish) +DEFINE_SYSOP_TYPE_FUNC(dsb, nsh) +DEFINE_SYSOP_TYPE_FUNC(dsb, ishst) +DEFINE_SYSOP_TYPE_FUNC(dmb, oshld) +DEFINE_SYSOP_TYPE_FUNC(dmb, oshst) +DEFINE_SYSOP_TYPE_FUNC(dmb, osh) +DEFINE_SYSOP_TYPE_FUNC(dmb, nshld) +DEFINE_SYSOP_TYPE_FUNC(dmb, nshst) +DEFINE_SYSOP_TYPE_FUNC(dmb, nsh) +DEFINE_SYSOP_TYPE_FUNC(dmb, ishld) +DEFINE_SYSOP_TYPE_FUNC(dmb, ishst) +DEFINE_SYSOP_TYPE_FUNC(dmb, ish) +DEFINE_SYSOP_FUNC(isb) + +static inline void enable_irq(void) +{ + /* + * The compiler memory barrier will prevent the compiler from + * scheduling non-volatile memory access after the write to the + * register. + * + * This could happen if some initialization code issues non-volatile + * accesses to an area used by an interrupt handler, in the assumption + * that it is safe as the interrupts are disabled at the time it does + * that (according to program order). However, non-volatile accesses + * are not necessarily in program order relatively with volatile inline + * assembly statements (and volatile accesses). + */ + COMPILER_BARRIER(); + write_daifclr(DAIF_IRQ_BIT); + isb(); +} + +static inline void enable_fiq(void) +{ + COMPILER_BARRIER(); + write_daifclr(DAIF_FIQ_BIT); + isb(); +} + +static inline void enable_serror(void) +{ + COMPILER_BARRIER(); + write_daifclr(DAIF_ABT_BIT); + isb(); +} + +static inline void enable_debug_exceptions(void) +{ + COMPILER_BARRIER(); + write_daifclr(DAIF_DBG_BIT); + isb(); +} + +static inline void disable_irq(void) +{ + COMPILER_BARRIER(); + write_daifset(DAIF_IRQ_BIT); + isb(); +} + +static inline void disable_fiq(void) +{ + COMPILER_BARRIER(); + write_daifset(DAIF_FIQ_BIT); + isb(); +} + +static inline void disable_serror(void) +{ + COMPILER_BARRIER(); + write_daifset(DAIF_ABT_BIT); + isb(); +} + +static inline void disable_debug_exceptions(void) +{ + COMPILER_BARRIER(); + write_daifset(DAIF_DBG_BIT); + isb(); +} + +void __dead2 smc(uint64_t x0, uint64_t x1, uint64_t x2, uint64_t x3, + uint64_t x4, uint64_t x5, uint64_t x6, uint64_t x7); + +/******************************************************************************* + * System register accessor prototypes + ******************************************************************************/ +DEFINE_SYSREG_READ_FUNC(midr_el1) +DEFINE_SYSREG_READ_FUNC(mpidr_el1) +DEFINE_SYSREG_READ_FUNC(id_aa64mmfr0_el1) +DEFINE_SYSREG_READ_FUNC(id_aa64mmfr1_el1) + +DEFINE_SYSREG_RW_FUNCS(scr_el3) +DEFINE_SYSREG_RW_FUNCS(hcr_el2) + +DEFINE_SYSREG_RW_FUNCS(vbar_el1) +DEFINE_SYSREG_RW_FUNCS(vbar_el2) +DEFINE_SYSREG_RW_FUNCS(vbar_el3) + +DEFINE_SYSREG_RW_FUNCS(sctlr_el1) +DEFINE_SYSREG_RW_FUNCS(sctlr_el2) +DEFINE_SYSREG_RW_FUNCS(sctlr_el3) + +DEFINE_SYSREG_RW_FUNCS(actlr_el1) +DEFINE_SYSREG_RW_FUNCS(actlr_el2) +DEFINE_SYSREG_RW_FUNCS(actlr_el3) + +DEFINE_SYSREG_RW_FUNCS(esr_el1) +DEFINE_SYSREG_RW_FUNCS(esr_el2) +DEFINE_SYSREG_RW_FUNCS(esr_el3) + +DEFINE_SYSREG_RW_FUNCS(afsr0_el1) +DEFINE_SYSREG_RW_FUNCS(afsr0_el2) +DEFINE_SYSREG_RW_FUNCS(afsr0_el3) + +DEFINE_SYSREG_RW_FUNCS(afsr1_el1) +DEFINE_SYSREG_RW_FUNCS(afsr1_el2) +DEFINE_SYSREG_RW_FUNCS(afsr1_el3) + +DEFINE_SYSREG_RW_FUNCS(far_el1) +DEFINE_SYSREG_RW_FUNCS(far_el2) +DEFINE_SYSREG_RW_FUNCS(far_el3) + +DEFINE_SYSREG_RW_FUNCS(mair_el1) +DEFINE_SYSREG_RW_FUNCS(mair_el2) +DEFINE_SYSREG_RW_FUNCS(mair_el3) + +DEFINE_SYSREG_RW_FUNCS(amair_el1) +DEFINE_SYSREG_RW_FUNCS(amair_el2) +DEFINE_SYSREG_RW_FUNCS(amair_el3) + +DEFINE_SYSREG_READ_FUNC(rvbar_el1) +DEFINE_SYSREG_READ_FUNC(rvbar_el2) +DEFINE_SYSREG_READ_FUNC(rvbar_el3) + +DEFINE_SYSREG_RW_FUNCS(rmr_el1) +DEFINE_SYSREG_RW_FUNCS(rmr_el2) +DEFINE_SYSREG_RW_FUNCS(rmr_el3) + +DEFINE_SYSREG_RW_FUNCS(tcr_el1) +DEFINE_SYSREG_RW_FUNCS(tcr_el2) +DEFINE_SYSREG_RW_FUNCS(tcr_el3) + +DEFINE_SYSREG_RW_FUNCS(ttbr0_el1) +DEFINE_SYSREG_RW_FUNCS(ttbr0_el2) +DEFINE_SYSREG_RW_FUNCS(ttbr0_el3) + +DEFINE_SYSREG_RW_FUNCS(ttbr1_el1) + +DEFINE_SYSREG_RW_FUNCS(vttbr_el2) + +DEFINE_SYSREG_RW_FUNCS(cptr_el2) +DEFINE_SYSREG_RW_FUNCS(cptr_el3) + +DEFINE_SYSREG_RW_FUNCS(cpacr_el1) +DEFINE_SYSREG_RW_FUNCS(cntfrq_el0) +DEFINE_SYSREG_RW_FUNCS(cnthp_ctl_el2) +DEFINE_SYSREG_RW_FUNCS(cnthp_tval_el2) +DEFINE_SYSREG_RW_FUNCS(cnthp_cval_el2) +DEFINE_SYSREG_RW_FUNCS(cntps_ctl_el1) +DEFINE_SYSREG_RW_FUNCS(cntps_tval_el1) +DEFINE_SYSREG_RW_FUNCS(cntps_cval_el1) +DEFINE_SYSREG_RW_FUNCS(cntp_ctl_el0) +DEFINE_SYSREG_RW_FUNCS(cntp_tval_el0) +DEFINE_SYSREG_RW_FUNCS(cntp_cval_el0) +DEFINE_SYSREG_READ_FUNC(cntpct_el0) +DEFINE_SYSREG_RW_FUNCS(cnthctl_el2) + +#define get_cntp_ctl_enable(x) (((x) >> CNTP_CTL_ENABLE_SHIFT) & \ + CNTP_CTL_ENABLE_MASK) +#define get_cntp_ctl_imask(x) (((x) >> CNTP_CTL_IMASK_SHIFT) & \ + CNTP_CTL_IMASK_MASK) +#define get_cntp_ctl_istatus(x) (((x) >> CNTP_CTL_ISTATUS_SHIFT) & \ + CNTP_CTL_ISTATUS_MASK) + +#define set_cntp_ctl_enable(x) ((x) |= (U(1) << CNTP_CTL_ENABLE_SHIFT)) +#define set_cntp_ctl_imask(x) ((x) |= (U(1) << CNTP_CTL_IMASK_SHIFT)) + +#define clr_cntp_ctl_enable(x) ((x) &= ~(U(1) << CNTP_CTL_ENABLE_SHIFT)) +#define clr_cntp_ctl_imask(x) ((x) &= ~(U(1) << CNTP_CTL_IMASK_SHIFT)) + +DEFINE_SYSREG_RW_FUNCS(tpidr_el3) + +DEFINE_SYSREG_RW_FUNCS(cntvoff_el2) + +DEFINE_SYSREG_RW_FUNCS(vpidr_el2) +DEFINE_SYSREG_RW_FUNCS(vmpidr_el2) + +DEFINE_SYSREG_READ_FUNC(isr_el1) + +DEFINE_SYSREG_RW_FUNCS(mdcr_el2) +DEFINE_SYSREG_RW_FUNCS(mdcr_el3) +DEFINE_SYSREG_RW_FUNCS(hstr_el2) +DEFINE_SYSREG_RW_FUNCS(pmcr_el0) + +/* GICv3 System Registers */ + +DEFINE_RENAME_SYSREG_RW_FUNCS(icc_sre_el1, ICC_SRE_EL1) +DEFINE_RENAME_SYSREG_RW_FUNCS(icc_sre_el2, ICC_SRE_EL2) +DEFINE_RENAME_SYSREG_RW_FUNCS(icc_sre_el3, ICC_SRE_EL3) +DEFINE_RENAME_SYSREG_RW_FUNCS(icc_pmr_el1, ICC_PMR_EL1) +DEFINE_RENAME_SYSREG_READ_FUNC(icc_rpr_el1, ICC_RPR_EL1) +DEFINE_RENAME_SYSREG_RW_FUNCS(icc_igrpen1_el3, ICC_IGRPEN1_EL3) +DEFINE_RENAME_SYSREG_RW_FUNCS(icc_igrpen1_el1, ICC_IGRPEN1_EL1) +DEFINE_RENAME_SYSREG_RW_FUNCS(icc_igrpen0_el1, ICC_IGRPEN0_EL1) +DEFINE_RENAME_SYSREG_READ_FUNC(icc_hppir0_el1, ICC_HPPIR0_EL1) +DEFINE_RENAME_SYSREG_READ_FUNC(icc_hppir1_el1, ICC_HPPIR1_EL1) +DEFINE_RENAME_SYSREG_READ_FUNC(icc_iar0_el1, ICC_IAR0_EL1) +DEFINE_RENAME_SYSREG_READ_FUNC(icc_iar1_el1, ICC_IAR1_EL1) +DEFINE_RENAME_SYSREG_WRITE_FUNC(icc_eoir0_el1, ICC_EOIR0_EL1) +DEFINE_RENAME_SYSREG_WRITE_FUNC(icc_eoir1_el1, ICC_EOIR1_EL1) +DEFINE_RENAME_SYSREG_WRITE_FUNC(icc_sgi0r_el1, ICC_SGI0R_EL1) +DEFINE_RENAME_SYSREG_RW_FUNCS(icc_sgi1r, ICC_SGI1R) + +DEFINE_RENAME_SYSREG_READ_FUNC(amcfgr_el0, AMCFGR_EL0) +DEFINE_RENAME_SYSREG_READ_FUNC(amcgcr_el0, AMCGCR_EL0) +DEFINE_RENAME_SYSREG_READ_FUNC(amcg1idr_el0, AMCG1IDR_EL0) +DEFINE_RENAME_SYSREG_RW_FUNCS(amcr_el0, AMCR_EL0) +DEFINE_RENAME_SYSREG_RW_FUNCS(amcntenclr0_el0, AMCNTENCLR0_EL0) +DEFINE_RENAME_SYSREG_RW_FUNCS(amcntenset0_el0, AMCNTENSET0_EL0) +DEFINE_RENAME_SYSREG_RW_FUNCS(amcntenclr1_el0, AMCNTENCLR1_EL0) +DEFINE_RENAME_SYSREG_RW_FUNCS(amcntenset1_el0, AMCNTENSET1_EL0) + +DEFINE_RENAME_SYSREG_READ_FUNC(mpamidr_el1, MPAMIDR_EL1) +DEFINE_RENAME_SYSREG_RW_FUNCS(mpam3_el3, MPAM3_EL3) +DEFINE_RENAME_SYSREG_RW_FUNCS(mpam2_el2, MPAM2_EL2) +DEFINE_RENAME_SYSREG_RW_FUNCS(mpamhcr_el2, MPAMHCR_EL2) + +DEFINE_RENAME_SYSREG_RW_FUNCS(pmblimitr_el1, PMBLIMITR_EL1) + +DEFINE_RENAME_SYSREG_WRITE_FUNC(zcr_el3, ZCR_EL3) +DEFINE_RENAME_SYSREG_WRITE_FUNC(zcr_el2, ZCR_EL2) + +DEFINE_RENAME_SYSREG_READ_FUNC(erridr_el1, ERRIDR_EL1) +DEFINE_RENAME_SYSREG_WRITE_FUNC(errselr_el1, ERRSELR_EL1) + +DEFINE_RENAME_SYSREG_READ_FUNC(erxfr_el1, ERXFR_EL1) +DEFINE_RENAME_SYSREG_RW_FUNCS(erxctlr_el1, ERXCTLR_EL1) +DEFINE_RENAME_SYSREG_RW_FUNCS(erxstatus_el1, ERXSTATUS_EL1) +DEFINE_RENAME_SYSREG_READ_FUNC(erxaddr_el1, ERXADDR_EL1) +DEFINE_RENAME_SYSREG_READ_FUNC(erxmisc0_el1, ERXMISC0_EL1) +DEFINE_RENAME_SYSREG_READ_FUNC(erxmisc1_el1, ERXMISC1_EL1) + +/* Armv8.2 Registers */ +DEFINE_RENAME_SYSREG_READ_FUNC(id_aa64mmfr2_el1, ID_AA64MMFR2_EL1) + +/* Armv8.3 Pointer Authentication Registers */ +DEFINE_RENAME_SYSREG_RW_FUNCS(apiakeyhi_el1, APIAKeyHi_EL1) +DEFINE_RENAME_SYSREG_RW_FUNCS(apiakeylo_el1, APIAKeyLo_EL1) + +/* Armv8.5 MTE Registers */ +DEFINE_RENAME_SYSREG_RW_FUNCS(tfsre0_el1, TFSRE0_EL1) +DEFINE_RENAME_SYSREG_RW_FUNCS(tfsr_el1, TFSR_EL1) +DEFINE_RENAME_SYSREG_RW_FUNCS(rgsr_el1, RGSR_EL1) +DEFINE_RENAME_SYSREG_RW_FUNCS(gcr_el1, GCR_EL1) + +/* Armv8.5 FEAT_RNG Registers */ +DEFINE_SYSREG_READ_FUNC(rndr) +DEFINE_SYSREG_READ_FUNC(rndrrs) + +/* DynamIQ Shared Unit power management */ +DEFINE_RENAME_SYSREG_RW_FUNCS(clusterpwrdn_el1, CLUSTERPWRDN_EL1) + +#define IS_IN_EL(x) \ + (GET_EL(read_CurrentEl()) == MODE_EL##x) + +#define IS_IN_EL1() IS_IN_EL(1) +#define IS_IN_EL2() IS_IN_EL(2) +#define IS_IN_EL3() IS_IN_EL(3) + +static inline unsigned int get_current_el(void) +{ + return GET_EL(read_CurrentEl()); +} + +static inline unsigned int get_current_el_maybe_constant(void) +{ +#if defined(IMAGE_AT_EL1) + return 1; +#elif defined(IMAGE_AT_EL2) + return 2; /* no use-case in TF-A */ +#elif defined(IMAGE_AT_EL3) + return 3; +#else + /* + * If we do not know which exception level this is being built for + * (e.g. built for library), fall back to run-time detection. + */ + return get_current_el(); +#endif +} + +/* + * Check if an EL is implemented from AA64PFR0 register fields. + */ +static inline uint64_t el_implemented(unsigned int el) +{ + if (el > 3U) { + return EL_IMPL_NONE; + } else { + unsigned int shift = ID_AA64PFR0_EL1_SHIFT * el; + + return (read_id_aa64pfr0_el1() >> shift) & ID_AA64PFR0_ELX_MASK; + } +} + +/* Previously defined accesor functions with incomplete register names */ + +#define read_current_el() read_CurrentEl() + +#define dsb() dsbsy() + +#define read_midr() read_midr_el1() + +#define read_mpidr() read_mpidr_el1() + +#define read_scr() read_scr_el3() +#define write_scr(_v) write_scr_el3(_v) + +#define read_hcr() read_hcr_el2() +#define write_hcr(_v) write_hcr_el2(_v) + +#define read_cpacr() read_cpacr_el1() +#define write_cpacr(_v) write_cpacr_el1(_v) + +#define read_clusterpwrdn() read_clusterpwrdn_el1() +#define write_clusterpwrdn(_v) write_clusterpwrdn_el1(_v) + +#if ERRATA_SPECULATIVE_AT +/* + * Assuming SCTLR.M bit is already enabled + * 1. Enable page table walk by clearing TCR_EL1.EPDx bits + * 2. Execute AT instruction for lower EL1/0 + * 3. Disable page table walk by setting TCR_EL1.EPDx bits + */ +#define AT(_at_inst, _va) \ +{ \ + assert((read_sctlr_el1() & SCTLR_M_BIT) != 0ULL); \ + write_tcr_el1(read_tcr_el1() & ~(TCR_EPD0_BIT | TCR_EPD1_BIT)); \ + isb(); \ + _at_inst(_va); \ + write_tcr_el1(read_tcr_el1() | (TCR_EPD0_BIT | TCR_EPD1_BIT)); \ + isb(); \ +} +#else +#define AT(_at_inst, _va) _at_inst(_va); +#endif + +#endif /* ARCH_HELPERS_H */ diff --git a/drivers/rz/ipl/rza/include/arch/aarch64/asm_macros.S b/drivers/rz/ipl/rza/include/arch/aarch64/asm_macros.S new file mode 100644 index 00000000..464c05be --- /dev/null +++ b/drivers/rz/ipl/rza/include/arch/aarch64/asm_macros.S @@ -0,0 +1,235 @@ +/* + * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef ASM_MACROS_S +#define ASM_MACROS_S + +#include +#include +#include + +#if ENABLE_BTI && !ARM_ARCH_AT_LEAST(8, 5) +#error Branch Target Identification requires ARM_ARCH_MINOR >= 5 +#endif + +/* + * TLBI instruction with type specifier that implements the workaround for + * errata 813419 of Cortex-A57 or errata 1286807 of Cortex-A76. + */ +#if ERRATA_A57_813419 || ERRATA_A76_1286807 +#define TLB_INVALIDATE(_type) \ + tlbi _type; \ + dsb ish; \ + tlbi _type +#else +#define TLB_INVALIDATE(_type) \ + tlbi _type +#endif + + + .macro func_prologue + stp x29, x30, [sp, #-0x10]! + mov x29,sp + .endm + + .macro func_epilogue + ldp x29, x30, [sp], #0x10 + .endm + + + .macro dcache_line_size reg, tmp + mrs \tmp, ctr_el0 + ubfx \tmp, \tmp, #16, #4 + mov \reg, #4 + lsl \reg, \reg, \tmp + .endm + + + .macro icache_line_size reg, tmp + mrs \tmp, ctr_el0 + and \tmp, \tmp, #0xf + mov \reg, #4 + lsl \reg, \reg, \tmp + .endm + + + .macro smc_check label + mrs x0, esr_el3 + ubfx x0, x0, #ESR_EC_SHIFT, #ESR_EC_LENGTH + cmp x0, #EC_AARCH64_SMC + b.ne $label + .endm + + /* + * Declare the exception vector table, enforcing it is aligned on a + * 2KB boundary, as required by the ARMv8 architecture. + * Use zero bytes as the fill value to be stored in the padding bytes + * so that it inserts illegal AArch64 instructions. This increases + * security, robustness and potentially facilitates debugging. + */ + .macro vector_base label, section_name=.vectors + .section \section_name, "ax" + .align 11, 0 + \label: + .endm + + /* + * Create an entry in the exception vector table, enforcing it is + * aligned on a 128-byte boundary, as required by the ARMv8 architecture. + * Use zero bytes as the fill value to be stored in the padding bytes + * so that it inserts illegal AArch64 instructions. This increases + * security, robustness and potentially facilitates debugging. + */ + .macro vector_entry label, section_name=.vectors + .cfi_sections .debug_frame + .section \section_name, "ax" + .align 7, 0 + .type \label, %function + .cfi_startproc + \label: + .endm + + /* + * Add the bytes until fill the full exception vector, whose size is always + * 32 instructions. If there are more than 32 instructions in the + * exception vector then an error is emitted. + */ + .macro end_vector_entry label + .cfi_endproc + .fill \label + (32 * 4) - . + .endm + + /* + * This macro calculates the base address of the current CPU's MP stack + * using the plat_my_core_pos() index, the name of the stack storage + * and the size of each stack + * Out: X0 = physical address of stack base + * Clobber: X30, X1, X2 + */ + .macro get_my_mp_stack _name, _size + bl plat_my_core_pos + adrp x2, (\_name + \_size) + add x2, x2, :lo12:(\_name + \_size) + mov x1, #\_size + madd x0, x0, x1, x2 + .endm + + /* + * This macro calculates the base address of a UP stack using the + * name of the stack storage and the size of the stack + * Out: X0 = physical address of stack base + */ + .macro get_up_stack _name, _size + adrp x0, (\_name + \_size) + add x0, x0, :lo12:(\_name + \_size) + .endm + + /* + * Helper macro to generate the best mov/movk combinations according + * the value to be moved. The 16 bits from '_shift' are tested and + * if not zero, they are moved into '_reg' without affecting + * other bits. + */ + .macro _mov_imm16 _reg, _val, _shift + .if (\_val >> \_shift) & 0xffff + .if (\_val & (1 << \_shift - 1)) + movk \_reg, (\_val >> \_shift) & 0xffff, LSL \_shift + .else + mov \_reg, \_val & (0xffff << \_shift) + .endif + .endif + .endm + + /* + * Helper macro to load arbitrary values into 32 or 64-bit registers + * which generates the best mov/movk combinations. Many base addresses + * are 64KB aligned the macro will eliminate updating bits 15:0 in + * that case + */ + .macro mov_imm _reg, _val + .if (\_val) == 0 + mov \_reg, #0 + .else + _mov_imm16 \_reg, (\_val), 0 + _mov_imm16 \_reg, (\_val), 16 + _mov_imm16 \_reg, (\_val), 32 + _mov_imm16 \_reg, (\_val), 48 + .endif + .endm + + /* + * Macro to mark instances where we're jumping to a function and don't + * expect a return. To provide the function being jumped to with + * additional information, we use 'bl' instruction to jump rather than + * 'b'. + * + * Debuggers infer the location of a call from where LR points to, which + * is usually the instruction after 'bl'. If this macro expansion + * happens to be the last location in a function, that'll cause the LR + * to point a location beyond the function, thereby misleading debugger + * back trace. We therefore insert a 'nop' after the function call for + * debug builds, unless 'skip_nop' parameter is non-zero. + */ + .macro no_ret _func:req, skip_nop=0 + bl \_func +#if DEBUG + .ifeq \skip_nop + nop + .endif +#endif + .endm + + /* + * Reserve space for a spin lock in assembly file. + */ + .macro define_asm_spinlock _name:req + .align SPINLOCK_ASM_ALIGN + \_name: + .space SPINLOCK_ASM_SIZE + .endm + +#if RAS_EXTENSION + .macro esb + .inst 0xd503221f + .endm +#endif + + /* + * Helper macro to read system register value into x0 + */ + .macro read reg:req +#if ENABLE_BTI + bti j +#endif + mrs x0, \reg + ret + .endm + + /* + * Helper macro to write value from x1 to system register + */ + .macro write reg:req +#if ENABLE_BTI + bti j +#endif + msr \reg, x1 + ret + .endm + + /* + * Macro for mitigating against speculative execution beyond ERET. Uses the + * speculation barrier instruction introduced by FEAT_SB, if it's enabled. + */ + .macro exception_return + eret +#if ENABLE_FEAT_SB + sb +#else + dsb nsh + isb +#endif + .endm + +#endif /* ASM_MACROS_S */ diff --git a/drivers/rz/ipl/rza/include/arch/aarch64/assert_macros.S b/drivers/rz/ipl/rza/include/arch/aarch64/assert_macros.S new file mode 100644 index 00000000..06371c42 --- /dev/null +++ b/drivers/rz/ipl/rza/include/arch/aarch64/assert_macros.S @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2014-2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef ASSERT_MACROS_S +#define ASSERT_MACROS_S + + /* + * Assembler macro to enable asm_assert. Use this macro wherever + * assert is required in assembly. Please note that the macro makes + * use of label '300' to provide the logic and the caller + * should make sure that this label is not used to branch prior + * to calling this macro. + */ +#define ASM_ASSERT(_cc) \ +.ifndef .L_assert_filename ;\ + .pushsection .rodata.str1.1, "aS" ;\ + .L_assert_filename: ;\ + .string __FILE__ ;\ + .popsection ;\ +.endif ;\ + b._cc 300f ;\ + adr x0, .L_assert_filename ;\ + mov x1, __LINE__ ;\ + b asm_assert ;\ +300: + +#endif /* ASSERT_MACROS_S */ diff --git a/drivers/rz/ipl/rza/include/arch/aarch64/console_macros.S b/drivers/rz/ipl/rza/include/arch/aarch64/console_macros.S new file mode 100644 index 00000000..3285d855 --- /dev/null +++ b/drivers/rz/ipl/rza/include/arch/aarch64/console_macros.S @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef CONSOLE_MACROS_S +#define CONSOLE_MACROS_S + +#include + +/* + * This macro encapsulates the common setup that has to be done at the end of + * a console driver's register function. It will register all of the driver's + * callbacks in the console_t structure and initialize the flags field (by + * default consoles are enabled for the "boot" and "crash" states, this can be + * changed after registration with the console_set_scope() function). It ends + * with a tail call that will include return to the caller. + * REQUIRES console_t pointer in x0 and a valid return address in x30. + */ + .macro finish_console_register _driver, putc=0, getc=0, flush=0 + /* + * If any of the callback is not specified or set as 0, then the + * corresponding callback entry in console_t is set to 0. + */ + .ifne \putc + adrp x1, console_\_driver\()_putc + add x1, x1, :lo12:console_\_driver\()_putc + str x1, [x0, #CONSOLE_T_PUTC] + .else + str xzr, [x0, #CONSOLE_T_PUTC] + .endif + + .ifne \getc + adrp x1, console_\_driver\()_getc + add x1, x1, :lo12:console_\_driver\()_getc + str x1, [x0, #CONSOLE_T_GETC] + .else + str xzr, [x0, #CONSOLE_T_GETC] + .endif + + .ifne \flush + adrp x1, console_\_driver\()_flush + add x1, x1, :lo12:console_\_driver\()_flush + str x1, [x0, #CONSOLE_T_FLUSH] + .else + str xzr, [x0, #CONSOLE_T_FLUSH] + .endif + + mov x1, #(CONSOLE_FLAG_BOOT | CONSOLE_FLAG_CRASH) + str x1, [x0, #CONSOLE_T_FLAGS] + b console_register + .endm + +#endif /* CONSOLE_MACROS_S */ diff --git a/drivers/rz/ipl/rza/include/arch/aarch64/el3_common_macros.S b/drivers/rz/ipl/rza/include/arch/aarch64/el3_common_macros.S new file mode 100644 index 00000000..f7599835 --- /dev/null +++ b/drivers/rz/ipl/rza/include/arch/aarch64/el3_common_macros.S @@ -0,0 +1,489 @@ +/* + * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef EL3_COMMON_MACROS_S +#define EL3_COMMON_MACROS_S + +#include +#include +#include +#include + + /* + * Helper macro to initialise EL3 registers we care about. + */ + .macro el3_arch_init_common + /* --------------------------------------------------------------------- + * SCTLR_EL3 has already been initialised - read current value before + * modifying. + * + * SCTLR_EL3.I: Enable the instruction cache. + * + * SCTLR_EL3.SA: Enable Stack Alignment check. A SP alignment fault + * exception is generated if a load or store instruction executed at + * EL3 uses the SP as the base address and the SP is not aligned to a + * 16-byte boundary. + * + * SCTLR_EL3.A: Enable Alignment fault checking. All instructions that + * load or store one or more registers have an alignment check that the + * address being accessed is aligned to the size of the data element(s) + * being accessed. + * --------------------------------------------------------------------- + */ + mov x1, #(SCTLR_I_BIT | SCTLR_A_BIT | SCTLR_SA_BIT) + mrs x0, sctlr_el3 + orr x0, x0, x1 + msr sctlr_el3, x0 + isb + +#ifdef IMAGE_BL31 + /* --------------------------------------------------------------------- + * Initialise the per-cpu cache pointer to the CPU. + * This is done early to enable crash reporting to have access to crash + * stack. Since crash reporting depends on cpu_data to report the + * unhandled exception, not doing so can lead to recursive exceptions + * due to a NULL TPIDR_EL3. + * --------------------------------------------------------------------- + */ + bl init_cpu_data_ptr +#endif /* IMAGE_BL31 */ + + /* --------------------------------------------------------------------- + * Initialise SCR_EL3, setting all fields rather than relying on hw. + * All fields are architecturally UNKNOWN on reset. The following fields + * do not change during the TF lifetime. The remaining fields are set to + * zero here but are updated ahead of transitioning to a lower EL in the + * function cm_init_context_common(). + * + * SCR_EL3.TWE: Set to zero so that execution of WFE instructions at + * EL2, EL1 and EL0 are not trapped to EL3. + * + * SCR_EL3.TWI: Set to zero so that execution of WFI instructions at + * EL2, EL1 and EL0 are not trapped to EL3. + * + * SCR_EL3.SIF: Set to one to disable instruction fetches from + * Non-secure memory. + * + * SCR_EL3.SMD: Set to zero to enable SMC calls at EL1 and above, from + * both Security states and both Execution states. + * + * SCR_EL3.EA: Set to one to route External Aborts and SError Interrupts + * to EL3 when executing at any EL. + * + * SCR_EL3.{API,APK}: For Armv8.3 pointer authentication feature, + * disable traps to EL3 when accessing key registers or using pointer + * authentication instructions from lower ELs. + * --------------------------------------------------------------------- + */ + mov_imm x0, ((SCR_RESET_VAL | SCR_EA_BIT | SCR_SIF_BIT) \ + & ~(SCR_TWE_BIT | SCR_TWI_BIT | SCR_SMD_BIT)) +#if CTX_INCLUDE_PAUTH_REGS + /* + * If the pointer authentication registers are saved during world + * switches, enable pointer authentication everywhere, as it is safe to + * do so. + */ + orr x0, x0, #(SCR_API_BIT | SCR_APK_BIT) +#endif + msr scr_el3, x0 + + /* --------------------------------------------------------------------- + * Initialise MDCR_EL3, setting all fields rather than relying on hw. + * Some fields are architecturally UNKNOWN on reset. + * + * MDCR_EL3.SDD: Set to one to disable AArch64 Secure self-hosted debug. + * Debug exceptions, other than Breakpoint Instruction exceptions, are + * disabled from all ELs in Secure state. + * + * MDCR_EL3.SPD32: Set to 0b10 to disable AArch32 Secure self-hosted + * privileged debug from S-EL1. + * + * MDCR_EL3.TDOSA: Set to zero so that EL2 and EL2 System register + * access to the powerdown debug registers do not trap to EL3. + * + * MDCR_EL3.TDA: Set to zero to allow EL0, EL1 and EL2 access to the + * debug registers, other than those registers that are controlled by + * MDCR_EL3.TDOSA. + * + * MDCR_EL3.TPM: Set to zero so that EL0, EL1, and EL2 System register + * accesses to all Performance Monitors registers do not trap to EL3. + * + * MDCR_EL3.SCCD: Set to one so that cycle counting by PMCCNTR_EL0 is + * prohibited in Secure state. This bit is RES0 in versions of the + * architecture earlier than ARMv8.5, setting it to 1 doesn't have any + * effect on them. + * + * MDCR_EL3.SPME: Set to zero so that event counting by the programmable + * counters PMEVCNTR_EL0 is prohibited in Secure state. If ARMv8.2 + * Debug is not implemented this bit does not have any effect on the + * counters unless there is support for the implementation defined + * authentication interface ExternalSecureNoninvasiveDebugEnabled(). + * --------------------------------------------------------------------- + */ + mov_imm x0, ((MDCR_EL3_RESET_VAL | MDCR_SDD_BIT | \ + MDCR_SPD32(MDCR_SPD32_DISABLE) | MDCR_SCCD_BIT) & \ + ~(MDCR_SPME_BIT | MDCR_TDOSA_BIT | MDCR_TDA_BIT | \ + MDCR_TPM_BIT)) + + msr mdcr_el3, x0 + + /* --------------------------------------------------------------------- + * Initialise PMCR_EL0 setting all fields rather than relying + * on hw. Some fields are architecturally UNKNOWN on reset. + * + * PMCR_EL0.LP: Set to one so that event counter overflow, that + * is recorded in PMOVSCLR_EL0[0-30], occurs on the increment + * that changes PMEVCNTR_EL0[63] from 1 to 0, when ARMv8.5-PMU + * is implemented. This bit is RES0 in versions of the architecture + * earlier than ARMv8.5, setting it to 1 doesn't have any effect + * on them. + * + * PMCR_EL0.LC: Set to one so that cycle counter overflow, that + * is recorded in PMOVSCLR_EL0[31], occurs on the increment + * that changes PMCCNTR_EL0[63] from 1 to 0. + * + * PMCR_EL0.DP: Set to one so that the cycle counter, + * PMCCNTR_EL0 does not count when event counting is prohibited. + * + * PMCR_EL0.X: Set to zero to disable export of events. + * + * PMCR_EL0.D: Set to zero so that, when enabled, PMCCNTR_EL0 + * counts on every clock cycle. + * --------------------------------------------------------------------- + */ + mov_imm x0, ((PMCR_EL0_RESET_VAL | PMCR_EL0_LP_BIT | \ + PMCR_EL0_LC_BIT | PMCR_EL0_DP_BIT) & \ + ~(PMCR_EL0_X_BIT | PMCR_EL0_D_BIT)) + + msr pmcr_el0, x0 + + /* --------------------------------------------------------------------- + * Enable External Aborts and SError Interrupts now that the exception + * vectors have been setup. + * --------------------------------------------------------------------- + */ + msr daifclr, #DAIF_ABT_BIT + + /* --------------------------------------------------------------------- + * Initialise CPTR_EL3, setting all fields rather than relying on hw. + * All fields are architecturally UNKNOWN on reset. + * + * CPTR_EL3.TCPAC: Set to zero so that any accesses to CPACR_EL1, + * CPTR_EL2, CPACR, or HCPTR do not trap to EL3. + * + * CPTR_EL3.TTA: Set to zero so that System register accesses to the + * trace registers do not trap to EL3. + * + * CPTR_EL3.TFP: Set to zero so that accesses to the V- or Z- registers + * by Advanced SIMD, floating-point or SVE instructions (if implemented) + * do not trap to EL3. + */ + mov_imm x0, (CPTR_EL3_RESET_VAL & ~(TCPAC_BIT | TTA_BIT | TFP_BIT)) + msr cptr_el3, x0 + + /* + * If Data Independent Timing (DIT) functionality is implemented, + * always enable DIT in EL3 + */ + mrs x0, id_aa64pfr0_el1 + ubfx x0, x0, #ID_AA64PFR0_DIT_SHIFT, #ID_AA64PFR0_DIT_LENGTH + cmp x0, #ID_AA64PFR0_DIT_SUPPORTED + bne 1f + mov x0, #DIT_BIT + msr DIT, x0 +1: + .endm + +/* ----------------------------------------------------------------------------- + * This is the super set of actions that need to be performed during a cold boot + * or a warm boot in EL3. This code is shared by BL1 and BL31. + * + * This macro will always perform reset handling, architectural initialisations + * and stack setup. The rest of the actions are optional because they might not + * be needed, depending on the context in which this macro is called. This is + * why this macro is parameterised ; each parameter allows to enable/disable + * some actions. + * + * _init_sctlr: + * Whether the macro needs to initialise SCTLR_EL3, including configuring + * the endianness of data accesses. + * + * _warm_boot_mailbox: + * Whether the macro needs to detect the type of boot (cold/warm). The + * detection is based on the platform entrypoint address : if it is zero + * then it is a cold boot, otherwise it is a warm boot. In the latter case, + * this macro jumps on the platform entrypoint address. + * + * _secondary_cold_boot: + * Whether the macro needs to identify the CPU that is calling it: primary + * CPU or secondary CPU. The primary CPU will be allowed to carry on with + * the platform initialisations, while the secondaries will be put in a + * platform-specific state in the meantime. + * + * If the caller knows this macro will only be called by the primary CPU + * then this parameter can be defined to 0 to skip this step. + * + * _init_memory: + * Whether the macro needs to initialise the memory. + * + * _init_c_runtime: + * Whether the macro needs to initialise the C runtime environment. + * + * _exception_vectors: + * Address of the exception vectors to program in the VBAR_EL3 register. + * + * _pie_fixup_size: + * Size of memory region to fixup Global Descriptor Table (GDT). + * + * A non-zero value is expected when firmware needs GDT to be fixed-up. + * + * ----------------------------------------------------------------------------- + */ + .macro el3_entrypoint_common \ + _init_sctlr, _warm_boot_mailbox, _secondary_cold_boot, \ + _init_memory, _init_c_runtime, _exception_vectors, \ + _pie_fixup_size + + .if \_init_sctlr + /* ------------------------------------------------------------- + * This is the initialisation of SCTLR_EL3 and so must ensure + * that all fields are explicitly set rather than relying on hw. + * Some fields reset to an IMPLEMENTATION DEFINED value and + * others are architecturally UNKNOWN on reset. + * + * SCTLR.EE: Set the CPU endianness before doing anything that + * might involve memory reads or writes. Set to zero to select + * Little Endian. + * + * SCTLR_EL3.WXN: For the EL3 translation regime, this field can + * force all memory regions that are writeable to be treated as + * XN (Execute-never). Set to zero so that this control has no + * effect on memory access permissions. + * + * SCTLR_EL3.SA: Set to zero to disable Stack Alignment check. + * + * SCTLR_EL3.A: Set to zero to disable Alignment fault checking. + * + * SCTLR.DSSBS: Set to zero to disable speculation store bypass + * safe behaviour upon exception entry to EL3. + * ------------------------------------------------------------- + */ + mov_imm x0, (SCTLR_RESET_VAL & ~(SCTLR_EE_BIT | SCTLR_WXN_BIT \ + | SCTLR_SA_BIT | SCTLR_A_BIT | SCTLR_DSSBS_BIT)) + msr sctlr_el3, x0 + isb + .endif /* _init_sctlr */ + +#if DISABLE_MTPMU + bl mtpmu_disable +#endif + + .if \_warm_boot_mailbox + /* ------------------------------------------------------------- + * This code will be executed for both warm and cold resets. + * Now is the time to distinguish between the two. + * Query the platform entrypoint address and if it is not zero + * then it means it is a warm boot so jump to this address. + * ------------------------------------------------------------- + */ + bl plat_get_my_entrypoint + cbz x0, do_cold_boot + br x0 + + do_cold_boot: + .endif /* _warm_boot_mailbox */ + + .if \_pie_fixup_size +#if ENABLE_PIE + /* + * ------------------------------------------------------------ + * If PIE is enabled fixup the Global descriptor Table only + * once during primary core cold boot path. + * + * Compile time base address, required for fixup, is calculated + * using "pie_fixup" label present within first page. + * ------------------------------------------------------------ + */ + pie_fixup: + ldr x0, =pie_fixup + and x0, x0, #~(PAGE_SIZE_MASK) + mov_imm x1, \_pie_fixup_size + add x1, x1, x0 + bl fixup_gdt_reloc +#endif /* ENABLE_PIE */ + .endif /* _pie_fixup_size */ + + /* --------------------------------------------------------------------- + * Set the exception vectors. + * --------------------------------------------------------------------- + */ + adr x0, \_exception_vectors + msr vbar_el3, x0 + isb + + /* --------------------------------------------------------------------- + * It is a cold boot. + * Perform any processor specific actions upon reset e.g. cache, TLB + * invalidations etc. + * --------------------------------------------------------------------- + */ + bl reset_handler + + el3_arch_init_common + + .if \_secondary_cold_boot + /* ------------------------------------------------------------- + * Check if this is a primary or secondary CPU cold boot. + * The primary CPU will set up the platform while the + * secondaries are placed in a platform-specific state until the + * primary CPU performs the necessary actions to bring them out + * of that state and allows entry into the OS. + * ------------------------------------------------------------- + */ + bl plat_is_my_cpu_primary + cbnz w0, do_primary_cold_boot + + /* This is a cold boot on a secondary CPU */ + bl plat_secondary_cold_boot_setup + /* plat_secondary_cold_boot_setup() is not supposed to return */ + bl el3_panic + + do_primary_cold_boot: + .endif /* _secondary_cold_boot */ + + /* --------------------------------------------------------------------- + * Initialize memory now. Secondary CPU initialization won't get to this + * point. + * --------------------------------------------------------------------- + */ + + .if \_init_memory + bl platform_mem_init + .endif /* _init_memory */ + + /* --------------------------------------------------------------------- + * Init C runtime environment: + * - Zero-initialise the NOBITS sections. There are 2 of them: + * - the .bss section; + * - the coherent memory section (if any). + * - Relocate the data section from ROM to RAM, if required. + * --------------------------------------------------------------------- + */ + .if \_init_c_runtime +#if defined(IMAGE_BL31) || (defined(IMAGE_BL2) && BL2_AT_EL3 && BL2_INV_DCACHE) + /* ------------------------------------------------------------- + * Invalidate the RW memory used by the BL31 image. This + * includes the data and NOBITS sections. This is done to + * safeguard against possible corruption of this memory by + * dirty cache lines in a system cache as a result of use by + * an earlier boot loader stage. + * ------------------------------------------------------------- + */ + adrp x0, __RW_START__ + add x0, x0, :lo12:__RW_START__ + adrp x1, __RW_END__ + add x1, x1, :lo12:__RW_END__ + sub x1, x1, x0 + bl inv_dcache_range +#if defined(IMAGE_BL31) && SEPARATE_NOBITS_REGION + adrp x0, __NOBITS_START__ + add x0, x0, :lo12:__NOBITS_START__ + adrp x1, __NOBITS_END__ + add x1, x1, :lo12:__NOBITS_END__ + sub x1, x1, x0 + bl inv_dcache_range +#endif +#endif + adrp x0, __BSS_START__ + add x0, x0, :lo12:__BSS_START__ + + adrp x1, __BSS_END__ + add x1, x1, :lo12:__BSS_END__ + sub x1, x1, x0 + bl zeromem + +#if USE_COHERENT_MEM + adrp x0, __COHERENT_RAM_START__ + add x0, x0, :lo12:__COHERENT_RAM_START__ + adrp x1, __COHERENT_RAM_END_UNALIGNED__ + add x1, x1, :lo12: __COHERENT_RAM_END_UNALIGNED__ + sub x1, x1, x0 + bl zeromem +#endif + +#if defined(IMAGE_BL1) || (defined(IMAGE_BL2) && BL2_AT_EL3 && BL2_IN_XIP_MEM) + adrp x0, __DATA_RAM_START__ + add x0, x0, :lo12:__DATA_RAM_START__ + adrp x1, __DATA_ROM_START__ + add x1, x1, :lo12:__DATA_ROM_START__ + adrp x2, __DATA_RAM_END__ + add x2, x2, :lo12:__DATA_RAM_END__ + sub x2, x2, x0 + bl memcpy16 +#endif + .endif /* _init_c_runtime */ + + /* --------------------------------------------------------------------- + * Use SP_EL0 for the C runtime stack. + * --------------------------------------------------------------------- + */ + msr spsel, #0 + + /* --------------------------------------------------------------------- + * Allocate a stack whose memory will be marked as Normal-IS-WBWA when + * the MMU is enabled. There is no risk of reading stale stack memory + * after enabling the MMU as only the primary CPU is running at the + * moment. + * --------------------------------------------------------------------- + */ + bl plat_set_my_stack + +#if STACK_PROTECTOR_ENABLED + .if \_init_c_runtime + bl update_stack_protector_canary + .endif /* _init_c_runtime */ +#endif + .endm + + .macro apply_at_speculative_wa +#if ERRATA_SPECULATIVE_AT + /* + * Explicitly save x30 so as to free up a register and to enable + * branching and also, save x29 which will be used in the called + * function + */ + stp x29, x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X29] + bl save_and_update_ptw_el1_sys_regs + ldp x29, x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X29] +#endif + .endm + + .macro restore_ptw_el1_sys_regs +#if ERRATA_SPECULATIVE_AT + /* ----------------------------------------------------------- + * In case of ERRATA_SPECULATIVE_AT, must follow below order + * to ensure that page table walk is not enabled until + * restoration of all EL1 system registers. TCR_EL1 register + * should be updated at the end which restores previous page + * table walk setting of stage1 i.e.(TCR_EL1.EPDx) bits. ISB + * ensures that CPU does below steps in order. + * + * 1. Ensure all other system registers are written before + * updating SCTLR_EL1 using ISB. + * 2. Restore SCTLR_EL1 register. + * 3. Ensure SCTLR_EL1 written successfully using ISB. + * 4. Restore TCR_EL1 register. + * ----------------------------------------------------------- + */ + isb + ldp x28, x29, [sp, #CTX_EL1_SYSREGS_OFFSET + CTX_SCTLR_EL1] + msr sctlr_el1, x28 + isb + msr tcr_el1, x29 +#endif + .endm + +#endif /* EL3_COMMON_MACROS_S */ diff --git a/drivers/rz/ipl/rza/include/arch/aarch64/smccc_helpers.h b/drivers/rz/ipl/rza/include/arch/aarch64/smccc_helpers.h new file mode 100644 index 00000000..fac6fd9c --- /dev/null +++ b/drivers/rz/ipl/rza/include/arch/aarch64/smccc_helpers.h @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SMCCC_HELPERS_H +#define SMCCC_HELPERS_H + +#include + +#ifndef __ASSEMBLER__ + +#include + +#include + +/* Convenience macros to return from SMC handler */ +#define SMC_RET0(_h) { \ + return (uint64_t) (_h); \ +} +#define SMC_RET1(_h, _x0) { \ + write_ctx_reg((get_gpregs_ctx(_h)), (CTX_GPREG_X0), (_x0)); \ + SMC_RET0(_h); \ +} +#define SMC_RET2(_h, _x0, _x1) { \ + write_ctx_reg((get_gpregs_ctx(_h)), (CTX_GPREG_X1), (_x1)); \ + SMC_RET1(_h, (_x0)); \ +} +#define SMC_RET3(_h, _x0, _x1, _x2) { \ + write_ctx_reg((get_gpregs_ctx(_h)), (CTX_GPREG_X2), (_x2)); \ + SMC_RET2(_h, (_x0), (_x1)); \ +} +#define SMC_RET4(_h, _x0, _x1, _x2, _x3) { \ + write_ctx_reg((get_gpregs_ctx(_h)), (CTX_GPREG_X3), (_x3)); \ + SMC_RET3(_h, (_x0), (_x1), (_x2)); \ +} +#define SMC_RET5(_h, _x0, _x1, _x2, _x3, _x4) { \ + write_ctx_reg((get_gpregs_ctx(_h)), (CTX_GPREG_X4), (_x4)); \ + SMC_RET4(_h, (_x0), (_x1), (_x2), (_x3)); \ +} +#define SMC_RET6(_h, _x0, _x1, _x2, _x3, _x4, _x5) { \ + write_ctx_reg((get_gpregs_ctx(_h)), (CTX_GPREG_X5), (_x5)); \ + SMC_RET5(_h, (_x0), (_x1), (_x2), (_x3), (_x4)); \ +} +#define SMC_RET7(_h, _x0, _x1, _x2, _x3, _x4, _x5, _x6) { \ + write_ctx_reg((get_gpregs_ctx(_h)), (CTX_GPREG_X6), (_x6)); \ + SMC_RET6(_h, (_x0), (_x1), (_x2), (_x3), (_x4), (_x5)); \ +} +#define SMC_RET8(_h, _x0, _x1, _x2, _x3, _x4, _x5, _x6, _x7) { \ + write_ctx_reg((get_gpregs_ctx(_h)), (CTX_GPREG_X7), (_x7)); \ + SMC_RET7(_h, (_x0), (_x1), (_x2), (_x3), (_x4), (_x5), (_x6)); \ +} + +/* + * Convenience macros to access general purpose registers using handle provided + * to SMC handler. These take the offset values defined in context.h + */ +#define SMC_GET_GP(_h, _g) \ + read_ctx_reg((get_gpregs_ctx(_h)), (_g)) +#define SMC_SET_GP(_h, _g, _v) \ + write_ctx_reg((get_gpregs_ctx(_h)), (_g), (_v)) + +/* + * Convenience macros to access EL3 context registers using handle provided to + * SMC handler. These take the offset values defined in context.h + */ +#define SMC_GET_EL3(_h, _e) \ + read_ctx_reg((get_el3state_ctx(_h)), (_e)) +#define SMC_SET_EL3(_h, _e, _v) \ + write_ctx_reg((get_el3state_ctx(_h)), (_e), (_v)) + +/* + * Helper macro to retrieve the SMC parameters from cpu_context_t. + */ +#define get_smc_params_from_ctx(_hdl, _x1, _x2, _x3, _x4) \ + do { \ + const gp_regs_t *regs = get_gpregs_ctx(_hdl); \ + _x1 = read_ctx_reg(regs, CTX_GPREG_X1); \ + _x2 = read_ctx_reg(regs, CTX_GPREG_X2); \ + _x3 = read_ctx_reg(regs, CTX_GPREG_X3); \ + _x4 = read_ctx_reg(regs, CTX_GPREG_X4); \ + } while (false) + +#endif /*__ASSEMBLER__*/ + +#endif /* SMCCC_HELPERS_H */ diff --git a/drivers/rz/ipl/rza/include/bl1/bl1.h b/drivers/rz/ipl/rza/include/bl1/bl1.h new file mode 100644 index 00000000..21d3ae7b --- /dev/null +++ b/drivers/rz/ipl/rza/include/bl1/bl1.h @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef BL1_H +#define BL1_H + +#include + +/* + * Defines for BL1 SMC function ids. + */ +#define BL1_SMC_CALL_COUNT 0x0 +#define BL1_SMC_UID 0x1 +/* SMC #0x2 reserved */ +#define BL1_SMC_VERSION 0x3 + +/* + * Corresponds to the function ID of the SMC that + * the BL1 exception handler service to execute BL31. + */ +#define BL1_SMC_RUN_IMAGE 0x4 + +/* + * BL1 SMC version + */ +#define BL1_SMC_MAJOR_VER UL(0x0) +#define BL1_SMC_MINOR_VER UL(0x1) + +/* + * Defines for FWU SMC function ids. + */ + +#define FWU_SMC_IMAGE_COPY 0x10 +#define FWU_SMC_IMAGE_AUTH 0x11 +#define FWU_SMC_IMAGE_EXECUTE 0x12 +#define FWU_SMC_IMAGE_RESUME 0x13 +#define FWU_SMC_SEC_IMAGE_DONE 0x14 +#define FWU_SMC_UPDATE_DONE 0x15 +#define FWU_SMC_IMAGE_RESET 0x16 + +/* + * Number of FWU calls (above) implemented + */ +#define FWU_NUM_SMC_CALLS 7 + +#if TRUSTED_BOARD_BOOT +# define BL1_NUM_SMC_CALLS (FWU_NUM_SMC_CALLS + 4) +#else +# define BL1_NUM_SMC_CALLS 4 +#endif + +/* + * The macros below are used to identify FWU + * calls from the SMC function ID + */ +#define FWU_SMC_FID_START FWU_SMC_IMAGE_COPY +#define FWU_SMC_FID_END FWU_SMC_IMAGE_RESET +#define is_fwu_fid(_fid) \ + ((_fid >= FWU_SMC_FID_START) && (_fid <= FWU_SMC_FID_END)) + +#ifndef __ASSEMBLER__ + +#include + +struct entry_point_info; + +u_register_t bl1_smc_wrapper(uint32_t smc_fid, + void *cookie, + void *handle, + unsigned int flags); + +u_register_t bl1_smc_handler(unsigned int smc_fid, + u_register_t x1, + u_register_t x2, + u_register_t x3, + u_register_t x4, + void *cookie, + void *handle, + unsigned int flags); + +void bl1_print_next_bl_ep_info(const struct entry_point_info *bl_ep_info); + +void bl1_setup(void); +void bl1_main(void); +void bl1_plat_prepare_exit(entry_point_info_t *ep_info); + +/* + * Check if the total number of FWU SMC calls are as expected. + */ +CASSERT(FWU_NUM_SMC_CALLS == \ + (FWU_SMC_FID_END - FWU_SMC_FID_START + 1),\ + assert_FWU_NUM_SMC_CALLS_mismatch); + +/* Utility functions */ +void bl1_calc_bl2_mem_layout(const meminfo_t *bl1_mem_layout, + meminfo_t *bl2_mem_layout); + +#endif /* __ASSEMBLER__ */ +#endif /* BL1_H */ diff --git a/drivers/rz/ipl/rza/include/bl1/tbbr/tbbr_img_desc.h b/drivers/rz/ipl/rza/include/bl1/tbbr/tbbr_img_desc.h new file mode 100644 index 00000000..db15cdbf --- /dev/null +++ b/drivers/rz/ipl/rza/include/bl1/tbbr/tbbr_img_desc.h @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TBBR_IMG_DESC_H +#define TBBR_IMG_DESC_H + +#include + +extern image_desc_t bl1_tbbr_image_descs[]; + +#endif /* TBBR_IMG_DESC_H */ diff --git a/drivers/rz/ipl/rza/include/bl2/bl2.h b/drivers/rz/ipl/rza/include/bl2/bl2.h new file mode 100644 index 00000000..73f5ac7a --- /dev/null +++ b/drivers/rz/ipl/rza/include/bl2/bl2.h @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef BL2_H +#define BL2_H + +#include + +void bl2_setup(u_register_t arg0, u_register_t arg1, u_register_t arg2, + u_register_t arg3); +void bl2_el3_setup(u_register_t arg0, u_register_t arg1, u_register_t arg2, + u_register_t arg3); +void bl2_main(void); + +#endif /* BL2_H */ diff --git a/drivers/rz/ipl/rza/include/bl31/bl31.h b/drivers/rz/ipl/rza/include/bl31/bl31.h new file mode 100644 index 00000000..3deb0a51 --- /dev/null +++ b/drivers/rz/ipl/rza/include/bl31/bl31.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef BL31_H +#define BL31_H + +#include + +/******************************************************************************* + * Function prototypes + ******************************************************************************/ +void bl31_setup(u_register_t arg0, u_register_t arg1, u_register_t arg2, + u_register_t arg3); +void bl31_next_el_arch_setup(uint32_t security_state); +void bl31_set_next_image_type(uint32_t security_state); +uint32_t bl31_get_next_image_type(void); +void bl31_prepare_next_image_entry(void); +void bl31_register_bl32_init(int32_t (*func)(void)); +void bl31_warm_entrypoint(void); +void bl31_main(void); +void bl31_lib_init(void); + +#endif /* BL31_H */ diff --git a/drivers/rz/ipl/rza/include/bl31/ea_handle.h b/drivers/rz/ipl/rza/include/bl31/ea_handle.h new file mode 100644 index 00000000..68f012c1 --- /dev/null +++ b/drivers/rz/ipl/rza/include/bl31/ea_handle.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef EA_HANDLE_H +#define EA_HANDLE_H + +/* Constants indicating the reason for an External Abort */ + +/* External Abort received at SError vector */ +#define ERROR_EA_ASYNC 0 + +/* Synchronous External Abort received at Synchronous exception vector */ +#define ERROR_EA_SYNC 1 + +/* External Abort synchronized by ESB instruction */ +#define ERROR_EA_ESB 2 + +/* RAS event signalled as peripheral interrupt */ +#define ERROR_INTERRUPT 3 + +#endif /* EA_HANDLE_H */ diff --git a/drivers/rz/ipl/rza/include/bl31/ehf.h b/drivers/rz/ipl/rza/include/bl31/ehf.h new file mode 100644 index 00000000..c13d28c3 --- /dev/null +++ b/drivers/rz/ipl/rza/include/bl31/ehf.h @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef EHF_H +#define EHF_H + +#ifndef __ASSEMBLER__ + +#include +#include + +#include + +/* Valid priorities set bit 0 of the priority handler. */ +#define EHF_PRI_VALID_ BIT(0) + +/* Marker for no handler registered for a valid priority */ +#define EHF_NO_HANDLER_ (0U | EHF_PRI_VALID_) + +/* Extract the specified number of top bits from 7 lower bits of priority */ +#define EHF_PRI_TO_IDX(pri, plat_bits) \ + ((((unsigned) (pri)) & 0x7fu) >> (7u - (plat_bits))) + +/* Install exception priority descriptor at a suitable index */ +#define EHF_PRI_DESC(plat_bits, priority) \ + [EHF_PRI_TO_IDX(priority, plat_bits)] = { \ + .ehf_handler = EHF_NO_HANDLER_, \ + } + +/* Macro for platforms to regiter its exception priorities */ +#define EHF_REGISTER_PRIORITIES(priorities, num, bits) \ + const ehf_priorities_t exception_data = { \ + .num_priorities = (num), \ + .ehf_priorities = (priorities), \ + .pri_bits = (bits), \ + } + +/* + * Priority stack, managed as a bitmap. + * + * Currently only supports 32 priority levels, allowing platforms to use up to 5 + * top bits of priority. But the type can be changed to uint64_t should need + * arise to support 64 priority levels, allowing platforms to use up to 6 top + * bits of priority. + */ +typedef uint32_t ehf_pri_bits_t; + +/* + * Per-PE exception data. The data for each PE is kept as a per-CPU data field. + * See cpu_data.h. + */ +typedef struct { + ehf_pri_bits_t active_pri_bits; + + /* Priority mask value before any priority levels were active */ + uint8_t init_pri_mask; + + /* Non-secure priority mask value stashed during Secure execution */ + uint8_t ns_pri_mask; +} __aligned(sizeof(uint64_t)) pe_exc_data_t; + +typedef int (*ehf_handler_t)(uint32_t intr_raw, uint32_t flags, void *handle, + void *cookie); + +typedef struct ehf_pri_desc { + /* + * 4-byte-aligned exception handler. Bit 0 indicates the corresponding + * priority level is valid. This is effectively of ehf_handler_t type, + * but left as uintptr_t in order to make pointer arithmetic convenient. + */ + uintptr_t ehf_handler; +} ehf_pri_desc_t; + +typedef struct ehf_priority_type { + ehf_pri_desc_t *ehf_priorities; + unsigned int num_priorities; + unsigned int pri_bits; +} ehf_priorities_t; + +void ehf_init(void); +void ehf_activate_priority(unsigned int priority); +void ehf_deactivate_priority(unsigned int priority); +void ehf_register_priority_handler(unsigned int pri, ehf_handler_t handler); +void ehf_allow_ns_preemption(uint64_t preempt_ret_code); +unsigned int ehf_is_ns_preemption_allowed(void); + +#endif /* __ASSEMBLER__ */ + +#endif /* EHF_H */ diff --git a/drivers/rz/ipl/rza/include/bl31/interrupt_mgmt.h b/drivers/rz/ipl/rza/include/bl31/interrupt_mgmt.h new file mode 100644 index 00000000..935bf776 --- /dev/null +++ b/drivers/rz/ipl/rza/include/bl31/interrupt_mgmt.h @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef INTERRUPT_MGMT_H +#define INTERRUPT_MGMT_H + +#include +#include + +/******************************************************************************* + * Constants for the types of interrupts recognised by the IM framework + ******************************************************************************/ +#define INTR_TYPE_S_EL1 U(0) +#define INTR_TYPE_EL3 U(1) +#define INTR_TYPE_NS U(2) +#define MAX_INTR_TYPES U(3) +#define INTR_TYPE_INVAL MAX_INTR_TYPES + +/* Interrupt routing modes */ +#define INTR_ROUTING_MODE_PE 0 +#define INTR_ROUTING_MODE_ANY 1 + +/* + * Constant passed to the interrupt handler in the 'id' field when the + * framework does not read the gic registers to determine the interrupt id. + */ +#define INTR_ID_UNAVAILABLE U(0xFFFFFFFF) + + +/******************************************************************************* + * Mask for _both_ the routing model bits in the 'flags' parameter and + * constants to define the valid routing models for each supported interrupt + * type + ******************************************************************************/ +#define INTR_RM_FLAGS_SHIFT U(0x0) +#define INTR_RM_FLAGS_MASK U(0x3) +/* Routed to EL3 from NS. Taken to S-EL1 from Secure */ +#define INTR_SEL1_VALID_RM0 U(0x2) +/* Routed to EL3 from NS and Secure */ +#define INTR_SEL1_VALID_RM1 U(0x3) +/* Routed to EL1/EL2 from NS and to S-EL1 from Secure */ +#define INTR_NS_VALID_RM0 U(0x0) +/* Routed to EL1/EL2 from NS and to EL3 from Secure */ +#define INTR_NS_VALID_RM1 U(0x1) +/* Routed to EL3 from NS. Taken to S-EL1 from Secure and handed over to EL3 */ +#define INTR_EL3_VALID_RM0 U(0x2) +/* Routed to EL3 from NS and Secure */ +#define INTR_EL3_VALID_RM1 U(0x3) +/* This is the default routing model */ +#define INTR_DEFAULT_RM U(0x0) + +/******************************************************************************* + * Constants for the _individual_ routing model bits in the 'flags' field for + * each interrupt type and mask to validate the 'flags' parameter while + * registering an interrupt handler + ******************************************************************************/ +#define INTR_TYPE_FLAGS_MASK U(0xFFFFFFFC) + +#define INTR_RM_FROM_SEC_SHIFT SECURE /* BIT[0] */ +#define INTR_RM_FROM_NS_SHIFT NON_SECURE /* BIT[1] */ +#define INTR_RM_FROM_FLAG_MASK U(1) +#define get_interrupt_rm_flag(flag, ss) \ + ((((flag) >> INTR_RM_FLAGS_SHIFT) >> (ss)) & INTR_RM_FROM_FLAG_MASK) +#define set_interrupt_rm_flag(flag, ss) ((flag) |= U(1) << (ss)) +#define clr_interrupt_rm_flag(flag, ss) ((flag) &= ~(U(1) << (ss))) + +/******************************************************************************* + * Macros to set the 'flags' parameter passed to an interrupt type handler. Only + * the flag to indicate the security state when the exception was generated is + * supported. + ******************************************************************************/ +#define INTR_SRC_SS_FLAG_SHIFT U(0) /* BIT[0] */ +#define INTR_SRC_SS_FLAG_MASK U(1) +#define set_interrupt_src_ss(flag, val) ((flag) |= (val) << INTR_SRC_SS_FLAG_SHIFT) +#define clr_interrupt_src_ss(flag) ((flag) &= ~(U(1) << INTR_SRC_SS_FLAG_SHIFT)) +#define get_interrupt_src_ss(flag) (((flag) >> INTR_SRC_SS_FLAG_SHIFT) & \ + INTR_SRC_SS_FLAG_MASK) + +#ifndef __ASSEMBLER__ + +#include +#include + +/******************************************************************************* + * Helpers to validate the routing model bits in the 'flags' for a type + * of interrupt. If the model does not match one of the valid masks + * -EINVAL is returned. + ******************************************************************************/ +static inline int32_t validate_sel1_interrupt_rm(uint32_t x) +{ + if ((x == INTR_SEL1_VALID_RM0) || (x == INTR_SEL1_VALID_RM1)) + return 0; + + return -EINVAL; +} + +static inline int32_t validate_ns_interrupt_rm(uint32_t x) +{ + if ((x == INTR_NS_VALID_RM0) || (x == INTR_NS_VALID_RM1)) + return 0; + + return -EINVAL; +} + +static inline int32_t validate_el3_interrupt_rm(uint32_t x) +{ +#if EL3_EXCEPTION_HANDLING + /* + * With EL3 exception handling, EL3 interrupts are always routed to EL3 + * from both Secure and Non-secure, and therefore INTR_EL3_VALID_RM1 is + * the only valid routing model. + */ + if (x == INTR_EL3_VALID_RM1) + return 0; +#else + if ((x == INTR_EL3_VALID_RM0) || (x == INTR_EL3_VALID_RM1)) + return 0; +#endif + + return -EINVAL; +} + +/******************************************************************************* + * Prototype for defining a handler for an interrupt type + ******************************************************************************/ +typedef uint64_t (*interrupt_type_handler_t)(uint32_t id, + uint32_t flags, + void *handle, + void *cookie); + +/******************************************************************************* + * Function & variable prototypes + ******************************************************************************/ +u_register_t get_scr_el3_from_routing_model(uint32_t security_state); +int32_t set_routing_model(uint32_t type, uint32_t flags); +int32_t register_interrupt_type_handler(uint32_t type, + interrupt_type_handler_t handler, + uint32_t flags); +interrupt_type_handler_t get_interrupt_type_handler(uint32_t type); +int disable_intr_rm_local(uint32_t type, uint32_t security_state); +int enable_intr_rm_local(uint32_t type, uint32_t security_state); + +#endif /*__ASSEMBLER__*/ +#endif /* INTERRUPT_MGMT_H */ diff --git a/drivers/rz/ipl/rza/include/common/asm_macros_common.S b/drivers/rz/ipl/rza/include/common/asm_macros_common.S new file mode 100644 index 00000000..fd0ea81d --- /dev/null +++ b/drivers/rz/ipl/rza/include/common/asm_macros_common.S @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef ASM_MACROS_COMMON_S +#define ASM_MACROS_COMMON_S + + /* + * This macro is used to create a function label and place the + * code into a separate text section based on the function name + * to enable elimination of unused code during linking. It also adds + * basic debug information to enable call stack printing most of the + * time. The optional _align parameter can be used to force a + * non-standard alignment (indicated in powers of 2). The default is + * _align=2 because both Aarch32 and Aarch64 instructions must be + * word aligned. Do *not* try to use a raw .align directive. Since func + * switches to a new section, this would not have the desired effect. + */ + .macro func _name, _align=2 + /* + * Add Call Frame Information entry in the .debug_frame section for + * debugger consumption. This enables callstack printing in debuggers. + * This does not use any space in the final loaded binary, only in the + * ELF file. + * Note that a function manipulating the CFA pointer location (i.e. the + * x29 frame pointer on AArch64) should declare it using the + * appropriate .cfi* directives, or be prepared to have a degraded + * debugging experience. + */ + .cfi_sections .debug_frame + .section .text.asm.\_name, "ax" + .type \_name, %function + /* + * .cfi_startproc and .cfi_endproc are needed to output entries in + * .debug_frame + */ + .cfi_startproc + .align \_align + \_name: +#if ENABLE_BTI + /* When Branch Target Identification is enabled, insert "bti jc" + * instruction to enable indirect calls and branches + */ + bti jc +#endif + .endm + + /* + * This macro is used to mark the end of a function. + */ + .macro endfunc _name + .cfi_endproc + .size \_name, . - \_name + .endm + + /* + * Theses macros are used to create function labels for deprecated + * APIs. If ERROR_DEPRECATED is non zero, the callers of these APIs + * will fail to link and cause build failure. + */ +#if ERROR_DEPRECATED + .macro func_deprecated _name + func deprecated\_name + .endm + + .macro endfunc_deprecated _name + endfunc deprecated\_name + .endm +#else + .macro func_deprecated _name + func \_name + .endm + + .macro endfunc_deprecated _name + endfunc \_name + .endm +#endif + + /* + * Helper assembler macro to count trailing zeros. The output is + * populated in the `TZ_COUNT` symbol. + */ + .macro count_tz _value, _tz_count + .if \_value + count_tz "(\_value >> 1)", "(\_tz_count + 1)" + .else + .equ TZ_COUNT, (\_tz_count - 1) + .endif + .endm + + /* + * This macro declares an array of 1 or more stacks, properly + * aligned and in the requested section + */ +#define DEFAULT_STACK_ALIGN (1 << 6) /* In case the caller doesnt provide alignment */ + + .macro declare_stack _name, _section, _size, _count, _align=DEFAULT_STACK_ALIGN + count_tz \_align, 0 + .if (\_align - (1 << TZ_COUNT)) + .error "Incorrect stack alignment specified (Must be a power of 2)." + .endif + .if ((\_size & ((1 << TZ_COUNT) - 1)) <> 0) + .error "Stack size not correctly aligned" + .endif + .section \_section, "aw", %nobits + .align TZ_COUNT + \_name: + .space ((\_count) * (\_size)), 0 + .endm + + +#endif /* ASM_MACROS_COMMON_S */ diff --git a/drivers/rz/ipl/rza/include/common/bl_common.h b/drivers/rz/ipl/rza/include/common/bl_common.h new file mode 100644 index 00000000..77fb1f67 --- /dev/null +++ b/drivers/rz/ipl/rza/include/common/bl_common.h @@ -0,0 +1,184 @@ +/* + * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef BL_COMMON_H +#define BL_COMMON_H + +#include +#include +#include + +#ifndef __ASSEMBLER__ +#include +#include +#include +#endif /* __ASSEMBLER__ */ + +#include + +#define UP U(1) +#define DOWN U(0) + +/******************************************************************************* + * Constants to identify the location of a memory region in a given memory + * layout. +******************************************************************************/ +#define TOP U(0x1) +#define BOTTOM U(0x0) + +/******************************************************************************* + * Constants to indicate type of exception to the common exception handler. + ******************************************************************************/ +#define SYNC_EXCEPTION_SP_EL0 U(0x0) +#define IRQ_SP_EL0 U(0x1) +#define FIQ_SP_EL0 U(0x2) +#define SERROR_SP_EL0 U(0x3) +#define SYNC_EXCEPTION_SP_ELX U(0x4) +#define IRQ_SP_ELX U(0x5) +#define FIQ_SP_ELX U(0x6) +#define SERROR_SP_ELX U(0x7) +#define SYNC_EXCEPTION_AARCH64 U(0x8) +#define IRQ_AARCH64 U(0x9) +#define FIQ_AARCH64 U(0xa) +#define SERROR_AARCH64 U(0xb) +#define SYNC_EXCEPTION_AARCH32 U(0xc) +#define IRQ_AARCH32 U(0xd) +#define FIQ_AARCH32 U(0xe) +#define SERROR_AARCH32 U(0xf) + +/* + * Mapping to connect linker symbols from .ld.S with their counterparts + * from .scat for the BL31 image + */ +#if defined(USE_ARM_LINK) +#define __BL31_END__ Load$$LR$$LR_END$$Base +#define __BSS_START__ Load$$LR$$LR_BSS$$Base +#define __BSS_END__ Load$$LR$$LR_BSS$$Limit +#define __BSS_SIZE__ Load$$LR$$LR_BSS$$Length +#define __COHERENT_RAM_START__ Load$$LR$$LR_COHERENT_RAM$$Base +#define __COHERENT_RAM_END_UNALIGNED__ Load$$__COHERENT_RAM_EPILOGUE_UNALIGNED__$$Base +#define __COHERENT_RAM_END__ Load$$LR$$LR_COHERENT_RAM$$Limit +#define __COHERENT_RAM_UNALIGNED_SIZE__ Load$$__COHERENT_RAM__$$Length +#define __CPU_OPS_START__ Load$$__CPU_OPS__$$Base +#define __CPU_OPS_END__ Load$$__CPU_OPS__$$Limit +#define __DATA_START__ Load$$__DATA__$$Base +#define __DATA_END__ Load$$__DATA__$$Limit +#define __GOT_START__ Load$$__GOT__$$Base +#define __GOT_END__ Load$$__GOT__$$Limit +#define __PERCPU_BAKERY_LOCK_START__ Load$$__BAKERY_LOCKS__$$Base +#define __PERCPU_BAKERY_LOCK_END__ Load$$__BAKERY_LOCKS_EPILOGUE__$$Base +#define __PMF_SVC_DESCS_START__ Load$$__PMF_SVC_DESCS__$$Base +#define __PMF_SVC_DESCS_END__ Load$$__PMF_SVC_DESCS__$$Limit +#define __PMF_TIMESTAMP_START__ Load$$__PMF_TIMESTAMP__$$Base +#define __PMF_TIMESTAMP_END__ Load$$__PER_CPU_TIMESTAMPS__$$Limit +#define __PMF_PERCPU_TIMESTAMP_END__ Load$$__PMF_TIMESTAMP_EPILOGUE__$$Base +#define __RELA_END__ Load$$__RELA__$$Limit +#define __RELA_START__ Load$$__RELA__$$Base +#define __RODATA_START__ Load$$__RODATA__$$Base +#define __RODATA_END__ Load$$__RODATA_EPILOGUE__$$Base +#define __RT_SVC_DESCS_START__ Load$$__RT_SVC_DESCS__$$Base +#define __RT_SVC_DESCS_END__ Load$$__RT_SVC_DESCS__$$Limit +#define __RW_START__ Load$$LR$$LR_RW_DATA$$Base +#define __RW_END__ Load$$LR$$LR_END$$Base +#define __SPM_SHIM_EXCEPTIONS_START__ Load$$__SPM_SHIM_EXCEPTIONS__$$Base +#define __SPM_SHIM_EXCEPTIONS_END__ Load$$__SPM_SHIM_EXCEPTIONS_EPILOGUE__$$Base +#define __STACKS_START__ Load$$__STACKS__$$Base +#define __STACKS_END__ Load$$__STACKS__$$Limit +#define __TEXT_START__ Load$$__TEXT__$$Base +#define __TEXT_END__ Load$$__TEXT_EPILOGUE__$$Base +#endif /* USE_ARM_LINK */ + +#ifndef __ASSEMBLER__ + +/* + * Declarations of linker defined symbols to help determine memory layout of + * BL images + */ +#if SEPARATE_CODE_AND_RODATA +IMPORT_SYM(uintptr_t, __TEXT_START__, BL_CODE_BASE); +IMPORT_SYM(uintptr_t, __TEXT_END__, BL_CODE_END); +IMPORT_SYM(uintptr_t, __RODATA_START__, BL_RO_DATA_BASE); +IMPORT_SYM(uintptr_t, __RODATA_END__, BL_RO_DATA_END); +#else +IMPORT_SYM(uintptr_t, __RO_START__, BL_CODE_BASE); +IMPORT_SYM(uintptr_t, __RO_END__, BL_CODE_END); +#endif +IMPORT_SYM(uintptr_t, __RW_END__, BL_END); + +#if defined(IMAGE_BL1) +IMPORT_SYM(uintptr_t, __BL1_ROM_END__, BL1_ROM_END); + +IMPORT_SYM(uintptr_t, __BL1_RAM_START__, BL1_RAM_BASE); +IMPORT_SYM(uintptr_t, __BL1_RAM_END__, BL1_RAM_LIMIT); +#elif defined(IMAGE_BL2) +IMPORT_SYM(uintptr_t, __BL2_END__, BL2_END); +#elif defined(IMAGE_BL2U) +IMPORT_SYM(uintptr_t, __BL2U_END__, BL2U_END); +#elif defined(IMAGE_BL31) +IMPORT_SYM(uintptr_t, __BL31_START__, BL31_START); +IMPORT_SYM(uintptr_t, __BL31_END__, BL31_END); +#elif defined(IMAGE_BL32) +IMPORT_SYM(uintptr_t, __BL32_END__, BL32_END); +#endif /* IMAGE_BLX */ + +/* The following symbols are only exported from the BL2 at EL3 linker script. */ +#if BL2_IN_XIP_MEM && defined(IMAGE_BL2) +IMPORT_SYM(uintptr_t, __BL2_ROM_END__, BL2_ROM_END); + +IMPORT_SYM(uintptr_t, __BL2_RAM_START__, BL2_RAM_BASE); +IMPORT_SYM(uintptr_t, __BL2_RAM_END__, BL2_RAM_END); +#endif /* BL2_IN_XIP_MEM */ + +/* + * The next 2 constants identify the extents of the coherent memory region. + * These addresses are used by the MMU setup code and therefore they must be + * page-aligned. It is the responsibility of the linker script to ensure that + * __COHERENT_RAM_START__ and __COHERENT_RAM_END__ linker symbols refer to + * page-aligned addresses. + */ +#if USE_COHERENT_MEM +IMPORT_SYM(uintptr_t, __COHERENT_RAM_START__, BL_COHERENT_RAM_BASE); +IMPORT_SYM(uintptr_t, __COHERENT_RAM_END__, BL_COHERENT_RAM_END); +#endif + +/******************************************************************************* + * Structure used for telling the next BL how much of a particular type of + * memory is available for its use and how much is already used. + ******************************************************************************/ +typedef struct meminfo { + uintptr_t total_base; + size_t total_size; +} meminfo_t; + +/******************************************************************************* + * Function & variable prototypes + ******************************************************************************/ +int load_auth_image(unsigned int image_id, image_info_t *image_data); + +#if TRUSTED_BOARD_BOOT && defined(DYN_DISABLE_AUTH) +/* + * API to dynamically disable authentication. Only meant for development + * systems. + */ +void dyn_disable_auth(void); +#endif + +extern const char build_message[]; +extern const char version_string[]; + +void print_entry_point_info(const entry_point_info_t *ep_info); +uintptr_t page_align(uintptr_t value, unsigned dir); + +struct mmap_region; + +void setup_page_tables(const struct mmap_region *bl_regions, + const struct mmap_region *plat_regions); + +void bl_handle_pauth(void); + +#endif /*__ASSEMBLER__*/ + +#endif /* BL_COMMON_H */ diff --git a/drivers/rz/ipl/rza/include/common/bl_common.ld.h b/drivers/rz/ipl/rza/include/common/bl_common.ld.h new file mode 100644 index 00000000..5147e376 --- /dev/null +++ b/drivers/rz/ipl/rza/include/common/bl_common.ld.h @@ -0,0 +1,216 @@ +/* + * Copyright (c) 2020-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef BL_COMMON_LD_H +#define BL_COMMON_LD_H + +#include + +#ifdef __aarch64__ +#define STRUCT_ALIGN 8 +#define BSS_ALIGN 16 +#else +#define STRUCT_ALIGN 4 +#define BSS_ALIGN 8 +#endif + +#ifndef DATA_ALIGN +#define DATA_ALIGN 1 +#endif + +#define CPU_OPS \ + . = ALIGN(STRUCT_ALIGN); \ + __CPU_OPS_START__ = .; \ + KEEP(*(cpu_ops)) \ + __CPU_OPS_END__ = .; + +#define PARSER_LIB_DESCS \ + . = ALIGN(STRUCT_ALIGN); \ + __PARSER_LIB_DESCS_START__ = .; \ + KEEP(*(.img_parser_lib_descs)) \ + __PARSER_LIB_DESCS_END__ = .; + +#define RT_SVC_DESCS \ + . = ALIGN(STRUCT_ALIGN); \ + __RT_SVC_DESCS_START__ = .; \ + KEEP(*(rt_svc_descs)) \ + __RT_SVC_DESCS_END__ = .; + +#define PMF_SVC_DESCS \ + . = ALIGN(STRUCT_ALIGN); \ + __PMF_SVC_DESCS_START__ = .; \ + KEEP(*(pmf_svc_descs)) \ + __PMF_SVC_DESCS_END__ = .; + +#define FCONF_POPULATOR \ + . = ALIGN(STRUCT_ALIGN); \ + __FCONF_POPULATOR_START__ = .; \ + KEEP(*(.fconf_populator)) \ + __FCONF_POPULATOR_END__ = .; + +/* + * Keep the .got section in the RO section as it is patched prior to enabling + * the MMU and having the .got in RO is better for security. GOT is a table of + * addresses so ensure pointer size alignment. + */ +#define GOT \ + . = ALIGN(STRUCT_ALIGN); \ + __GOT_START__ = .; \ + *(.got) \ + __GOT_END__ = .; + +/* + * The base xlat table + * + * It is put into the rodata section if PLAT_RO_XLAT_TABLES=1, + * or into the bss section otherwise. + */ +#define BASE_XLAT_TABLE \ + . = ALIGN(16); \ + *(base_xlat_table) + +#if PLAT_RO_XLAT_TABLES +#define BASE_XLAT_TABLE_RO BASE_XLAT_TABLE +#define BASE_XLAT_TABLE_BSS +#else +#define BASE_XLAT_TABLE_RO +#define BASE_XLAT_TABLE_BSS BASE_XLAT_TABLE +#endif + +#define RODATA_COMMON \ + RT_SVC_DESCS \ + FCONF_POPULATOR \ + PMF_SVC_DESCS \ + PARSER_LIB_DESCS \ + CPU_OPS \ + GOT \ + BASE_XLAT_TABLE_RO + +/* + * .data must be placed at a lower address than the stacks if the stack + * protector is enabled. Alternatively, the .data.stack_protector_canary + * section can be placed independently of the main .data section. + */ +#define DATA_SECTION \ + .data . : ALIGN(DATA_ALIGN) { \ + __DATA_START__ = .; \ + *(SORT_BY_ALIGNMENT(.data*)) \ + __DATA_END__ = .; \ + } + +/* + * .rela.dyn needs to come after .data for the read-elf utility to parse + * this section correctly. + */ +#if __aarch64__ +#define RELA_DYN_NAME .rela.dyn +#define RELOC_SECTIONS_PATTERN *(.rela*) +#else +#define RELA_DYN_NAME .rel.dyn +#define RELOC_SECTIONS_PATTERN *(.rel*) +#endif + +#define RELA_SECTION \ + RELA_DYN_NAME : ALIGN(STRUCT_ALIGN) { \ + __RELA_START__ = .; \ + RELOC_SECTIONS_PATTERN \ + __RELA_END__ = .; \ + } + +#if !(defined(IMAGE_BL31) && RECLAIM_INIT_CODE) +#define STACK_SECTION \ + stacks (NOLOAD) : { \ + __STACKS_START__ = .; \ + *(tzfw_normal_stacks) \ + __STACKS_END__ = .; \ + } +#endif + +/* + * If BL doesn't use any bakery lock then __PERCPU_BAKERY_LOCK_SIZE__ + * will be zero. For this reason, the only two valid values for + * __PERCPU_BAKERY_LOCK_SIZE__ are 0 or the platform defined value + * PLAT_PERCPU_BAKERY_LOCK_SIZE. + */ +#ifdef PLAT_PERCPU_BAKERY_LOCK_SIZE +#define BAKERY_LOCK_SIZE_CHECK \ + ASSERT((__PERCPU_BAKERY_LOCK_SIZE__ == 0) || \ + (__PERCPU_BAKERY_LOCK_SIZE__ == PLAT_PERCPU_BAKERY_LOCK_SIZE), \ + "PLAT_PERCPU_BAKERY_LOCK_SIZE does not match bakery lock requirements"); +#else +#define BAKERY_LOCK_SIZE_CHECK +#endif + +/* + * Bakery locks are stored in normal .bss memory + * + * Each lock's data is spread across multiple cache lines, one per CPU, + * but multiple locks can share the same cache line. + * The compiler will allocate enough memory for one CPU's bakery locks, + * the remaining cache lines are allocated by the linker script + */ +#if !USE_COHERENT_MEM +#define BAKERY_LOCK_NORMAL \ + . = ALIGN(CACHE_WRITEBACK_GRANULE); \ + __BAKERY_LOCK_START__ = .; \ + __PERCPU_BAKERY_LOCK_START__ = .; \ + *(bakery_lock) \ + . = ALIGN(CACHE_WRITEBACK_GRANULE); \ + __PERCPU_BAKERY_LOCK_END__ = .; \ + __PERCPU_BAKERY_LOCK_SIZE__ = ABSOLUTE(__PERCPU_BAKERY_LOCK_END__ - __PERCPU_BAKERY_LOCK_START__); \ + . = . + (__PERCPU_BAKERY_LOCK_SIZE__ * (PLATFORM_CORE_COUNT - 1)); \ + __BAKERY_LOCK_END__ = .; \ + BAKERY_LOCK_SIZE_CHECK +#else +#define BAKERY_LOCK_NORMAL +#endif + +/* + * Time-stamps are stored in normal .bss memory + * + * The compiler will allocate enough memory for one CPU's time-stamps, + * the remaining memory for other CPUs is allocated by the + * linker script + */ +#define PMF_TIMESTAMP \ + . = ALIGN(CACHE_WRITEBACK_GRANULE); \ + __PMF_TIMESTAMP_START__ = .; \ + KEEP(*(pmf_timestamp_array)) \ + . = ALIGN(CACHE_WRITEBACK_GRANULE); \ + __PMF_PERCPU_TIMESTAMP_END__ = .; \ + __PERCPU_TIMESTAMP_SIZE__ = ABSOLUTE(. - __PMF_TIMESTAMP_START__); \ + . = . + (__PERCPU_TIMESTAMP_SIZE__ * (PLATFORM_CORE_COUNT - 1)); \ + __PMF_TIMESTAMP_END__ = .; + + +/* + * The .bss section gets initialised to 0 at runtime. + * Its base address has bigger alignment for better performance of the + * zero-initialization code. + */ +#define BSS_SECTION \ + .bss (NOLOAD) : ALIGN(BSS_ALIGN) { \ + __BSS_START__ = .; \ + *(SORT_BY_ALIGNMENT(.bss*)) \ + *(COMMON) \ + BAKERY_LOCK_NORMAL \ + PMF_TIMESTAMP \ + BASE_XLAT_TABLE_BSS \ + __BSS_END__ = .; \ + } + +/* + * The xlat_table section is for full, aligned page tables (4K). + * Removing them from .bss avoids forcing 4K alignment on + * the .bss section. The tables are initialized to zero by the translation + * tables library. + */ +#define XLAT_TABLE_SECTION \ + xlat_table (NOLOAD) : { \ + *(xlat_table) \ + } + +#endif /* BL_COMMON_LD_H */ diff --git a/drivers/rz/ipl/rza/include/common/debug.h b/drivers/rz/ipl/rza/include/common/debug.h new file mode 100644 index 00000000..ed0e8bf9 --- /dev/null +++ b/drivers/rz/ipl/rza/include/common/debug.h @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef DEBUG_H +#define DEBUG_H + +#include + +/* + * The log output macros print output to the console. These macros produce + * compiled log output only if the LOG_LEVEL defined in the makefile (or the + * make command line) is greater or equal than the level required for that + * type of log output. + * + * The format expected is the same as for printf(). For example: + * INFO("Info %s.\n", "message") -> INFO: Info message. + * WARN("Warning %s.\n", "message") -> WARNING: Warning message. + */ + +#define LOG_LEVEL_NONE U(0) +#define LOG_LEVEL_ERROR U(10) +#define LOG_LEVEL_NOTICE U(20) +#define LOG_LEVEL_WARNING U(30) +#define LOG_LEVEL_INFO U(40) +#define LOG_LEVEL_VERBOSE U(50) + +#ifndef __ASSEMBLER__ + +#include +#include +#include +#include + +#include + +/* + * Define Log Markers corresponding to each log level which will + * be embedded in the format string and is expected by tf_log() to determine + * the log level. + */ +#define LOG_MARKER_ERROR "\xa" /* 10 */ +#define LOG_MARKER_NOTICE "\x14" /* 20 */ +#define LOG_MARKER_WARNING "\x1e" /* 30 */ +#define LOG_MARKER_INFO "\x28" /* 40 */ +#define LOG_MARKER_VERBOSE "\x32" /* 50 */ + +/* + * If the log output is too low then this macro is used in place of tf_log() + * below. The intent is to get the compiler to evaluate the function call for + * type checking and format specifier correctness but let it optimize it out. + */ +#define no_tf_log(fmt, ...) \ + do { \ + if (false) { \ + tf_log(fmt, ##__VA_ARGS__); \ + } \ + } while (false) + +#if LOG_LEVEL >= LOG_LEVEL_ERROR +# define ERROR(...) tf_log(LOG_MARKER_ERROR __VA_ARGS__) +#else +# define ERROR(...) no_tf_log(LOG_MARKER_ERROR __VA_ARGS__) +#endif + +#if LOG_LEVEL >= LOG_LEVEL_NOTICE +# define NOTICE(...) tf_log(LOG_MARKER_NOTICE __VA_ARGS__) +#else +# define NOTICE(...) no_tf_log(LOG_MARKER_NOTICE __VA_ARGS__) +#endif + +#if LOG_LEVEL >= LOG_LEVEL_WARNING +# define WARN(...) tf_log(LOG_MARKER_WARNING __VA_ARGS__) +#else +# define WARN(...) no_tf_log(LOG_MARKER_WARNING __VA_ARGS__) +#endif + +#if LOG_LEVEL >= LOG_LEVEL_INFO +# define INFO(...) tf_log(LOG_MARKER_INFO __VA_ARGS__) +#else +# define INFO(...) no_tf_log(LOG_MARKER_INFO __VA_ARGS__) +#endif + +#if LOG_LEVEL >= LOG_LEVEL_VERBOSE +# define VERBOSE(...) tf_log(LOG_MARKER_VERBOSE __VA_ARGS__) +#else +# define VERBOSE(...) no_tf_log(LOG_MARKER_VERBOSE __VA_ARGS__) +#endif + +#if ENABLE_BACKTRACE +void backtrace(const char *cookie); +const char *get_el_str(unsigned int el); +#else +#define backtrace(x) +#endif + +void __dead2 do_panic(void); + +#define panic() \ + do { \ + backtrace(__func__); \ + console_flush(); \ + do_panic(); \ + } while (false) + +/* Function called when stack protection check code detects a corrupted stack */ +void __dead2 __stack_chk_fail(void); + +void tf_log(const char *fmt, ...) __printflike(1, 2); +void tf_log_set_max_level(unsigned int log_level); + +#endif /* __ASSEMBLER__ */ +#endif /* DEBUG_H */ diff --git a/drivers/rz/ipl/rza/include/common/desc_image_load.h b/drivers/rz/ipl/rza/include/common/desc_image_load.h new file mode 100644 index 00000000..b044f3e7 --- /dev/null +++ b/drivers/rz/ipl/rza/include/common/desc_image_load.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef DESC_IMAGE_LOAD_H +#define DESC_IMAGE_LOAD_H + +#include + +/* Following structure is used to store BL ep/image info. */ +typedef struct bl_mem_params_node { + unsigned int image_id; + image_info_t image_info; + entry_point_info_t ep_info; + unsigned int next_handoff_image_id; + bl_load_info_node_t load_node_mem; + bl_params_node_t params_node_mem; +} bl_mem_params_node_t; + +extern bl_mem_params_node_t *bl_mem_params_desc_ptr; +extern unsigned int bl_mem_params_desc_num; + +/* + * Macro to register list of BL image descriptors, + * defined as an array of bl_mem_params_node_t. + */ +#define REGISTER_BL_IMAGE_DESCS(_img_desc) \ + bl_mem_params_node_t *bl_mem_params_desc_ptr = &_img_desc[0]; \ + unsigned int bl_mem_params_desc_num = ARRAY_SIZE(_img_desc); + +/* BL image loading utility functions */ +void flush_bl_params_desc(void); +void flush_bl_params_desc_args(bl_mem_params_node_t *mem_params_desc_ptr, + unsigned int mem_params_desc_num, + bl_params_t *next_bl_params_ptr); +int get_bl_params_node_index(unsigned int image_id); +bl_mem_params_node_t *get_bl_mem_params_node(unsigned int image_id); +bl_load_info_t *get_bl_load_info_from_mem_params_desc(void); +bl_params_t *get_next_bl_params_from_mem_params_desc(void); +void populate_next_bl_params_config(bl_params_t *bl2_to_next_bl_params); + +/* Helper to extract BL32/BL33 entry point info from arg0 passed to BL31. */ +void bl31_params_parse_helper(u_register_t param, + entry_point_info_t *bl32_ep_info_out, + entry_point_info_t *bl33_ep_info_out); + +#endif /* DESC_IMAGE_LOAD_H */ diff --git a/drivers/rz/ipl/rza/include/common/ep_info.h b/drivers/rz/ipl/rza/include/common/ep_info.h new file mode 100644 index 00000000..4bfa1fa6 --- /dev/null +++ b/drivers/rz/ipl/rza/include/common/ep_info.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef EP_INFO_H +#define EP_INFO_H + +#include + +#ifndef __ASSEMBLER__ +#include +#include +#endif /* __ASSEMBLER__ */ + +#include + +#define SECURE EP_SECURE +#define NON_SECURE EP_NON_SECURE +#define sec_state_is_valid(s) (((s) == SECURE) || ((s) == NON_SECURE)) + +#define PARAM_EP_SECURITY_MASK EP_SECURITY_MASK + +#define NON_EXECUTABLE EP_NON_EXECUTABLE +#define EXECUTABLE EP_EXECUTABLE + +/* Secure or Non-secure image */ +#define GET_SECURITY_STATE(x) ((x) & EP_SECURITY_MASK) +#define SET_SECURITY_STATE(x, security) \ + ((x) = ((x) & ~EP_SECURITY_MASK) | (security)) + +#ifndef __ASSEMBLER__ + +/* + * Compile time assertions related to the 'entry_point_info' structure to + * ensure that the assembler and the compiler view of the offsets of + * the structure members is the same. + */ +CASSERT(ENTRY_POINT_INFO_PC_OFFSET == + __builtin_offsetof(entry_point_info_t, pc), \ + assert_BL31_pc_offset_mismatch); + +#ifndef __aarch64__ +CASSERT(ENTRY_POINT_INFO_LR_SVC_OFFSET == + __builtin_offsetof(entry_point_info_t, lr_svc), + assert_entrypoint_lr_offset_error); +#endif + +CASSERT(ENTRY_POINT_INFO_ARGS_OFFSET == \ + __builtin_offsetof(entry_point_info_t, args), \ + assert_BL31_args_offset_mismatch); + +CASSERT(sizeof(uintptr_t) == + __builtin_offsetof(entry_point_info_t, spsr) - \ + __builtin_offsetof(entry_point_info_t, pc), \ + assert_entrypoint_and_spsr_should_be_adjacent); + +#endif /*__ASSEMBLER__*/ + +#endif /* EP_INFO_H */ diff --git a/drivers/rz/ipl/rza/include/common/fdt_fixup.h b/drivers/rz/ipl/rza/include/common/fdt_fixup.h new file mode 100644 index 00000000..2e9d49d5 --- /dev/null +++ b/drivers/rz/ipl/rza/include/common/fdt_fixup.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef FDT_FIXUP_H +#define FDT_FIXUP_H + +int dt_add_psci_node(void *fdt); +int dt_add_psci_cpu_enable_methods(void *fdt); +int fdt_add_reserved_memory(void *dtb, const char *node_name, + uintptr_t base, size_t size); +int fdt_add_cpus_node(void *dtb, unsigned int afflv0, + unsigned int afflv1, unsigned int afflv2); +int fdt_adjust_gic_redist(void *dtb, unsigned int nr_cores, + unsigned int gicr_frame_size); + +#endif /* FDT_FIXUP_H */ diff --git a/drivers/rz/ipl/rza/include/common/fdt_wrappers.h b/drivers/rz/ipl/rza/include/common/fdt_wrappers.h new file mode 100644 index 00000000..e8b39335 --- /dev/null +++ b/drivers/rz/ipl/rza/include/common/fdt_wrappers.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2018-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* Helper functions to offer easier navigation of Device Tree Blob */ + +#ifndef FDT_WRAPPERS_H +#define FDT_WRAPPERS_H + +#include + +/* Number of cells, given total length in bytes. Each cell is 4 bytes long */ +#define NCELLS(len) ((len) / 4U) + +int fdt_read_uint32(const void *dtb, int node, const char *prop_name, + uint32_t *value); +uint32_t fdt_read_uint32_default(const void *dtb, int node, + const char *prop_name, uint32_t dflt_value); +int fdt_read_uint64(const void *dtb, int node, const char *prop_name, + uint64_t *value); +int fdt_read_uint32_array(const void *dtb, int node, const char *prop_name, + unsigned int cells, uint32_t *value); +int fdtw_read_string(const void *dtb, int node, const char *prop, + char *str, size_t size); +int fdtw_read_uuid(const void *dtb, int node, const char *prop, + unsigned int length, uint8_t *uuid); +int fdtw_write_inplace_cells(void *dtb, int node, const char *prop, + unsigned int cells, void *value); +int fdtw_read_bytes(const void *dtb, int node, const char *prop, + unsigned int length, void *value); +int fdtw_write_inplace_bytes(void *dtb, int node, const char *prop, + unsigned int length, const void *data); +int fdt_get_reg_props_by_index(const void *dtb, int node, int index, + uintptr_t *base, size_t *size); +int fdt_get_reg_props_by_name(const void *dtb, int node, const char *name, + uintptr_t *base, size_t *size); +int fdt_get_stdout_node_offset(const void *dtb); + +uint64_t fdtw_translate_address(const void *dtb, int bus_node, + uint64_t base_address); + +static inline uint32_t fdt_blob_size(const void *dtb) +{ + const uint32_t *dtb_header = dtb; + + return fdt32_to_cpu(dtb_header[1]); +} + +#endif /* FDT_WRAPPERS_H */ diff --git a/drivers/rz/ipl/rza/include/common/image_decompress.h b/drivers/rz/ipl/rza/include/common/image_decompress.h new file mode 100644 index 00000000..bb35c3ba --- /dev/null +++ b/drivers/rz/ipl/rza/include/common/image_decompress.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef IMAGE_DECOMPRESS_H +#define IMAGE_DECOMPRESS_H + +#include +#include + +struct image_info; + +typedef int (decompressor_t)(uintptr_t *in_buf, size_t in_len, + uintptr_t *out_buf, size_t out_len, + uintptr_t work_buf, size_t work_len); + +void image_decompress_init(uintptr_t buf_base, uint32_t buf_size, + decompressor_t *decompressor); +void image_decompress_prepare(struct image_info *info); +int image_decompress(struct image_info *info); + +#endif /* IMAGE_DECOMPRESS_H */ diff --git a/drivers/rz/ipl/rza/include/common/interrupt_props.h b/drivers/rz/ipl/rza/include/common/interrupt_props.h new file mode 100644 index 00000000..07bafaae --- /dev/null +++ b/drivers/rz/ipl/rza/include/common/interrupt_props.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef INTERRUPT_PROPS_H +#define INTERRUPT_PROPS_H + +#ifndef __ASSEMBLER__ + +/* Create an interrupt property descriptor from various interrupt properties */ +#define INTR_PROP_DESC(num, pri, grp, cfg) \ + { \ + .intr_num = (num), \ + .intr_pri = (pri), \ + .intr_grp = (grp), \ + .intr_cfg = (cfg), \ + } + +typedef struct interrupt_prop { + unsigned int intr_num:10; + unsigned int intr_pri:8; + unsigned int intr_grp:2; + unsigned int intr_cfg:2; +} interrupt_prop_t; + +#endif /* __ASSEMBLER__ */ +#endif /* INTERRUPT_PROPS_H */ diff --git a/drivers/rz/ipl/rza/include/common/nv_cntr_ids.h b/drivers/rz/ipl/rza/include/common/nv_cntr_ids.h new file mode 100644 index 00000000..a15c431d --- /dev/null +++ b/drivers/rz/ipl/rza/include/common/nv_cntr_ids.h @@ -0,0 +1,9 @@ +/* + * Copyright (c) 2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#define TRUSTED_NV_CTR_ID U(0) +#define NON_TRUSTED_NV_CTR_ID U(1) +#define MAX_NV_CTR_IDS U(2) diff --git a/drivers/rz/ipl/rza/include/common/param_header.h b/drivers/rz/ipl/rza/include/common/param_header.h new file mode 100644 index 00000000..4dab4e3c --- /dev/null +++ b/drivers/rz/ipl/rza/include/common/param_header.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PARAM_HEADER_H +#define PARAM_HEADER_H + +#include + +#ifndef __ASSEMBLER__ +#include +#endif /*__ASSEMBLER__*/ + +#include + +#define VERSION_1 PARAM_VERSION_1 +#define VERSION_2 PARAM_VERSION_2 + +#define SET_PARAM_HEAD(_p, _type, _ver, _attr) do { \ + (_p)->h.type = (uint8_t)(_type); \ + (_p)->h.version = (uint8_t)(_ver); \ + (_p)->h.size = (uint16_t)sizeof(*(_p)); \ + (_p)->h.attr = (uint32_t)(_attr) ; \ + } while (false) + +/* Following is used for populating structure members statically. */ +#define SET_STATIC_PARAM_HEAD(_p, _type, _ver, _p_type, _attr) \ + ._p.h.type = (uint8_t)(_type), \ + ._p.h.version = (uint8_t)(_ver), \ + ._p.h.size = (uint16_t)sizeof(_p_type), \ + ._p.h.attr = (uint32_t)(_attr) + +#endif /* PARAM_HEADER_H */ diff --git a/drivers/rz/ipl/rza/include/common/romlib.h b/drivers/rz/ipl/rza/include/common/romlib.h new file mode 100644 index 00000000..7f53c475 --- /dev/null +++ b/drivers/rz/ipl/rza/include/common/romlib.h @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef ROMLIB_H +#define ROMLIB_H + +#define ROMLIB_MAJOR 0 +#define ROMLIB_MINOR 1 +#define ROMLIB_VERSION ((ROMLIB_MAJOR << 8) | ROMLIB_MINOR) + +int rom_lib_init(int version); + +#endif /* ROMLIB_H */ diff --git a/drivers/rz/ipl/rza/include/common/runtime_svc.h b/drivers/rz/ipl/rza/include/common/runtime_svc.h new file mode 100644 index 00000000..472a32a1 --- /dev/null +++ b/drivers/rz/ipl/rza/include/common/runtime_svc.h @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef RUNTIME_SVC_H +#define RUNTIME_SVC_H + +#include /* to include exception types */ +#include +#include +#include /* to include SMCCC definitions */ + +/******************************************************************************* + * Structure definition, typedefs & constants for the runtime service framework + ******************************************************************************/ + +/* + * Constants to allow the assembler access a runtime service + * descriptor + */ +#ifdef __aarch64__ +#define RT_SVC_SIZE_LOG2 U(5) +#define RT_SVC_DESC_INIT U(16) +#define RT_SVC_DESC_HANDLE U(24) +#else +#define RT_SVC_SIZE_LOG2 U(4) +#define RT_SVC_DESC_INIT U(8) +#define RT_SVC_DESC_HANDLE U(12) +#endif /* __aarch64__ */ +#define SIZEOF_RT_SVC_DESC (U(1) << RT_SVC_SIZE_LOG2) + + +/* + * In SMCCC 1.X, the function identifier has 6 bits for the owning entity number + * and a single bit for the type of smc call. When taken together, those values + * limit the maximum number of runtime services to 128. + */ +#define MAX_RT_SVCS U(128) + +#ifndef __ASSEMBLER__ + +/* Prototype for runtime service initializing function */ +typedef int32_t (*rt_svc_init_t)(void); + +/* + * Prototype for runtime service SMC handler function. x0 (SMC Function ID) to + * x4 are as passed by the caller. Rest of the arguments to SMC and the context + * can be accessed using the handle pointer. The cookie parameter is reserved + * for future use + */ +typedef uintptr_t (*rt_svc_handle_t)(uint32_t smc_fid, + u_register_t x1, + u_register_t x2, + u_register_t x3, + u_register_t x4, + void *cookie, + void *handle, + u_register_t flags); +typedef struct rt_svc_desc { + uint8_t start_oen; + uint8_t end_oen; + uint8_t call_type; + const char *name; + rt_svc_init_t init; + rt_svc_handle_t handle; +} rt_svc_desc_t; + +/* + * Convenience macros to declare a service descriptor + */ +#define DECLARE_RT_SVC(_name, _start, _end, _type, _setup, _smch) \ + static const rt_svc_desc_t __svc_desc_ ## _name \ + __section("rt_svc_descs") __used = { \ + .start_oen = (_start), \ + .end_oen = (_end), \ + .call_type = (_type), \ + .name = #_name, \ + .init = (_setup), \ + .handle = (_smch) \ + } + +/* + * Compile time assertions related to the 'rt_svc_desc' structure to: + * 1. ensure that the assembler and the compiler view of the size + * of the structure are the same. + * 2. ensure that the assembler and the compiler see the initialisation + * routine at the same offset. + * 3. ensure that the assembler and the compiler see the handler + * routine at the same offset. + */ +CASSERT((sizeof(rt_svc_desc_t) == SIZEOF_RT_SVC_DESC), \ + assert_sizeof_rt_svc_desc_mismatch); +CASSERT(RT_SVC_DESC_INIT == __builtin_offsetof(rt_svc_desc_t, init), \ + assert_rt_svc_desc_init_offset_mismatch); +CASSERT(RT_SVC_DESC_HANDLE == __builtin_offsetof(rt_svc_desc_t, handle), \ + assert_rt_svc_desc_handle_offset_mismatch); + + +/* + * This function combines the call type and the owning entity number + * corresponding to a runtime service to generate a unique owning entity number. + * This unique oen is used to access an entry in the 'rt_svc_descs_indices' + * array. The entry contains the index of the service descriptor in the + * 'rt_svc_descs' array. + */ +static inline uint32_t get_unique_oen(uint32_t oen, uint32_t call_type) +{ + return ((call_type & FUNCID_TYPE_MASK) << FUNCID_OEN_WIDTH) | + (oen & FUNCID_OEN_MASK); +} + +/* + * This function generates the unique owning entity number from the SMC Function + * ID. This unique oen is used to access an entry in the 'rt_svc_descs_indices' + * array to invoke the corresponding runtime service handler during SMC + * handling. + */ +static inline uint32_t get_unique_oen_from_smc_fid(uint32_t fid) +{ + return get_unique_oen(GET_SMC_OEN(fid), GET_SMC_TYPE(fid)); +} + +/******************************************************************************* + * Function & variable prototypes + ******************************************************************************/ +void runtime_svc_init(void); +uintptr_t handle_runtime_svc(uint32_t smc_fid, void *cookie, void *handle, + unsigned int flags); +IMPORT_SYM(uintptr_t, __RT_SVC_DESCS_START__, RT_SVC_DESCS_START); +IMPORT_SYM(uintptr_t, __RT_SVC_DESCS_END__, RT_SVC_DESCS_END); +void init_crash_reporting(void); + +extern uint8_t rt_svc_descs_indices[MAX_RT_SVCS]; + +#endif /*__ASSEMBLER__*/ +#endif /* RUNTIME_SVC_H */ diff --git a/drivers/rz/ipl/rza/include/common/tbbr/cot_def.h b/drivers/rz/ipl/rza/include/common/tbbr/cot_def.h new file mode 100644 index 00000000..800ad07e --- /dev/null +++ b/drivers/rz/ipl/rza/include/common/tbbr/cot_def.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef COT_DEF_H +#define COT_DEF_H + +#ifdef MBEDTLS_CONFIG_FILE +#include MBEDTLS_CONFIG_FILE +#endif + +/* TBBR CoT definitions */ +#if defined(SPD_spmd) +#define COT_MAX_VERIFIED_PARAMS 8 +#else +#define COT_MAX_VERIFIED_PARAMS 4 +#endif + +/* + * Maximum key and hash sizes (in DER format). + * + * Both RSA and ECDSA keys may be used at the same time. In this case, the key + * buffers must be big enough to hold either. As RSA keys are bigger than ECDSA + * ones for all key sizes we support, they impose the minimum size of these + * buffers. + */ +#if TF_MBEDTLS_USE_RSA +#if TF_MBEDTLS_KEY_SIZE == 1024 +#define PK_DER_LEN 162 +#elif TF_MBEDTLS_KEY_SIZE == 2048 +#define PK_DER_LEN 294 +#elif TF_MBEDTLS_KEY_SIZE == 3072 +#define PK_DER_LEN 422 +#elif TF_MBEDTLS_KEY_SIZE == 4096 +#define PK_DER_LEN 550 +#else +#error "Invalid value for TF_MBEDTLS_KEY_SIZE" +#endif +#else /* Only using ECDSA keys. */ +#define PK_DER_LEN 91 +#endif + +#if TF_MBEDTLS_HASH_ALG_ID == TF_MBEDTLS_SHA256 +#define HASH_DER_LEN 51 +#elif TF_MBEDTLS_HASH_ALG_ID == TF_MBEDTLS_SHA384 +#define HASH_DER_LEN 67 +#elif TF_MBEDTLS_HASH_ALG_ID == TF_MBEDTLS_SHA512 +#define HASH_DER_LEN 83 +#else +#error "Invalid value for TF_MBEDTLS_HASH_ALG_ID" +#endif + +#endif /* COT_DEF_H */ diff --git a/drivers/rz/ipl/rza/include/common/tbbr/tbbr_img_def.h b/drivers/rz/ipl/rza/include/common/tbbr/tbbr_img_def.h new file mode 100644 index 00000000..e1c8c298 --- /dev/null +++ b/drivers/rz/ipl/rza/include/common/tbbr/tbbr_img_def.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TBBR_IMG_DEF_H +#define TBBR_IMG_DEF_H + +#include + +#if defined(SPD_spmd) +#define SIP_SP_CONTENT_CERT_ID MAX_IMAGE_IDS +#define PLAT_SP_CONTENT_CERT_ID (MAX_IMAGE_IDS + 1) +#define SP_PKG1_ID (MAX_IMAGE_IDS + 2) +#define SP_PKG2_ID (MAX_IMAGE_IDS + 3) +#define SP_PKG3_ID (MAX_IMAGE_IDS + 4) +#define SP_PKG4_ID (MAX_IMAGE_IDS + 5) +#define SP_PKG5_ID (MAX_IMAGE_IDS + 6) +#define SP_PKG6_ID (MAX_IMAGE_IDS + 7) +#define SP_PKG7_ID (MAX_IMAGE_IDS + 8) +#define SP_PKG8_ID (MAX_IMAGE_IDS + 9) +#define MAX_SP_IDS U(8) +#define MAX_IMG_IDS_WITH_SPMDS (MAX_IMAGE_IDS + MAX_SP_IDS + U(2)) +#else +#define MAX_IMG_IDS_WITH_SPMDS MAX_IMAGE_IDS +#endif + +#ifdef PLAT_TBBR_IMG_DEF +#include +#endif + +#ifndef MAX_NUMBER_IDS +#define MAX_NUMBER_IDS MAX_IMG_IDS_WITH_SPMDS +#endif + +#endif /* TBBR_IMG_DEF_H */ diff --git a/drivers/rz/ipl/rza/include/common/uuid.h b/drivers/rz/ipl/rza/include/common/uuid.h new file mode 100644 index 00000000..5651d0d5 --- /dev/null +++ b/drivers/rz/ipl/rza/include/common/uuid.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef UUID_H +#define UUID_H + +#define UUID_BYTES_LENGTH 16 +#define UUID_STRING_LENGTH 36 + +int read_uuid(uint8_t *dest, char *uuid); + +#endif /* UUID_H */ diff --git a/drivers/rz/ipl/rza/include/drivers/arm/arm_gicv3_common.h b/drivers/rz/ipl/rza/include/drivers/arm/arm_gicv3_common.h new file mode 100644 index 00000000..b88b59fb --- /dev/null +++ b/drivers/rz/ipl/rza/include/drivers/arm/arm_gicv3_common.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef ARM_GICV3_COMMON_H +#define ARM_GICV3_COMMON_H + +/******************************************************************************* + * GIC500/GIC600 Re-distributor interface registers & constants + ******************************************************************************/ + +/* GICR_WAKER implementation-defined bit definitions */ +#define WAKER_SL_SHIFT 0 +#define WAKER_QSC_SHIFT 31 + +#define WAKER_SL_BIT (1U << WAKER_SL_SHIFT) +#define WAKER_QSC_BIT (1U << WAKER_QSC_SHIFT) + +#endif /* ARM_GICV3_COMMON_H */ diff --git a/drivers/rz/ipl/rza/include/drivers/arm/gic600_multichip.h b/drivers/rz/ipl/rza/include/drivers/arm/gic600_multichip.h new file mode 100644 index 00000000..bda406bb --- /dev/null +++ b/drivers/rz/ipl/rza/include/drivers/arm/gic600_multichip.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2019, ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef GIC600_MULTICHIP_H +#define GIC600_MULTICHIP_H + +#include + +/* + * GIC-600 microarchitecture supports coherent multichip environments containing + * up to 16 chips. + */ +#define GIC600_MAX_MULTICHIP 16 + +/* SPI IDs array consist of min and max ids */ +#define GIC600_SPI_IDS_SIZE 2 + +/******************************************************************************* + * GIC-600 multichip data structure describes platform specific attributes + * related to GIC-600 multichip. Platform port is expected to define these + * attributes to initialize the multichip related registers and create + * successful connections between the GIC-600s in a multichip system. + * + * The 'rt_owner_base' field contains the base address of the GIC Distributor + * which owns the routing table. + * + * The 'rt_owner' field contains the chip number which owns the routing table. + * Chip number or chip_id starts from 0. + * + * The 'chip_count' field contains the total number of chips in a multichip + * system. This should match the number of entries in 'chip_addrs' and 'spi_ids' + * fields. + * + * The 'chip_addrs' field contains array of chip addresses. These addresses are + * implementation specific values. + * + * The 'spi_ids' field contains array of minimum and maximum SPI interrupt ids + * that each chip owns. Note that SPI interrupt ids can range from 32 to 960 and + * it should be group of 32 (i.e., SPI minimum and (SPI maximum + 1) should be + * a multiple of 32). If a chip doesn't own any SPI interrupts a value of {0, 0} + * should be passed. + ******************************************************************************/ +struct gic600_multichip_data { + uintptr_t rt_owner_base; + unsigned int rt_owner; + unsigned int chip_count; + uint64_t chip_addrs[GIC600_MAX_MULTICHIP]; + unsigned int spi_ids[GIC600_MAX_MULTICHIP][GIC600_SPI_IDS_SIZE]; +}; + +void gic600_multichip_init(struct gic600_multichip_data *multichip_data); +#endif /* GIC600_MULTICHIP_H */ diff --git a/drivers/rz/ipl/rza/include/drivers/arm/gic_common.h b/drivers/rz/ipl/rza/include/drivers/arm/gic_common.h new file mode 100644 index 00000000..dc23721b --- /dev/null +++ b/drivers/rz/ipl/rza/include/drivers/arm/gic_common.h @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef GIC_COMMON_H +#define GIC_COMMON_H + +#include + +/******************************************************************************* + * GIC Distributor interface general definitions + ******************************************************************************/ +/* Constants to categorise interrupts */ +#define MIN_SGI_ID U(0) +#define MIN_SEC_SGI_ID U(8) +#define MIN_PPI_ID U(16) +#define MIN_SPI_ID U(32) +#define MAX_SPI_ID U(1019) + +#define TOTAL_SPI_INTR_NUM (MAX_SPI_ID - MIN_SPI_ID + U(1)) +#define TOTAL_PCPU_INTR_NUM (MIN_SPI_ID - MIN_SGI_ID) + +/* Mask for the priority field common to all GIC interfaces */ +#define GIC_PRI_MASK U(0xff) + +/* Mask for the configuration field common to all GIC interfaces */ +#define GIC_CFG_MASK U(0x3) + +/* Constant to indicate a spurious interrupt in all GIC versions */ +#define GIC_SPURIOUS_INTERRUPT U(1023) + +/* Interrupt configurations: 2-bit fields with LSB reserved */ +#define GIC_INTR_CFG_LEVEL (0 << 1) +#define GIC_INTR_CFG_EDGE (1 << 1) + +/* Highest possible interrupt priorities */ +#define GIC_HIGHEST_SEC_PRIORITY U(0x00) +#define GIC_HIGHEST_NS_PRIORITY U(0x80) + +/******************************************************************************* + * Common GIC Distributor interface register offsets + ******************************************************************************/ +#define GICD_CTLR U(0x0) +#define GICD_TYPER U(0x4) +#define GICD_IIDR U(0x8) +#define GICD_IGROUPR U(0x80) +#define GICD_ISENABLER U(0x100) +#define GICD_ICENABLER U(0x180) +#define GICD_ISPENDR U(0x200) +#define GICD_ICPENDR U(0x280) +#define GICD_ISACTIVER U(0x300) +#define GICD_ICACTIVER U(0x380) +#define GICD_IPRIORITYR U(0x400) +#define GICD_ICFGR U(0xc00) +#define GICD_NSACR U(0xe00) + +/* GICD_CTLR bit definitions */ +#define CTLR_ENABLE_G0_SHIFT 0 +#define CTLR_ENABLE_G0_MASK U(0x1) +#define CTLR_ENABLE_G0_BIT BIT_32(CTLR_ENABLE_G0_SHIFT) + +/******************************************************************************* + * Common GIC Distributor interface register constants + ******************************************************************************/ +#define PIDR2_ARCH_REV_SHIFT 4 +#define PIDR2_ARCH_REV_MASK U(0xf) + +/* GIC revision as reported by PIDR2.ArchRev register field */ +#define ARCH_REV_GICV1 U(0x1) +#define ARCH_REV_GICV2 U(0x2) +#define ARCH_REV_GICV3 U(0x3) +#define ARCH_REV_GICV4 U(0x4) + +#define IGROUPR_SHIFT 5 +#define ISENABLER_SHIFT 5 +#define ICENABLER_SHIFT ISENABLER_SHIFT +#define ISPENDR_SHIFT 5 +#define ICPENDR_SHIFT ISPENDR_SHIFT +#define ISACTIVER_SHIFT 5 +#define ICACTIVER_SHIFT ISACTIVER_SHIFT +#define IPRIORITYR_SHIFT 2 +#define ITARGETSR_SHIFT 2 +#define ICFGR_SHIFT 4 +#define NSACR_SHIFT 4 + +/* GICD_TYPER shifts and masks */ +#define TYPER_IT_LINES_NO_SHIFT U(0) +#define TYPER_IT_LINES_NO_MASK U(0x1f) + +/* Value used to initialize Normal world interrupt priorities four at a time */ +#define GICD_IPRIORITYR_DEF_VAL \ + (GIC_HIGHEST_NS_PRIORITY | \ + (GIC_HIGHEST_NS_PRIORITY << 8) | \ + (GIC_HIGHEST_NS_PRIORITY << 16) | \ + (GIC_HIGHEST_NS_PRIORITY << 24)) + +#endif /* GIC_COMMON_H */ diff --git a/drivers/rz/ipl/rza/include/drivers/arm/gicv3.h b/drivers/rz/ipl/rza/include/drivers/arm/gicv3.h new file mode 100644 index 00000000..d8ac4cb3 --- /dev/null +++ b/drivers/rz/ipl/rza/include/drivers/arm/gicv3.h @@ -0,0 +1,529 @@ +/* + * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef GICV3_H +#define GICV3_H + +/******************************************************************************* + * GICv3 and 3.1 miscellaneous definitions + ******************************************************************************/ +/* Interrupt group definitions */ +#define INTR_GROUP1S U(0) +#define INTR_GROUP0 U(1) +#define INTR_GROUP1NS U(2) + +/* Interrupt IDs reported by the HPPIR and IAR registers */ +#define PENDING_G1S_INTID U(1020) +#define PENDING_G1NS_INTID U(1021) + +/* Constant to categorize LPI interrupt */ +#define MIN_LPI_ID U(8192) + +/* GICv3 can only target up to 16 PEs with SGI */ +#define GICV3_MAX_SGI_TARGETS U(16) + +/* PPIs INTIDs 16-31 */ +#define MAX_PPI_ID U(31) + +#if GIC_EXT_INTID + +/* GICv3.1 extended PPIs INTIDs 1056-1119 */ +#define MIN_EPPI_ID U(1056) +#define MAX_EPPI_ID U(1119) + +/* Total number of GICv3.1 EPPIs */ +#define TOTAL_EPPI_INTR_NUM (MAX_EPPI_ID - MIN_EPPI_ID + U(1)) + +/* Total number of GICv3.1 PPIs and EPPIs */ +#define TOTAL_PRIVATE_INTR_NUM (TOTAL_PCPU_INTR_NUM + TOTAL_EPPI_INTR_NUM) + +/* GICv3.1 extended SPIs INTIDs 4096 - 5119 */ +#define MIN_ESPI_ID U(4096) +#define MAX_ESPI_ID U(5119) + +/* Total number of GICv3.1 ESPIs */ +#define TOTAL_ESPI_INTR_NUM (MAX_ESPI_ID - MIN_ESPI_ID + U(1)) + +/* Total number of GICv3.1 SPIs and ESPIs */ +#define TOTAL_SHARED_INTR_NUM (TOTAL_SPI_INTR_NUM + TOTAL_ESPI_INTR_NUM) + +/* SGIs: 0-15, PPIs: 16-31, EPPIs: 1056-1119 */ +#define IS_SGI_PPI(id) (((id) <= MAX_PPI_ID) || \ + (((id) >= MIN_EPPI_ID) && \ + ((id) <= MAX_EPPI_ID))) + +/* SPIs: 32-1019, ESPIs: 4096-5119 */ +#define IS_SPI(id) ((((id) >= MIN_SPI_ID) && \ + ((id) <= MAX_SPI_ID)) || \ + (((id) >= MIN_ESPI_ID) && \ + ((id) <= MAX_ESPI_ID))) +#else /* GICv3 */ + +/* Total number of GICv3 PPIs */ +#define TOTAL_PRIVATE_INTR_NUM TOTAL_PCPU_INTR_NUM + +/* Total number of GICv3 SPIs */ +#define TOTAL_SHARED_INTR_NUM TOTAL_SPI_INTR_NUM + +/* SGIs: 0-15, PPIs: 16-31 */ +#define IS_SGI_PPI(id) ((id) <= MAX_PPI_ID) + +/* SPIs: 32-1019 */ +#define IS_SPI(id) (((id) >= MIN_SPI_ID) && ((id) <= MAX_SPI_ID)) + +#endif /* GIC_EXT_INTID */ + +/******************************************************************************* + * GICv3 and 3.1 specific Distributor interface register offsets and constants + ******************************************************************************/ +#define GICD_TYPER2 U(0x0c) +#define GICD_STATUSR U(0x10) +#define GICD_SETSPI_NSR U(0x40) +#define GICD_CLRSPI_NSR U(0x48) +#define GICD_SETSPI_SR U(0x50) +#define GICD_CLRSPI_SR U(0x58) +#define GICD_IGRPMODR U(0xd00) +#define GICD_IGROUPRE U(0x1000) +#define GICD_ISENABLERE U(0x1200) +#define GICD_ICENABLERE U(0x1400) +#define GICD_ISPENDRE U(0x1600) +#define GICD_ICPENDRE U(0x1800) +#define GICD_ISACTIVERE U(0x1a00) +#define GICD_ICACTIVERE U(0x1c00) +#define GICD_IPRIORITYRE U(0x2000) +#define GICD_ICFGRE U(0x3000) +#define GICD_IGRPMODRE U(0x3400) +#define GICD_NSACRE U(0x3600) +/* + * GICD_IROUTER register is at 0x6000 + 8n, where n is the interrupt ID + * and n >= 32, making the effective offset as 0x6100 + */ +#define GICD_IROUTER U(0x6000) +#define GICD_IROUTERE U(0x8000) + +#define GICD_PIDR2_GICV3 U(0xffe8) + +#define IGRPMODR_SHIFT 5 + +/* GICD_CTLR bit definitions */ +#define CTLR_ENABLE_G1NS_SHIFT 1 +#define CTLR_ENABLE_G1S_SHIFT 2 +#define CTLR_ARE_S_SHIFT 4 +#define CTLR_ARE_NS_SHIFT 5 +#define CTLR_DS_SHIFT 6 +#define CTLR_E1NWF_SHIFT 7 +#define GICD_CTLR_RWP_SHIFT 31 + +#define CTLR_ENABLE_G1NS_MASK U(0x1) +#define CTLR_ENABLE_G1S_MASK U(0x1) +#define CTLR_ARE_S_MASK U(0x1) +#define CTLR_ARE_NS_MASK U(0x1) +#define CTLR_DS_MASK U(0x1) +#define CTLR_E1NWF_MASK U(0x1) +#define GICD_CTLR_RWP_MASK U(0x1) + +#define CTLR_ENABLE_G1NS_BIT BIT_32(CTLR_ENABLE_G1NS_SHIFT) +#define CTLR_ENABLE_G1S_BIT BIT_32(CTLR_ENABLE_G1S_SHIFT) +#define CTLR_ARE_S_BIT BIT_32(CTLR_ARE_S_SHIFT) +#define CTLR_ARE_NS_BIT BIT_32(CTLR_ARE_NS_SHIFT) +#define CTLR_DS_BIT BIT_32(CTLR_DS_SHIFT) +#define CTLR_E1NWF_BIT BIT_32(CTLR_E1NWF_SHIFT) +#define GICD_CTLR_RWP_BIT BIT_32(GICD_CTLR_RWP_SHIFT) + +/* GICD_IROUTER shifts and masks */ +#define IROUTER_SHIFT 0 +#define IROUTER_IRM_SHIFT 31 +#define IROUTER_IRM_MASK U(0x1) + +#define GICV3_IRM_PE U(0) +#define GICV3_IRM_ANY U(1) + +#define NUM_OF_DIST_REGS 30 + +/* GICD_TYPER shifts and masks */ +#define TYPER_ESPI U(1 << 8) +#define TYPER_DVIS U(1 << 18) +#define TYPER_ESPI_RANGE_MASK U(0x1f) +#define TYPER_ESPI_RANGE_SHIFT U(27) +#define TYPER_ESPI_RANGE U(TYPER_ESPI_MASK << TYPER_ESPI_SHIFT) + +/******************************************************************************* + * Common GIC Redistributor interface registers & constants + ******************************************************************************/ +#if GIC_ENABLE_V4_EXTN +#define GICR_PCPUBASE_SHIFT 0x12 +#else +#define GICR_PCPUBASE_SHIFT 0x11 +#endif +#define GICR_SGIBASE_OFFSET U(65536) /* 64 KB */ +#define GICR_CTLR U(0x0) +#define GICR_IIDR U(0x04) +#define GICR_TYPER U(0x08) +#define GICR_STATUSR U(0x10) +#define GICR_WAKER U(0x14) +#define GICR_PROPBASER U(0x70) +#define GICR_PENDBASER U(0x78) +#define GICR_IGROUPR0 (GICR_SGIBASE_OFFSET + U(0x80)) +#define GICR_ISENABLER0 (GICR_SGIBASE_OFFSET + U(0x100)) +#define GICR_ICENABLER0 (GICR_SGIBASE_OFFSET + U(0x180)) +#define GICR_ISPENDR0 (GICR_SGIBASE_OFFSET + U(0x200)) +#define GICR_ICPENDR0 (GICR_SGIBASE_OFFSET + U(0x280)) +#define GICR_ISACTIVER0 (GICR_SGIBASE_OFFSET + U(0x300)) +#define GICR_ICACTIVER0 (GICR_SGIBASE_OFFSET + U(0x380)) +#define GICR_IPRIORITYR (GICR_SGIBASE_OFFSET + U(0x400)) +#define GICR_ICFGR0 (GICR_SGIBASE_OFFSET + U(0xc00)) +#define GICR_ICFGR1 (GICR_SGIBASE_OFFSET + U(0xc04)) +#define GICR_IGRPMODR0 (GICR_SGIBASE_OFFSET + U(0xd00)) +#define GICR_NSACR (GICR_SGIBASE_OFFSET + U(0xe00)) + +#define GICR_IGROUPR GICR_IGROUPR0 +#define GICR_ISENABLER GICR_ISENABLER0 +#define GICR_ICENABLER GICR_ICENABLER0 +#define GICR_ISPENDR GICR_ISPENDR0 +#define GICR_ICPENDR GICR_ICPENDR0 +#define GICR_ISACTIVER GICR_ISACTIVER0 +#define GICR_ICACTIVER GICR_ICACTIVER0 +#define GICR_ICFGR GICR_ICFGR0 +#define GICR_IGRPMODR GICR_IGRPMODR0 + +/* GICR_CTLR bit definitions */ +#define GICR_CTLR_UWP_SHIFT 31 +#define GICR_CTLR_UWP_MASK U(0x1) +#define GICR_CTLR_UWP_BIT BIT_32(GICR_CTLR_UWP_SHIFT) +#define GICR_CTLR_RWP_SHIFT 3 +#define GICR_CTLR_RWP_MASK U(0x1) +#define GICR_CTLR_RWP_BIT BIT_32(GICR_CTLR_RWP_SHIFT) +#define GICR_CTLR_EN_LPIS_BIT BIT_32(0) + +/* GICR_WAKER bit definitions */ +#define WAKER_CA_SHIFT 2 +#define WAKER_PS_SHIFT 1 + +#define WAKER_CA_MASK U(0x1) +#define WAKER_PS_MASK U(0x1) + +#define WAKER_CA_BIT BIT_32(WAKER_CA_SHIFT) +#define WAKER_PS_BIT BIT_32(WAKER_PS_SHIFT) + +/* GICR_TYPER bit definitions */ +#define TYPER_AFF_VAL_SHIFT 32 +#define TYPER_PROC_NUM_SHIFT 8 +#define TYPER_LAST_SHIFT 4 + +#define TYPER_AFF_VAL_MASK U(0xffffffff) +#define TYPER_PROC_NUM_MASK U(0xffff) +#define TYPER_LAST_MASK U(0x1) + +#define TYPER_LAST_BIT BIT_32(TYPER_LAST_SHIFT) + +#define TYPER_PPI_NUM_SHIFT U(27) +#define TYPER_PPI_NUM_MASK U(0x1f) + +/* GICR_IIDR bit definitions */ +#define IIDR_PRODUCT_ID_MASK U(0xff000000) +#define IIDR_VARIANT_MASK U(0x000f0000) +#define IIDR_REVISION_MASK U(0x0000f000) +#define IIDR_IMPLEMENTER_MASK U(0x00000fff) +#define IIDR_MODEL_MASK (IIDR_PRODUCT_ID_MASK | \ + IIDR_IMPLEMENTER_MASK) + +/******************************************************************************* + * GICv3 and 3.1 CPU interface registers & constants + ******************************************************************************/ +/* ICC_SRE bit definitions */ +#define ICC_SRE_EN_BIT BIT_32(3) +#define ICC_SRE_DIB_BIT BIT_32(2) +#define ICC_SRE_DFB_BIT BIT_32(1) +#define ICC_SRE_SRE_BIT BIT_32(0) + +/* ICC_IGRPEN1_EL3 bit definitions */ +#define IGRPEN1_EL3_ENABLE_G1NS_SHIFT 0 +#define IGRPEN1_EL3_ENABLE_G1S_SHIFT 1 + +#define IGRPEN1_EL3_ENABLE_G1NS_BIT BIT_32(IGRPEN1_EL3_ENABLE_G1NS_SHIFT) +#define IGRPEN1_EL3_ENABLE_G1S_BIT BIT_32(IGRPEN1_EL3_ENABLE_G1S_SHIFT) + +/* ICC_IGRPEN0_EL1 bit definitions */ +#define IGRPEN1_EL1_ENABLE_G0_SHIFT 0 +#define IGRPEN1_EL1_ENABLE_G0_BIT BIT_32(IGRPEN1_EL1_ENABLE_G0_SHIFT) + +/* ICC_HPPIR0_EL1 bit definitions */ +#define HPPIR0_EL1_INTID_SHIFT 0 +#define HPPIR0_EL1_INTID_MASK U(0xffffff) + +/* ICC_HPPIR1_EL1 bit definitions */ +#define HPPIR1_EL1_INTID_SHIFT 0 +#define HPPIR1_EL1_INTID_MASK U(0xffffff) + +/* ICC_IAR0_EL1 bit definitions */ +#define IAR0_EL1_INTID_SHIFT 0 +#define IAR0_EL1_INTID_MASK U(0xffffff) + +/* ICC_IAR1_EL1 bit definitions */ +#define IAR1_EL1_INTID_SHIFT 0 +#define IAR1_EL1_INTID_MASK U(0xffffff) + +/* ICC SGI macros */ +#define SGIR_TGT_MASK ULL(0xffff) +#define SGIR_AFF1_SHIFT 16 +#define SGIR_INTID_SHIFT 24 +#define SGIR_INTID_MASK ULL(0xf) +#define SGIR_AFF2_SHIFT 32 +#define SGIR_IRM_SHIFT 40 +#define SGIR_IRM_MASK ULL(0x1) +#define SGIR_AFF3_SHIFT 48 +#define SGIR_AFF_MASK ULL(0xf) + +#define SGIR_IRM_TO_AFF U(0) + +#define GICV3_SGIR_VALUE(_aff3, _aff2, _aff1, _intid, _irm, _tgt) \ + ((((uint64_t) (_aff3) & SGIR_AFF_MASK) << SGIR_AFF3_SHIFT) | \ + (((uint64_t) (_irm) & SGIR_IRM_MASK) << SGIR_IRM_SHIFT) | \ + (((uint64_t) (_aff2) & SGIR_AFF_MASK) << SGIR_AFF2_SHIFT) | \ + (((_intid) & SGIR_INTID_MASK) << SGIR_INTID_SHIFT) | \ + (((_aff1) & SGIR_AFF_MASK) << SGIR_AFF1_SHIFT) | \ + ((_tgt) & SGIR_TGT_MASK)) + +/***************************************************************************** + * GICv3 and 3.1 ITS registers and constants + *****************************************************************************/ +#define GITS_CTLR U(0x0) +#define GITS_IIDR U(0x4) +#define GITS_TYPER U(0x8) +#define GITS_CBASER U(0x80) +#define GITS_CWRITER U(0x88) +#define GITS_CREADR U(0x90) +#define GITS_BASER U(0x100) + +/* GITS_CTLR bit definitions */ +#define GITS_CTLR_ENABLED_BIT BIT_32(0) +#define GITS_CTLR_QUIESCENT_BIT BIT_32(1) + +#ifndef __ASSEMBLER__ + +#include +#include + +#include +#include +#include +#include + +static inline bool gicv3_is_intr_id_special_identifier(unsigned int id) +{ + return (id >= PENDING_G1S_INTID) && (id <= GIC_SPURIOUS_INTERRUPT); +} + +/******************************************************************************* + * Helper GICv3 and 3.1 macros for SEL1 + ******************************************************************************/ +static inline uint32_t gicv3_acknowledge_interrupt_sel1(void) +{ + return (uint32_t)read_icc_iar1_el1() & IAR1_EL1_INTID_MASK; +} + +static inline uint32_t gicv3_get_pending_interrupt_id_sel1(void) +{ + return (uint32_t)read_icc_hppir1_el1() & HPPIR1_EL1_INTID_MASK; +} + +static inline void gicv3_end_of_interrupt_sel1(unsigned int id) +{ + /* + * Interrupt request deassertion from peripheral to GIC happens + * by clearing interrupt condition by a write to the peripheral + * register. It is desired that the write transfer is complete + * before the core tries to change GIC state from 'AP/Active' to + * a new state on seeing 'EOI write'. + * Since ICC interface writes are not ordered against Device + * memory writes, a barrier is required to ensure the ordering. + * The dsb will also ensure *completion* of previous writes with + * DEVICE nGnRnE attribute. + */ + dsbishst(); + write_icc_eoir1_el1(id); +} + +/******************************************************************************* + * Helper GICv3 macros for EL3 + ******************************************************************************/ +static inline uint32_t gicv3_acknowledge_interrupt(void) +{ + return (uint32_t)read_icc_iar0_el1() & IAR0_EL1_INTID_MASK; +} + +static inline void gicv3_end_of_interrupt(unsigned int id) +{ + /* + * Interrupt request deassertion from peripheral to GIC happens + * by clearing interrupt condition by a write to the peripheral + * register. It is desired that the write transfer is complete + * before the core tries to change GIC state from 'AP/Active' to + * a new state on seeing 'EOI write'. + * Since ICC interface writes are not ordered against Device + * memory writes, a barrier is required to ensure the ordering. + * The dsb will also ensure *completion* of previous writes with + * DEVICE nGnRnE attribute. + */ + dsbishst(); + return write_icc_eoir0_el1(id); +} + +/* + * This macro returns the total number of GICD/GICR registers corresponding to + * the register name + */ +#define GICD_NUM_REGS(reg_name) \ + DIV_ROUND_UP_2EVAL(TOTAL_SHARED_INTR_NUM, (1 << reg_name##_SHIFT)) + +#define GICR_NUM_REGS(reg_name) \ + DIV_ROUND_UP_2EVAL(TOTAL_PRIVATE_INTR_NUM, (1 << reg_name##_SHIFT)) + +/* Interrupt ID mask for HPPIR, AHPPIR, IAR and AIAR CPU Interface registers */ +#define INT_ID_MASK U(0xffffff) + +/******************************************************************************* + * This structure describes some of the implementation defined attributes of the + * GICv3 IP. It is used by the platform port to specify these attributes in order + * to initialise the GICV3 driver. The attributes are described below. + * + * The 'gicd_base' field contains the base address of the Distributor interface + * programmer's view. + * + * The 'gicr_base' field contains the base address of the Re-distributor + * interface programmer's view. + * + * The 'interrupt_props' field is a pointer to an array that enumerates secure + * interrupts and their properties. If this field is not NULL, both + * 'g0_interrupt_array' and 'g1s_interrupt_array' fields are ignored. + * + * The 'interrupt_props_num' field contains the number of entries in the + * 'interrupt_props' array. If this field is non-zero, both 'g0_interrupt_num' + * and 'g1s_interrupt_num' are ignored. + * + * The 'rdistif_num' field contains the number of Redistributor interfaces the + * GIC implements. This is equal to the number of CPUs or CPU interfaces + * instantiated in the GIC. + * + * The 'rdistif_base_addrs' field is a pointer to an array that has an entry for + * storing the base address of the Redistributor interface frame of each CPU in + * the system. The size of the array = 'rdistif_num'. The base addresses are + * detected during driver initialisation. + * + * The 'mpidr_to_core_pos' field is a pointer to a hash function which the + * driver will use to convert an MPIDR value to a linear core index. This index + * will be used for accessing the 'rdistif_base_addrs' array. This is an + * optional field. A GICv3 implementation maps each MPIDR to a linear core index + * as well. This mapping can be found by reading the "Affinity Value" and + * "Processor Number" fields in the GICR_TYPER. It is IMP. DEF. if the + * "Processor Numbers" are suitable to index into an array to access core + * specific information. If this not the case, the platform port must provide a + * hash function. Otherwise, the "Processor Number" field will be used to access + * the array elements. + ******************************************************************************/ +typedef unsigned int (*mpidr_hash_fn)(u_register_t mpidr); + +typedef struct gicv3_driver_data { + uintptr_t gicd_base; + uintptr_t gicr_base; + const interrupt_prop_t *interrupt_props; + unsigned int interrupt_props_num; + unsigned int rdistif_num; + uintptr_t *rdistif_base_addrs; + mpidr_hash_fn mpidr_to_core_pos; +} gicv3_driver_data_t; + +typedef struct gicv3_redist_ctx { + /* 64 bits registers */ + uint64_t gicr_propbaser; + uint64_t gicr_pendbaser; + + /* 32 bits registers */ + uint32_t gicr_ctlr; + uint32_t gicr_igroupr[GICR_NUM_REGS(IGROUPR)]; + uint32_t gicr_isenabler[GICR_NUM_REGS(ISENABLER)]; + uint32_t gicr_ispendr[GICR_NUM_REGS(ISPENDR)]; + uint32_t gicr_isactiver[GICR_NUM_REGS(ISACTIVER)]; + uint32_t gicr_ipriorityr[GICR_NUM_REGS(IPRIORITYR)]; + uint32_t gicr_icfgr[GICR_NUM_REGS(ICFGR)]; + uint32_t gicr_igrpmodr[GICR_NUM_REGS(IGRPMODR)]; + uint32_t gicr_nsacr; +} gicv3_redist_ctx_t; + +typedef struct gicv3_dist_ctx { + /* 64 bits registers */ + uint64_t gicd_irouter[TOTAL_SHARED_INTR_NUM]; + + /* 32 bits registers */ + uint32_t gicd_ctlr; + uint32_t gicd_igroupr[GICD_NUM_REGS(IGROUPR)]; + uint32_t gicd_isenabler[GICD_NUM_REGS(ISENABLER)]; + uint32_t gicd_ispendr[GICD_NUM_REGS(ISPENDR)]; + uint32_t gicd_isactiver[GICD_NUM_REGS(ISACTIVER)]; + uint32_t gicd_ipriorityr[GICD_NUM_REGS(IPRIORITYR)]; + uint32_t gicd_icfgr[GICD_NUM_REGS(ICFGR)]; + uint32_t gicd_igrpmodr[GICD_NUM_REGS(IGRPMODR)]; + uint32_t gicd_nsacr[GICD_NUM_REGS(NSACR)]; +} gicv3_dist_ctx_t; + +typedef struct gicv3_its_ctx { + /* 64 bits registers */ + uint64_t gits_cbaser; + uint64_t gits_cwriter; + uint64_t gits_baser[8]; + + /* 32 bits registers */ + uint32_t gits_ctlr; +} gicv3_its_ctx_t; + +/******************************************************************************* + * GICv3 EL3 driver API + ******************************************************************************/ +void gicv3_driver_init(const gicv3_driver_data_t *plat_driver_data); +int gicv3_rdistif_probe(const uintptr_t gicr_frame); +void gicv3_distif_init(void); +void gicv3_rdistif_init(unsigned int proc_num); +void gicv3_rdistif_on(unsigned int proc_num); +void gicv3_rdistif_off(unsigned int proc_num); +unsigned int gicv3_rdistif_get_number_frames(const uintptr_t gicr_frame); +void gicv3_cpuif_enable(unsigned int proc_num); +void gicv3_cpuif_disable(unsigned int proc_num); +unsigned int gicv3_get_pending_interrupt_type(void); +unsigned int gicv3_get_pending_interrupt_id(void); +unsigned int gicv3_get_interrupt_type(unsigned int id, + unsigned int proc_num); +void gicv3_distif_init_restore(const gicv3_dist_ctx_t * const dist_ctx); +void gicv3_distif_save(gicv3_dist_ctx_t * const dist_ctx); +/* + * gicv3_distif_post_restore and gicv3_distif_pre_save must be implemented if + * gicv3_distif_save and gicv3_rdistif_init_restore are used. If no + * implementation-defined sequence is needed at these steps, an empty function + * can be provided. + */ +void gicv3_distif_post_restore(unsigned int proc_num); +void gicv3_distif_pre_save(unsigned int proc_num); +void gicv3_rdistif_init_restore(unsigned int proc_num, const gicv3_redist_ctx_t * const rdist_ctx); +void gicv3_rdistif_save(unsigned int proc_num, gicv3_redist_ctx_t * const rdist_ctx); +void gicv3_its_save_disable(uintptr_t gits_base, gicv3_its_ctx_t * const its_ctx); +void gicv3_its_restore(uintptr_t gits_base, const gicv3_its_ctx_t * const its_ctx); + +unsigned int gicv3_get_running_priority(void); +unsigned int gicv3_get_interrupt_active(unsigned int id, unsigned int proc_num); +void gicv3_enable_interrupt(unsigned int id, unsigned int proc_num); +void gicv3_disable_interrupt(unsigned int id, unsigned int proc_num); +void gicv3_set_interrupt_priority(unsigned int id, unsigned int proc_num, + unsigned int priority); +void gicv3_set_interrupt_type(unsigned int id, unsigned int proc_num, + unsigned int type); +void gicv3_raise_secure_g0_sgi(unsigned int sgi_num, u_register_t target); +void gicv3_set_spi_routing(unsigned int id, unsigned int irm, + u_register_t mpidr); +void gicv3_set_interrupt_pending(unsigned int id, unsigned int proc_num); +void gicv3_clear_interrupt_pending(unsigned int id, unsigned int proc_num); +unsigned int gicv3_set_pmr(unsigned int mask); + +#endif /* __ASSEMBLER__ */ +#endif /* GICV3_H */ diff --git a/drivers/rz/ipl/rza/include/drivers/arm/tzc400.h b/drivers/rz/ipl/rza/include/drivers/arm/tzc400.h new file mode 100644 index 00000000..5f8a48f5 --- /dev/null +++ b/drivers/rz/ipl/rza/include/drivers/arm/tzc400.h @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2014-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TZC400_H +#define TZC400_H + +#include +#include + +#define BUILD_CONFIG_OFF U(0x000) +#define GATE_KEEPER_OFF U(0x008) +#define SPECULATION_CTRL_OFF U(0x00c) +#define INT_STATUS U(0x010) +#define INT_CLEAR U(0x014) + +#define FAIL_ADDRESS_LOW_OFF U(0x020) +#define FAIL_ADDRESS_HIGH_OFF U(0x024) +#define FAIL_CONTROL_OFF U(0x028) +#define FAIL_ID U(0x02c) + +/* ID registers not common across different varieties of TZC */ +#define PID5 U(0xFD4) +#define PID6 U(0xFD8) +#define PID7 U(0xFDC) + +#define BUILD_CONFIG_NF_SHIFT 24 +#define BUILD_CONFIG_NF_MASK U(0x3) +#define BUILD_CONFIG_AW_SHIFT 8 +#define BUILD_CONFIG_AW_MASK U(0x3f) +#define BUILD_CONFIG_NR_SHIFT 0 +#define BUILD_CONFIG_NR_MASK U(0x1f) + +/* + * Number of gate keepers is implementation defined. But we know the max for + * this device is 4. Get implementation details from BUILD_CONFIG. + */ +#define GATE_KEEPER_OS_SHIFT 16 +#define GATE_KEEPER_OS_MASK U(0xf) +#define GATE_KEEPER_OR_SHIFT 0 +#define GATE_KEEPER_OR_MASK U(0xf) +#define GATE_KEEPER_FILTER_MASK U(0x1) + +/* Speculation is enabled by default. */ +#define SPECULATION_CTRL_WRITE_DISABLE BIT_32(1) +#define SPECULATION_CTRL_READ_DISABLE BIT_32(0) + +/* Max number of filters allowed is 4. */ +#define INT_STATUS_OVERLAP_SHIFT 16 +#define INT_STATUS_OVERLAP_MASK U(0xf) +#define INT_STATUS_OVERRUN_SHIFT 8 +#define INT_STATUS_OVERRUN_MASK U(0xf) +#define INT_STATUS_STATUS_SHIFT 0 +#define INT_STATUS_STATUS_MASK U(0xf) + +#define INT_CLEAR_CLEAR_SHIFT 0 +#define INT_CLEAR_CLEAR_MASK U(0xf) + +#define FAIL_CONTROL_DIR_SHIFT 24 +#define FAIL_CONTROL_DIR_READ U(0) +#define FAIL_CONTROL_DIR_WRITE U(1) +#define FAIL_CONTROL_NS_SHIFT 21 +#define FAIL_CONTROL_NS_SECURE U(0) +#define FAIL_CONTROL_NS_NONSECURE U(1) +#define FAIL_CONTROL_PRIV_SHIFT 20 +#define FAIL_CONTROL_PRIV_UNPRIV U(0) +#define FAIL_CONTROL_PRIV_PRIV U(1) + +/* + * FAIL_ID_ID_MASK depends on AID_WIDTH which is platform specific. + * Platform should provide the value on initialisation. + */ +#define FAIL_ID_VNET_SHIFT 24 +#define FAIL_ID_VNET_MASK U(0xf) +#define FAIL_ID_ID_SHIFT 0 + +#define TZC_400_PERIPHERAL_ID U(0x460) + +/* Filter enable bits in a TZC */ +#define TZC_400_REGION_ATTR_F_EN_MASK U(0xf) +#define TZC_400_REGION_ATTR_FILTER_BIT(x) (U(1) << (x)) +#define TZC_400_REGION_ATTR_FILTER_BIT_ALL TZC_400_REGION_ATTR_F_EN_MASK + +/* + * All TZC region configuration registers are placed one after another. It + * depicts size of block of registers for programming each region. + */ +#define TZC_400_REGION_SIZE U(0x20) +#define TZC_400_ACTION_OFF U(0x4) + +#define FILTER_OFFSET U(0x10) + +#ifndef __ASSEMBLER__ + +#include +#include + +/******************************************************************************* + * Function & variable prototypes + ******************************************************************************/ +void tzc400_init(uintptr_t base); +void tzc400_configure_region0(unsigned int sec_attr, + unsigned int ns_device_access); +void tzc400_configure_region(unsigned int filters, + unsigned int region, + unsigned long long region_base, + unsigned long long region_top, + unsigned int sec_attr, + unsigned int nsaid_permissions); +void tzc400_set_action(unsigned int action); +void tzc400_enable_filters(void); +void tzc400_disable_filters(void); +int tzc400_it_handler(void); + +static inline void tzc_init(uintptr_t base) +{ + tzc400_init(base); +} + +static inline void tzc_configure_region0( + unsigned int sec_attr, + unsigned int ns_device_access) +{ + tzc400_configure_region0(sec_attr, ns_device_access); +} + +static inline void tzc_configure_region( + unsigned int filters, + unsigned int region, + unsigned long long region_base, + unsigned long long region_top, + unsigned int sec_attr, + unsigned int ns_device_access) +{ + tzc400_configure_region(filters, region, region_base, + region_top, sec_attr, ns_device_access); +} + +static inline void tzc_set_action(unsigned int action) +{ + tzc400_set_action(action); +} + + +static inline void tzc_enable_filters(void) +{ + tzc400_enable_filters(); +} + +static inline void tzc_disable_filters(void) +{ + tzc400_disable_filters(); +} + +#endif /* __ASSEMBLER__ */ + +#endif /* TZC400_H */ diff --git a/drivers/rz/ipl/rza/include/drivers/arm/tzc_common.h b/drivers/rz/ipl/rza/include/drivers/arm/tzc_common.h new file mode 100644 index 00000000..e58201c3 --- /dev/null +++ b/drivers/rz/ipl/rza/include/drivers/arm/tzc_common.h @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TZC_COMMON_H +#define TZC_COMMON_H + +#include + +/* + * Offset of core registers from the start of the base of configuration + * registers for each region. + */ + +/* ID Registers */ +#define PID0_OFF U(0xfe0) +#define PID1_OFF U(0xfe4) +#define PID2_OFF U(0xfe8) +#define PID3_OFF U(0xfec) +#define PID4_OFF U(0xfd0) +#define CID0_OFF U(0xff0) +#define CID1_OFF U(0xff4) +#define CID2_OFF U(0xff8) +#define CID3_OFF U(0xffc) + +/* + * What type of action is expected when an access violation occurs. + * The memory requested is returned as zero. But we can also raise an event to + * let the system know it happened. + * We can raise an interrupt(INT) and/or cause an exception(ERR). + * TZC_ACTION_NONE - No interrupt, no Exception + * TZC_ACTION_ERR - No interrupt, raise exception -> sync external + * data abort + * TZC_ACTION_INT - Raise interrupt, no exception + * TZC_ACTION_ERR_INT - Raise interrupt, raise exception -> sync + * external data abort + */ +#define TZC_ACTION_NONE U(0) +#define TZC_ACTION_ERR U(1) +#define TZC_ACTION_INT U(2) +#define TZC_ACTION_ERR_INT (TZC_ACTION_ERR | TZC_ACTION_INT) + +/* Bit positions of TZC_ACTION registers */ +#define TZC_ACTION_RV_SHIFT 0 +#define TZC_ACTION_RV_MASK U(0x3) +#define TZC_ACTION_RV_LOWOK U(0x0) +#define TZC_ACTION_RV_LOWERR U(0x1) +#define TZC_ACTION_RV_HIGHOK U(0x2) +#define TZC_ACTION_RV_HIGHERR U(0x3) + +/* + * Controls secure access to a region. If not enabled secure access is not + * allowed to region. + */ +#define TZC_REGION_S_NONE U(0) +#define TZC_REGION_S_RD U(1) +#define TZC_REGION_S_WR U(2) +#define TZC_REGION_S_RDWR (TZC_REGION_S_RD | TZC_REGION_S_WR) + +#define TZC_REGION_ATTR_S_RD_SHIFT 30 +#define TZC_REGION_ATTR_S_WR_SHIFT 31 +#define TZC_REGION_ATTR_F_EN_SHIFT 0 +#define TZC_REGION_ATTR_SEC_SHIFT 30 +#define TZC_REGION_ATTR_S_RD_MASK U(0x1) +#define TZC_REGION_ATTR_S_WR_MASK U(0x1) +#define TZC_REGION_ATTR_SEC_MASK U(0x3) + +#define TZC_REGION_ACCESS_WR_EN_SHIFT 16 +#define TZC_REGION_ACCESS_RD_EN_SHIFT 0 +#define TZC_REGION_ACCESS_ID_MASK U(0xf) + +/* Macros for allowing Non-Secure access to a region based on NSAID */ +#define TZC_REGION_ACCESS_RD(nsaid) \ + ((U(1) << ((nsaid) & TZC_REGION_ACCESS_ID_MASK)) << \ + TZC_REGION_ACCESS_RD_EN_SHIFT) +#define TZC_REGION_ACCESS_WR(nsaid) \ + ((U(1) << ((nsaid) & TZC_REGION_ACCESS_ID_MASK)) << \ + TZC_REGION_ACCESS_WR_EN_SHIFT) +#define TZC_REGION_ACCESS_RDWR(nsaid) \ + (TZC_REGION_ACCESS_RD(nsaid) | \ + TZC_REGION_ACCESS_WR(nsaid)) + +/* Returns offset of registers to program for a given region no */ +#define TZC_REGION_OFFSET(region_size, region_no) \ + ((region_size) * (region_no)) + +#endif /* TZC_COMMON_H */ diff --git a/drivers/rz/ipl/rza/include/drivers/auth/auth_common.h b/drivers/rz/ipl/rza/include/drivers/auth/auth_common.h new file mode 100644 index 00000000..e6859fdb --- /dev/null +++ b/drivers/rz/ipl/rza/include/drivers/auth/auth_common.h @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef AUTH_COMMON_H +#define AUTH_COMMON_H + +/* + * Authentication framework common types + */ + +/* + * Type of parameters that can be extracted from an image and + * used for authentication + */ +typedef enum auth_param_type_enum { + AUTH_PARAM_NONE, + AUTH_PARAM_RAW_DATA, /* Raw image data */ + AUTH_PARAM_SIG, /* The image signature */ + AUTH_PARAM_SIG_ALG, /* The image signature algorithm */ + AUTH_PARAM_HASH, /* A hash (including the algorithm) */ + AUTH_PARAM_PUB_KEY, /* A public key */ + AUTH_PARAM_NV_CTR, /* A non-volatile counter */ +} auth_param_type_t; + +/* + * Defines an authentication parameter. The cookie will be interpreted by the + * image parser module. + */ +typedef struct auth_param_type_desc_s { + auth_param_type_t type; + void *cookie; +} auth_param_type_desc_t; + +/* + * Store a pointer to the authentication parameter and its length + */ +typedef struct auth_param_data_desc_s { + void *ptr; + unsigned int len; +} auth_param_data_desc_t; + +/* + * Authentication parameter descriptor, including type and value + */ +typedef struct auth_param_desc_s { + auth_param_type_desc_t *type_desc; + auth_param_data_desc_t data; +} auth_param_desc_t; + +/* + * The method type defines how an image is authenticated + */ +typedef enum auth_method_type_enum { + AUTH_METHOD_NONE = 0, + AUTH_METHOD_HASH, /* Authenticate by hash matching */ + AUTH_METHOD_SIG, /* Authenticate by PK operation */ + AUTH_METHOD_NV_CTR, /* Authenticate by Non-Volatile Counter */ + AUTH_METHOD_NUM /* Number of methods */ +} auth_method_type_t; + +/* + * Parameters for authentication by hash matching + */ +typedef struct auth_method_param_hash_s { + auth_param_type_desc_t *data; /* Data to hash */ + auth_param_type_desc_t *hash; /* Hash to match with */ +} auth_method_param_hash_t; + +/* + * Parameters for authentication by signature + */ +typedef struct auth_method_param_sig_s { + auth_param_type_desc_t *pk; /* Public key */ + auth_param_type_desc_t *sig; /* Signature to check */ + auth_param_type_desc_t *alg; /* Signature algorithm */ + auth_param_type_desc_t *data; /* Data signed */ +} auth_method_param_sig_t; + +/* + * Parameters for authentication by NV counter + */ +typedef struct auth_method_param_nv_ctr_s { + auth_param_type_desc_t *cert_nv_ctr; /* NV counter in certificate */ + auth_param_type_desc_t *plat_nv_ctr; /* NV counter in platform */ +} auth_method_param_nv_ctr_t; + +/* + * Authentication method descriptor + */ +typedef struct auth_method_desc_s { + auth_method_type_t type; + union { + auth_method_param_hash_t hash; + auth_method_param_sig_t sig; + auth_method_param_nv_ctr_t nv_ctr; + } param; +} auth_method_desc_t; + +/* + * Helper macro to define an authentication parameter type descriptor + */ +#define AUTH_PARAM_TYPE_DESC(_type, _cookie) \ + { \ + .type = _type, \ + .cookie = (void *)_cookie \ + } + +/* + * Helper macro to define an authentication parameter data descriptor + */ +#define AUTH_PARAM_DATA_DESC(_ptr, _len) \ + { \ + .ptr = (void *)_ptr, \ + .len = (unsigned int)_len \ + } + +#endif /* AUTH_COMMON_H */ diff --git a/drivers/rz/ipl/rza/include/drivers/auth/auth_mod.h b/drivers/rz/ipl/rza/include/drivers/auth/auth_mod.h new file mode 100644 index 00000000..d1fd52c8 --- /dev/null +++ b/drivers/rz/ipl/rza/include/drivers/auth/auth_mod.h @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef AUTH_MOD_H +#define AUTH_MOD_H + +#if TRUSTED_BOARD_BOOT + +#include +#include +#include +#include + +#include + +/* + * Image flags + */ +#define IMG_FLAG_AUTHENTICATED (1 << 0) + +#if COT_DESC_IN_DTB && !IMAGE_BL1 +/* + * Authentication image descriptor + */ +typedef struct auth_img_desc_s { + unsigned int img_id; + img_type_t img_type; + const struct auth_img_desc_s *parent; + auth_method_desc_t *img_auth_methods; + auth_param_desc_t *authenticated_data; +} auth_img_desc_t; +#else +/* + * Authentication image descriptor + */ +typedef struct auth_img_desc_s { + unsigned int img_id; + img_type_t img_type; + const struct auth_img_desc_s *parent; + const auth_method_desc_t *const img_auth_methods; + const auth_param_desc_t *const authenticated_data; +} auth_img_desc_t; +#endif /* COT_DESC_IN_DTB && !IMAGE_BL1 */ + +/* Public functions */ +void auth_mod_init(void); +int auth_mod_get_parent_id(unsigned int img_id, unsigned int *parent_id); +int auth_mod_verify_img(unsigned int img_id, + void *img_ptr, + unsigned int img_len); + +/* Macro to register a CoT defined as an array of auth_img_desc_t pointers */ +#define REGISTER_COT(_cot) \ + const auth_img_desc_t *const *const cot_desc_ptr = (_cot); \ + const size_t cot_desc_size = ARRAY_SIZE(_cot); \ + unsigned int auth_img_flags[MAX_NUMBER_IDS] + +extern const auth_img_desc_t *const *const cot_desc_ptr; +extern const size_t cot_desc_size; +extern unsigned int auth_img_flags[MAX_NUMBER_IDS]; + +#if defined(SPD_spmd) + +#define DEFINE_SIP_SP_PKG(n) DEFINE_SP_PKG(n, sip_sp_content_cert) +#define DEFINE_PLAT_SP_PKG(n) DEFINE_SP_PKG(n, plat_sp_content_cert) + +#define DEFINE_SP_PKG(n, cert) \ + static const auth_img_desc_t sp_pkg##n = { \ + .img_id = SP_PKG##n##_ID, \ + .img_type = IMG_RAW, \ + .parent = &cert, \ + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { \ + [0] = { \ + .type = AUTH_METHOD_HASH, \ + .param.hash = { \ + .data = &raw_data, \ + .hash = &sp_pkg##n##_hash \ + } \ + } \ + } \ + } + +#endif + +#endif /* TRUSTED_BOARD_BOOT */ + +#endif /* AUTH_MOD_H */ diff --git a/drivers/rz/ipl/rza/include/drivers/auth/crypto_mod.h b/drivers/rz/ipl/rza/include/drivers/auth/crypto_mod.h new file mode 100644 index 00000000..71cf6730 --- /dev/null +++ b/drivers/rz/ipl/rza/include/drivers/auth/crypto_mod.h @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CRYPTO_MOD_H +#define CRYPTO_MOD_H + +/* Return values */ +enum crypto_ret_value { + CRYPTO_SUCCESS = 0, + CRYPTO_ERR_INIT, + CRYPTO_ERR_HASH, + CRYPTO_ERR_SIGNATURE, + CRYPTO_ERR_DECRYPTION, + CRYPTO_ERR_UNKNOWN +}; + +#define CRYPTO_MAX_IV_SIZE 16U +#define CRYPTO_MAX_TAG_SIZE 16U + +/* Decryption algorithm */ +enum crypto_dec_algo { + CRYPTO_GCM_DECRYPT = 0 +}; + +/* + * Cryptographic library descriptor + */ +typedef struct crypto_lib_desc_s { + const char *name; + + /* Initialize library. This function is not expected to fail. All errors + * must be handled inside the function, asserting or panicing in case of + * a non-recoverable error */ + void (*init)(void); + + /* Verify a digital signature. Return one of the + * 'enum crypto_ret_value' options */ + int (*verify_signature)(void *data_ptr, unsigned int data_len, + void *sig_ptr, unsigned int sig_len, + void *sig_alg, unsigned int sig_alg_len, + void *pk_ptr, unsigned int pk_len); + + /* Verify a hash. Return one of the 'enum crypto_ret_value' options */ + int (*verify_hash)(void *data_ptr, unsigned int data_len, + void *digest_info_ptr, unsigned int digest_info_len); + +#if MEASURED_BOOT + /* Calculate a hash. Return hash value */ + int (*calc_hash)(unsigned int alg, void *data_ptr, + unsigned int data_len, unsigned char *output); +#endif /* MEASURED_BOOT */ + + /* + * Authenticated decryption. Return one of the + * 'enum crypto_ret_value' options. + */ + int (*auth_decrypt)(enum crypto_dec_algo dec_algo, void *data_ptr, + size_t len, const void *key, unsigned int key_len, + unsigned int key_flags, const void *iv, + unsigned int iv_len, const void *tag, + unsigned int tag_len); +} crypto_lib_desc_t; + +/* Public functions */ +void crypto_mod_init(void); +int crypto_mod_verify_signature(void *data_ptr, unsigned int data_len, + void *sig_ptr, unsigned int sig_len, + void *sig_alg_ptr, unsigned int sig_alg_len, + void *pk_ptr, unsigned int pk_len); +int crypto_mod_verify_hash(void *data_ptr, unsigned int data_len, + void *digest_info_ptr, unsigned int digest_info_len); +int crypto_mod_auth_decrypt(enum crypto_dec_algo dec_algo, void *data_ptr, + size_t len, const void *key, unsigned int key_len, + unsigned int key_flags, const void *iv, + unsigned int iv_len, const void *tag, + unsigned int tag_len); + +#if MEASURED_BOOT +int crypto_mod_calc_hash(unsigned int alg, void *data_ptr, + unsigned int data_len, unsigned char *output); + +/* Macro to register a cryptographic library */ +#define REGISTER_CRYPTO_LIB(_name, _init, _verify_signature, _verify_hash, \ + _calc_hash, _auth_decrypt) \ + const crypto_lib_desc_t crypto_lib_desc = { \ + .name = _name, \ + .init = _init, \ + .verify_signature = _verify_signature, \ + .verify_hash = _verify_hash, \ + .calc_hash = _calc_hash, \ + .auth_decrypt = _auth_decrypt \ + } +#else +#define REGISTER_CRYPTO_LIB(_name, _init, _verify_signature, _verify_hash, \ + _auth_decrypt) \ + const crypto_lib_desc_t crypto_lib_desc = { \ + .name = _name, \ + .init = _init, \ + .verify_signature = _verify_signature, \ + .verify_hash = _verify_hash, \ + .auth_decrypt = _auth_decrypt \ + } +#endif /* MEASURED_BOOT */ + +extern const crypto_lib_desc_t crypto_lib_desc; + +#endif /* CRYPTO_MOD_H */ diff --git a/drivers/rz/ipl/rza/include/drivers/auth/img_parser_mod.h b/drivers/rz/ipl/rza/include/drivers/auth/img_parser_mod.h new file mode 100644 index 00000000..b2fb60ed --- /dev/null +++ b/drivers/rz/ipl/rza/include/drivers/auth/img_parser_mod.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef IMG_PARSER_MOD_H +#define IMG_PARSER_MOD_H + +#include + +/* + * Return values + */ +enum img_parser_ret_value { + IMG_PARSER_OK, + IMG_PARSER_ERR, /* Parser internal error */ + IMG_PARSER_ERR_FORMAT, /* Malformed image */ + IMG_PARSER_ERR_NOT_FOUND /* Authentication data not found */ +}; + +/* + * Image types. A parser should be instantiated and registered for each type + */ +typedef enum img_type_enum { + IMG_RAW, /* Binary image */ + IMG_PLAT, /* Platform specific format */ + IMG_CERT, /* X509v3 certificate */ + IMG_MAX_TYPES, +} img_type_t; + +/* Image parser library structure */ +typedef struct img_parser_lib_desc_s { + img_type_t img_type; + const char *name; + + void (*init)(void); + int (*check_integrity)(void *img, unsigned int img_len); + int (*get_auth_param)(const auth_param_type_desc_t *type_desc, + void *img, unsigned int img_len, + void **param, unsigned int *param_len); +} img_parser_lib_desc_t; + +/* Exported functions */ +void img_parser_init(void); +int img_parser_check_integrity(img_type_t img_type, + void *img_ptr, unsigned int img_len); +int img_parser_get_auth_param(img_type_t img_type, + const auth_param_type_desc_t *type_desc, + void *img_ptr, unsigned int img_len, + void **param_ptr, unsigned int *param_len); + +/* Macro to register an image parser library */ +#define REGISTER_IMG_PARSER_LIB(_type, _name, _init, _check_int, _get_param) \ + static const img_parser_lib_desc_t __img_parser_lib_desc_##_type \ + __section(".img_parser_lib_descs") __used = { \ + .img_type = _type, \ + .name = _name, \ + .init = _init, \ + .check_integrity = _check_int, \ + .get_auth_param = _get_param \ + } + +#endif /* IMG_PARSER_MOD_H */ diff --git a/drivers/rz/ipl/rza/include/drivers/auth/tbbr_cot_common.h b/drivers/rz/ipl/rza/include/drivers/auth/tbbr_cot_common.h new file mode 100644 index 00000000..a51faee1 --- /dev/null +++ b/drivers/rz/ipl/rza/include/drivers/auth/tbbr_cot_common.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TBBR_COT_COMMON_H +#define TBBR_COT_COMMON_H + +#include + +extern unsigned char tb_fw_hash_buf[HASH_DER_LEN]; +extern unsigned char scp_fw_hash_buf[HASH_DER_LEN]; +extern unsigned char nt_world_bl_hash_buf[HASH_DER_LEN]; + +extern auth_param_type_desc_t trusted_nv_ctr; +extern auth_param_type_desc_t subject_pk; +extern auth_param_type_desc_t sig; +extern auth_param_type_desc_t sig_alg; +extern auth_param_type_desc_t raw_data; + +extern auth_param_type_desc_t tb_fw_hash; +extern auth_param_type_desc_t tb_fw_config_hash; +extern auth_param_type_desc_t fw_config_hash; + +extern const auth_img_desc_t trusted_boot_fw_cert; +extern const auth_img_desc_t hw_config; + +#endif /* TBBR_COT_COMMON_H */ diff --git a/drivers/rz/ipl/rza/include/drivers/console.h b/drivers/rz/ipl/rza/include/drivers/console.h new file mode 100644 index 00000000..99bf9604 --- /dev/null +++ b/drivers/rz/ipl/rza/include/drivers/console.h @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CONSOLE_H +#define CONSOLE_H + +#include + +#define CONSOLE_T_NEXT (U(0) * REGSZ) +#define CONSOLE_T_FLAGS (U(1) * REGSZ) +#define CONSOLE_T_PUTC (U(2) * REGSZ) +#define CONSOLE_T_GETC (U(3) * REGSZ) +#define CONSOLE_T_FLUSH (U(4) * REGSZ) +#define CONSOLE_T_BASE (U(5) * REGSZ) +#define CONSOLE_T_DRVDATA (U(6) * REGSZ) + +#define CONSOLE_FLAG_BOOT (U(1) << 0) +#define CONSOLE_FLAG_RUNTIME (U(1) << 1) +#define CONSOLE_FLAG_CRASH (U(1) << 2) +/* Bits 3 to 7 reserved for additional scopes in future expansion. */ +#define CONSOLE_FLAG_SCOPE_MASK ((U(1) << 8) - 1) +/* Bits 8 to 31 for non-scope use. */ +#define CONSOLE_FLAG_TRANSLATE_CRLF (U(1) << 8) + +/* Returned by getc callbacks when receive FIFO is empty. */ +#define ERROR_NO_PENDING_CHAR (-1) +/* Returned by console_xxx() if no registered console implements xxx. */ +#define ERROR_NO_VALID_CONSOLE (-128) + +#ifndef __ASSEMBLER__ + +#include + +typedef struct console { + struct console *next; + /* + * Only the low 32 bits are used. The type is u_register_t to align the + * fields of the struct to 64 bits in AArch64 and 32 bits in AArch32 + */ + u_register_t flags; + int (*const putc)(int character, struct console *console); + int (*const getc)(struct console *console); + void (*const flush)(struct console *console); + uintptr_t base; + /* Additional private driver data may follow here. */ +} console_t; + +/* offset macro assertions for console_t */ +#include + +/* + * Add a console_t instance to the console list. This should only be called by + * console drivers after they have initialized all fields in the console + * structure. Platforms seeking to register a new console need to call the + * respective console__register() function instead. + */ +int console_register(console_t *console); +/* Remove a single console_t instance from the console list. Return a pointer to + * the console that was removed if it was found, or NULL if not. */ +console_t *console_unregister(console_t *console); +/* Returns 1 if this console is already registered, 0 if not */ +int console_is_registered(console_t *console); +/* + * Set scope mask of a console that determines in what states it is active. + * By default they are registered with (CONSOLE_FLAG_BOOT|CONSOLE_FLAG_CRASH). + */ +void console_set_scope(console_t *console, unsigned int scope); + +/* Switch to a new global console state (CONSOLE_FLAG_BOOT/RUNTIME/CRASH). */ +void console_switch_state(unsigned int new_state); +/* Output a character on all consoles registered for the current state. */ +int console_putc(int c); +/* Read a character (blocking) from any console registered for current state. */ +int console_getc(void); +/* Flush all consoles registered for the current state. */ +void console_flush(void); + +#endif /* __ASSEMBLER__ */ + +#endif /* CONSOLE_H */ diff --git a/drivers/rz/ipl/rza/include/drivers/console_assertions.h b/drivers/rz/ipl/rza/include/drivers/console_assertions.h new file mode 100644 index 00000000..00caa314 --- /dev/null +++ b/drivers/rz/ipl/rza/include/drivers/console_assertions.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CONSOLE_ASSERTIONS_H +#define CONSOLE_ASSERTIONS_H + +#include + +/* + * This file contains some separate assertions about console_t, moved here to + * keep them out of the way. Should only be included from . + */ +CASSERT(CONSOLE_T_NEXT == __builtin_offsetof(console_t, next), + assert_console_t_next_offset_mismatch); +CASSERT(CONSOLE_T_FLAGS == __builtin_offsetof(console_t, flags), + assert_console_t_flags_offset_mismatch); +CASSERT(CONSOLE_T_PUTC == __builtin_offsetof(console_t, putc), + assert_console_t_putc_offset_mismatch); +CASSERT(CONSOLE_T_GETC == __builtin_offsetof(console_t, getc), + assert_console_t_getc_offset_mismatch); +CASSERT(CONSOLE_T_FLUSH == __builtin_offsetof(console_t, flush), + assert_console_t_flush_offset_mismatch); +CASSERT(CONSOLE_T_DRVDATA == sizeof(console_t), + assert_console_t_drvdata_offset_mismatch); + +#endif /* CONSOLE_ASSERTIONS_H */ diff --git a/drivers/rz/ipl/rza/include/drivers/delay_timer.h b/drivers/rz/ipl/rza/include/drivers/delay_timer.h new file mode 100644 index 00000000..20a55435 --- /dev/null +++ b/drivers/rz/ipl/rza/include/drivers/delay_timer.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2019, Linaro Limited + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef DELAY_TIMER_H +#define DELAY_TIMER_H + +#include +#include + +#include + +/******************************************************************** + * A simple timer driver providing synchronous delay functionality. + * The driver must be initialized with a structure that provides a + * function pointer to return the timer value and a clock + * multiplier/divider. The ratio of the multiplier and the divider is + * the clock period in microseconds. + ********************************************************************/ + +typedef struct timer_ops { + uint32_t (*get_timer_value)(void); + uint32_t clk_mult; + uint32_t clk_div; +} timer_ops_t; + +static inline uint64_t timeout_cnt_us2cnt(uint32_t us) +{ + return ((uint64_t)us * (uint64_t)read_cntfrq_el0()) / 1000000ULL; +} + +static inline uint64_t timeout_init_us(uint32_t us) +{ + uint64_t cnt = timeout_cnt_us2cnt(us); + + cnt += read_cntpct_el0(); + + return cnt; +} + +static inline bool timeout_elapsed(uint64_t expire_cnt) +{ + return read_cntpct_el0() > expire_cnt; +} + +void mdelay(uint32_t msec); +void udelay(uint32_t usec); +void timer_init(const timer_ops_t *ops_ptr); + +#endif /* DELAY_TIMER_H */ diff --git a/drivers/rz/ipl/rza/include/drivers/dw_ufs.h b/drivers/rz/ipl/rza/include/drivers/dw_ufs.h new file mode 100644 index 00000000..13e53f14 --- /dev/null +++ b/drivers/rz/ipl/rza/include/drivers/dw_ufs.h @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef DW_UFS_H +#define DW_UFS_H + +#include + +/* Bus Throtting */ +#define BUSTHRTL 0xC0 +/* Outstanding OCP Requests */ +#define OOCPR 0xC4 +/* Fatal Error Interrupt Enable */ +#define FEIE 0xC8 +/* C-Port Direct Access Configuration register */ +#define CDACFG 0xD0 +/* C-Port Direct Access Transmit 1 register */ +#define CDATX1 0xD4 +/* C-Port Direct Access Transmit 2 register */ +#define CDATX2 0xD8 +/* C-Port Direct Access Receive 1 register */ +#define CDARX1 0xDC +/* C-Port Direct Access Receive 2 register */ +#define CDARX2 0xE0 +/* C-Port Direct Access Status register */ +#define CDASTA 0xE4 +/* UPIU Loopback Configuration register */ +#define LBMCFG 0xF0 +/* UPIU Loopback Status */ +#define LBMSTA 0xF4 +/* Debug register */ +#define DBG 0xF8 +/* HClk Divider register */ +#define HCLKDIV 0xFC + +#define TX_HIBERN8TIME_CAP_OFFSET 0x000F +#define TX_FSM_STATE_OFFSET 0x0041 +#define TX_FSM_STATE_LINE_RESET 7 +#define TX_FSM_STATE_LINE_CFG 6 +#define TX_FSM_STATE_HS_BURST 5 +#define TX_FSM_STATE_LS_BURST 4 +#define TX_FSM_STATE_STALL 3 +#define TX_FSM_STATE_SLEEP 2 +#define TX_FSM_STATE_HIBERN8 1 +#define TX_FSM_STATE_DISABLE 0 + +#define RX_MIN_ACTIVATETIME_CAP_OFFSET 0x008F +#define RX_HS_G2_SYNC_LENGTH_CAP_OFFSET 0x0094 +#define RX_HS_G3_SYNC_LENGTH_CAP_OFFSET 0x0095 + +#define PA_AVAIL_TX_DATA_LANES_OFFSET 0x1520 +#define PA_TX_SKIP_OFFSET 0x155C +#define PA_TX_SKIP_PERIOD_OFFSET 0x155D +#define PA_LOCAL_TX_LCC_ENABLE_OFFSET 0x155E +#define PA_ACTIVE_TX_DATA_LANES_OFFSET 0x1560 +#define PA_CONNECTED_TX_DATA_LANES_OFFSET 0x1561 +#define PA_TX_TRAILING_CLOCKS_OFFSET 0x1564 +#define PA_TX_GEAR_OFFSET 0x1568 +#define PA_TX_TERMINATION_OFFSET 0x1569 +#define PA_HS_SERIES_OFFSET 0x156A +#define PA_PWR_MODE_OFFSET 0x1571 +#define PA_ACTIVE_RX_DATA_LANES_OFFSET 0x1580 +#define PA_CONNECTED_RX_DATA_LANES_OFFSET 0x1581 +#define PA_RX_PWR_STATUS_OFFSET 0x1582 +#define PA_RX_GEAR_OFFSET 0x1583 +#define PA_RX_TERMINATION_OFFSET 0x1584 +#define PA_SCRAMBLING_OFFSET 0x1585 +#define PA_MAX_RX_PWM_GEAR_OFFSET 0x1586 +#define PA_MAX_RX_HS_GEAR_OFFSET 0x1587 +#define PA_PACP_REQ_TIMEOUT_OFFSET 0x1590 +#define PA_PACP_REQ_EOB_TIMEOUT_OFFSET 0x1591 +#define PA_REMOTE_VER_INFO_OFFSET 0x15A0 +#define PA_LOGICAL_LANE_MAP_OFFSET 0x15A1 +#define PA_TACTIVATE_OFFSET 0x15A8 +#define PA_PWR_MODE_USER_DATA0_OFFSET 0x15B0 +#define PA_PWR_MODE_USER_DATA1_OFFSET 0x15B1 +#define PA_PWR_MODE_USER_DATA2_OFFSET 0x15B2 +#define PA_PWR_MODE_USER_DATA3_OFFSET 0x15B3 +#define PA_PWR_MODE_USER_DATA4_OFFSET 0x15B4 +#define PA_PWR_MODE_USER_DATA5_OFFSET 0x15B5 + +#define DL_TC0_TX_FC_THRESHOLD_OFFSET 0x2040 +#define DL_AFC0_CREDIT_THRESHOLD_OFFSET 0x2044 +#define DL_TC0_OUT_ACK_THRESHOLD_OFFSET 0x2045 + +#define DME_FC0_PROTECTION_TIMEOUT_OFFSET 0xD041 +#define DME_TC0_REPLAY_TIMEOUT_OFFSET 0xD042 +#define DME_AFC0_REQ_TIMEOUT_OFFSET 0xD043 +#define DME_FC1_PROTECTION_TIMEOUT_OFFSET 0xD044 +#define DME_TC1_REPLAY_TIMEOUT_OFFSET 0xD045 +#define DME_AFC1_REQ_TIMEOUT_OFFSET 0xD046 + +#define VS_MPHY_CFG_UPDT_OFFSET 0xD085 +#define VS_MK2_EXTN_SUPPORT_OFFSET 0xD0AB +#define VS_MPHY_DISABLE_OFFSET 0xD0C1 +#define VS_MPHY_DISABLE_MPHYDIS (1 << 0) + +typedef struct dw_ufs_params { + uintptr_t reg_base; + uintptr_t desc_base; + size_t desc_size; + unsigned long flags; +} dw_ufs_params_t; + +int dw_ufs_init(dw_ufs_params_t *params); + +#endif /* DW_UFS_H */ diff --git a/drivers/rz/ipl/rza/include/drivers/generic_delay_timer.h b/drivers/rz/ipl/rza/include/drivers/generic_delay_timer.h new file mode 100644 index 00000000..adba10f8 --- /dev/null +++ b/drivers/rz/ipl/rza/include/drivers/generic_delay_timer.h @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef GENERIC_DELAY_TIMER_H +#define GENERIC_DELAY_TIMER_H + +#include + +void generic_delay_timer_init_args(uint32_t mult, uint32_t div); + +void generic_delay_timer_init(void); + +#endif /* GENERIC_DELAY_TIMER_H */ diff --git a/drivers/rz/ipl/rza/include/drivers/gpio.h b/drivers/rz/ipl/rza/include/drivers/gpio.h new file mode 100644 index 00000000..99c18a4b --- /dev/null +++ b/drivers/rz/ipl/rza/include/drivers/gpio.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef GPIO_H +#define GPIO_H + +#include + +#define GPIO_DIR_OUT ARM_TF_GPIO_DIR_OUT +#define GPIO_DIR_IN ARM_TF_GPIO_DIR_IN + +#define GPIO_LEVEL_LOW ARM_TF_GPIO_LEVEL_LOW +#define GPIO_LEVEL_HIGH ARM_TF_GPIO_LEVEL_HIGH + +#define GPIO_PULL_NONE ARM_TF_GPIO_PULL_NONE +#define GPIO_PULL_UP ARM_TF_GPIO_PULL_UP +#define GPIO_PULL_DOWN ARM_TF_GPIO_PULL_DOWN + +typedef struct gpio_ops { + int (*get_direction)(int gpio); + void (*set_direction)(int gpio, int direction); + int (*get_value)(int gpio); + void (*set_value)(int gpio, int value); + void (*set_pull)(int gpio, int pull); + int (*get_pull)(int gpio); +} gpio_ops_t; + +int gpio_get_direction(int gpio); +void gpio_set_direction(int gpio, int direction); +int gpio_get_value(int gpio); +void gpio_set_value(int gpio, int value); +void gpio_set_pull(int gpio, int pull); +int gpio_get_pull(int gpio); +void gpio_init(const gpio_ops_t *ops); + +#endif /* GPIO_H */ diff --git a/drivers/rz/ipl/rza/include/drivers/io/io_block.h b/drivers/rz/ipl/rza/include/drivers/io/io_block.h new file mode 100644 index 00000000..c99e8c7c --- /dev/null +++ b/drivers/rz/ipl/rza/include/drivers/io/io_block.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef IO_BLOCK_H +#define IO_BLOCK_H + +#include + +/* block devices ops */ +typedef struct io_block_ops { + size_t (*read)(int lba, uintptr_t buf, size_t size); + size_t (*write)(int lba, const uintptr_t buf, size_t size); +} io_block_ops_t; + +typedef struct io_block_dev_spec { + io_block_spec_t buffer; + io_block_ops_t ops; + size_t block_size; +} io_block_dev_spec_t; + +struct io_dev_connector; + +int register_io_dev_block(const struct io_dev_connector **dev_con); + +#endif /* IO_BLOCK_H */ diff --git a/drivers/rz/ipl/rza/include/drivers/io/io_driver.h b/drivers/rz/ipl/rza/include/drivers/io/io_driver.h new file mode 100644 index 00000000..d8bb435a --- /dev/null +++ b/drivers/rz/ipl/rza/include/drivers/io/io_driver.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef IO_DRIVER_H +#define IO_DRIVER_H + +#include + +#include + +/* Generic IO entity structure,representing an accessible IO construct on the + * device, such as a file */ +typedef struct io_entity { + struct io_dev_info *dev_handle; + uintptr_t info; +} io_entity_t; + + +/* Device info structure, providing device-specific functions and a means of + * adding driver-specific state */ +typedef struct io_dev_info { + const struct io_dev_funcs *funcs; + uintptr_t info; +} io_dev_info_t; + + +/* Structure used to create a connection to a type of device */ +typedef struct io_dev_connector { + /* dev_open opens a connection to a particular device driver */ + int (*dev_open)(const uintptr_t dev_spec, io_dev_info_t **dev_info); +} io_dev_connector_t; + + +/* Structure to hold device driver function pointers */ +typedef struct io_dev_funcs { + io_type_t (*type)(void); + int (*open)(io_dev_info_t *dev_info, const uintptr_t spec, + io_entity_t *entity); + int (*seek)(io_entity_t *entity, int mode, signed long long offset); + int (*size)(io_entity_t *entity, size_t *length); + int (*read)(io_entity_t *entity, uintptr_t buffer, size_t length, + size_t *length_read); + int (*write)(io_entity_t *entity, const uintptr_t buffer, + size_t length, size_t *length_written); + int (*close)(io_entity_t *entity); + int (*dev_init)(io_dev_info_t *dev_info, const uintptr_t init_params); + int (*dev_close)(io_dev_info_t *dev_info); +} io_dev_funcs_t; + + +/* Operations intended to be performed during platform initialisation */ + +/* Register an IO device */ +int io_register_device(const io_dev_info_t *dev_info); + +#endif /* IO_DRIVER_H */ diff --git a/drivers/rz/ipl/rza/include/drivers/io/io_dummy.h b/drivers/rz/ipl/rza/include/drivers/io/io_dummy.h new file mode 100644 index 00000000..edfc6993 --- /dev/null +++ b/drivers/rz/ipl/rza/include/drivers/io/io_dummy.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef IO_DUMMY_H +#define IO_DUMMY_H + +int register_io_dev_dummy(const struct io_dev_connector **dev_con); + +#endif /* IO_DUMMY_H */ diff --git a/drivers/rz/ipl/rza/include/drivers/io/io_encrypted.h b/drivers/rz/ipl/rza/include/drivers/io/io_encrypted.h new file mode 100644 index 00000000..9dcf061b --- /dev/null +++ b/drivers/rz/ipl/rza/include/drivers/io/io_encrypted.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2020, Linaro Limited. All rights reserved. + * Author: Sumit Garg + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef IO_ENCRYPTED_H +#define IO_ENCRYPTED_H + +struct io_dev_connector; + +int register_io_dev_enc(const struct io_dev_connector **dev_con); + +#endif /* IO_ENCRYPTED_H */ diff --git a/drivers/rz/ipl/rza/include/drivers/io/io_fip.h b/drivers/rz/ipl/rza/include/drivers/io/io_fip.h new file mode 100644 index 00000000..7e654361 --- /dev/null +++ b/drivers/rz/ipl/rza/include/drivers/io/io_fip.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef IO_FIP_H +#define IO_FIP_H + +struct io_dev_connector; + +int register_io_dev_fip(const struct io_dev_connector **dev_con); +int fip_dev_get_plat_toc_flag(io_dev_info_t *dev_info, uint16_t *plat_toc_flag); + +#endif /* IO_FIP_H */ diff --git a/drivers/rz/ipl/rza/include/drivers/io/io_memmap.h b/drivers/rz/ipl/rza/include/drivers/io/io_memmap.h new file mode 100644 index 00000000..87e34662 --- /dev/null +++ b/drivers/rz/ipl/rza/include/drivers/io/io_memmap.h @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef IO_MEMMAP_H +#define IO_MEMMAP_H + +struct io_dev_connector; + +int register_io_dev_memmap(const struct io_dev_connector **dev_con); + +#endif /* IO_MEMMAP_H */ diff --git a/drivers/rz/ipl/rza/include/drivers/io/io_mtd.h b/drivers/rz/ipl/rza/include/drivers/io/io_mtd.h new file mode 100644 index 00000000..1395ff60 --- /dev/null +++ b/drivers/rz/ipl/rza/include/drivers/io/io_mtd.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef IO_MTD_H +#define IO_MTD_H + +#include +#include + +#include + +/* MTD devices ops */ +typedef struct io_mtd_ops { + /* + * Initialize MTD framework and retrieve device information. + * + * @size: [out] MTD device size in bytes. + * @erase_size: [out] MTD erase size in bytes. + * Return 0 on success, a negative error code otherwise. + */ + int (*init)(unsigned long long *size, unsigned int *erase_size); + + /* + * Execute a read memory operation. + * + * @offset: Offset in bytes to start read operation. + * @buffer: [out] Buffer to store read data. + * @length: Required length to be read in bytes. + * @out_length: [out] Length read in bytes. + * Return 0 on success, a negative error code otherwise. + */ + int (*read)(unsigned int offset, uintptr_t buffer, size_t length, + size_t *out_length); + + /* + * Execute a write memory operation. + * + * @offset: Offset in bytes to start write operation. + * @buffer: Buffer to be written in device. + * @length: Required length to be written in bytes. + * Return 0 on success, a negative error code otherwise. + */ + int (*write)(unsigned int offset, uintptr_t buffer, size_t length); +} io_mtd_ops_t; + +typedef struct io_mtd_dev_spec { + unsigned long long device_size; + unsigned int erase_size; + io_mtd_ops_t ops; +} io_mtd_dev_spec_t; + +struct io_dev_connector; + +int register_io_dev_mtd(const struct io_dev_connector **dev_con); + +#endif /* IO_MTD_H */ diff --git a/drivers/rz/ipl/rza/include/drivers/io/io_semihosting.h b/drivers/rz/ipl/rza/include/drivers/io/io_semihosting.h new file mode 100644 index 00000000..e90ea5c0 --- /dev/null +++ b/drivers/rz/ipl/rza/include/drivers/io/io_semihosting.h @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef IO_SEMIHOSTING_H +#define IO_SEMIHOSTING_H + +struct io_dev_connector; + +int register_io_dev_sh(const struct io_dev_connector **dev_con); + +#endif /* IO_SEMIHOSTING_H */ diff --git a/drivers/rz/ipl/rza/include/drivers/io/io_storage.h b/drivers/rz/ipl/rza/include/drivers/io/io_storage.h new file mode 100644 index 00000000..f2d641c2 --- /dev/null +++ b/drivers/rz/ipl/rza/include/drivers/io/io_storage.h @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef IO_STORAGE_H +#define IO_STORAGE_H + +#include +#include +#include /* For ssize_t */ + +#include + +/* Device type which can be used to enable policy decisions about which device + * to access */ +typedef enum { + IO_TYPE_INVALID, + IO_TYPE_SEMIHOSTING, + IO_TYPE_MEMMAP, + IO_TYPE_DUMMY, + IO_TYPE_FIRMWARE_IMAGE_PACKAGE, + IO_TYPE_BLOCK, + IO_TYPE_MTD, + IO_TYPE_MMC, + IO_TYPE_STM32IMAGE, + IO_TYPE_ENCRYPTED, + IO_TYPE_MAX +} io_type_t; + + +/* Modes used when seeking data on a supported device */ +typedef enum { + IO_SEEK_INVALID, + IO_SEEK_SET, + IO_SEEK_END, + IO_SEEK_CUR, + IO_SEEK_MAX +} io_seek_mode_t; + + +/* Connector type, providing a means of identifying a device to open */ +struct io_dev_connector; + + +/* File specification - used to refer to data on a device supporting file-like + * entities */ +typedef struct io_file_spec { + const char *path; + unsigned int mode; +} io_file_spec_t; + +/* UUID specification - used to refer to data accessed using UUIDs (i.e. FIP + * images) */ +typedef struct io_uuid_spec { + uuid_t uuid; +} io_uuid_spec_t; + +/* Block specification - used to refer to data on a device supporting + * block-like entities */ +typedef struct io_block_spec { + size_t offset; + size_t length; +} io_block_spec_t; + + +/* Access modes used when accessing data on a device */ +#define IO_MODE_INVALID (0) +#define IO_MODE_RO (1 << 0) +#define IO_MODE_RW (1 << 1) + + +/* Open a connection to a device */ +int io_dev_open(const struct io_dev_connector *dev_con, + const uintptr_t dev_spec, + uintptr_t *handle); + + +/* Initialise a device explicitly - to permit lazy initialisation or + * re-initialisation */ +int io_dev_init(uintptr_t dev_handle, const uintptr_t init_params); + +/* Close a connection to a device */ +int io_dev_close(uintptr_t dev_handle); + + +/* Synchronous operations */ +int io_open(uintptr_t dev_handle, const uintptr_t spec, uintptr_t *handle); + +int io_seek(uintptr_t handle, io_seek_mode_t mode, signed long long offset); + +int io_size(uintptr_t handle, size_t *length); + +int io_read(uintptr_t handle, uintptr_t buffer, size_t length, + size_t *length_read); + +int io_write(uintptr_t handle, const uintptr_t buffer, size_t length, + size_t *length_written); + +int io_close(uintptr_t handle); + + +#endif /* IO_STORAGE_H */ diff --git a/drivers/rz/ipl/rza/include/drivers/mmc.h b/drivers/rz/ipl/rza/include/drivers/mmc.h new file mode 100644 index 00000000..7611f019 --- /dev/null +++ b/drivers/rz/ipl/rza/include/drivers/mmc.h @@ -0,0 +1,237 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MMC_H +#define MMC_H + +#include + +#include + +#define MMC_BLOCK_SIZE U(512) +#define MMC_BLOCK_MASK (MMC_BLOCK_SIZE - U(1)) +#define MMC_BOOT_CLK_RATE (400 * 1000) + +#define MMC_CMD(_x) U(_x) + +#define MMC_ACMD(_x) U(_x) + +#define OCR_POWERUP BIT(31) +#define OCR_HCS BIT(30) +#define OCR_BYTE_MODE (U(0) << 29) +#define OCR_SECTOR_MODE (U(2) << 29) +#define OCR_ACCESS_MODE_MASK (U(3) << 29) +#define OCR_3_5_3_6 BIT(23) +#define OCR_3_4_3_5 BIT(22) +#define OCR_3_3_3_4 BIT(21) +#define OCR_3_2_3_3 BIT(20) +#define OCR_3_1_3_2 BIT(19) +#define OCR_3_0_3_1 BIT(18) +#define OCR_2_9_3_0 BIT(17) +#define OCR_2_8_2_9 BIT(16) +#define OCR_2_7_2_8 BIT(15) +#define OCR_VDD_MIN_2V7 GENMASK(23, 15) +#define OCR_VDD_MIN_2V0 GENMASK(14, 8) +#define OCR_VDD_MIN_1V7 BIT(7) + +#define MMC_RSP_48 BIT(0) +#define MMC_RSP_136 BIT(1) /* 136 bit response */ +#define MMC_RSP_CRC BIT(2) /* expect valid crc */ +#define MMC_RSP_CMD_IDX BIT(3) /* response contains cmd idx */ +#define MMC_RSP_BUSY BIT(4) /* device may be busy */ + +/* JEDEC 4.51 chapter 6.12 */ +#define MMC_RESPONSE_R1 (MMC_RSP_48 | MMC_RSP_CMD_IDX | MMC_RSP_CRC) +#define MMC_RESPONSE_R1B (MMC_RESPONSE_R1 | MMC_RSP_BUSY) +#define MMC_RESPONSE_R2 (MMC_RSP_48 | MMC_RSP_136 | MMC_RSP_CRC) +#define MMC_RESPONSE_R3 (MMC_RSP_48) +#define MMC_RESPONSE_R4 (MMC_RSP_48) +#define MMC_RESPONSE_R5 (MMC_RSP_48 | MMC_RSP_CRC | MMC_RSP_CMD_IDX) +#define MMC_RESPONSE_R6 (MMC_RSP_48 | MMC_RSP_CRC | MMC_RSP_CMD_IDX) +#define MMC_RESPONSE_R7 (MMC_RSP_48 | MMC_RSP_CRC | MMC_RSP_CMD_IDX) + +/* Value randomly chosen for eMMC RCA, it should be > 1 */ +#define MMC_FIX_RCA 6 +#define RCA_SHIFT_OFFSET 16 + +#define CMD_EXTCSD_PARTITION_CONFIG 179 +#define CMD_EXTCSD_BUS_WIDTH 183 +#define CMD_EXTCSD_HS_TIMING 185 +#define CMD_EXTCSD_SEC_CNT 212 + +#define PART_CFG_BOOT_PARTITION1_ENABLE (U(1) << 3) +#define PART_CFG_PARTITION1_ACCESS (U(1) << 0) + +/* Values in EXT CSD register */ +#define MMC_BUS_WIDTH_1 U(0) +#define MMC_BUS_WIDTH_4 U(1) +#define MMC_BUS_WIDTH_8 U(2) +#define MMC_BUS_WIDTH_DDR_4 U(5) +#define MMC_BUS_WIDTH_DDR_8 U(6) +#define MMC_BOOT_MODE_BACKWARD (U(0) << 3) +#define MMC_BOOT_MODE_HS_TIMING (U(1) << 3) +#define MMC_BOOT_MODE_DDR (U(2) << 3) + +#define EXTCSD_SET_CMD (U(0) << 24) +#define EXTCSD_SET_BITS (U(1) << 24) +#define EXTCSD_CLR_BITS (U(2) << 24) +#define EXTCSD_WRITE_BYTES (U(3) << 24) +#define EXTCSD_CMD(x) (((x) & 0xff) << 16) +#define EXTCSD_VALUE(x) (((x) & 0xff) << 8) +#define EXTCSD_CMD_SET_NORMAL U(1) + +#define CSD_TRAN_SPEED_UNIT_MASK GENMASK(2, 0) +#define CSD_TRAN_SPEED_MULT_MASK GENMASK(6, 3) +#define CSD_TRAN_SPEED_MULT_SHIFT 3 + +#define STATUS_CURRENT_STATE(x) (((x) & 0xf) << 9) +#define STATUS_READY_FOR_DATA BIT(8) +#define STATUS_SWITCH_ERROR BIT(7) +#define MMC_GET_STATE(x) (((x) >> 9) & 0xf) +#define MMC_STATE_IDLE 0 +#define MMC_STATE_READY 1 +#define MMC_STATE_IDENT 2 +#define MMC_STATE_STBY 3 +#define MMC_STATE_TRAN 4 +#define MMC_STATE_DATA 5 +#define MMC_STATE_RCV 6 +#define MMC_STATE_PRG 7 +#define MMC_STATE_DIS 8 +#define MMC_STATE_BTST 9 +#define MMC_STATE_SLP 10 + +#define MMC_FLAG_CMD23 (U(1) << 0) + +#define CMD8_CHECK_PATTERN U(0xAA) +#define VHS_2_7_3_6_V BIT(8) + +#define SD_SCR_BUS_WIDTH_1 BIT(8) +#define SD_SCR_BUS_WIDTH_4 BIT(10) + +struct mmc_cmd { + unsigned int cmd_idx; + unsigned int cmd_arg; + unsigned int resp_type; + unsigned int resp_data[4]; +}; + +struct mmc_ops { + void (*init)(void); + int (*send_cmd)(struct mmc_cmd *cmd); + int (*set_ios)(unsigned int clk, unsigned int width); + int (*prepare)(int lba, uintptr_t buf, size_t size); + int (*read)(int lba, uintptr_t buf, size_t size); + int (*write)(int lba, const uintptr_t buf, size_t size); +}; + +struct mmc_csd_emmc { + unsigned int not_used: 1; + unsigned int crc: 7; + unsigned int ecc: 2; + unsigned int file_format: 2; + unsigned int tmp_write_protect: 1; + unsigned int perm_write_protect: 1; + unsigned int copy: 1; + unsigned int file_format_grp: 1; + + unsigned int reserved_1: 5; + unsigned int write_bl_partial: 1; + unsigned int write_bl_len: 4; + unsigned int r2w_factor: 3; + unsigned int default_ecc: 2; + unsigned int wp_grp_enable: 1; + + unsigned int wp_grp_size: 5; + unsigned int erase_grp_mult: 5; + unsigned int erase_grp_size: 5; + unsigned int c_size_mult: 3; + unsigned int vdd_w_curr_max: 3; + unsigned int vdd_w_curr_min: 3; + unsigned int vdd_r_curr_max: 3; + unsigned int vdd_r_curr_min: 3; + unsigned int c_size_low: 2; + + unsigned int c_size_high: 10; + unsigned int reserved_2: 2; + unsigned int dsr_imp: 1; + unsigned int read_blk_misalign: 1; + unsigned int write_blk_misalign: 1; + unsigned int read_bl_partial: 1; + unsigned int read_bl_len: 4; + unsigned int ccc: 12; + + unsigned int tran_speed: 8; + unsigned int nsac: 8; + unsigned int taac: 8; + unsigned int reserved_3: 2; + unsigned int spec_vers: 4; + unsigned int csd_structure: 2; +}; + +struct mmc_csd_sd_v2 { + unsigned int not_used: 1; + unsigned int crc: 7; + unsigned int reserved_1: 2; + unsigned int file_format: 2; + unsigned int tmp_write_protect: 1; + unsigned int perm_write_protect: 1; + unsigned int copy: 1; + unsigned int file_format_grp: 1; + + unsigned int reserved_2: 5; + unsigned int write_bl_partial: 1; + unsigned int write_bl_len: 4; + unsigned int r2w_factor: 3; + unsigned int reserved_3: 2; + unsigned int wp_grp_enable: 1; + + unsigned int wp_grp_size: 7; + unsigned int sector_size: 7; + unsigned int erase_block_en: 1; + unsigned int reserved_4: 1; + unsigned int c_size_low: 16; + + unsigned int c_size_high: 6; + unsigned int reserved_5: 6; + unsigned int dsr_imp: 1; + unsigned int read_blk_misalign: 1; + unsigned int write_blk_misalign: 1; + unsigned int read_bl_partial: 1; + unsigned int read_bl_len: 4; + unsigned int ccc: 12; + + unsigned int tran_speed: 8; + unsigned int nsac: 8; + unsigned int taac: 8; + unsigned int reserved_6: 6; + unsigned int csd_structure: 2; +}; + +enum mmc_device_type { + MMC_IS_EMMC, + MMC_IS_SD, + MMC_IS_SD_HC, +}; + +struct mmc_device_info { + unsigned long long device_size; /* Size of device in bytes */ + unsigned int block_size; /* Block size in bytes */ + unsigned int max_bus_freq; /* Max bus freq in Hz */ + unsigned int ocr_voltage; /* OCR voltage */ + enum mmc_device_type mmc_dev_type; /* Type of MMC */ +}; + +size_t mmc_read_blocks(int lba, uintptr_t buf, size_t size); +size_t mmc_write_blocks(int lba, const uintptr_t buf, size_t size); +size_t mmc_erase_blocks(int lba, size_t size); +size_t mmc_rpmb_read_blocks(int lba, uintptr_t buf, size_t size); +size_t mmc_rpmb_write_blocks(int lba, const uintptr_t buf, size_t size); +size_t mmc_rpmb_erase_blocks(int lba, size_t size); +int mmc_init(const struct mmc_ops *ops_ptr, unsigned int clk, + unsigned int width, unsigned int flags, + struct mmc_device_info *device_info); + +#endif /* MMC_H */ diff --git a/drivers/rz/ipl/rza/include/drivers/renesas/rcar/console/console.h b/drivers/rz/ipl/rza/include/drivers/renesas/rcar/console/console.h new file mode 100644 index 00000000..7d5b5d3c --- /dev/null +++ b/drivers/rz/ipl/rza/include/drivers/renesas/rcar/console/console.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2015-2019, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef RCAR_PRINTF_H +#define RCAR_PRINTF_H + +#ifndef __ASSEMBLER__ + +#include + +/* + * Initialize a new rcar console instance and register it with the console + * framework. The |console| pointer must point to storage that will be valid + * for the lifetime of the console, such as a global or static local variable. + * Its contents will be reinitialized from scratch. + */ +int console_rcar_register(uintptr_t baseaddr, uint32_t clock, uint32_t baud, + console_t *console); + +#endif /*__ASSEMBLER__*/ + +#endif /* RCAR_PRINTF_H */ diff --git a/drivers/rz/ipl/rza/include/drivers/scmi-msg.h b/drivers/rz/ipl/rza/include/drivers/scmi-msg.h new file mode 100644 index 00000000..a9a99cf5 --- /dev/null +++ b/drivers/rz/ipl/rza/include/drivers/scmi-msg.h @@ -0,0 +1,207 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright (c) 2015-2019, Arm Limited and Contributors. All rights reserved. + * Copyright (c) 2019, Linaro Limited + */ + +#ifndef SCMI_MSG_H +#define SCMI_MSG_H + +#include +#include +#include + +/* Minimum size expected for SMT based shared memory message buffers */ +#define SMT_BUF_SLOT_SIZE 128U + +/* A channel abstract a communication path between agent and server */ +struct scmi_msg_channel; + +/* + * struct scmi_msg_channel - Shared memory buffer for a agent-to-server channel + * + * @shm_addr: Address of the shared memory for the SCMI channel + * @shm_size: Byte size of the shared memory for the SCMI channel + * @busy: True when channel is busy, flase when channel is free + * @agent_name: Agent name, SCMI protocol exposes 16 bytes max, or NULL + */ +struct scmi_msg_channel { + uintptr_t shm_addr; + size_t shm_size; + bool busy; + const char *agent_name; +}; + +/* + * Initialize SMT memory buffer, called by platform at init for each + * agent channel using the SMT header format. + * + * @chan: Pointer to the channel shared memory to be initialized + */ +void scmi_smt_init_agent_channel(struct scmi_msg_channel *chan); + +/* + * Process SMT formatted message in a fastcall SMC execution context. + * Called by platform on SMC entry. When returning, output message is + * available in shared memory for agent to read the response. + * + * @agent_id: SCMI agent ID the SMT belongs to + */ +void scmi_smt_fastcall_smc_entry(unsigned int agent_id); + +/* + * Process SMT formatted message in a secure interrupt execution context. + * Called by platform interrupt handler. When returning, output message is + * available in shared memory for agent to read the response. + * + * @agent_id: SCMI agent ID the SMT belongs to + */ +void scmi_smt_interrupt_entry(unsigned int agent_id); + +/* Platform callback functions */ + +/* + * Return the SCMI channel related to an agent + * @agent_id: SCMI agent ID + * Return a pointer to channel on success, NULL otherwise + */ +struct scmi_msg_channel *plat_scmi_get_channel(unsigned int agent_id); + +/* + * Return how many SCMI protocols supported by the platform + * According to the SCMI specification, this function does not target + * a specific agent ID and shall return all platform known capabilities. + */ +size_t plat_scmi_protocol_count(void); + +/* + * Get the count and list of SCMI protocols (but base) supported for an agent + * + * @agent_id: SCMI agent ID + * Return a pointer to a null terminated array supported protocol IDs. + */ +const uint8_t *plat_scmi_protocol_list(unsigned int agent_id); + +/* Get the name of the SCMI vendor for the platform */ +const char *plat_scmi_vendor_name(void); + +/* Get the name of the SCMI sub-vendor for the platform */ +const char *plat_scmi_sub_vendor_name(void); + +/* Handlers for SCMI Clock protocol services */ + +/* + * Return number of clock controllers for an agent + * @agent_id: SCMI agent ID + * Return number of clock controllers + */ +size_t plat_scmi_clock_count(unsigned int agent_id); + +/* + * Get clock controller string ID (aka name) + * @agent_id: SCMI agent ID + * @scmi_id: SCMI clock ID + * Return pointer to name or NULL + */ +const char *plat_scmi_clock_get_name(unsigned int agent_id, + unsigned int scmi_id); + +/* + * Get clock possible rate as an array of frequencies in Hertz. + * + * @agent_id: SCMI agent ID + * @scmi_id: SCMI clock ID + * @rates: If NULL, function returns, else output rates array + * @nb_elts: Array size of @rates. + * Return an SCMI compliant error code + */ +int32_t plat_scmi_clock_rates_array(unsigned int agent_id, unsigned int scmi_id, + unsigned long *rates, size_t *nb_elts); + +/* + * Get clock possible rate as range with regular steps in Hertz + * + * @agent_id: SCMI agent ID + * @scmi_id: SCMI clock ID + * @min_max_step: 3 cell array for min, max and step rate data + * Return an SCMI compliant error code + */ +int32_t plat_scmi_clock_rates_by_step(unsigned int agent_id, + unsigned int scmi_id, + unsigned long *min_max_step); + +/* + * Get clock rate in Hertz + * @agent_id: SCMI agent ID + * @scmi_id: SCMI clock ID + * Return clock rate or 0 if not supported + */ +unsigned long plat_scmi_clock_get_rate(unsigned int agent_id, + unsigned int scmi_id); + +/* + * Set clock rate in Hertz + * @agent_id: SCMI agent ID + * @scmi_id: SCMI clock ID + * @rate: Target clock frequency in Hertz + * Return a compliant SCMI error code + */ +int32_t plat_scmi_clock_set_rate(unsigned int agent_id, unsigned int scmi_id, + unsigned long rate); + +/* + * Get clock state (enabled or disabled) + * @agent_id: SCMI agent ID + * @scmi_id: SCMI clock ID + * Return 1 if clock is enabled, 0 if disables, or a negative SCMI error code + */ +int32_t plat_scmi_clock_get_state(unsigned int agent_id, unsigned int scmi_id); + +/* + * Get clock state (enabled or disabled) + * @agent_id: SCMI agent ID + * @scmi_id: SCMI clock ID + * @enable_not_disable: Enable clock if true, disable clock otherwise + * Return a compliant SCMI error code + */ +int32_t plat_scmi_clock_set_state(unsigned int agent_id, unsigned int scmi_id, + bool enable_not_disable); + +/* Handlers for SCMI Reset Domain protocol services */ + +/* + * Return number of reset domains for the agent + * @agent_id: SCMI agent ID + * Return number of reset domains + */ +size_t plat_scmi_rstd_count(unsigned int agent_id); + +/* + * Get reset domain string ID (aka name) + * @agent_id: SCMI agent ID + * @scmi_id: SCMI reset domain ID + * Return pointer to name or NULL + */ +const char *plat_scmi_rstd_get_name(unsigned int agent_id, unsigned int scmi_id); + +/* + * Perform a reset cycle on a target reset domain + * @agent_id: SCMI agent ID + * @scmi_id: SCMI reset domain ID + * @state: Target reset state (see SCMI specification, 0 means context loss) + * Return a compliant SCMI error code + */ +int32_t plat_scmi_rstd_autonomous(unsigned int agent_id, unsigned int scmi_id, + unsigned int state); + +/* + * Assert or deassert target reset domain + * @agent_id: SCMI agent ID + * @scmi_id: SCMI reset domain ID + * @assert_not_deassert: Assert domain if true, otherwise deassert domain + * Return a compliant SCMI error code + */ +int32_t plat_scmi_rstd_set_state(unsigned int agent_id, unsigned int scmi_id, + bool assert_not_deassert); + +#endif /* SCMI_MSG_H */ diff --git a/drivers/rz/ipl/rza/include/drivers/scmi.h b/drivers/rz/ipl/rza/include/drivers/scmi.h new file mode 100644 index 00000000..ac5dc387 --- /dev/null +++ b/drivers/rz/ipl/rza/include/drivers/scmi.h @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright (c) 2015-2019, Arm Limited and Contributors. All rights reserved. + */ +#ifndef SCMI_MSG_SCMI_H +#define SCMI_MSG_SCMI_H + +#define SCMI_PROTOCOL_ID_BASE 0x10U +#define SCMI_PROTOCOL_ID_POWER_DOMAIN 0x11U +#define SCMI_PROTOCOL_ID_SYS_POWER 0x12U +#define SCMI_PROTOCOL_ID_PERF 0x13U +#define SCMI_PROTOCOL_ID_CLOCK 0x14U +#define SCMI_PROTOCOL_ID_SENSOR 0x15U +#define SCMI_PROTOCOL_ID_RESET_DOMAIN 0x16U + +/* SCMI error codes reported to agent through server-to-agent messages */ +#define SCMI_SUCCESS 0 +#define SCMI_NOT_SUPPORTED (-1) +#define SCMI_INVALID_PARAMETERS (-2) +#define SCMI_DENIED (-3) +#define SCMI_NOT_FOUND (-4) +#define SCMI_OUT_OF_RANGE (-5) +#define SCMI_BUSY (-6) +#define SCMI_COMMS_ERROR (-7) +#define SCMI_GENERIC_ERROR (-8) +#define SCMI_HARDWARE_ERROR (-9) +#define SCMI_PROTOCOL_ERROR (-10) + +#endif /* SCMI_MSG_SCMI_H */ diff --git a/drivers/rz/ipl/rza/include/drivers/ufs.h b/drivers/rz/ipl/rza/include/drivers/ufs.h new file mode 100644 index 00000000..574c4ea0 --- /dev/null +++ b/drivers/rz/ipl/rza/include/drivers/ufs.h @@ -0,0 +1,548 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef UFS_H +#define UFS_H + +#include + +/* register map of UFSHCI */ +/* Controller Capabilities */ +#define CAP 0x00 +#define CAP_NUTRS_MASK 0x1F + +/* UFS Version */ +#define VER 0x08 +/* Host Controller Identification - Product ID */ +#define HCDDID 0x10 +/* Host Controller Identification Descriptor - Manufacturer ID */ +#define HCPMID 0x14 +/* Auto-Hibernate Idle Timer */ +#define AHIT 0x18 +/* Interrupt Status */ +#define IS 0x20 +/* Interrupt Enable */ +#define IE 0x24 +/* System Bus Fatal Error Status */ +#define UFS_INT_SBFES (1 << 17) +/* Host Controller Fatal Error Status */ +#define UFS_INT_HCFES (1 << 16) +/* UTP Error Status */ +#define UFS_INT_UTPES (1 << 12) +/* Device Fatal Error Status */ +#define UFS_INT_DFES (1 << 11) +/* UIC Command Completion Status */ +#define UFS_INT_UCCS (1 << 10) +/* UTP Task Management Request Completion Status */ +#define UFS_INT_UTMRCS (1 << 9) +/* UIC Link Startup Status */ +#define UFS_INT_ULSS (1 << 8) +/* UIC Link Lost Status */ +#define UFS_INT_ULLS (1 << 7) +/* UIC Hibernate Enter Status */ +#define UFS_INT_UHES (1 << 6) +/* UIC Hibernate Exit Status */ +#define UFS_INT_UHXS (1 << 5) +/* UIC Power Mode Status */ +#define UFS_INT_UPMS (1 << 4) +/* UIC Test Mode Status */ +#define UFS_INT_UTMS (1 << 3) +/* UIC Error */ +#define UFS_INT_UE (1 << 2) +/* UIC DME_ENDPOINTRESET Indication */ +#define UFS_INT_UDEPRI (1 << 1) +/* UTP Transfer Request Completion Status */ +#define UFS_INT_UTRCS (1 << 0) + +/* Host Controller Status */ +#define HCS 0x30 +#define HCS_UPMCRS_MASK (7 << 8) +#define HCS_PWR_LOCAL (1 << 8) +#define HCS_UCRDY (1 << 3) +#define HCS_UTMRLRDY (1 << 2) +#define HCS_UTRLRDY (1 << 1) +#define HCS_DP (1 << 0) + +/* Host Controller Enable */ +#define HCE 0x34 +#define HCE_ENABLE 1 + +/* Host UIC Error Code PHY Adapter Layer */ +#define UECPA 0x38 +/* Host UIC Error Code Data Link Layer */ +#define UECDL 0x3C +/* Host UIC Error Code Network Layer */ +#define UECN 0x40 +/* Host UIC Error Code Transport Layer */ +#define UECT 0x44 +/* Host UIC Error Code */ +#define UECDME 0x48 +/* UTP Transfer Request Interrupt Aggregation Control Register */ +#define UTRIACR 0x4C +#define UTRIACR_IAEN (1U << 31) +#define UTRIACR_IAPWEN (1 << 24) +#define UTRIACR_IASB (1 << 20) +#define UTRIACR_CTR (1 << 16) +#define UTRIACR_IACTH(x) (((x) & 0x1F) << 8) +#define UTRIACR_IATOVAL(x) ((x) & 0xFF) + +/* UTP Transfer Request List Base Address */ +#define UTRLBA 0x50 +/* UTP Transfer Request List Base Address Upper 32-bits */ +#define UTRLBAU 0x54 +/* UTP Transfer Request List Door Bell Register */ +#define UTRLDBR 0x58 +/* UTP Transfer Request List Clear Register */ +#define UTRLCLR 0x5C +/* UTP Transfer Request List Run Stop Register */ +#define UTRLRSR 0x60 +#define UTMRLBA 0x70 +#define UTMRLBAU 0x74 +#define UTMRLDBR 0x78 +#define UTMRLCLR 0x7C +#define UTMRLRSR 0x80 +/* UIC Command */ +#define UICCMD 0x90 +/* UIC Command Argument 1 */ +#define UCMDARG1 0x94 +/* UIC Command Argument 2 */ +#define UCMDARG2 0x98 +/* UIC Command Argument 3 */ +#define UCMDARG3 0x9C + +#define UFS_BLOCK_SHIFT 12 /* 4KB */ +#define UFS_BLOCK_SIZE (1 << UFS_BLOCK_SHIFT) +#define UFS_BLOCK_MASK (UFS_BLOCK_SIZE - 1) +#define UFS_MAX_LUNS 8 + +/* UTP Transfer Request Descriptor */ +/* Command Type */ +#define CT_UFS_STORAGE 1 +#define CT_SCSI 0 + +/* Data Direction */ +#define DD_OUT 2 /* Device --> Host */ +#define DD_IN 1 /* Host --> Device */ +#define DD_NO_DATA_TRANSFER 0 + +#define UTP_TRD_SIZE 32 + +/* Transaction Type */ +#define TRANS_TYPE_HD (1 << 7) /* E2ECRC */ +#define TRANS_TYPE_DD (1 << 6) +#define TRANS_TYPE_CODE_MASK 0x3F +#define QUERY_RESPONSE_UPIU (0x36 << 0) +#define READY_TO_TRANSACTION_UPIU (0x31 << 0) +#define DATA_IN_UPIU (0x22 << 0) +#define RESPONSE_UPIU (0x21 << 0) +#define NOP_IN_UPIU (0x20 << 0) +#define QUERY_REQUEST_UPIU (0x16 << 0) +#define DATA_OUT_UPIU (0x02 << 0) +#define CMD_UPIU (0x01 << 0) +#define NOP_OUT_UPIU (0x00 << 0) + +#define OCS_SUCCESS 0x0 +#define OCS_INVALID_FUNC_ATTRIBUTE 0x1 +#define OCS_MISMATCH_REQUEST_SIZE 0x2 +#define OCS_MISMATCH_RESPONSE_SIZE 0x3 +#define OCS_PEER_COMMUNICATION_FAILURE 0x4 +#define OCS_ABORTED 0x5 +#define OCS_FATAL_ERROR 0x6 +#define OCS_MASK 0xF + +/* UIC Command */ +#define DME_GET 0x01 +#define DME_SET 0x02 +#define DME_PEER_GET 0x03 +#define DME_PEER_SET 0x04 +#define DME_POWERON 0x10 +#define DME_POWEROFF 0x11 +#define DME_ENABLE 0x12 +#define DME_RESET 0x14 +#define DME_ENDPOINTRESET 0x15 +#define DME_LINKSTARTUP 0x16 +#define DME_HIBERNATE_ENTER 0x17 +#define DME_HIBERNATE_EXIT 0x18 +#define DME_TEST_MODE 0x1A + +#define GEN_SELECTOR_IDX(x) ((x) & 0xFFFF) + +#define CONFIG_RESULT_CODE_MASK 0xFF + +#define CDBCMD_TEST_UNIT_READY 0x00 +#define CDBCMD_READ_6 0x08 +#define CDBCMD_WRITE_6 0x0A +#define CDBCMD_START_STOP_UNIT 0x1B +#define CDBCMD_READ_CAPACITY_10 0x25 +#define CDBCMD_READ_10 0x28 +#define CDBCMD_WRITE_10 0x2A +#define CDBCMD_READ_16 0x88 +#define CDBCMD_WRITE_16 0x8A +#define CDBCMD_READ_CAPACITY_16 0x9E +#define CDBCMD_REPORT_LUNS 0xA0 + +#define UPIU_FLAGS_R (1 << 6) +#define UPIU_FLAGS_W (1 << 5) +#define UPIU_FLAGS_ATTR_MASK (3 << 0) +#define UPIU_FLAGS_ATTR_S (0 << 0) /* Simple */ +#define UPIU_FLAGS_ATTR_O (1 << 0) /* Ordered */ +#define UPIU_FLAGS_ATTR_HQ (2 << 0) /* Head of Queue */ +#define UPIU_FLAGS_ATTR_ACA (3 << 0) +#define UPIU_FLAGS_O (1 << 6) +#define UPIU_FLAGS_U (1 << 5) +#define UPIU_FLAGS_D (1 << 4) + +#define QUERY_FUNC_STD_READ 0x01 +#define QUERY_FUNC_STD_WRITE 0x81 + +#define QUERY_NOP 0x00 +#define QUERY_READ_DESC 0x01 +#define QUERY_WRITE_DESC 0x02 +#define QUERY_READ_ATTR 0x03 +#define QUERY_WRITE_ATTR 0x04 +#define QUERY_READ_FLAG 0x05 +#define QUERY_SET_FLAG 0x06 +#define QUERY_CLEAR_FLAG 0x07 +#define QUERY_TOGGLE_FLAG 0x08 + +#define RW_WITHOUT_CACHE 0x18 + +#define DESC_TYPE_DEVICE 0x00 +#define DESC_TYPE_CONFIGURATION 0x01 +#define DESC_TYPE_UNIT 0x02 +#define DESC_TYPE_INTERCONNECT 0x04 +#define DESC_TYPE_STRING 0x05 + +#define DESC_DEVICE_MAX_SIZE 0x1F +#define DEVICE_DESC_PARAM_MANF_ID 0x18 + +#define ATTR_CUR_PWR_MODE 0x02 /* bCurrentPowerMode */ +#define ATTR_ACTIVECC 0x03 /* bActiveICCLevel */ + +#define DEVICE_DESCRIPTOR_LEN 0x40 +#define UNIT_DESCRIPTOR_LEN 0x23 + +#define QUERY_RESP_SUCCESS 0x00 +#define QUERY_RESP_OPCODE 0xFE +#define QUERY_RESP_GENERAL_FAIL 0xFF + +#define SENSE_KEY_NO_SENSE 0x00 +#define SENSE_KEY_RECOVERED_ERROR 0x01 +#define SENSE_KEY_NOT_READY 0x02 +#define SENSE_KEY_MEDIUM_ERROR 0x03 +#define SENSE_KEY_HARDWARE_ERROR 0x04 +#define SENSE_KEY_ILLEGAL_REQUEST 0x05 +#define SENSE_KEY_UNIT_ATTENTION 0x06 +#define SENSE_KEY_DATA_PROTECT 0x07 +#define SENSE_KEY_BLANK_CHECK 0x08 +#define SENSE_KEY_VENDOR_SPECIFIC 0x09 +#define SENSE_KEY_COPY_ABORTED 0x0A +#define SENSE_KEY_ABORTED_COMMAND 0x0B +#define SENSE_KEY_VOLUME_OVERFLOW 0x0D +#define SENSE_KEY_MISCOMPARE 0x0E + +#define SENSE_DATA_VALID 0x70 +#define SENSE_DATA_LENGTH 18 + +#define READ_CAPACITY_LENGTH 8 + +#define FLAG_DEVICE_INIT 0x01 + +#define UFS_VENDOR_SKHYNIX U(0x1AD) + +#define MAX_MODEL_LEN 16 +/** + * ufs_dev_desc - ufs device details from the device descriptor + * @wmanufacturerid: card details + * @model: card model + */ +struct ufs_dev_desc { + uint16_t wmanufacturerid; + int8_t model[MAX_MODEL_LEN + 1]; +}; + +/* UFS Driver Flags */ +#define UFS_FLAGS_SKIPINIT (1 << 0) +#define UFS_FLAGS_VENDOR_SKHYNIX (U(1) << 2) + +typedef struct sense_data { + uint8_t resp_code : 7; + uint8_t valid : 1; + uint8_t reserved0; + uint8_t sense_key : 4; + uint8_t reserved1 : 1; + uint8_t ili : 1; + uint8_t eom : 1; + uint8_t file_mark : 1; + uint8_t info[4]; + uint8_t asl; + uint8_t cmd_spec_len[4]; + uint8_t asc; + uint8_t ascq; + uint8_t fruc; + uint8_t sense_key_spec0 : 7; + uint8_t sksv : 1; + uint8_t sense_key_spec1; + uint8_t sense_key_spec2; +} sense_data_t; + +/* UTP Transfer Request Descriptor */ +typedef struct utrd_header { + uint32_t reserved0 : 24; + uint32_t i : 1; /* interrupt */ + uint32_t dd : 2; /* data direction */ + uint32_t reserved1 : 1; + uint32_t ct : 4; /* command type */ + uint32_t reserved2; + uint32_t ocs : 8; /* Overall Command Status */ + uint32_t reserved3 : 24; + uint32_t reserved4; + uint32_t ucdba; /* aligned to 128-byte */ + uint32_t ucdbau; /* Upper 32-bits */ + uint32_t rul : 16; /* Response UPIU Length */ + uint32_t ruo : 16; /* Response UPIU Offset */ + uint32_t prdtl : 16; /* PRDT Length */ + uint32_t prdto : 16; /* PRDT Offset */ +} utrd_header_t; /* 8 words with little endian */ + +/* UTP Task Management Request Descriptor */ +typedef struct utp_utmrd { + /* 4 words with little endian */ + uint32_t reserved0 : 24; + uint32_t i : 1; /* interrupt */ + uint32_t reserved1 : 7; + uint32_t reserved2; + uint32_t ocs : 8; /* Overall Command Status */ + uint32_t reserved3 : 24; + uint32_t reserved4; + + /* followed by 8 words UPIU with big endian */ + + /* followed by 8 words Response UPIU with big endian */ +} utp_utmrd_t; + +/* NOP OUT UPIU */ +typedef struct nop_out_upiu { + uint8_t trans_type; + uint8_t flags; + uint8_t reserved0; + uint8_t task_tag; + uint8_t reserved1; + uint8_t reserved2; + uint8_t reserved3; + uint8_t reserved4; + uint8_t total_ehs_len; + uint8_t reserved5; + uint16_t data_segment_len; + uint32_t reserved6; + uint32_t reserved7; + uint32_t reserved8; + uint32_t reserved9; + uint32_t reserved10; + uint32_t e2ecrc; +} nop_out_upiu_t; /* 36 bytes with big endian */ + +/* NOP IN UPIU */ +typedef struct nop_in_upiu { + uint8_t trans_type; + uint8_t flags; + uint8_t reserved0; + uint8_t task_tag; + uint8_t reserved1; + uint8_t reserved2; + uint8_t response; + uint8_t reserved3; + uint8_t total_ehs_len; + uint8_t dev_info; + uint16_t data_segment_len; + uint32_t reserved4; + uint32_t reserved5; + uint32_t reserved6; + uint32_t reserved7; + uint32_t reserved8; + uint32_t e2ecrc; +} nop_in_upiu_t; /* 36 bytes with big endian */ + +/* Command UPIU */ +typedef struct cmd_upiu { + uint8_t trans_type; + uint8_t flags; + uint8_t lun; + uint8_t task_tag; + uint8_t cmd_set_type; + uint8_t reserved0; + uint8_t reserved1; + uint8_t reserved2; + uint8_t total_ehs_len; + uint8_t reserved3; + uint16_t data_segment_len; + uint32_t exp_data_trans_len; + /* + * A CDB has a fixed length of 16bytes or a variable length + * of between 12 and 260 bytes + */ + uint8_t cdb[16]; /* little endian */ +} cmd_upiu_t; /* 32 bytes with big endian except for cdb[] */ + +typedef struct query_desc { + uint8_t opcode; + uint8_t idn; + uint8_t index; + uint8_t selector; + uint8_t reserved0[2]; + uint16_t length; + uint32_t reserved2[2]; +} query_desc_t; /* 16 bytes with big endian */ + +typedef struct query_flag { + uint8_t opcode; + uint8_t idn; + uint8_t index; + uint8_t selector; + uint8_t reserved0[7]; + uint8_t value; + uint32_t reserved8; +} query_flag_t; /* 16 bytes with big endian */ + +typedef struct query_attr { + uint8_t opcode; + uint8_t idn; + uint8_t index; + uint8_t selector; + uint8_t reserved0[4]; + uint32_t value; /* little endian */ + uint32_t reserved4; +} query_attr_t; /* 16 bytes with big endian except for value */ + +/* Query Request UPIU */ +typedef struct query_upiu { + uint8_t trans_type; + uint8_t flags; + uint8_t reserved0; + uint8_t task_tag; + uint8_t reserved1; + uint8_t query_func; + uint8_t reserved2; + uint8_t reserved3; + uint8_t total_ehs_len; + uint8_t reserved4; + uint16_t data_segment_len; + /* Transaction Specific Fields */ + union { + query_desc_t desc; + query_flag_t flag; + query_attr_t attr; + } ts; + uint32_t reserved5; +} query_upiu_t; /* 32 bytes with big endian */ + +/* Query Response UPIU */ +typedef struct query_resp_upiu { + uint8_t trans_type; + uint8_t flags; + uint8_t reserved0; + uint8_t task_tag; + uint8_t reserved1; + uint8_t query_func; + uint8_t query_resp; + uint8_t reserved2; + uint8_t total_ehs_len; + uint8_t dev_info; + uint16_t data_segment_len; + union { + query_desc_t desc; + query_flag_t flag; + query_attr_t attr; + } ts; + uint32_t reserved3; +} query_resp_upiu_t; /* 32 bytes with big endian */ + +/* Response UPIU */ +typedef struct resp_upiu { + uint8_t trans_type; + uint8_t flags; + uint8_t lun; + uint8_t task_tag; + uint8_t cmd_set_type; + uint8_t reserved0; + uint8_t reserved1; + uint8_t status; + uint8_t total_ehs_len; + uint8_t dev_info; + uint16_t data_segment_len; + uint32_t res_trans_cnt; /* Residual Transfer Count */ + uint32_t reserved2[4]; + uint16_t sense_data_len; + union { + uint8_t sense_data[18]; + sense_data_t sense; + } sd; +} resp_upiu_t; /* 52 bytes with big endian */ + +typedef struct cmd_info { + uintptr_t buf; + size_t length; + int lba; + uint8_t op; + uint8_t direction; + uint8_t lun; +} cmd_info_t; + +typedef struct utp_utrd { + uintptr_t header; /* utrd_header_t */ + uintptr_t upiu; + uintptr_t resp_upiu; + uintptr_t prdt; + size_t size_upiu; + size_t size_resp_upiu; + size_t size_prdt; + int task_tag; +} utp_utrd_t; + +/* Physical Region Description Table */ +typedef struct prdt { + uint32_t dba; /* Data Base Address */ + uint32_t dbau; /* Data Base Address Upper 32-bits */ + uint32_t reserved0; + uint32_t dbc : 18; /* Data Byte Count */ + uint32_t reserved1 : 14; +} prdt_t; + +typedef struct uic_cmd { + uint32_t op; + uint32_t arg1; + uint32_t arg2; + uint32_t arg3; +} uic_cmd_t; + +typedef struct ufs_params { + uintptr_t reg_base; + uintptr_t desc_base; + size_t desc_size; + unsigned long flags; +} ufs_params_t; + +typedef struct ufs_ops { + int (*phy_init)(ufs_params_t *params); + int (*phy_set_pwr_mode)(ufs_params_t *params); +} ufs_ops_t; + +int ufshc_send_uic_cmd(uintptr_t base, uic_cmd_t *cmd); +int ufshc_dme_get(unsigned int attr, unsigned int idx, unsigned int *val); +int ufshc_dme_set(unsigned int attr, unsigned int idx, unsigned int val); + +unsigned int ufs_read_attr(int idn); +void ufs_write_attr(int idn, unsigned int value); +unsigned int ufs_read_flag(int idn); +void ufs_set_flag(int idn); +void ufs_clear_flag(int idn); +void ufs_read_desc(int idn, int index, uintptr_t buf, size_t size); +void ufs_write_desc(int idn, int index, uintptr_t buf, size_t size); +size_t ufs_read_blocks(int lun, int lba, uintptr_t buf, size_t size); +size_t ufs_write_blocks(int lun, int lba, const uintptr_t buf, size_t size); +int ufs_init(const ufs_ops_t *ops, ufs_params_t *params); + +#endif /* UFS_H */ diff --git a/drivers/rz/ipl/rza/include/export/common/bl_common_exp.h b/drivers/rz/ipl/rza/include/export/common/bl_common_exp.h new file mode 100644 index 00000000..8f090176 --- /dev/null +++ b/drivers/rz/ipl/rza/include/export/common/bl_common_exp.h @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef ARM_TRUSTED_FIRMWARE_EXPORT_COMMON_BL_COMMON_EXP_H +#define ARM_TRUSTED_FIRMWARE_EXPORT_COMMON_BL_COMMON_EXP_H + +/* EXPORT HEADER -- See include/export/README for details! -- EXPORT HEADER */ + +#include "ep_info_exp.h" +#include "tbbr/tbbr_img_def_exp.h" + +/* + * The following are used for image state attributes. + * Image can only be in one of the following state. + */ +#define IMAGE_STATE_RESET U(0) +#define IMAGE_STATE_COPIED U(1) +#define IMAGE_STATE_COPYING U(2) +#define IMAGE_STATE_AUTHENTICATED U(3) +#define IMAGE_STATE_EXECUTED U(4) +#define IMAGE_STATE_INTERRUPTED U(5) + +#define IMAGE_ATTRIB_SKIP_LOADING U(0x02) +#define IMAGE_ATTRIB_PLAT_SETUP U(0x04) + +#define INVALID_IMAGE_ID U(0xFFFFFFFF) + +#ifndef __ASSEMBLER__ + +/***************************************************************************** + * Image info binary provides information from the image loader that + * can be used by the firmware to manage available trusted RAM. + * More advanced firmware image formats can provide additional + * information that enables optimization or greater flexibility in the + * common firmware code + *****************************************************************************/ +typedef struct image_info { + param_header_t h; + uintptr_t image_base; /* physical address of base of image */ + uint32_t image_size; /* bytes read from image file */ + uint32_t image_max_size; +} image_info_t; + +/* BL image node in the BL image execution sequence */ +typedef struct bl_params_node { + unsigned int image_id; + image_info_t *image_info; + entry_point_info_t *ep_info; + struct bl_params_node *next_params_info; +} bl_params_node_t; + +/* + * BL image head node in the BL image execution sequence + * It is also used to pass information to next BL image. + */ +typedef struct bl_params { + param_header_t h; + bl_params_node_t *head; +} bl_params_t; + +/***************************************************************************** + * The image descriptor struct definition. + *****************************************************************************/ +typedef struct image_desc { + /* Contains unique image id for the image. */ + unsigned int image_id; + /* + * This member contains Image state information. + * Refer IMAGE_STATE_XXX defined above. + */ + unsigned int state; + uint32_t copied_size; /* image size copied in blocks */ + image_info_t image_info; + entry_point_info_t ep_info; +} image_desc_t; + +/* BL image node in the BL image loading sequence */ +typedef struct bl_load_info_node { + unsigned int image_id; + image_info_t *image_info; + struct bl_load_info_node *next_load_info; +} bl_load_info_node_t; + +/* BL image head node in the BL image loading sequence */ +typedef struct bl_load_info { + param_header_t h; + bl_load_info_node_t *head; +} bl_load_info_t; + +#endif /* __ASSEMBLER__ */ + +#endif /* ARM_TRUSTED_FIRMWARE_EXPORT_COMMON_BL_COMMON_EXP_H */ diff --git a/drivers/rz/ipl/rza/include/export/common/ep_info_exp.h b/drivers/rz/ipl/rza/include/export/common/ep_info_exp.h new file mode 100644 index 00000000..9d2969f3 --- /dev/null +++ b/drivers/rz/ipl/rza/include/export/common/ep_info_exp.h @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef ARM_TRUSTED_FIRMWARE_EXPORT_COMMON_EP_INFO_EXP_H +#define ARM_TRUSTED_FIRMWARE_EXPORT_COMMON_EP_INFO_EXP_H + +/* EXPORT HEADER -- See include/export/README for details! -- EXPORT HEADER */ + +#include "../lib/utils_def_exp.h" +#include "param_header_exp.h" + +/******************************************************************************* + * Constants that allow assembler code to access members of and the + * 'entry_point_info' structure at their correct offsets. + ******************************************************************************/ +#define ENTRY_POINT_INFO_PC_OFFSET U(0x08) +#ifdef __aarch64__ +#define ENTRY_POINT_INFO_ARGS_OFFSET U(0x18) +#else +#define ENTRY_POINT_INFO_LR_SVC_OFFSET U(0x10) +#define ENTRY_POINT_INFO_ARGS_OFFSET U(0x14) +#endif + +/* Security state of the image. */ +#define EP_SECURITY_MASK UL(0x1) +#define EP_SECURITY_SHIFT UL(0) +#define EP_SECURE UL(0x0) +#define EP_NON_SECURE UL(0x1) + +/* Endianness of the image. */ +#define EP_EE_MASK U(0x2) +#define EP_EE_SHIFT U(1) +#define EP_EE_LITTLE U(0x0) +#define EP_EE_BIG U(0x2) +#define EP_GET_EE(x) ((x) & EP_EE_MASK) +#define EP_SET_EE(x, ee) ((x) = ((x) & ~EP_EE_MASK) | (ee)) + +/* Enable or disable access to the secure timer from secure images. */ +#define EP_ST_MASK U(0x4) +#define EP_ST_SHIFT U(2) +#define EP_ST_DISABLE U(0x0) +#define EP_ST_ENABLE U(0x4) +#define EP_GET_ST(x) ((x) & EP_ST_MASK) +#define EP_SET_ST(x, ee) ((x) = ((x) & ~EP_ST_MASK) | (ee)) + +/* Determine if an image is executable or not. */ +#define EP_EXE_MASK U(0x8) +#define EP_EXE_SHIFT U(3) +#define EP_NON_EXECUTABLE U(0x0) +#define EP_EXECUTABLE U(0x8) +#define EP_GET_EXE(x) ((x) & EP_EXE_MASK) +#define EP_SET_EXE(x, ee) ((x) = ((x) & ~EP_EXE_MASK) | (ee)) + +/* Flag to indicate the first image that is executed. */ +#define EP_FIRST_EXE_MASK U(0x10) +#define EP_FIRST_EXE_SHIFT U(4) +#define EP_FIRST_EXE U(0x10) +#define EP_GET_FIRST_EXE(x) ((x) & EP_FIRST_EXE_MASK) +#define EP_SET_FIRST_EXE(x, ee) ((x) = ((x) & ~EP_FIRST_EXE_MASK) | (ee)) + +#ifndef __ASSEMBLER__ + +typedef struct aapcs64_params { + uint64_t arg0; + uint64_t arg1; + uint64_t arg2; + uint64_t arg3; + uint64_t arg4; + uint64_t arg5; + uint64_t arg6; + uint64_t arg7; +} aapcs64_params_t; + +typedef struct aapcs32_params { + uint32_t arg0; + uint32_t arg1; + uint32_t arg2; + uint32_t arg3; +} aapcs32_params_t; + +/***************************************************************************** + * This structure represents the superset of information needed while + * switching exception levels. The only two mechanisms to do so are + * ERET & SMC. Security state is indicated using bit zero of header + * attribute + * NOTE: BL1 expects entrypoint followed by spsr at an offset from the start + * of this structure defined by the macro `ENTRY_POINT_INFO_PC_OFFSET` while + * processing SMC to jump to BL31. + *****************************************************************************/ +typedef struct entry_point_info { + param_header_t h; + uintptr_t pc; + uint32_t spsr; +#ifdef __aarch64__ + aapcs64_params_t args; +#else + uintptr_t lr_svc; + aapcs32_params_t args; +#endif +} entry_point_info_t; + +#endif /*__ASSEMBLER__*/ + +#endif /* ARM_TRUSTED_FIRMWARE_EXPORT_COMMON_EP_INFO_EXP_H */ diff --git a/drivers/rz/ipl/rza/include/export/common/param_header_exp.h b/drivers/rz/ipl/rza/include/export/common/param_header_exp.h new file mode 100644 index 00000000..15bb6f2a --- /dev/null +++ b/drivers/rz/ipl/rza/include/export/common/param_header_exp.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef ARM_TRUSTED_FIRMWARE_EXPORT_COMMON_PARAM_HEADER_EXP_H +#define ARM_TRUSTED_FIRMWARE_EXPORT_COMMON_PARAM_HEADER_EXP_H + +/* EXPORT HEADER -- See include/export/README for details! -- EXPORT HEADER */ + +#include "../lib/utils_def_exp.h" + +/* Param header types */ +#define PARAM_EP U(0x01) +#define PARAM_IMAGE_BINARY U(0x02) +#define PARAM_BL31 U(0x03) +#define PARAM_BL_LOAD_INFO U(0x04) +#define PARAM_BL_PARAMS U(0x05) +#define PARAM_PSCI_LIB_ARGS U(0x06) +#define PARAM_SP_IMAGE_BOOT_INFO U(0x07) + +/* Param header version */ +#define PARAM_VERSION_1 U(0x01) +#define PARAM_VERSION_2 U(0x02) + +#ifndef __ASSEMBLER__ + +/*************************************************************************** + * This structure provides version information and the size of the + * structure, attributes for the structure it represents + ***************************************************************************/ +typedef struct param_header { + uint8_t type; /* type of the structure */ + uint8_t version; /* version of this structure */ + uint16_t size; /* size of this structure in bytes */ + uint32_t attr; /* attributes: unused bits SBZ */ +} param_header_t; + +#endif /*__ASSEMBLER__*/ + +#endif /* ARM_TRUSTED_FIRMWARE_EXPORT_COMMON_PARAM_HEADER_EXP_H */ diff --git a/drivers/rz/ipl/rza/include/export/common/tbbr/tbbr_img_def_exp.h b/drivers/rz/ipl/rza/include/export/common/tbbr/tbbr_img_def_exp.h new file mode 100644 index 00000000..18f01251 --- /dev/null +++ b/drivers/rz/ipl/rza/include/export/common/tbbr/tbbr_img_def_exp.h @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef ARM_TRUSTED_FIRMWARE_EXPORT_COMMON_TBBR_TBBR_IMG_DEF_EXP_H +#define ARM_TRUSTED_FIRMWARE_EXPORT_COMMON_TBBR_TBBR_IMG_DEF_EXP_H + +/* EXPORT HEADER -- See include/export/README for details! -- EXPORT HEADER */ + +#include "../../lib/utils_def_exp.h" + +/* Firmware Image Package */ +#define FIP_IMAGE_ID U(0) + +/* Trusted Boot Firmware BL2 */ +#define BL2_IMAGE_ID U(1) + +/* SCP Firmware SCP_BL2 */ +#define SCP_BL2_IMAGE_ID U(2) + +/* EL3 Runtime Firmware BL31 */ +#define BL31_IMAGE_ID U(3) + +/* Secure Payload BL32 (Trusted OS) */ +#define BL32_IMAGE_ID U(4) + +/* Non-Trusted Firmware BL33 */ +#define BL33_IMAGE_ID U(5) + +/* Certificates */ +#define TRUSTED_BOOT_FW_CERT_ID U(6) +#define TRUSTED_KEY_CERT_ID U(7) + +#define SCP_FW_KEY_CERT_ID U(8) +#define SOC_FW_KEY_CERT_ID U(9) +#define TRUSTED_OS_FW_KEY_CERT_ID U(10) +#define NON_TRUSTED_FW_KEY_CERT_ID U(11) + +#define SCP_FW_CONTENT_CERT_ID U(12) +#define SOC_FW_CONTENT_CERT_ID U(13) +#define TRUSTED_OS_FW_CONTENT_CERT_ID U(14) +#define NON_TRUSTED_FW_CONTENT_CERT_ID U(15) + +/* Non-Trusted ROM Firmware NS_BL1U */ +#define NS_BL1U_IMAGE_ID U(16) + +/* Trusted FWU Certificate */ +#define FWU_CERT_ID U(17) + +/* Trusted FWU SCP Firmware SCP_BL2U */ +#define SCP_BL2U_IMAGE_ID U(18) + +/* Trusted FWU Boot Firmware BL2U */ +#define BL2U_IMAGE_ID U(19) + +/* Non-Trusted FWU Firmware NS_BL2U */ +#define NS_BL2U_IMAGE_ID U(20) + +/* Secure Payload BL32_EXTRA1 (Trusted OS Extra1) */ +#define BL32_EXTRA1_IMAGE_ID U(21) + +/* Secure Payload BL32_EXTRA2 (Trusted OS Extra2) */ +#define BL32_EXTRA2_IMAGE_ID U(22) + +/* HW_CONFIG (e.g. Kernel DT) */ +#define HW_CONFIG_ID U(23) + +/* TB_FW_CONFIG */ +#define TB_FW_CONFIG_ID U(24) + +/* SOC_FW_CONFIG */ +#define SOC_FW_CONFIG_ID U(25) + +/* TOS_FW_CONFIG */ +#define TOS_FW_CONFIG_ID U(26) + +/* NT_FW_CONFIG */ +#define NT_FW_CONFIG_ID U(27) + +/* GPT Partition */ +#define GPT_IMAGE_ID U(28) + +/* Binary with STM32 header */ +#define STM32_IMAGE_ID U(29) + +/* Encrypted image identifier */ +#define ENC_IMAGE_ID U(30) + +/* FW_CONFIG */ +#define FW_CONFIG_ID U(31) + +/* Max Images */ +#define MAX_IMAGE_IDS U(32) + +#endif /* ARM_TRUSTED_FIRMWARE_EXPORT_COMMON_TBBR_TBBR_IMG_DEF_EXP_H */ diff --git a/drivers/rz/ipl/rza/include/export/lib/bl_aux_params/bl_aux_params_exp.h b/drivers/rz/ipl/rza/include/export/lib/bl_aux_params/bl_aux_params_exp.h new file mode 100644 index 00000000..7391dec3 --- /dev/null +++ b/drivers/rz/ipl/rza/include/export/lib/bl_aux_params/bl_aux_params_exp.h @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef ARM_TRUSTED_FIRMWARE_EXPORT_LIB_BL_AUX_PARAMS_EXP_H +#define ARM_TRUSTED_FIRMWARE_EXPORT_LIB_BL_AUX_PARAMS_EXP_H + +/* EXPORT HEADER -- See include/export/README for details! -- EXPORT HEADER */ + +#include "../../drivers/gpio_exp.h" + +/* + * This API implements a lightweight parameter passing mechanism that can be + * used to pass SoC Firmware configuration data from BL2 to BL31 by platforms or + * configurations that do not want to depend on libfdt. It is structured as a + * singly-linked list of parameter structures that all share the same common + * header but may have different (and differently-sized) structure bodies after + * that. The header contains a type field to indicate the parameter type (which + * is used to infer the structure length and how to interpret its contents) and + * a next pointer which contains the absolute physical address of the next + * parameter structure. The next pointer in the last structure block is set to + * NULL. The picture below shows how the parameters are kept in memory. + * + * head of list ---> +----------------+ --+ + * | type | | + * +----------------+ |--> struct bl_aux_param + * +----| next | | + * | +----------------+ --+ + * | | parameter data | + * | +----------------+ + * | + * +--> +----------------+ --+ + * | type | | + * +----------------+ |--> struct bl_aux_param + * NULL <---| next | | + * +----------------+ --+ + * | parameter data | + * +----------------+ + * + * Note: The SCTLR_EL3.A bit (Alignment fault check enable) is set in TF-A, so + * BL2 must ensure that each parameter struct starts on a 64-bit aligned address + * to avoid alignment faults. Parameters may be allocated in any address range + * accessible at the time of BL31 handoff (e.g. SRAM, DRAM, SoC-internal scratch + * registers, etc.), in particular address ranges that may not be mapped in + * BL31's page tables, so the parameter list must be parsed before the MMU is + * enabled and any information that is required at a later point should be + * deep-copied out into BL31-internal data structures. + */ + +enum bl_aux_param_type { + BL_AUX_PARAM_NONE = 0, + BL_AUX_PARAM_VENDOR_SPECIFIC_FIRST = 0x1, + /* 0x1 - 0x7fffffff can be used by vendor-specific handlers. */ + BL_AUX_PARAM_VENDOR_SPECIFIC_LAST = 0x7fffffff, + BL_AUX_PARAM_GENERIC_FIRST = 0x80000001, + BL_AUX_PARAM_COREBOOT_TABLE = BL_AUX_PARAM_GENERIC_FIRST, + /* 0x80000001 - 0xffffffff are reserved for the generic handler. */ + BL_AUX_PARAM_GENERIC_LAST = 0xffffffff, + /* Top 32 bits of the type field are reserved for future use. */ +}; + +/* common header for all BL aux parameters */ +struct bl_aux_param_header { + uint64_t type; + uint64_t next; +}; + +/* commonly useful parameter structures that can be shared by multiple types */ +struct bl_aux_param_uint64 { + struct bl_aux_param_header h; + uint64_t value; +}; + +struct bl_aux_gpio_info { + uint8_t polarity; + uint8_t direction; + uint8_t pull_mode; + uint8_t reserved; + uint32_t index; +}; + +struct bl_aux_param_gpio { + struct bl_aux_param_header h; + struct bl_aux_gpio_info gpio; +}; + +#endif /* ARM_TRUSTED_FIRMWARE_EXPORT_LIB_BL_AUX_PARAMS_EXP_H */ diff --git a/drivers/rz/ipl/rza/include/export/lib/utils_def_exp.h b/drivers/rz/ipl/rza/include/export/lib/utils_def_exp.h new file mode 100644 index 00000000..d4a4a85d --- /dev/null +++ b/drivers/rz/ipl/rza/include/export/lib/utils_def_exp.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef ARM_TRUSTED_FIRMWARE_EXPORT_LIB_UTILS_DEF_EXP_H +#define ARM_TRUSTED_FIRMWARE_EXPORT_LIB_UTILS_DEF_EXP_H + +/* EXPORT HEADER -- See include/export/README for details! -- EXPORT HEADER */ + +/* + * For those constants to be shared between C and other sources, apply a 'U', + * 'UL', 'ULL', 'L' or 'LL' suffix to the argument only in C, to avoid + * undefined or unintended behaviour. + * + * The GNU assembler and linker do not support these suffixes (it causes the + * build process to fail) therefore the suffix is omitted when used in linker + * scripts and assembler files. +*/ +#if defined(__ASSEMBLER__) +# define U(_x) (_x) +# define UL(_x) (_x) +# define ULL(_x) (_x) +# define L(_x) (_x) +# define LL(_x) (_x) +#else +# define U_(_x) (_x##U) +# define U(_x) U_(_x) +# define UL(_x) (_x##UL) +# define ULL(_x) (_x##ULL) +# define L(_x) (_x##L) +# define LL(_x) (_x##LL) + +#endif + +#endif /* ARM_TRUSTED_FIRMWARE_EXPORT_LIB_UTILS_DEF_EXP_H */ diff --git a/drivers/rz/ipl/rza/include/lib/bakery_lock.h b/drivers/rz/ipl/rza/include/lib/bakery_lock.h new file mode 100644 index 00000000..1fece01a --- /dev/null +++ b/drivers/rz/ipl/rza/include/lib/bakery_lock.h @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef BAKERY_LOCK_H +#define BAKERY_LOCK_H + +#include + +#define BAKERY_LOCK_MAX_CPUS PLATFORM_CORE_COUNT + +#ifndef __ASSEMBLER__ +#include +#include +#include + +#include + +/***************************************************************************** + * Internal helpers used by the bakery lock implementation. + ****************************************************************************/ + +/* Convert a ticket to priority */ +static inline unsigned int bakery_get_priority(unsigned int t, unsigned int pos) +{ + return (t << 8) | pos; +} + +#define CHOOSING_TICKET U(0x1) +#define CHOSEN_TICKET U(0x0) + +static inline bool bakery_is_choosing(unsigned int info) +{ + return (info & 1U) == CHOOSING_TICKET; +} + +static inline unsigned int bakery_ticket_number(unsigned int info) +{ + return (info >> 1) & 0x7FFFU; +} + +static inline uint16_t make_bakery_data(unsigned int choosing, unsigned int num) +{ + unsigned int val = (choosing & 0x1U) | (num << 1); + + return (uint16_t) val; +} + +/***************************************************************************** + * External bakery lock interface. + ****************************************************************************/ +#if USE_COHERENT_MEM +/* + * Bakery locks are stored in coherent memory + * + * Each lock's data is contiguous and fully allocated by the compiler + */ + +typedef struct bakery_lock { + /* + * The lock_data is a bit-field of 2 members: + * Bit[0] : choosing. This field is set when the CPU is + * choosing its bakery number. + * Bits[1 - 15] : number. This is the bakery number allocated. + */ + volatile uint16_t lock_data[BAKERY_LOCK_MAX_CPUS]; +} bakery_lock_t; + +#else +/* + * Bakery locks are stored in normal .bss memory + * + * Each lock's data is spread across multiple cache lines, one per CPU, + * but multiple locks can share the same cache line. + * The compiler will allocate enough memory for one CPU's bakery locks, + * the remaining cache lines are allocated by the linker script + */ + +typedef struct bakery_info { + /* + * The lock_data is a bit-field of 2 members: + * Bit[0] : choosing. This field is set when the CPU is + * choosing its bakery number. + * Bits[1 - 15] : number. This is the bakery number allocated. + */ + volatile uint16_t lock_data; +} bakery_info_t; + +typedef bakery_info_t bakery_lock_t; + +#endif /* __USE_COHERENT_MEM__ */ + +static inline void bakery_lock_init(bakery_lock_t *bakery) {} +void bakery_lock_get(bakery_lock_t *bakery); +void bakery_lock_release(bakery_lock_t *bakery); + +#define DEFINE_BAKERY_LOCK(_name) bakery_lock_t _name __section("bakery_lock") + +#define DECLARE_BAKERY_LOCK(_name) extern bakery_lock_t _name + + +#endif /* __ASSEMBLER__ */ +#endif /* BAKERY_LOCK_H */ diff --git a/drivers/rz/ipl/rza/include/lib/bl_aux_params/bl_aux_params.h b/drivers/rz/ipl/rza/include/lib/bl_aux_params/bl_aux_params.h new file mode 100644 index 00000000..f6ce8024 --- /dev/null +++ b/drivers/rz/ipl/rza/include/lib/bl_aux_params/bl_aux_params.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef LIB_BL_AUX_PARAMS_H +#define LIB_BL_AUX_PARAMS_H + +#include +#include + +#include + +/* + * Handler function that handles an individual aux parameter. Return true if + * the parameter was handled, and flase if bl_aux_params_parse() should make its + * own attempt at handling it (for generic parameters). + */ +typedef bool (*bl_aux_param_handler_t)(struct bl_aux_param_header *param); + +/* + * Interprets head as the start of an aux parameter list, and passes the + * parameters individually to handler(). Handles generic parameters directly if + * handler() hasn't already done so. If only generic parameters are expected, + * handler() can be NULL. + */ +void bl_aux_params_parse(u_register_t head, + bl_aux_param_handler_t handler); + +#endif /* LIB_BL_AUX_PARAMS_H */ diff --git a/drivers/rz/ipl/rza/include/lib/cassert.h b/drivers/rz/ipl/rza/include/lib/cassert.h new file mode 100644 index 00000000..bbfdfdb2 --- /dev/null +++ b/drivers/rz/ipl/rza/include/lib/cassert.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2014-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CASSERT_H +#define CASSERT_H + +#include + +/******************************************************************************* + * Macro to flag a compile time assertion. It uses the preprocessor to generate + * an invalid C construct if 'cond' evaluates to false. + * The following compilation error is triggered if the assertion fails: + * "error: size of array 'msg' is negative" + * The 'unused' attribute ensures that the unused typedef does not emit a + * compiler warning. + ******************************************************************************/ +#define CASSERT(cond, msg) \ + typedef char msg[(cond) ? 1 : -1] __unused + +#endif /* CASSERT_H */ diff --git a/drivers/rz/ipl/rza/include/lib/coreboot.h b/drivers/rz/ipl/rza/include/lib/coreboot.h new file mode 100644 index 00000000..0aa65791 --- /dev/null +++ b/drivers/rz/ipl/rza/include/lib/coreboot.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef COREBOOT_H +#define COREBOOT_H + +#include + +typedef struct { + uint32_t type; /* always 2 (memory-mapped) on ARM */ + uint32_t baseaddr; + uint32_t baud; + uint32_t regwidth; /* in bytes, i.e. usually 4 */ + uint32_t input_hertz; + uint32_t uart_pci_addr; /* unused on current ARM systems */ +} coreboot_serial_t; +extern coreboot_serial_t coreboot_serial; + +#define COREBOOT_MAX_MEMRANGES 32 /* libpayload also uses this limit */ + +typedef struct __packed { + uint64_t start; + uint64_t size; + uint32_t type; +} coreboot_memrange_t; +extern coreboot_memrange_t coreboot_memranges[COREBOOT_MAX_MEMRANGES]; + +typedef enum { + CB_MEM_NONE = 0, /* coreboot will never report this */ + CB_MEM_RAM = 1, + CB_MEM_RESERVED = 2, + CB_MEM_ACPI = 3, + CB_MEM_NVS = 4, + CB_MEM_UNUSABLE = 5, + CB_MEM_VENDOR_RSVD = 6, + CB_MEM_TABLE = 16, +} coreboot_memory_t; + +coreboot_memory_t coreboot_get_memory_type(uintptr_t start, size_t size); +void coreboot_table_setup(void *base); + +#endif /* COREBOOT_H */ diff --git a/drivers/rz/ipl/rza/include/lib/cpus/aarch64/cortex_a55.h b/drivers/rz/ipl/rza/include/lib/cpus/aarch64/cortex_a55.h new file mode 100644 index 00000000..60ed957d --- /dev/null +++ b/drivers/rz/ipl/rza/include/lib/cpus/aarch64/cortex_a55.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CORTEX_A55_H +#define CORTEX_A55_H + +#include + +/* Cortex-A55 MIDR for revision 0 */ +#define CORTEX_A55_MIDR U(0x410fd050) + +/******************************************************************************* + * CPU Extended Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A55_CPUPWRCTLR_EL1 S3_0_C15_C2_7 +#define CORTEX_A55_CPUECTLR_EL1 S3_0_C15_C1_4 + +#define CORTEX_A55_CPUECTLR_EL1_L1WSCTL (ULL(3) << 25) + +/******************************************************************************* + * CPU Auxiliary Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A55_CPUACTLR_EL1 S3_0_C15_C1_0 + +#define CORTEX_A55_CPUACTLR_EL1_DISABLE_WRITE_STREAMING (ULL(1) << 24) +#define CORTEX_A55_CPUACTLR_EL1_DISABLE_DUAL_ISSUE (ULL(1) << 31) +#define CORTEX_A55_CPUACTLR_EL1_DISABLE_L1_PAGEWALKS (ULL(1) << 49) + +/******************************************************************************* + * CPU Identification register specific definitions. + ******************************************************************************/ +#define CORTEX_A55_CLIDR_EL1 S3_1_C0_C0_1 + +#define CORTEX_A55_CLIDR_EL1_CTYPE3 (ULL(7) << 6) + +/* Definitions of register field mask in CORTEX_A55_CPUPWRCTLR_EL1 */ +#define CORTEX_A55_CORE_PWRDN_EN_MASK U(0x1) + +/* Instruction patching registers */ +#define CPUPSELR_EL3 S3_6_C15_C8_0 +#define CPUPCR_EL3 S3_6_C15_C8_1 +#define CPUPOR_EL3 S3_6_C15_C8_2 +#define CPUPMR_EL3 S3_6_C15_C8_3 + +#endif /* CORTEX_A55_H */ diff --git a/drivers/rz/ipl/rza/include/lib/cpus/aarch64/cpu_macros.S b/drivers/rz/ipl/rza/include/lib/cpus/aarch64/cpu_macros.S new file mode 100644 index 00000000..92891ce3 --- /dev/null +++ b/drivers/rz/ipl/rza/include/lib/cpus/aarch64/cpu_macros.S @@ -0,0 +1,306 @@ +/* + * Copyright (c) 2014-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef CPU_MACROS_S +#define CPU_MACROS_S + +#include +#include +#include + +#define CPU_IMPL_PN_MASK (MIDR_IMPL_MASK << MIDR_IMPL_SHIFT) | \ + (MIDR_PN_MASK << MIDR_PN_SHIFT) + +/* The number of CPU operations allowed */ +#define CPU_MAX_PWR_DWN_OPS 2 + +/* Special constant to specify that CPU has no reset function */ +#define CPU_NO_RESET_FUNC 0 + +#define CPU_NO_EXTRA1_FUNC 0 +#define CPU_NO_EXTRA2_FUNC 0 + +/* Word size for 64-bit CPUs */ +#define CPU_WORD_SIZE 8 + +/* + * Whether errata status needs reporting. Errata status is printed in debug + * builds for both BL1 and BL31 images. + */ +#if (defined(IMAGE_BL1) || defined(IMAGE_BL31)) && DEBUG +# define REPORT_ERRATA 1 +#else +# define REPORT_ERRATA 0 +#endif + + + .equ CPU_MIDR_SIZE, CPU_WORD_SIZE + .equ CPU_EXTRA1_FUNC_SIZE, CPU_WORD_SIZE + .equ CPU_EXTRA2_FUNC_SIZE, CPU_WORD_SIZE + .equ CPU_E_HANDLER_FUNC_SIZE, CPU_WORD_SIZE + .equ CPU_RESET_FUNC_SIZE, CPU_WORD_SIZE + .equ CPU_PWR_DWN_OPS_SIZE, CPU_WORD_SIZE * CPU_MAX_PWR_DWN_OPS + .equ CPU_ERRATA_FUNC_SIZE, CPU_WORD_SIZE + .equ CPU_ERRATA_LOCK_SIZE, CPU_WORD_SIZE + .equ CPU_ERRATA_PRINTED_SIZE, CPU_WORD_SIZE + .equ CPU_REG_DUMP_SIZE, CPU_WORD_SIZE + +#ifndef IMAGE_AT_EL3 + .equ CPU_RESET_FUNC_SIZE, 0 +#endif + +/* The power down core and cluster is needed only in BL31 */ +#ifndef IMAGE_BL31 + .equ CPU_PWR_DWN_OPS_SIZE, 0 +#endif + +/* Fields required to print errata status. */ +#if !REPORT_ERRATA + .equ CPU_ERRATA_FUNC_SIZE, 0 +#endif + +/* Only BL31 requieres mutual exclusion and printed flag. */ +#if !(REPORT_ERRATA && defined(IMAGE_BL31)) + .equ CPU_ERRATA_LOCK_SIZE, 0 + .equ CPU_ERRATA_PRINTED_SIZE, 0 +#endif + +#if !defined(IMAGE_BL31) || !CRASH_REPORTING + .equ CPU_REG_DUMP_SIZE, 0 +#endif + +/* + * Define the offsets to the fields in cpu_ops structure. + * Every offset is defined based in the offset and size of the previous + * field. + */ + .equ CPU_MIDR, 0 + .equ CPU_RESET_FUNC, CPU_MIDR + CPU_MIDR_SIZE + .equ CPU_EXTRA1_FUNC, CPU_RESET_FUNC + CPU_RESET_FUNC_SIZE + .equ CPU_EXTRA2_FUNC, CPU_EXTRA1_FUNC + CPU_EXTRA1_FUNC_SIZE + .equ CPU_E_HANDLER_FUNC, CPU_EXTRA2_FUNC + CPU_EXTRA2_FUNC_SIZE + .equ CPU_PWR_DWN_OPS, CPU_E_HANDLER_FUNC + CPU_E_HANDLER_FUNC_SIZE + .equ CPU_ERRATA_FUNC, CPU_PWR_DWN_OPS + CPU_PWR_DWN_OPS_SIZE + .equ CPU_ERRATA_LOCK, CPU_ERRATA_FUNC + CPU_ERRATA_FUNC_SIZE + .equ CPU_ERRATA_PRINTED, CPU_ERRATA_LOCK + CPU_ERRATA_LOCK_SIZE + .equ CPU_REG_DUMP, CPU_ERRATA_PRINTED + CPU_ERRATA_PRINTED_SIZE + .equ CPU_OPS_SIZE, CPU_REG_DUMP + CPU_REG_DUMP_SIZE + + /* + * Write given expressions as quad words + * + * _count: + * Write at least _count quad words. If the given number of + * expressions is less than _count, repeat the last expression to + * fill _count quad words in total + * _rest: + * Optional list of expressions. _this is for parameter extraction + * only, and has no significance to the caller + * + * Invoked as: + * fill_constants 2, foo, bar, blah, ... + */ + .macro fill_constants _count:req, _this, _rest:vararg + .ifgt \_count + /* Write the current expression */ + .ifb \_this + .error "Nothing to fill" + .endif + .quad \_this + + /* Invoke recursively for remaining expressions */ + .ifnb \_rest + fill_constants \_count-1, \_rest + .else + fill_constants \_count-1, \_this + .endif + .endif + .endm + + /* + * Declare CPU operations + * + * _name: + * Name of the CPU for which operations are being specified + * _midr: + * Numeric value expected to read from CPU's MIDR + * _resetfunc: + * Reset function for the CPU. If there's no CPU reset function, + * specify CPU_NO_RESET_FUNC + * _extra1: + * This is a placeholder for future per CPU operations. Currently, + * some CPUs use this entry to set a test function to determine if + * the workaround for CVE-2017-5715 needs to be applied or not. + * _extra2: + * This is a placeholder for future per CPU operations. Currently + * some CPUs use this entry to set a function to disable the + * workaround for CVE-2018-3639. + * _e_handler: + * This is a placeholder for future per CPU exception handlers. + * _power_down_ops: + * Comma-separated list of functions to perform power-down + * operatios on the CPU. At least one, and up to + * CPU_MAX_PWR_DWN_OPS number of functions may be specified. + * Starting at power level 0, these functions shall handle power + * down at subsequent power levels. If there aren't exactly + * CPU_MAX_PWR_DWN_OPS functions, the last specified one will be + * used to handle power down at subsequent levels + */ + .macro declare_cpu_ops_base _name:req, _midr:req, _resetfunc:req, \ + _extra1:req, _extra2:req, _e_handler:req, _power_down_ops:vararg + .section cpu_ops, "a" + .align 3 + .type cpu_ops_\_name, %object + .quad \_midr +#if defined(IMAGE_AT_EL3) + .quad \_resetfunc +#endif + .quad \_extra1 + .quad \_extra2 + .quad \_e_handler +#ifdef IMAGE_BL31 + /* Insert list of functions */ + fill_constants CPU_MAX_PWR_DWN_OPS, \_power_down_ops +#endif + +#if REPORT_ERRATA + .ifndef \_name\()_cpu_str + /* + * Place errata reported flag, and the spinlock to arbitrate access to + * it in the data section. + */ + .pushsection .data + define_asm_spinlock \_name\()_errata_lock + \_name\()_errata_reported: + .word 0 + .popsection + + /* Place CPU string in rodata */ + .pushsection .rodata + \_name\()_cpu_str: + .asciz "\_name" + .popsection + .endif + + /* + * Mandatory errata status printing function for CPUs of + * this class. + */ + .quad \_name\()_errata_report + +#ifdef IMAGE_BL31 + /* Pointers to errata lock and reported flag */ + .quad \_name\()_errata_lock + .quad \_name\()_errata_reported +#endif +#endif + +#if defined(IMAGE_BL31) && CRASH_REPORTING + .quad \_name\()_cpu_reg_dump +#endif + .endm + + .macro declare_cpu_ops _name:req, _midr:req, _resetfunc:req, \ + _power_down_ops:vararg + declare_cpu_ops_base \_name, \_midr, \_resetfunc, 0, 0, 0, \ + \_power_down_ops + .endm + + .macro declare_cpu_ops_eh _name:req, _midr:req, _resetfunc:req, \ + _e_handler:req, _power_down_ops:vararg + declare_cpu_ops_base \_name, \_midr, \_resetfunc, \ + 0, 0, \_e_handler, \_power_down_ops + .endm + + .macro declare_cpu_ops_wa _name:req, _midr:req, \ + _resetfunc:req, _extra1:req, _extra2:req, \ + _power_down_ops:vararg + declare_cpu_ops_base \_name, \_midr, \_resetfunc, \ + \_extra1, \_extra2, 0, \_power_down_ops + .endm + +#if REPORT_ERRATA + /* + * Print status of a CPU errata + * + * _chosen: + * Identifier indicating whether or not a CPU errata has been + * compiled in. + * _cpu: + * Name of the CPU + * _id: + * Errata identifier + * _rev_var: + * Register containing the combined value CPU revision and variant + * - typically the return value of cpu_get_rev_var + */ + .macro report_errata _chosen, _cpu, _id, _rev_var=x8 + /* Stash a string with errata ID */ + .pushsection .rodata + \_cpu\()_errata_\_id\()_str: + .asciz "\_id" + .popsection + + /* Check whether errata applies */ + mov x0, \_rev_var + /* Shall clobber: x0-x7 */ + bl check_errata_\_id + + .ifeq \_chosen + /* + * Errata workaround has not been compiled in. If the errata would have + * applied had it been compiled in, print its status as missing. + */ + cbz x0, 900f + mov x0, #ERRATA_MISSING + .endif +900: + adr x1, \_cpu\()_cpu_str + adr x2, \_cpu\()_errata_\_id\()_str + bl errata_print_msg + .endm +#endif + + /* + * This macro is used on some CPUs to detect if they are vulnerable + * to CVE-2017-5715. + */ + .macro cpu_check_csv2 _reg _label + mrs \_reg, id_aa64pfr0_el1 + ubfx \_reg, \_reg, #ID_AA64PFR0_CSV2_SHIFT, #ID_AA64PFR0_CSV2_LENGTH + /* + * If the field equals 1, branch targets trained in one context cannot + * affect speculative execution in a different context. + * + * If the field equals 2, it means that the system is also aware of + * SCXTNUM_ELx register contexts. We aren't using them in the TF, so we + * expect users of the registers to do the right thing. + * + * Only apply mitigations if the value of this field is 0. + */ +#if ENABLE_ASSERTIONS + cmp \_reg, #3 /* Only values 0 to 2 are expected */ + ASM_ASSERT(lo) +#endif + + cmp \_reg, #0 + bne \_label + .endm + + /* + * Helper macro that reads the part number of the current + * CPU and jumps to the given label if it matches the CPU + * MIDR provided. + * + * Clobbers x0. + */ + .macro jump_if_cpu_midr _cpu_midr, _label + mrs x0, midr_el1 + ubfx x0, x0, MIDR_PN_SHIFT, #12 + cmp w0, #((\_cpu_midr >> MIDR_PN_SHIFT) & MIDR_PN_MASK) + b.eq \_label + .endm + +#endif /* CPU_MACROS_S */ diff --git a/drivers/rz/ipl/rza/include/lib/cpus/aarch64/dsu_def.h b/drivers/rz/ipl/rza/include/lib/cpus/aarch64/dsu_def.h new file mode 100644 index 00000000..0969acf5 --- /dev/null +++ b/drivers/rz/ipl/rza/include/lib/cpus/aarch64/dsu_def.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef DSU_DEF_H +#define DSU_DEF_H + +#include + +/******************************************************************** + * DSU Cluster Configuration registers definitions + ********************************************************************/ +#define CLUSTERCFR_EL1 S3_0_C15_C3_0 + +#define CLUSTERCFR_ACP_SHIFT U(11) + +/******************************************************************** + * DSU Cluster Main Revision ID registers definitions + ********************************************************************/ +#define CLUSTERIDR_EL1 S3_0_C15_C3_1 + +#define CLUSTERIDR_REV_SHIFT U(0) +#define CLUSTERIDR_REV_BITS U(4) +#define CLUSTERIDR_VAR_SHIFT U(4) +#define CLUSTERIDR_VAR_BITS U(4) + +/******************************************************************** + * DSU Cluster Auxiliary Control registers definitions + ********************************************************************/ +#define CLUSTERACTLR_EL1 S3_0_C15_C3_3 + +#define CLUSTERACTLR_EL1_DISABLE_CLOCK_GATING (ULL(1) << 15) + +/******************************************************************** + * Masks applied for DSU errata workarounds + ********************************************************************/ +#define DSU_ERRATA_936184_MASK (U(0x3) << 15) + +#endif /* DSU_DEF_H */ diff --git a/drivers/rz/ipl/rza/include/lib/cpus/errata_report.h b/drivers/rz/ipl/rza/include/lib/cpus/errata_report.h new file mode 100644 index 00000000..efdedf0a --- /dev/null +++ b/drivers/rz/ipl/rza/include/lib/cpus/errata_report.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef ERRATA_REPORT_H +#define ERRATA_REPORT_H + +#ifndef __ASSEMBLER__ + +#include +#include +#include +#include + +#if DEBUG +void print_errata_status(void); +#else +static inline void print_errata_status(void) {} +#endif + +void errata_print_msg(unsigned int status, const char *cpu, const char *id); +int errata_needs_reporting(spinlock_t *lock, uint32_t *reported); + +#endif /* __ASSEMBLER__ */ + +/* Errata status */ +#define ERRATA_NOT_APPLIES 0 +#define ERRATA_APPLIES 1 +#define ERRATA_MISSING 2 + +/* Macro to get CPU revision code for checking errata version compatibility. */ +#define CPU_REV(r, p) ((r << 4) | p) + +#endif /* ERRATA_REPORT_H */ diff --git a/drivers/rz/ipl/rza/include/lib/cpus/wa_cve_2017_5715.h b/drivers/rz/ipl/rza/include/lib/cpus/wa_cve_2017_5715.h new file mode 100644 index 00000000..940fc659 --- /dev/null +++ b/drivers/rz/ipl/rza/include/lib/cpus/wa_cve_2017_5715.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef WA_CVE_2017_5715_H +#define WA_CVE_2017_5715_H + +int check_wa_cve_2017_5715(void); + +#endif /* WA_CVE_2017_5715_H */ diff --git a/drivers/rz/ipl/rza/include/lib/cpus/wa_cve_2018_3639.h b/drivers/rz/ipl/rza/include/lib/cpus/wa_cve_2018_3639.h new file mode 100644 index 00000000..e37db377 --- /dev/null +++ b/drivers/rz/ipl/rza/include/lib/cpus/wa_cve_2018_3639.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef WA_CVE_2018_3639_H +#define WA_CVE_2018_3639_H + +void *wa_cve_2018_3639_get_disable_ptr(void); + +#endif /* WA_CVE_2018_3639_H */ diff --git a/drivers/rz/ipl/rza/include/lib/debugfs.h b/drivers/rz/ipl/rza/include/lib/debugfs.h new file mode 100644 index 00000000..8ed237ae --- /dev/null +++ b/drivers/rz/ipl/rza/include/lib/debugfs.h @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef DEBUGFS_H +#define DEBUGFS_H + +#define NAMELEN 13 /* Maximum length of a file name */ +#define PATHLEN 41 /* Maximum length of a path */ +#define STATLEN 41 /* Size of static part of dir format */ +#define ROOTLEN (2 + 4) /* Size needed to encode root string */ +#define FILNAMLEN (2 + NAMELEN) /* Size needed to encode filename */ +#define DIRLEN (STATLEN + FILNAMLEN + 3*ROOTLEN) /* Size of dir entry */ + +#define KSEEK_SET 0 +#define KSEEK_CUR 1 +#define KSEEK_END 2 + +#define NELEM(tab) (sizeof(tab) / sizeof((tab)[0])) + +typedef unsigned short qid_t; /* FIXME: short type not recommended? */ + +/******************************************************************************* + * This structure contains the necessary information to represent a 9p + * directory. + ******************************************************************************/ +typedef struct { + char name[NAMELEN]; + long length; + unsigned char mode; + unsigned char index; + unsigned char dev; + qid_t qid; +} dir_t; + +/* Permission definitions used as flags */ +#define O_READ (1 << 0) +#define O_WRITE (1 << 1) +#define O_RDWR (1 << 2) +#define O_BIND (1 << 3) +#define O_DIR (1 << 4) +#define O_STAT (1 << 5) + +/* 9p interface */ +int mount(const char *srv, const char *mnt, const char *spec); +int create(const char *name, int flags); +int open(const char *name, int flags); +int close(int fd); +int read(int fd, void *buf, int n); +int write(int fd, void *buf, int n); +int seek(int fd, long off, int whence); +int bind(const char *path, const char *where); +int stat(const char *path, dir_t *dir); + +/* DebugFS initialization */ +void debugfs_init(void); +int debugfs_smc_setup(void); + +/* Debugfs version returned through SMC interface */ +#define DEBUGFS_VERSION (0x000000001U) + +/* Function ID for accessing the debugfs interface */ +#define DEBUGFS_FID_VALUE (0x30U) + +#define is_debugfs_fid(_fid) \ + (((_fid) & FUNCID_NUM_MASK) == DEBUGFS_FID_VALUE) + +/* Error code for debugfs SMC interface failures */ +#define DEBUGFS_E_INVALID_PARAMS (-2) +#define DEBUGFS_E_DENIED (-3) + +uintptr_t debugfs_smc_handler(unsigned int smc_fid, + u_register_t cmd, + u_register_t arg2, + u_register_t arg3, + u_register_t arg4, + void *cookie, + void *handle, + uintptr_t flags); + +#endif /* DEBUGFS_H */ diff --git a/drivers/rz/ipl/rza/include/lib/el3_runtime/aarch64/context.h b/drivers/rz/ipl/rza/include/lib/el3_runtime/aarch64/context.h new file mode 100644 index 00000000..9d9f9d33 --- /dev/null +++ b/drivers/rz/ipl/rza/include/lib/el3_runtime/aarch64/context.h @@ -0,0 +1,521 @@ +/* + * Copyright (c) 2013-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CONTEXT_H +#define CONTEXT_H + +#include + +/******************************************************************************* + * Constants that allow assembler code to access members of and the 'gp_regs' + * structure at their correct offsets. + ******************************************************************************/ +#define CTX_GPREGS_OFFSET U(0x0) +#define CTX_GPREG_X0 U(0x0) +#define CTX_GPREG_X1 U(0x8) +#define CTX_GPREG_X2 U(0x10) +#define CTX_GPREG_X3 U(0x18) +#define CTX_GPREG_X4 U(0x20) +#define CTX_GPREG_X5 U(0x28) +#define CTX_GPREG_X6 U(0x30) +#define CTX_GPREG_X7 U(0x38) +#define CTX_GPREG_X8 U(0x40) +#define CTX_GPREG_X9 U(0x48) +#define CTX_GPREG_X10 U(0x50) +#define CTX_GPREG_X11 U(0x58) +#define CTX_GPREG_X12 U(0x60) +#define CTX_GPREG_X13 U(0x68) +#define CTX_GPREG_X14 U(0x70) +#define CTX_GPREG_X15 U(0x78) +#define CTX_GPREG_X16 U(0x80) +#define CTX_GPREG_X17 U(0x88) +#define CTX_GPREG_X18 U(0x90) +#define CTX_GPREG_X19 U(0x98) +#define CTX_GPREG_X20 U(0xa0) +#define CTX_GPREG_X21 U(0xa8) +#define CTX_GPREG_X22 U(0xb0) +#define CTX_GPREG_X23 U(0xb8) +#define CTX_GPREG_X24 U(0xc0) +#define CTX_GPREG_X25 U(0xc8) +#define CTX_GPREG_X26 U(0xd0) +#define CTX_GPREG_X27 U(0xd8) +#define CTX_GPREG_X28 U(0xe0) +#define CTX_GPREG_X29 U(0xe8) +#define CTX_GPREG_LR U(0xf0) +#define CTX_GPREG_SP_EL0 U(0xf8) +#define CTX_GPREGS_END U(0x100) + +/******************************************************************************* + * Constants that allow assembler code to access members of and the 'el3_state' + * structure at their correct offsets. Note that some of the registers are only + * 32-bits wide but are stored as 64-bit values for convenience + ******************************************************************************/ +#define CTX_EL3STATE_OFFSET (CTX_GPREGS_OFFSET + CTX_GPREGS_END) +#define CTX_SCR_EL3 U(0x0) +#define CTX_ESR_EL3 U(0x8) +#define CTX_RUNTIME_SP U(0x10) +#define CTX_SPSR_EL3 U(0x18) +#define CTX_ELR_EL3 U(0x20) +#define CTX_PMCR_EL0 U(0x28) +#define CTX_IS_IN_EL3 U(0x30) +#define CTX_EL3STATE_END U(0x40) /* Align to the next 16 byte boundary */ + +/******************************************************************************* + * Constants that allow assembler code to access members of and the + * 'el1_sys_regs' structure at their correct offsets. Note that some of the + * registers are only 32-bits wide but are stored as 64-bit values for + * convenience + ******************************************************************************/ +#define CTX_EL1_SYSREGS_OFFSET (CTX_EL3STATE_OFFSET + CTX_EL3STATE_END) +#define CTX_SPSR_EL1 U(0x0) +#define CTX_ELR_EL1 U(0x8) +#define CTX_SCTLR_EL1 U(0x10) +#define CTX_TCR_EL1 U(0x18) +#define CTX_CPACR_EL1 U(0x20) +#define CTX_CSSELR_EL1 U(0x28) +#define CTX_SP_EL1 U(0x30) +#define CTX_ESR_EL1 U(0x38) +#define CTX_TTBR0_EL1 U(0x40) +#define CTX_TTBR1_EL1 U(0x48) +#define CTX_MAIR_EL1 U(0x50) +#define CTX_AMAIR_EL1 U(0x58) +#define CTX_ACTLR_EL1 U(0x60) +#define CTX_TPIDR_EL1 U(0x68) +#define CTX_TPIDR_EL0 U(0x70) +#define CTX_TPIDRRO_EL0 U(0x78) +#define CTX_PAR_EL1 U(0x80) +#define CTX_FAR_EL1 U(0x88) +#define CTX_AFSR0_EL1 U(0x90) +#define CTX_AFSR1_EL1 U(0x98) +#define CTX_CONTEXTIDR_EL1 U(0xa0) +#define CTX_VBAR_EL1 U(0xa8) + +/* + * If the platform is AArch64-only, there is no need to save and restore these + * AArch32 registers. + */ +#if CTX_INCLUDE_AARCH32_REGS +#define CTX_SPSR_ABT U(0xb0) /* Align to the next 16 byte boundary */ +#define CTX_SPSR_UND U(0xb8) +#define CTX_SPSR_IRQ U(0xc0) +#define CTX_SPSR_FIQ U(0xc8) +#define CTX_DACR32_EL2 U(0xd0) +#define CTX_IFSR32_EL2 U(0xd8) +#define CTX_AARCH32_END U(0xe0) /* Align to the next 16 byte boundary */ +#else +#define CTX_AARCH32_END U(0xb0) /* Align to the next 16 byte boundary */ +#endif /* CTX_INCLUDE_AARCH32_REGS */ + +/* + * If the timer registers aren't saved and restored, we don't have to reserve + * space for them in the context + */ +#if NS_TIMER_SWITCH +#define CTX_CNTP_CTL_EL0 (CTX_AARCH32_END + U(0x0)) +#define CTX_CNTP_CVAL_EL0 (CTX_AARCH32_END + U(0x8)) +#define CTX_CNTV_CTL_EL0 (CTX_AARCH32_END + U(0x10)) +#define CTX_CNTV_CVAL_EL0 (CTX_AARCH32_END + U(0x18)) +#define CTX_CNTKCTL_EL1 (CTX_AARCH32_END + U(0x20)) +#define CTX_TIMER_SYSREGS_END (CTX_AARCH32_END + U(0x30)) /* Align to the next 16 byte boundary */ +#else +#define CTX_TIMER_SYSREGS_END CTX_AARCH32_END +#endif /* NS_TIMER_SWITCH */ + +#if CTX_INCLUDE_MTE_REGS +#define CTX_TFSRE0_EL1 (CTX_TIMER_SYSREGS_END + U(0x0)) +#define CTX_TFSR_EL1 (CTX_TIMER_SYSREGS_END + U(0x8)) +#define CTX_RGSR_EL1 (CTX_TIMER_SYSREGS_END + U(0x10)) +#define CTX_GCR_EL1 (CTX_TIMER_SYSREGS_END + U(0x18)) + +/* Align to the next 16 byte boundary */ +#define CTX_MTE_REGS_END (CTX_TIMER_SYSREGS_END + U(0x20)) +#else +#define CTX_MTE_REGS_END CTX_TIMER_SYSREGS_END +#endif /* CTX_INCLUDE_MTE_REGS */ + +/* + * End of system registers. + */ +#define CTX_EL1_SYSREGS_END CTX_MTE_REGS_END + +/* + * EL2 register set + */ + +#if CTX_INCLUDE_EL2_REGS +/* For later discussion + * ICH_AP0R_EL2 + * ICH_AP1R_EL2 + * AMEVCNTVOFF0_EL2 + * AMEVCNTVOFF1_EL2 + * ICH_LR_EL2 + */ +#define CTX_EL2_SYSREGS_OFFSET (CTX_EL1_SYSREGS_OFFSET + CTX_EL1_SYSREGS_END) + +#define CTX_ACTLR_EL2 U(0x0) +#define CTX_AFSR0_EL2 U(0x8) +#define CTX_AFSR1_EL2 U(0x10) +#define CTX_AMAIR_EL2 U(0x18) +#define CTX_CNTHCTL_EL2 U(0x20) +#define CTX_CNTVOFF_EL2 U(0x28) +#define CTX_CPTR_EL2 U(0x30) +#define CTX_DBGVCR32_EL2 U(0x38) +#define CTX_ELR_EL2 U(0x40) +#define CTX_ESR_EL2 U(0x48) +#define CTX_FAR_EL2 U(0x50) +#define CTX_HACR_EL2 U(0x58) +#define CTX_HCR_EL2 U(0x60) +#define CTX_HPFAR_EL2 U(0x68) +#define CTX_HSTR_EL2 U(0x70) +#define CTX_ICC_SRE_EL2 U(0x78) +#define CTX_ICH_HCR_EL2 U(0x80) +#define CTX_ICH_VMCR_EL2 U(0x88) +#define CTX_MAIR_EL2 U(0x90) +#define CTX_MDCR_EL2 U(0x98) +#define CTX_PMSCR_EL2 U(0xa0) +#define CTX_SCTLR_EL2 U(0xa8) +#define CTX_SPSR_EL2 U(0xb0) +#define CTX_SP_EL2 U(0xb8) +#define CTX_TCR_EL2 U(0xc0) +#define CTX_TPIDR_EL2 U(0xc8) +#define CTX_TTBR0_EL2 U(0xd0) +#define CTX_VBAR_EL2 U(0xd8) +#define CTX_VMPIDR_EL2 U(0xe0) +#define CTX_VPIDR_EL2 U(0xe8) +#define CTX_VTCR_EL2 U(0xf0) +#define CTX_VTTBR_EL2 U(0xf8) + +// Only if MTE registers in use +#define CTX_TFSR_EL2 U(0x100) + +// Only if ENABLE_MPAM_FOR_LOWER_ELS==1 +#define CTX_MPAM2_EL2 U(0x108) +#define CTX_MPAMHCR_EL2 U(0x110) +#define CTX_MPAMVPM0_EL2 U(0x118) +#define CTX_MPAMVPM1_EL2 U(0x120) +#define CTX_MPAMVPM2_EL2 U(0x128) +#define CTX_MPAMVPM3_EL2 U(0x130) +#define CTX_MPAMVPM4_EL2 U(0x138) +#define CTX_MPAMVPM5_EL2 U(0x140) +#define CTX_MPAMVPM6_EL2 U(0x148) +#define CTX_MPAMVPM7_EL2 U(0x150) +#define CTX_MPAMVPMV_EL2 U(0x158) + +// Starting with Armv8.6 +#define CTX_HAFGRTR_EL2 U(0x160) +#define CTX_HDFGRTR_EL2 U(0x168) +#define CTX_HDFGWTR_EL2 U(0x170) +#define CTX_HFGITR_EL2 U(0x178) +#define CTX_HFGRTR_EL2 U(0x180) +#define CTX_HFGWTR_EL2 U(0x188) +#define CTX_CNTPOFF_EL2 U(0x190) + +// Starting with Armv8.4 +#define CTX_CONTEXTIDR_EL2 U(0x198) +#define CTX_SDER32_EL2 U(0x1a0) +#define CTX_TTBR1_EL2 U(0x1a8) +#define CTX_VDISR_EL2 U(0x1b0) +#define CTX_VNCR_EL2 U(0x1b8) +#define CTX_VSESR_EL2 U(0x1c0) +#define CTX_VSTCR_EL2 U(0x1c8) +#define CTX_VSTTBR_EL2 U(0x1d0) +#define CTX_TRFCR_EL2 U(0x1d8) + +// Starting with Armv8.5 +#define CTX_SCXTNUM_EL2 U(0x1e0) +/* Align to the next 16 byte boundary */ +#define CTX_EL2_SYSREGS_END U(0x1f0) + +#endif /* CTX_INCLUDE_EL2_REGS */ + +/******************************************************************************* + * Constants that allow assembler code to access members of and the 'fp_regs' + * structure at their correct offsets. + ******************************************************************************/ +#if CTX_INCLUDE_EL2_REGS +# define CTX_FPREGS_OFFSET (CTX_EL2_SYSREGS_OFFSET + CTX_EL2_SYSREGS_END) +#else +# define CTX_FPREGS_OFFSET (CTX_EL1_SYSREGS_OFFSET + CTX_EL1_SYSREGS_END) +#endif +#if CTX_INCLUDE_FPREGS +#define CTX_FP_Q0 U(0x0) +#define CTX_FP_Q1 U(0x10) +#define CTX_FP_Q2 U(0x20) +#define CTX_FP_Q3 U(0x30) +#define CTX_FP_Q4 U(0x40) +#define CTX_FP_Q5 U(0x50) +#define CTX_FP_Q6 U(0x60) +#define CTX_FP_Q7 U(0x70) +#define CTX_FP_Q8 U(0x80) +#define CTX_FP_Q9 U(0x90) +#define CTX_FP_Q10 U(0xa0) +#define CTX_FP_Q11 U(0xb0) +#define CTX_FP_Q12 U(0xc0) +#define CTX_FP_Q13 U(0xd0) +#define CTX_FP_Q14 U(0xe0) +#define CTX_FP_Q15 U(0xf0) +#define CTX_FP_Q16 U(0x100) +#define CTX_FP_Q17 U(0x110) +#define CTX_FP_Q18 U(0x120) +#define CTX_FP_Q19 U(0x130) +#define CTX_FP_Q20 U(0x140) +#define CTX_FP_Q21 U(0x150) +#define CTX_FP_Q22 U(0x160) +#define CTX_FP_Q23 U(0x170) +#define CTX_FP_Q24 U(0x180) +#define CTX_FP_Q25 U(0x190) +#define CTX_FP_Q26 U(0x1a0) +#define CTX_FP_Q27 U(0x1b0) +#define CTX_FP_Q28 U(0x1c0) +#define CTX_FP_Q29 U(0x1d0) +#define CTX_FP_Q30 U(0x1e0) +#define CTX_FP_Q31 U(0x1f0) +#define CTX_FP_FPSR U(0x200) +#define CTX_FP_FPCR U(0x208) +#if CTX_INCLUDE_AARCH32_REGS +#define CTX_FP_FPEXC32_EL2 U(0x210) +#define CTX_FPREGS_END U(0x220) /* Align to the next 16 byte boundary */ +#else +#define CTX_FPREGS_END U(0x210) /* Align to the next 16 byte boundary */ +#endif +#else +#define CTX_FPREGS_END U(0) +#endif + +/******************************************************************************* + * Registers related to CVE-2018-3639 + ******************************************************************************/ +#define CTX_CVE_2018_3639_OFFSET (CTX_FPREGS_OFFSET + CTX_FPREGS_END) +#define CTX_CVE_2018_3639_DISABLE U(0) +#define CTX_CVE_2018_3639_END U(0x10) /* Align to the next 16 byte boundary */ + +/******************************************************************************* + * Registers related to ARMv8.3-PAuth. + ******************************************************************************/ +#define CTX_PAUTH_REGS_OFFSET (CTX_CVE_2018_3639_OFFSET + CTX_CVE_2018_3639_END) +#if CTX_INCLUDE_PAUTH_REGS +#define CTX_PACIAKEY_LO U(0x0) +#define CTX_PACIAKEY_HI U(0x8) +#define CTX_PACIBKEY_LO U(0x10) +#define CTX_PACIBKEY_HI U(0x18) +#define CTX_PACDAKEY_LO U(0x20) +#define CTX_PACDAKEY_HI U(0x28) +#define CTX_PACDBKEY_LO U(0x30) +#define CTX_PACDBKEY_HI U(0x38) +#define CTX_PACGAKEY_LO U(0x40) +#define CTX_PACGAKEY_HI U(0x48) +#define CTX_PAUTH_REGS_END U(0x50) /* Align to the next 16 byte boundary */ +#else +#define CTX_PAUTH_REGS_END U(0) +#endif /* CTX_INCLUDE_PAUTH_REGS */ + +#ifndef __ASSEMBLER__ + +#include + +#include + +/* + * Common constants to help define the 'cpu_context' structure and its + * members below. + */ +#define DWORD_SHIFT U(3) +#define DEFINE_REG_STRUCT(name, num_regs) \ + typedef struct name { \ + uint64_t ctx_regs[num_regs]; \ + } __aligned(16) name##_t + +/* Constants to determine the size of individual context structures */ +#define CTX_GPREG_ALL (CTX_GPREGS_END >> DWORD_SHIFT) +#define CTX_EL1_SYSREGS_ALL (CTX_EL1_SYSREGS_END >> DWORD_SHIFT) +#if CTX_INCLUDE_EL2_REGS +# define CTX_EL2_SYSREGS_ALL (CTX_EL2_SYSREGS_END >> DWORD_SHIFT) +#endif +#if CTX_INCLUDE_FPREGS +# define CTX_FPREG_ALL (CTX_FPREGS_END >> DWORD_SHIFT) +#endif +#define CTX_EL3STATE_ALL (CTX_EL3STATE_END >> DWORD_SHIFT) +#define CTX_CVE_2018_3639_ALL (CTX_CVE_2018_3639_END >> DWORD_SHIFT) +#if CTX_INCLUDE_PAUTH_REGS +# define CTX_PAUTH_REGS_ALL (CTX_PAUTH_REGS_END >> DWORD_SHIFT) +#endif + +/* + * AArch64 general purpose register context structure. Usually x0-x18, + * lr are saved as the compiler is expected to preserve the remaining + * callee saved registers if used by the C runtime and the assembler + * does not touch the remaining. But in case of world switch during + * exception handling, we need to save the callee registers too. + */ +DEFINE_REG_STRUCT(gp_regs, CTX_GPREG_ALL); + +/* + * AArch64 EL1 system register context structure for preserving the + * architectural state during world switches. + */ +DEFINE_REG_STRUCT(el1_sysregs, CTX_EL1_SYSREGS_ALL); + + +/* + * AArch64 EL2 system register context structure for preserving the + * architectural state during world switches. + */ +#if CTX_INCLUDE_EL2_REGS +DEFINE_REG_STRUCT(el2_sysregs, CTX_EL2_SYSREGS_ALL); +#endif + +/* + * AArch64 floating point register context structure for preserving + * the floating point state during switches from one security state to + * another. + */ +#if CTX_INCLUDE_FPREGS +DEFINE_REG_STRUCT(fp_regs, CTX_FPREG_ALL); +#endif + +/* + * Miscellaneous registers used by EL3 firmware to maintain its state + * across exception entries and exits + */ +DEFINE_REG_STRUCT(el3_state, CTX_EL3STATE_ALL); + +/* Function pointer used by CVE-2018-3639 dynamic mitigation */ +DEFINE_REG_STRUCT(cve_2018_3639, CTX_CVE_2018_3639_ALL); + +/* Registers associated to ARMv8.3-PAuth */ +#if CTX_INCLUDE_PAUTH_REGS +DEFINE_REG_STRUCT(pauth, CTX_PAUTH_REGS_ALL); +#endif + +/* + * Macros to access members of any of the above structures using their + * offsets + */ +#define read_ctx_reg(ctx, offset) ((ctx)->ctx_regs[(offset) >> DWORD_SHIFT]) +#define write_ctx_reg(ctx, offset, val) (((ctx)->ctx_regs[(offset) >> DWORD_SHIFT]) \ + = (uint64_t) (val)) + +/* + * Top-level context structure which is used by EL3 firmware to + * preserve the state of a core at EL1 in one of the two security + * states and save enough EL3 meta data to be able to return to that + * EL and security state. The context management library will be used + * to ensure that SP_EL3 always points to an instance of this + * structure at exception entry and exit. Each instance will + * correspond to either the secure or the non-secure state. + */ +typedef struct cpu_context { + gp_regs_t gpregs_ctx; + el3_state_t el3state_ctx; + el1_sysregs_t el1_sysregs_ctx; +#if CTX_INCLUDE_EL2_REGS + el2_sysregs_t el2_sysregs_ctx; +#endif +#if CTX_INCLUDE_FPREGS + fp_regs_t fpregs_ctx; +#endif + cve_2018_3639_t cve_2018_3639_ctx; +#if CTX_INCLUDE_PAUTH_REGS + pauth_t pauth_ctx; +#endif +} cpu_context_t; + +/* Macros to access members of the 'cpu_context_t' structure */ +#define get_el3state_ctx(h) (&((cpu_context_t *) h)->el3state_ctx) +#if CTX_INCLUDE_FPREGS +# define get_fpregs_ctx(h) (&((cpu_context_t *) h)->fpregs_ctx) +#endif +#define get_el1_sysregs_ctx(h) (&((cpu_context_t *) h)->el1_sysregs_ctx) +#if CTX_INCLUDE_EL2_REGS +# define get_el2_sysregs_ctx(h) (&((cpu_context_t *) h)->el2_sysregs_ctx) +#endif +#define get_gpregs_ctx(h) (&((cpu_context_t *) h)->gpregs_ctx) +#define get_cve_2018_3639_ctx(h) (&((cpu_context_t *) h)->cve_2018_3639_ctx) +#if CTX_INCLUDE_PAUTH_REGS +# define get_pauth_ctx(h) (&((cpu_context_t *) h)->pauth_ctx) +#endif + +/* + * Compile time assertions related to the 'cpu_context' structure to + * ensure that the assembler and the compiler view of the offsets of + * the structure members is the same. + */ +CASSERT(CTX_GPREGS_OFFSET == __builtin_offsetof(cpu_context_t, gpregs_ctx), \ + assert_core_context_gp_offset_mismatch); +CASSERT(CTX_EL1_SYSREGS_OFFSET == __builtin_offsetof(cpu_context_t, el1_sysregs_ctx), \ + assert_core_context_el1_sys_offset_mismatch); +#if CTX_INCLUDE_EL2_REGS +CASSERT(CTX_EL2_SYSREGS_OFFSET == __builtin_offsetof(cpu_context_t, el2_sysregs_ctx), \ + assert_core_context_el2_sys_offset_mismatch); +#endif +#if CTX_INCLUDE_FPREGS +CASSERT(CTX_FPREGS_OFFSET == __builtin_offsetof(cpu_context_t, fpregs_ctx), \ + assert_core_context_fp_offset_mismatch); +#endif +CASSERT(CTX_EL3STATE_OFFSET == __builtin_offsetof(cpu_context_t, el3state_ctx), \ + assert_core_context_el3state_offset_mismatch); +CASSERT(CTX_CVE_2018_3639_OFFSET == __builtin_offsetof(cpu_context_t, cve_2018_3639_ctx), \ + assert_core_context_cve_2018_3639_offset_mismatch); +#if CTX_INCLUDE_PAUTH_REGS +CASSERT(CTX_PAUTH_REGS_OFFSET == __builtin_offsetof(cpu_context_t, pauth_ctx), \ + assert_core_context_pauth_offset_mismatch); +#endif + +/* + * Helper macro to set the general purpose registers that correspond to + * parameters in an aapcs_64 call i.e. x0-x7 + */ +#define set_aapcs_args0(ctx, x0) do { \ + write_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X0, x0); \ + } while (0) +#define set_aapcs_args1(ctx, x0, x1) do { \ + write_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X1, x1); \ + set_aapcs_args0(ctx, x0); \ + } while (0) +#define set_aapcs_args2(ctx, x0, x1, x2) do { \ + write_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X2, x2); \ + set_aapcs_args1(ctx, x0, x1); \ + } while (0) +#define set_aapcs_args3(ctx, x0, x1, x2, x3) do { \ + write_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X3, x3); \ + set_aapcs_args2(ctx, x0, x1, x2); \ + } while (0) +#define set_aapcs_args4(ctx, x0, x1, x2, x3, x4) do { \ + write_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X4, x4); \ + set_aapcs_args3(ctx, x0, x1, x2, x3); \ + } while (0) +#define set_aapcs_args5(ctx, x0, x1, x2, x3, x4, x5) do { \ + write_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X5, x5); \ + set_aapcs_args4(ctx, x0, x1, x2, x3, x4); \ + } while (0) +#define set_aapcs_args6(ctx, x0, x1, x2, x3, x4, x5, x6) do { \ + write_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X6, x6); \ + set_aapcs_args5(ctx, x0, x1, x2, x3, x4, x5); \ + } while (0) +#define set_aapcs_args7(ctx, x0, x1, x2, x3, x4, x5, x6, x7) do { \ + write_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X7, x7); \ + set_aapcs_args6(ctx, x0, x1, x2, x3, x4, x5, x6); \ + } while (0) + +/******************************************************************************* + * Function prototypes + ******************************************************************************/ +void el1_sysregs_context_save(el1_sysregs_t *regs); +void el1_sysregs_context_restore(el1_sysregs_t *regs); + +#if CTX_INCLUDE_EL2_REGS +void el2_sysregs_context_save(el2_sysregs_t *regs); +void el2_sysregs_context_restore(el2_sysregs_t *regs); +#endif + +#if CTX_INCLUDE_FPREGS +void fpregs_context_save(fp_regs_t *regs); +void fpregs_context_restore(fp_regs_t *regs); +#endif + +#endif /* __ASSEMBLER__ */ + +#endif /* CONTEXT_H */ diff --git a/drivers/rz/ipl/rza/include/lib/el3_runtime/context_mgmt.h b/drivers/rz/ipl/rza/include/lib/el3_runtime/context_mgmt.h new file mode 100644 index 00000000..2090687e --- /dev/null +++ b/drivers/rz/ipl/rza/include/lib/el3_runtime/context_mgmt.h @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CONTEXT_MGMT_H +#define CONTEXT_MGMT_H + +#include +#include +#include + +#include + +/******************************************************************************* + * Forward declarations + ******************************************************************************/ +struct entry_point_info; + +/******************************************************************************* + * Function & variable prototypes + ******************************************************************************/ +void cm_init(void); +void *cm_get_context_by_index(unsigned int cpu_idx, + unsigned int security_state); +void cm_set_context_by_index(unsigned int cpu_idx, + void *context, + unsigned int security_state); +void *cm_get_context(uint32_t security_state); +void cm_set_context(void *context, uint32_t security_state); +void cm_init_my_context(const struct entry_point_info *ep); +void cm_init_context_by_index(unsigned int cpu_idx, + const struct entry_point_info *ep); +void cm_setup_context(cpu_context_t *ctx, const struct entry_point_info *ep); +void cm_prepare_el3_exit(uint32_t security_state); + +#ifdef __aarch64__ +#if CTX_INCLUDE_EL2_REGS +void cm_el2_sysregs_context_save(uint32_t security_state); +void cm_el2_sysregs_context_restore(uint32_t security_state); +#endif + +void cm_el1_sysregs_context_save(uint32_t security_state); +void cm_el1_sysregs_context_restore(uint32_t security_state); +void cm_set_elr_el3(uint32_t security_state, uintptr_t entrypoint); +void cm_set_elr_spsr_el3(uint32_t security_state, + uintptr_t entrypoint, uint32_t spsr); +void cm_write_scr_el3_bit(uint32_t security_state, + uint32_t bit_pos, + uint32_t value); +void cm_set_next_eret_context(uint32_t security_state); +u_register_t cm_get_scr_el3(uint32_t security_state); + +/* Inline definitions */ + +/******************************************************************************* + * This function is used to program the context that's used for exception + * return. This initializes the SP_EL3 to a pointer to a 'cpu_context' set for + * the required security state + ******************************************************************************/ +static inline void cm_set_next_context(void *context) +{ +#if ENABLE_ASSERTIONS + uint64_t sp_mode; + + /* + * Check that this function is called with SP_EL0 as the stack + * pointer + */ + __asm__ volatile("mrs %0, SPSel\n" + : "=r" (sp_mode)); + + assert(sp_mode == MODE_SP_EL0); +#endif /* ENABLE_ASSERTIONS */ + + __asm__ volatile("msr spsel, #1\n" + "mov sp, %0\n" + "msr spsel, #0\n" + : : "r" (context)); +} + +#else +void *cm_get_next_context(void); +void cm_set_next_context(void *context); +#endif /* __aarch64__ */ + +#endif /* CONTEXT_MGMT_H */ diff --git a/drivers/rz/ipl/rza/include/lib/el3_runtime/cpu_data.h b/drivers/rz/ipl/rza/include/lib/el3_runtime/cpu_data.h new file mode 100644 index 00000000..54261358 --- /dev/null +++ b/drivers/rz/ipl/rza/include/lib/el3_runtime/cpu_data.h @@ -0,0 +1,188 @@ +/* + * Copyright (c) 2014-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CPU_DATA_H +#define CPU_DATA_H + +#include /* CACHE_WRITEBACK_GRANULE required */ + +#include + +/* Size of psci_cpu_data structure */ +#define PSCI_CPU_DATA_SIZE 12 + +#ifdef __aarch64__ + +/* 8-bytes aligned size of psci_cpu_data structure */ +#define PSCI_CPU_DATA_SIZE_ALIGNED ((PSCI_CPU_DATA_SIZE + 7) & ~7) + +/* Offset of cpu_ops_ptr, size 8 bytes */ +#define CPU_DATA_CPU_OPS_PTR 0x10 + +#if ENABLE_PAUTH +/* 8-bytes aligned offset of apiakey[2], size 16 bytes */ +#define CPU_DATA_APIAKEY_OFFSET (0x18 + PSCI_CPU_DATA_SIZE_ALIGNED) +#define CPU_DATA_CRASH_BUF_OFFSET (CPU_DATA_APIAKEY_OFFSET + 0x10) +#else +#define CPU_DATA_CRASH_BUF_OFFSET (0x18 + PSCI_CPU_DATA_SIZE_ALIGNED) +#endif /* ENABLE_PAUTH */ + +/* need enough space in crash buffer to save 8 registers */ +#define CPU_DATA_CRASH_BUF_SIZE 64 + +#else /* !__aarch64__ */ + +#if CRASH_REPORTING +#error "Crash reporting is not supported in AArch32" +#endif +#define CPU_DATA_CPU_OPS_PTR 0x0 +#define CPU_DATA_CRASH_BUF_OFFSET (0x4 + PSCI_CPU_DATA_SIZE) + +#endif /* __aarch64__ */ + +#if CRASH_REPORTING +#define CPU_DATA_CRASH_BUF_END (CPU_DATA_CRASH_BUF_OFFSET + \ + CPU_DATA_CRASH_BUF_SIZE) +#else +#define CPU_DATA_CRASH_BUF_END CPU_DATA_CRASH_BUF_OFFSET +#endif + +/* cpu_data size is the data size rounded up to the platform cache line size */ +#define CPU_DATA_SIZE (((CPU_DATA_CRASH_BUF_END + \ + CACHE_WRITEBACK_GRANULE - 1) / \ + CACHE_WRITEBACK_GRANULE) * \ + CACHE_WRITEBACK_GRANULE) + +#if ENABLE_RUNTIME_INSTRUMENTATION +/* Temporary space to store PMF timestamps from assembly code */ +#define CPU_DATA_PMF_TS_COUNT 1 +#define CPU_DATA_PMF_TS0_OFFSET CPU_DATA_CRASH_BUF_END +#define CPU_DATA_PMF_TS0_IDX 0 +#endif + +#ifndef __ASSEMBLER__ + +#include +#include +#include +#include +#include + +/* Offsets for the cpu_data structure */ +#define CPU_DATA_PSCI_LOCK_OFFSET __builtin_offsetof\ + (cpu_data_t, psci_svc_cpu_data.pcpu_bakery_info) + +#if PLAT_PCPU_DATA_SIZE +#define CPU_DATA_PLAT_PCPU_OFFSET __builtin_offsetof\ + (cpu_data_t, platform_cpu_data) +#endif + +/******************************************************************************* + * Function & variable prototypes + ******************************************************************************/ + +/******************************************************************************* + * Cache of frequently used per-cpu data: + * Pointers to non-secure and secure security state contexts + * Address of the crash stack + * It is aligned to the cache line boundary to allow efficient concurrent + * manipulation of these pointers on different cpus + * + * TODO: Add other commonly used variables to this (tf_issues#90) + * + * The data structure and the _cpu_data accessors should not be used directly + * by components that have per-cpu members. The member access macros should be + * used for this. + ******************************************************************************/ +typedef struct cpu_data { +#ifdef __aarch64__ + void *cpu_context[2]; +#endif + uintptr_t cpu_ops_ptr; + struct psci_cpu_data psci_svc_cpu_data; +#if ENABLE_PAUTH + uint64_t apiakey[2]; +#endif +#if CRASH_REPORTING + u_register_t crash_buf[CPU_DATA_CRASH_BUF_SIZE >> 3]; +#endif +#if ENABLE_RUNTIME_INSTRUMENTATION + uint64_t cpu_data_pmf_ts[CPU_DATA_PMF_TS_COUNT]; +#endif +#if PLAT_PCPU_DATA_SIZE + uint8_t platform_cpu_data[PLAT_PCPU_DATA_SIZE]; +#endif +#if defined(IMAGE_BL31) && EL3_EXCEPTION_HANDLING + pe_exc_data_t ehf_data; +#endif +} __aligned(CACHE_WRITEBACK_GRANULE) cpu_data_t; + +extern cpu_data_t percpu_data[PLATFORM_CORE_COUNT]; + +#if ENABLE_PAUTH +CASSERT(CPU_DATA_APIAKEY_OFFSET == __builtin_offsetof + (cpu_data_t, apiakey), + assert_cpu_data_crash_stack_offset_mismatch); +#endif + +#if CRASH_REPORTING +/* verify assembler offsets match data structures */ +CASSERT(CPU_DATA_CRASH_BUF_OFFSET == __builtin_offsetof + (cpu_data_t, crash_buf), + assert_cpu_data_crash_stack_offset_mismatch); +#endif + +CASSERT(CPU_DATA_SIZE == sizeof(cpu_data_t), + assert_cpu_data_size_mismatch); + +CASSERT(CPU_DATA_CPU_OPS_PTR == __builtin_offsetof + (cpu_data_t, cpu_ops_ptr), + assert_cpu_data_cpu_ops_ptr_offset_mismatch); + +#if ENABLE_RUNTIME_INSTRUMENTATION +CASSERT(CPU_DATA_PMF_TS0_OFFSET == __builtin_offsetof + (cpu_data_t, cpu_data_pmf_ts[0]), + assert_cpu_data_pmf_ts0_offset_mismatch); +#endif + +struct cpu_data *_cpu_data_by_index(uint32_t cpu_index); + +#ifdef __aarch64__ +/* Return the cpu_data structure for the current CPU. */ +static inline struct cpu_data *_cpu_data(void) +{ + return (cpu_data_t *)read_tpidr_el3(); +} +#else +struct cpu_data *_cpu_data(void); +#endif + +/************************************************************************** + * APIs for initialising and accessing per-cpu data + *************************************************************************/ + +void init_cpu_data_ptr(void); +void init_cpu_ops(void); + +#define get_cpu_data(_m) _cpu_data()->_m +#define set_cpu_data(_m, _v) _cpu_data()->_m = (_v) +#define get_cpu_data_by_index(_ix, _m) _cpu_data_by_index(_ix)->_m +#define set_cpu_data_by_index(_ix, _m, _v) _cpu_data_by_index(_ix)->_m = (_v) +/* ((cpu_data_t *)0)->_m is a dummy to get the sizeof the struct member _m */ +#define flush_cpu_data(_m) flush_dcache_range((uintptr_t) \ + &(_cpu_data()->_m), \ + sizeof(((cpu_data_t *)0)->_m)) +#define inv_cpu_data(_m) inv_dcache_range((uintptr_t) \ + &(_cpu_data()->_m), \ + sizeof(((cpu_data_t *)0)->_m)) +#define flush_cpu_data_by_index(_ix, _m) \ + flush_dcache_range((uintptr_t) \ + &(_cpu_data_by_index(_ix)->_m), \ + sizeof(((cpu_data_t *)0)->_m)) + + +#endif /* __ASSEMBLER__ */ +#endif /* CPU_DATA_H */ diff --git a/drivers/rz/ipl/rza/include/lib/el3_runtime/pubsub.h b/drivers/rz/ipl/rza/include/lib/el3_runtime/pubsub.h new file mode 100644 index 00000000..64fe5ccb --- /dev/null +++ b/drivers/rz/ipl/rza/include/lib/el3_runtime/pubsub.h @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PUBSUB_H +#define PUBSUB_H + +#ifdef __LINKER__ + +/* For the linker ... */ +#define __pubsub_start_sym(event) __pubsub_##event##_start +#define __pubsub_end_sym(event) __pubsub_##event##_end +#define __pubsub_section(event) __pubsub_##event + +/* + * REGISTER_PUBSUB_EVENT has a different definition between linker and compiler + * contexts. In linker context, this collects pubsub sections for each event, + * placing guard symbols around each. + */ +#if defined(USE_ARM_LINK) +#define REGISTER_PUBSUB_EVENT(event) \ + __pubsub_start_sym(event) +0 FIXED \ + { \ + *(__pubsub_section(event)) \ + } \ + __pubsub_end_sym(event) +0 FIXED EMPTY 0 \ + { \ + /* placeholder */ \ + } +#else +#define REGISTER_PUBSUB_EVENT(event) \ + __pubsub_start_sym(event) = .; \ + KEEP(*(__pubsub_section(event))); \ + __pubsub_end_sym(event) = . +#endif + +#else /* __LINKER__ */ + +/* For the compiler ... */ + +#include +#include +#include + +#include + +#if defined(USE_ARM_LINK) +#define __pubsub_start_sym(event) Load$$__pubsub_##event##_start$$Base +#define __pubsub_end_sym(event) Load$$__pubsub_##event##_end$$Base +#else +#define __pubsub_start_sym(event) __pubsub_##event##_start +#define __pubsub_end_sym(event) __pubsub_##event##_end +#endif + +#define __pubsub_section(event) __section("__pubsub_" #event) + +/* + * In compiler context, REGISTER_PUBSUB_EVENT declares the per-event symbols + * exported by the linker required for the other pubsub macros to work. + */ +#define REGISTER_PUBSUB_EVENT(event) \ + extern pubsub_cb_t __pubsub_start_sym(event)[]; \ + extern pubsub_cb_t __pubsub_end_sym(event)[] + +/* + * Have the function func called back when the specified event happens. This + * macro places the function address into the pubsub section, which is picked up + * and invoked by the invoke_pubsubs() function via the PUBLISH_EVENT* macros. + * + * The extern declaration is there to satisfy MISRA C-2012 rule 8.4. + */ +#define SUBSCRIBE_TO_EVENT(event, func) \ + extern pubsub_cb_t __cb_func_##func##event __pubsub_section(event); \ + pubsub_cb_t __cb_func_##func##event __pubsub_section(event) = (func) + +/* + * Iterate over subscribed handlers for a defined event. 'event' is the name of + * the event, and 'subscriber' a local variable of type 'pubsub_cb_t *'. + */ +#define for_each_subscriber(event, subscriber) \ + for (subscriber = __pubsub_start_sym(event); \ + subscriber < __pubsub_end_sym(event); \ + subscriber++) + +/* + * Publish a defined event supplying an argument. All subscribed handlers are + * invoked, but the return value of handlers are ignored for now. + */ +#define PUBLISH_EVENT_ARG(event, arg) \ + do { \ + pubsub_cb_t *subscriber; \ + for_each_subscriber(event, subscriber) { \ + (*subscriber)(arg); \ + } \ + } while (0) + +/* Publish a defined event with NULL argument */ +#define PUBLISH_EVENT(event) PUBLISH_EVENT_ARG(event, NULL) + +/* Subscriber callback type */ +typedef void* (*pubsub_cb_t)(const void *arg); + +#endif /* __LINKER__ */ +#endif /* PUBSUB_H */ diff --git a/drivers/rz/ipl/rza/include/lib/el3_runtime/pubsub_events.h b/drivers/rz/ipl/rza/include/lib/el3_runtime/pubsub_events.h new file mode 100644 index 00000000..50120826 --- /dev/null +++ b/drivers/rz/ipl/rza/include/lib/el3_runtime/pubsub_events.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +/* + * This file defines a list of pubsub events, declared using + * REGISTER_PUBSUB_EVENT() macro. + */ + +/* + * Event published after a CPU has been powered up and finished its + * initialization. + */ +REGISTER_PUBSUB_EVENT(psci_cpu_on_finish); + +/* + * These events are published before/after a CPU has been powered down/up + * via the PSCI CPU SUSPEND API. + */ +REGISTER_PUBSUB_EVENT(psci_suspend_pwrdown_start); +REGISTER_PUBSUB_EVENT(psci_suspend_pwrdown_finish); + +#ifdef __aarch64__ +/* + * These events are published by the AArch64 context management framework + * after the secure context is restored/saved via + * cm_el1_sysregs_context_{restore,save}() API. + */ +REGISTER_PUBSUB_EVENT(cm_entering_secure_world); +REGISTER_PUBSUB_EVENT(cm_exited_secure_world); + +/* + * These events are published by the AArch64 context management framework + * after the normal context is restored/saved via + * cm_el1_sysregs_context_{restore,save}() API. + */ +REGISTER_PUBSUB_EVENT(cm_entering_normal_world); +REGISTER_PUBSUB_EVENT(cm_exited_normal_world); +#endif /* __aarch64__ */ diff --git a/drivers/rz/ipl/rza/include/lib/extensions/amu.h b/drivers/rz/ipl/rza/include/lib/extensions/amu.h new file mode 100644 index 00000000..3a70e4ff --- /dev/null +++ b/drivers/rz/ipl/rza/include/lib/extensions/amu.h @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef AMU_H +#define AMU_H + +#include +#include + +#include +#include + +#include + +/* All group 0 counters */ +#define AMU_GROUP0_COUNTERS_MASK U(0xf) +#define AMU_GROUP0_NR_COUNTERS U(4) + +#ifdef PLAT_AMU_GROUP1_COUNTERS_MASK +#define AMU_GROUP1_COUNTERS_MASK PLAT_AMU_GROUP1_COUNTERS_MASK +#else +#define AMU_GROUP1_COUNTERS_MASK U(0) +#endif + +/* Calculate number of group 1 counters */ +#if (AMU_GROUP1_COUNTERS_MASK & (1 << 15)) +#define AMU_GROUP1_NR_COUNTERS 16U +#elif (AMU_GROUP1_COUNTERS_MASK & (1 << 14)) +#define AMU_GROUP1_NR_COUNTERS 15U +#elif (AMU_GROUP1_COUNTERS_MASK & (1 << 13)) +#define AMU_GROUP1_NR_COUNTERS 14U +#elif (AMU_GROUP1_COUNTERS_MASK & (1 << 12)) +#define AMU_GROUP1_NR_COUNTERS 13U +#elif (AMU_GROUP1_COUNTERS_MASK & (1 << 11)) +#define AMU_GROUP1_NR_COUNTERS 12U +#elif (AMU_GROUP1_COUNTERS_MASK & (1 << 10)) +#define AMU_GROUP1_NR_COUNTERS 11U +#elif (AMU_GROUP1_COUNTERS_MASK & (1 << 9)) +#define AMU_GROUP1_NR_COUNTERS 10U +#elif (AMU_GROUP1_COUNTERS_MASK & (1 << 8)) +#define AMU_GROUP1_NR_COUNTERS 9U +#elif (AMU_GROUP1_COUNTERS_MASK & (1 << 7)) +#define AMU_GROUP1_NR_COUNTERS 8U +#elif (AMU_GROUP1_COUNTERS_MASK & (1 << 6)) +#define AMU_GROUP1_NR_COUNTERS 7U +#elif (AMU_GROUP1_COUNTERS_MASK & (1 << 5)) +#define AMU_GROUP1_NR_COUNTERS 6U +#elif (AMU_GROUP1_COUNTERS_MASK & (1 << 4)) +#define AMU_GROUP1_NR_COUNTERS 5U +#elif (AMU_GROUP1_COUNTERS_MASK & (1 << 3)) +#define AMU_GROUP1_NR_COUNTERS 4U +#elif (AMU_GROUP1_COUNTERS_MASK & (1 << 2)) +#define AMU_GROUP1_NR_COUNTERS 3U +#elif (AMU_GROUP1_COUNTERS_MASK & (1 << 1)) +#define AMU_GROUP1_NR_COUNTERS 2U +#elif (AMU_GROUP1_COUNTERS_MASK & (1 << 0)) +#define AMU_GROUP1_NR_COUNTERS 1U +#else +#define AMU_GROUP1_NR_COUNTERS 0U +#endif + +CASSERT(AMU_GROUP1_COUNTERS_MASK <= 0xffff, invalid_amu_group1_counters_mask); + +struct amu_ctx { + uint64_t group0_cnts[AMU_GROUP0_NR_COUNTERS]; +#if __aarch64__ + /* Architected event counter 1 does not have an offset register. */ + uint64_t group0_voffsets[AMU_GROUP0_NR_COUNTERS-1]; +#endif + +#if AMU_GROUP1_NR_COUNTERS + uint64_t group1_cnts[AMU_GROUP1_NR_COUNTERS]; +#if __aarch64__ + uint64_t group1_voffsets[AMU_GROUP1_NR_COUNTERS]; +#endif +#endif +}; + +unsigned int amu_get_version(void); +void amu_enable(bool el2_unused); + +/* Group 0 configuration helpers */ +uint64_t amu_group0_cnt_read(unsigned int idx); +void amu_group0_cnt_write(unsigned int idx, uint64_t val); + +#if __aarch64__ +uint64_t amu_group0_voffset_read(unsigned int idx); +void amu_group0_voffset_write(unsigned int idx, uint64_t val); +#endif + +#if AMU_GROUP1_NR_COUNTERS +bool amu_group1_supported(void); + +/* Group 1 configuration helpers */ +uint64_t amu_group1_cnt_read(unsigned int idx); +void amu_group1_cnt_write(unsigned int idx, uint64_t val); +void amu_group1_set_evtype(unsigned int idx, unsigned int val); + +#if __aarch64__ +uint64_t amu_group1_voffset_read(unsigned int idx); +void amu_group1_voffset_write(unsigned int idx, uint64_t val); +#endif + +#endif + +#endif /* AMU_H */ diff --git a/drivers/rz/ipl/rza/include/lib/extensions/amu_private.h b/drivers/rz/ipl/rza/include/lib/extensions/amu_private.h new file mode 100644 index 00000000..3b4b47ca --- /dev/null +++ b/drivers/rz/ipl/rza/include/lib/extensions/amu_private.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef AMU_PRIVATE_H +#define AMU_PRIVATE_H + +#include + +uint64_t amu_group0_cnt_read_internal(unsigned int idx); +void amu_group0_cnt_write_internal(unsigned int idx, uint64_t val); + +uint64_t amu_group1_cnt_read_internal(unsigned int idx); +void amu_group1_cnt_write_internal(unsigned int idx, uint64_t val); +void amu_group1_set_evtype_internal(unsigned int idx, unsigned int val); + +#if __aarch64__ +uint64_t amu_group0_voffset_read_internal(unsigned int idx); +void amu_group0_voffset_write_internal(unsigned int idx, uint64_t val); + +uint64_t amu_group1_voffset_read_internal(unsigned int idx); +void amu_group1_voffset_write_internal(unsigned int idx, uint64_t val); +#endif + +#endif /* AMU_PRIVATE_H */ diff --git a/drivers/rz/ipl/rza/include/lib/extensions/mpam.h b/drivers/rz/ipl/rza/include/lib/extensions/mpam.h new file mode 100644 index 00000000..ac8c00a4 --- /dev/null +++ b/drivers/rz/ipl/rza/include/lib/extensions/mpam.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MPAM_H +#define MPAM_H + +#include + +bool mpam_supported(void); +void mpam_enable(bool el2_unused); + +#endif /* MPAM_H */ diff --git a/drivers/rz/ipl/rza/include/lib/extensions/pauth.h b/drivers/rz/ipl/rza/include/lib/extensions/pauth.h new file mode 100644 index 00000000..2e780dec --- /dev/null +++ b/drivers/rz/ipl/rza/include/lib/extensions/pauth.h @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PAUTH_H +#define PAUTH_H + +/******************************************************************************* + * ARMv8.3-PAuth support functions + ******************************************************************************/ + +/* Disable ARMv8.3 pointer authentication in EL1/EL3 */ +void pauth_disable_el1(void); +void pauth_disable_el3(void); + +#endif /* PAUTH_H */ diff --git a/drivers/rz/ipl/rza/include/lib/extensions/ras.h b/drivers/rz/ipl/rza/include/lib/extensions/ras.h new file mode 100644 index 00000000..793ab9fa --- /dev/null +++ b/drivers/rz/ipl/rza/include/lib/extensions/ras.h @@ -0,0 +1,203 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2020, NVIDIA Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef RAS_H +#define RAS_H + +#define ERR_HANDLER_VERSION 1U + +/* Error record access mechanism */ +#define ERR_ACCESS_SYSREG 0 +#define ERR_ACCESS_MEMMAP 1 + +/* + * Register all error records on the platform. + * + * This macro must be used in the same file as the array of error record info + * are declared. Only then would ARRAY_SIZE() yield a meaningful value. + */ +#define REGISTER_ERR_RECORD_INFO(_records) \ + const struct err_record_mapping err_record_mappings = { \ + .err_records = (_records), \ + .num_err_records = ARRAY_SIZE(_records), \ + } + +/* Error record info iterator */ +#define for_each_err_record_info(_i, _info) \ + for ((_i) = 0, (_info) = err_record_mappings.err_records; \ + (_i) < err_record_mappings.num_err_records; \ + (_i)++, (_info)++) + +#define ERR_RECORD_COMMON_(_probe, _handler, _aux) \ + .probe = _probe, \ + .handler = _handler, \ + .aux_data = _aux, + +#define ERR_RECORD_SYSREG_V1(_idx_start, _num_idx, _probe, _handler, _aux) \ + { \ + .version = 1, \ + .sysreg.idx_start = _idx_start, \ + .sysreg.num_idx = _num_idx, \ + .access = ERR_ACCESS_SYSREG, \ + ERR_RECORD_COMMON_(_probe, _handler, _aux) \ + } + +#define ERR_RECORD_MEMMAP_V1(_base_addr, _size_num_k, _probe, _handler, _aux) \ + { \ + .version = 1, \ + .memmap.base_addr = _base_addr, \ + .memmap.size_num_k = _size_num_k, \ + .access = ERR_ACCESS_MEMMAP, \ + ERR_RECORD_COMMON_(_probe, _handler, _aux) \ + } + +/* + * Macro to be used to name and declare an array of RAS interrupts along with + * their handlers. + * + * This macro must be used in the same file as the array of interrupts are + * declared. Only then would ARRAY_SIZE() yield a meaningful value. Also, the + * array is expected to be sorted in the increasing order of interrupt number. + */ +#define REGISTER_RAS_INTERRUPTS(_array) \ + const struct ras_interrupt_mapping ras_interrupt_mappings = { \ + .intrs = (_array), \ + .num_intrs = ARRAY_SIZE(_array), \ + } + +#ifndef __ASSEMBLER__ + +#include + +#include + +struct err_record_info; + +struct ras_interrupt { + /* Interrupt number, and the associated error record info */ + unsigned int intr_number; + struct err_record_info *err_record; + void *cookie; +}; + +/* Function to probe a error record group for error */ +typedef int (*err_record_probe_t)(const struct err_record_info *info, + int *probe_data); + +/* Data passed to error record group handler */ +struct err_handler_data { + /* Info passed on from top-level exception handler */ + uint64_t flags; + void *cookie; + void *handle; + + /* Data structure version */ + unsigned int version; + + /* Reason for EA: one the ERROR_* constants */ + unsigned int ea_reason; + + /* + * For EAs received at vector, the value read from ESR; for an EA + * synchronized by ESB, the value of DISR. + */ + uint32_t syndrome; + + /* For errors signalled via interrupt, the raw interrupt ID; otherwise, 0. */ + unsigned int interrupt; +}; + +/* Function to handle error from an error record group */ +typedef int (*err_record_handler_t)(const struct err_record_info *info, + int probe_data, const struct err_handler_data *const data); + +/* Error record information */ +struct err_record_info { + /* Function to probe error record group for errors */ + err_record_probe_t probe; + + /* Function to handle error record group errors */ + err_record_handler_t handler; + + /* Opaque group-specific data */ + void *aux_data; + + /* Additional information for Standard Error Records */ + union { + struct { + /* + * For a group accessed via memory-mapped register, + * base address of the page hosting error records, and + * the size of the record group. + */ + uintptr_t base_addr; + + /* Size of group in number of KBs */ + unsigned int size_num_k; + } memmap; + + struct { + /* + * For error records accessed via system register, index of + * the error record. + */ + unsigned int idx_start; + unsigned int num_idx; + } sysreg; + }; + + /* Data structure version */ + unsigned int version; + + /* Error record access mechanism */ + unsigned int access:1; +}; + +struct err_record_mapping { + struct err_record_info *err_records; + size_t num_err_records; +}; + +struct ras_interrupt_mapping { + struct ras_interrupt *intrs; + size_t num_intrs; +}; + +extern const struct err_record_mapping err_record_mappings; +extern const struct ras_interrupt_mapping ras_interrupt_mappings; + + +/* + * Helper functions to probe memory-mapped and system registers implemented in + * Standard Error Record format + */ +static inline int ras_err_ser_probe_memmap(const struct err_record_info *info, + int *probe_data) +{ + assert(info->version == ERR_HANDLER_VERSION); + + return ser_probe_memmap(info->memmap.base_addr, info->memmap.size_num_k, + probe_data); +} + +static inline int ras_err_ser_probe_sysreg(const struct err_record_info *info, + int *probe_data) +{ + assert(info->version == ERR_HANDLER_VERSION); + + return ser_probe_sysreg(info->sysreg.idx_start, info->sysreg.num_idx, + probe_data); +} + +const char *ras_serr_to_str(unsigned int serr); +int ras_ea_handler(unsigned int ea_reason, uint64_t syndrome, void *cookie, + void *handle, uint64_t flags); +void ras_init(void); + +#endif /* __ASSEMBLER__ */ + +#endif /* RAS_H */ diff --git a/drivers/rz/ipl/rza/include/lib/extensions/ras_arch.h b/drivers/rz/ipl/rza/include/lib/extensions/ras_arch.h new file mode 100644 index 00000000..55760b06 --- /dev/null +++ b/drivers/rz/ipl/rza/include/lib/extensions/ras_arch.h @@ -0,0 +1,265 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2020, NVIDIA Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef RAS_ARCH_H +#define RAS_ARCH_H + +/* + * Size of nodes implementing Standard Error Records - currently only 4k is + * supported. + */ +#define STD_ERR_NODE_SIZE_NUM_K 4U + +/* + * Individual register offsets within an error record in Standard Error Record + * format when error records are accessed through memory-mapped registers. + */ +#define ERR_FR(n) (0x0ULL + (64ULL * (n))) +#define ERR_CTLR(n) (0x8ULL + (64ULL * (n))) +#define ERR_STATUS(n) (0x10ULL + (64ULL * (n))) +#define ERR_ADDR(n) (0x18ULL + (64ULL * (n))) +#define ERR_MISC0(n) (0x20ULL + (64ULL * (n))) +#define ERR_MISC1(n) (0x28ULL + (64ULL * (n))) + +/* Group Status Register (ERR_STATUS) offset */ +#define ERR_GSR(base, size_num_k, n) \ + ((base) + (0x380ULL * (size_num_k)) + (8ULL * (n))) + +/* Management register offsets */ +#define ERR_DEVID(base, size_num_k) \ + ((base) + ((0x400ULL * (size_num_k)) - 0x100ULL) + 0xc8ULL) + +#define ERR_DEVID_MASK 0xffffUL + +/* Standard Error Record status register fields */ +#define ERR_STATUS_AV_SHIFT 31 +#define ERR_STATUS_AV_MASK U(0x1) + +#define ERR_STATUS_V_SHIFT 30 +#define ERR_STATUS_V_MASK U(0x1) + +#define ERR_STATUS_UE_SHIFT 29 +#define ERR_STATUS_UE_MASK U(0x1) + +#define ERR_STATUS_ER_SHIFT 28 +#define ERR_STATUS_ER_MASK U(0x1) + +#define ERR_STATUS_OF_SHIFT 27 +#define ERR_STATUS_OF_MASK U(0x1) + +#define ERR_STATUS_MV_SHIFT 26 +#define ERR_STATUS_MV_MASK U(0x1) + +#define ERR_STATUS_CE_SHIFT 24 +#define ERR_STATUS_CE_MASK U(0x3) + +#define ERR_STATUS_DE_SHIFT 23 +#define ERR_STATUS_DE_MASK U(0x1) + +#define ERR_STATUS_PN_SHIFT 22 +#define ERR_STATUS_PN_MASK U(0x1) + +#define ERR_STATUS_UET_SHIFT 20 +#define ERR_STATUS_UET_MASK U(0x3) + +#define ERR_STATUS_IERR_SHIFT 8 +#define ERR_STATUS_IERR_MASK U(0xff) + +#define ERR_STATUS_SERR_SHIFT 0 +#define ERR_STATUS_SERR_MASK U(0xff) + +#define ERR_STATUS_GET_FIELD(_status, _field) \ + (((_status) >> ERR_STATUS_ ##_field ##_SHIFT) & ERR_STATUS_ ##_field ##_MASK) + +#define ERR_STATUS_CLR_FIELD(_status, _field) \ + (_status) &= ~(ERR_STATUS_ ##_field ##_MASK << ERR_STATUS_ ##_field ##_SHIFT) + +#define ERR_STATUS_SET_FIELD(_status, _field, _value) \ + (_status) |= (((_value) & ERR_STATUS_ ##_field ##_MASK) << ERR_STATUS_ ##_field ##_SHIFT) + +#define ERR_STATUS_WRITE_FIELD(_status, _field, _value) do { \ + ERR_STATUS_CLR_FIELD(_status, _field, _value); \ + ERR_STATUS_SET_FIELD(_status, _field, _value); \ + } while (0) + + +/* Standard Error Record control register fields */ +#define ERR_CTLR_WDUI_SHIFT 11 +#define ERR_CTLR_WDUI_MASK 0x1 + +#define ERR_CTLR_RDUI_SHIFT 10 +#define ERR_CTLR_RDUI_MASK 0x1 +#define ERR_CTLR_DUI_SHIFT ERR_CTLR_RDUI_SHIFT +#define ERR_CTLR_DUI_MASK ERR_CTLR_RDUI_MASK + +#define ERR_CTLR_WCFI_SHIFT 9 +#define ERR_CTLR_WCFI_MASK 0x1 + +#define ERR_CTLR_RCFI_SHIFT 8 +#define ERR_CTLR_RCFI_MASK 0x1 +#define ERR_CTLR_CFI_SHIFT ERR_CTLR_RCFI_SHIFT +#define ERR_CTLR_CFI_MASK ERR_CTLR_RCFI_MASK + +#define ERR_CTLR_WUE_SHIFT 7 +#define ERR_CTLR_WUE_MASK 0x1 + +#define ERR_CTLR_WFI_SHIFT 6 +#define ERR_CTLR_WFI_MASK 0x1 + +#define ERR_CTLR_WUI_SHIFT 5 +#define ERR_CTLR_WUI_MASK 0x1 + +#define ERR_CTLR_RUE_SHIFT 4 +#define ERR_CTLR_RUE_MASK 0x1 +#define ERR_CTLR_UE_SHIFT ERR_CTLR_RUE_SHIFT +#define ERR_CTLR_UE_MASK ERR_CTLR_RUE_MASK + +#define ERR_CTLR_RFI_SHIFT 3 +#define ERR_CTLR_RFI_MASK 0x1 +#define ERR_CTLR_FI_SHIFT ERR_CTLR_RFI_SHIFT +#define ERR_CTLR_FI_MASK ERR_CTLR_RFI_MASK + +#define ERR_CTLR_RUI_SHIFT 2 +#define ERR_CTLR_RUI_MASK 0x1 +#define ERR_CTLR_UI_SHIFT ERR_CTLR_RUI_SHIFT +#define ERR_CTLR_UI_MASK ERR_CTLR_RUI_MASK + +#define ERR_CTLR_ED_SHIFT 0 +#define ERR_CTLR_ED_MASK 0x1 + +#define ERR_CTLR_CLR_FIELD(_ctlr, _field) \ + (_ctlr) &= ~(ERR_CTLR_ ##_field _MASK << ERR_CTLR_ ##_field ##_SHIFT) + +#define ERR_CTLR_SET_FIELD(_ctlr, _field, _value) \ + (_ctlr) |= (((_value) & ERR_CTLR_ ##_field ##_MASK) << ERR_CTLR_ ##_field ##_SHIFT) + +#define ERR_CTLR_ENABLE_FIELD(_ctlr, _field) \ + ERR_CTLR_SET_FIELD(_ctlr, _field, ERR_CTLR_ ##_field ##_MASK) + +/* Uncorrected error types for Asynchronous exceptions */ +#define ERROR_STATUS_UET_UC 0x0 /* Uncontainable */ +#define ERROR_STATUS_UET_UEU 0x1 /* Unrecoverable */ +#define ERROR_STATUS_UET_UEO 0x2 /* Restable */ +#define ERROR_STATUS_UET_UER 0x3 /* Recoverable */ + +/* Error types for Synchronous exceptions */ +#define ERROR_STATUS_SET_UER 0x0 /* Recoverable */ +#define ERROR_STATUS_SET_UEO 0x1 /* Restable */ +#define ERROR_STATUS_SET_UC 0x2 /* Uncontainable */ +#define ERROR_STATUS_SET_CE 0x3 /* Corrected */ + +/* Number of architecturally-defined primary error codes */ +#define ERROR_STATUS_NUM_SERR U(22) + +/* Implementation Defined Syndrome bit in ESR */ +#define SERROR_IDS_BIT U(24) + +/* + * Asynchronous Error Type in exception syndrome. The field has same values in + * both DISR_EL1 and ESR_EL3 for SError. + */ +#define EABORT_AET_SHIFT U(10) +#define EABORT_AET_WIDTH U(3) +#define EABORT_AET_MASK U(0x7) + +/* DFSC field in Asynchronous exception syndrome */ +#define EABORT_DFSC_SHIFT U(0) +#define EABORT_DFSC_WIDTH U(6) +#define EABORT_DFSC_MASK U(0x3f) + +/* Synchronous Error Type in exception syndrome. */ +#define EABORT_SET_SHIFT U(11) +#define EABORT_SET_WIDTH U(2) +#define EABORT_SET_MASK U(0x3) + +/* DFSC code for SErrors */ +#define DFSC_SERROR 0x11 + +/* I/DFSC code for synchronous external abort */ +#define SYNC_EA_FSC 0x10 + +#ifndef __ASSEMBLER__ + +#include +#include +#include +#include +#include +#include + +/* + * Standard Error Record accessors for memory-mapped registers. + */ + +static inline uint64_t ser_get_feature(uintptr_t base, unsigned int idx) +{ + return mmio_read_64(base + ERR_FR(idx)); +} + +static inline uint64_t ser_get_control(uintptr_t base, unsigned int idx) +{ + return mmio_read_64(base + ERR_CTLR(idx)); +} + +static inline uint64_t ser_get_status(uintptr_t base, unsigned int idx) +{ + return mmio_read_64(base + ERR_STATUS(idx)); +} + +/* + * Error handling agent would write to the status register to clear an + * identified/handled error. Most fields in the status register are + * conditional write-one-to-clear. + * + * Typically, to clear the status, it suffices to write back the same value + * previously read. However, if there were new, higher-priority errors recorded + * on the node since status was last read, writing read value won't clear the + * status. Therefore, an error handling agent must wait on and verify the status + * has indeed been cleared. + */ +static inline void ser_set_status(uintptr_t base, unsigned int idx, + uint64_t status) +{ + mmio_write_64(base + ERR_STATUS(idx), status); +} + +static inline uint64_t ser_get_addr(uintptr_t base, unsigned int idx) +{ + return mmio_read_64(base + ERR_ADDR(idx)); +} + +static inline uint64_t ser_get_misc0(uintptr_t base, unsigned int idx) +{ + return mmio_read_64(base + ERR_MISC0(idx)); +} + +static inline uint64_t ser_get_misc1(uintptr_t base, unsigned int idx) +{ + return mmio_read_64(base + ERR_MISC1(idx)); +} + + +/* + * Standard Error Record helpers for System registers. + */ +static inline void ser_sys_select_record(unsigned int idx) +{ + unsigned int max_idx __unused = + (unsigned int) read_erridr_el1() & ERRIDR_MASK; + + assert(idx < max_idx); + + write_errselr_el1(idx); + isb(); +} + +/* Library functions to probe Standard Error Record */ +int ser_probe_memmap(uintptr_t base, unsigned int size_num_k, int *probe_data); +int ser_probe_sysreg(unsigned int idx_start, unsigned int num_idx, int *probe_data); +#endif /* __ASSEMBLER__ */ + +#endif /* RAS_ARCH_H */ diff --git a/drivers/rz/ipl/rza/include/lib/extensions/spe.h b/drivers/rz/ipl/rza/include/lib/extensions/spe.h new file mode 100644 index 00000000..d4b925fe --- /dev/null +++ b/drivers/rz/ipl/rza/include/lib/extensions/spe.h @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SPE_H +#define SPE_H + +#include + +bool spe_supported(void); +void spe_enable(bool el2_unused); +void spe_disable(void); + +#endif /* SPE_H */ diff --git a/drivers/rz/ipl/rza/include/lib/extensions/sve.h b/drivers/rz/ipl/rza/include/lib/extensions/sve.h new file mode 100644 index 00000000..83df1775 --- /dev/null +++ b/drivers/rz/ipl/rza/include/lib/extensions/sve.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SVE_H +#define SVE_H + +#include + +bool sve_supported(void); +void sve_enable(bool el2_unused); + +#endif /* SVE_H */ diff --git a/drivers/rz/ipl/rza/include/lib/extensions/twed.h b/drivers/rz/ipl/rza/include/lib/extensions/twed.h new file mode 100644 index 00000000..eac4aa31 --- /dev/null +++ b/drivers/rz/ipl/rza/include/lib/extensions/twed.h @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TWED_H +#define TWED_H + +#include + +#define TWED_DISABLED U(0xFFFFFFFF) + +uint32_t plat_arm_set_twedel_scr_el3(void); + +#endif /* TWEDE_H */ diff --git a/drivers/rz/ipl/rza/include/lib/libc/aarch64/endian_.h b/drivers/rz/ipl/rza/include/lib/libc/aarch64/endian_.h new file mode 100644 index 00000000..7c79fd43 --- /dev/null +++ b/drivers/rz/ipl/rza/include/lib/libc/aarch64/endian_.h @@ -0,0 +1,128 @@ +/*- + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright (c) 2001 David E. O'Brien + * + * 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 of the University 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 REGENTS 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 REGENTS 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. + * + * @(#)endian.h 8.1 (Berkeley) 6/10/93 + * $NetBSD: endian.h,v 1.7 1999/08/21 05:53:51 simonb Exp $ + * $FreeBSD$ + */ +/* + * Portions copyright (c) 2018, ARM Limited and Contributors. + * All rights reserved. + */ + +#ifndef ENDIAN__H +#define ENDIAN__H + +#include + +/* + * Definitions for byte order, according to byte significance from low + * address to high. + */ +#define _LITTLE_ENDIAN 1234 /* LSB first: i386, vax */ +#define _BIG_ENDIAN 4321 /* MSB first: 68000, ibm, net */ +#define _PDP_ENDIAN 3412 /* LSB first in word, MSW first in long */ + +#define _BYTE_ORDER _LITTLE_ENDIAN + +#if __BSD_VISIBLE +#define LITTLE_ENDIAN _LITTLE_ENDIAN +#define BIG_ENDIAN _BIG_ENDIAN +#define PDP_ENDIAN _PDP_ENDIAN +#define BYTE_ORDER _BYTE_ORDER +#endif + +#define _QUAD_HIGHWORD 1 +#define _QUAD_LOWWORD 0 +#define __ntohl(x) (__bswap32(x)) +#define __ntohs(x) (__bswap16(x)) +#define __htonl(x) (__bswap32(x)) +#define __htons(x) (__bswap16(x)) + +static __inline uint64_t +__bswap64(uint64_t x) +{ + uint64_t ret; + + __asm __volatile("rev %0, %1\n" + : "=&r" (ret), "+r" (x)); + + return (ret); +} + +static __inline uint32_t +__bswap32_var(uint32_t v) +{ + uint32_t ret; + + __asm __volatile("rev32 %x0, %x1\n" + : "=&r" (ret), "+r" (v)); + + return (ret); +} + +static __inline uint16_t +__bswap16_var(uint16_t v) +{ + uint32_t ret; + + __asm __volatile("rev16 %w0, %w1\n" + : "=&r" (ret), "+r" (v)); + + return ((uint16_t)ret); +} + +#ifdef __OPTIMIZE__ + +#define __bswap32_constant(x) \ + ((((x) & 0xff000000U) >> 24) | \ + (((x) & 0x00ff0000U) >> 8) | \ + (((x) & 0x0000ff00U) << 8) | \ + (((x) & 0x000000ffU) << 24)) + +#define __bswap16_constant(x) \ + ((((x) & 0xff00) >> 8) | \ + (((x) & 0x00ff) << 8)) + +#define __bswap16(x) \ + ((uint16_t)(__builtin_constant_p(x) ? \ + __bswap16_constant((uint16_t)(x)) : \ + __bswap16_var(x))) + +#define __bswap32(x) \ + ((uint32_t)(__builtin_constant_p(x) ? \ + __bswap32_constant((uint32_t)(x)) : \ + __bswap32_var(x))) + +#else +#define __bswap16(x) __bswap16_var(x) +#define __bswap32(x) __bswap32_var(x) + +#endif /* __OPTIMIZE__ */ +#endif /* ENDIAN__H */ diff --git a/drivers/rz/ipl/rza/include/lib/libc/aarch64/limits_.h b/drivers/rz/ipl/rza/include/lib/libc/aarch64/limits_.h new file mode 100644 index 00000000..e36cfe7d --- /dev/null +++ b/drivers/rz/ipl/rza/include/lib/libc/aarch64/limits_.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#define SCHAR_MAX 0x7F +#define SCHAR_MIN (-SCHAR_MIN - 1) +#define CHAR_MAX 0x7F +#define CHAR_MIN (-CHAR_MAX - 1) +#define UCHAR_MAX 0xFFU +#define SHRT_MAX 0x7FFF +#define SHRT_MIN (-SHRT_MAX - 1) +#define USHRT_MAX 0xFFFFU +#define INT_MAX 0x7FFFFFFF +#define INT_MIN (-INT_MAX - 1) +#define UINT_MAX 0xFFFFFFFFU +#define LONG_MAX 0x7FFFFFFFFFFFFFFFL +#define LONG_MIN (-LONG_MAX - 1L) +#define ULONG_MAX 0xFFFFFFFFFFFFFFFFUL +#define LLONG_MAX 0x7FFFFFFFFFFFFFFFLL +#define LLONG_MIN (-LLONG_MAX - 1LL) +#define ULLONG_MAX 0xFFFFFFFFFFFFFFFFULL + +#define __LONG_BIT 64 +#define __WORD_BIT 32 diff --git a/drivers/rz/ipl/rza/include/lib/libc/aarch64/setjmp_.h b/drivers/rz/ipl/rza/include/lib/libc/aarch64/setjmp_.h new file mode 100644 index 00000000..f880a17b --- /dev/null +++ b/drivers/rz/ipl/rza/include/lib/libc/aarch64/setjmp_.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SETJMP__H +#define SETJMP__H + +#define JMP_CTX_X19 0x0 +#define JMP_CTX_X21 0x10 +#define JMP_CTX_X23 0x20 +#define JMP_CTX_X25 0x30 +#define JMP_CTX_X27 0x40 +#define JMP_CTX_X29 0x50 +#define JMP_CTX_SP 0x60 +#define JMP_CTX_END 0x70 /* Aligned to 16 bytes */ + +#define JMP_SIZE (JMP_CTX_END >> 3) + +#ifndef __ASSEMBLER__ + +#include + +/* Jump buffer hosting x18 - x30 and sp_el0 registers */ +typedef uint64_t jmp_buf[JMP_SIZE] __aligned(16); + +#endif /* __ASSEMBLER__ */ + +#endif /* SETJMP__H */ diff --git a/drivers/rz/ipl/rza/include/lib/libc/aarch64/stddef_.h b/drivers/rz/ipl/rza/include/lib/libc/aarch64/stddef_.h new file mode 100644 index 00000000..6ecc6067 --- /dev/null +++ b/drivers/rz/ipl/rza/include/lib/libc/aarch64/stddef_.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef STDDEF__H +#define STDDEF__H + +#ifndef SIZET_ +typedef unsigned long size_t; +#define SIZET_ +#endif + +#endif /* STDDEF__H */ diff --git a/drivers/rz/ipl/rza/include/lib/libc/aarch64/stdio_.h b/drivers/rz/ipl/rza/include/lib/libc/aarch64/stdio_.h new file mode 100644 index 00000000..afaeadc2 --- /dev/null +++ b/drivers/rz/ipl/rza/include/lib/libc/aarch64/stdio_.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef STDIO__H +#define STDIO__H + +#ifndef SSIZET_ +typedef long ssize_t; +#define SSIZET_ +#endif + +#endif /* STDIO__H */ diff --git a/drivers/rz/ipl/rza/include/lib/libc/arm_acle.h b/drivers/rz/ipl/rza/include/lib/libc/arm_acle.h new file mode 100644 index 00000000..953933f1 --- /dev/null +++ b/drivers/rz/ipl/rza/include/lib/libc/arm_acle.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2021 ARM Limited + * + * SPDX-License-Identifier: BSD-3-Clause + * + * The definitions below are a subset of what we would normally get by using + * the compiler's version of arm_acle.h. We can't use that directly because + * we specify -nostdinc in the Makefiles. + * + * We just define the functions we need so far. + */ + +#ifndef ARM_ACLE_H +#define ARM_ACLE_H + +#if !defined(__aarch64__) || defined(__clang__) +# define __crc32w __builtin_arm_crc32w +#else +# define __crc32w __builtin_aarch64_crc32w +#endif + +#endif /* ARM_ACLE_H */ diff --git a/drivers/rz/ipl/rza/include/lib/libc/assert.h b/drivers/rz/ipl/rza/include/lib/libc/assert.h new file mode 100644 index 00000000..486bbc29 --- /dev/null +++ b/drivers/rz/ipl/rza/include/lib/libc/assert.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef ASSERT_H +#define ASSERT_H + +#include + +#include + +#include + +#ifndef PLAT_LOG_LEVEL_ASSERT +#define PLAT_LOG_LEVEL_ASSERT LOG_LEVEL +#endif + +#if ENABLE_ASSERTIONS +# if PLAT_LOG_LEVEL_ASSERT >= LOG_LEVEL_VERBOSE +# define assert(e) ((e) ? (void)0 : __assert(__FILE__, __LINE__, #e)) +# elif PLAT_LOG_LEVEL_ASSERT >= LOG_LEVEL_INFO +# define assert(e) ((e) ? (void)0 : __assert(__FILE__, __LINE__)) +# else +# define assert(e) ((e) ? (void)0 : __assert()) +# endif +#else +#define assert(e) ((void)0) +#endif /* ENABLE_ASSERTIONS */ + +#if PLAT_LOG_LEVEL_ASSERT >= LOG_LEVEL_VERBOSE +void __dead2 __assert(const char *file, unsigned int line, + const char *assertion); +#elif PLAT_LOG_LEVEL_ASSERT >= LOG_LEVEL_INFO +void __dead2 __assert(const char *file, unsigned int line); +#else +void __dead2 __assert(void); +#endif + +#endif /* ASSERT_H */ diff --git a/drivers/rz/ipl/rza/include/lib/libc/cdefs.h b/drivers/rz/ipl/rza/include/lib/libc/cdefs.h new file mode 100644 index 00000000..0d007225 --- /dev/null +++ b/drivers/rz/ipl/rza/include/lib/libc/cdefs.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CDEFS_H +#define CDEFS_H + +#define __dead2 __attribute__((__noreturn__)) +#define __deprecated __attribute__((__deprecated__)) +#define __packed __attribute__((__packed__)) +#define __used __attribute__((__used__)) +#define __unused __attribute__((__unused__)) +#define __aligned(x) __attribute__((__aligned__(x))) +#define __section(x) __attribute__((__section__(x))) +#if RECLAIM_INIT_CODE +/* + * Add each function to a section that is unique so the functions can still + * be garbage collected + */ +#define __init __section(".text.init." __FILE__ "." __XSTRING(__LINE__)) +#else +#define __init +#endif + +#define __printflike(fmtarg, firstvararg) \ + __attribute__((__format__ (__printf__, fmtarg, firstvararg))) + +#define __weak_reference(sym, alias) \ + __asm__(".weak alias"); \ + __asm__(".equ alias, sym") + +#define __STRING(x) #x +#define __XSTRING(x) __STRING(x) + +#endif /* CDEFS_H */ diff --git a/drivers/rz/ipl/rza/include/lib/libc/endian.h b/drivers/rz/ipl/rza/include/lib/libc/endian.h new file mode 100644 index 00000000..4100f573 --- /dev/null +++ b/drivers/rz/ipl/rza/include/lib/libc/endian.h @@ -0,0 +1,191 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2002 Thomas Moestl + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + * + * $FreeBSD$ + */ +/* + * Portions copyright (c) 2018, ARM Limited and Contributors. + * All rights reserved. + */ + +#ifndef ENDIAN_H +#define ENDIAN_H + +#include +#include +#include + +/* + * General byte order swapping functions. + */ +#define bswap16(x) __bswap16(x) +#define bswap32(x) __bswap32(x) +#define bswap64(x) __bswap64(x) + +/* + * Host to big endian, host to little endian, big endian to host, and little + * endian to host byte order functions as detailed in byteorder(9). + */ +#if _BYTE_ORDER == _LITTLE_ENDIAN +#define htobe16(x) bswap16((x)) +#define htobe32(x) bswap32((x)) +#define htobe64(x) bswap64((x)) +#define htole16(x) ((uint16_t)(x)) +#define htole32(x) ((uint32_t)(x)) +#define htole64(x) ((uint64_t)(x)) + +#define be16toh(x) bswap16((x)) +#define be32toh(x) bswap32((x)) +#define be64toh(x) bswap64((x)) +#define le16toh(x) ((uint16_t)(x)) +#define le32toh(x) ((uint32_t)(x)) +#define le64toh(x) ((uint64_t)(x)) +#else /* _BYTE_ORDER != _LITTLE_ENDIAN */ +#define htobe16(x) ((uint16_t)(x)) +#define htobe32(x) ((uint32_t)(x)) +#define htobe64(x) ((uint64_t)(x)) +#define htole16(x) bswap16((x)) +#define htole32(x) bswap32((x)) +#define htole64(x) bswap64((x)) + +#define be16toh(x) ((uint16_t)(x)) +#define be32toh(x) ((uint32_t)(x)) +#define be64toh(x) ((uint64_t)(x)) +#define le16toh(x) bswap16((x)) +#define le32toh(x) bswap32((x)) +#define le64toh(x) bswap64((x)) +#endif /* _BYTE_ORDER == _LITTLE_ENDIAN */ + +/* Alignment-agnostic encode/decode bytestream to/from little/big endian. */ + +static __inline uint16_t +be16dec(const void *pp) +{ + uint8_t const *p = (uint8_t const *)pp; + + return ((p[0] << 8) | p[1]); +} + +static __inline uint32_t +be32dec(const void *pp) +{ + uint8_t const *p = (uint8_t const *)pp; + + return (((unsigned)p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]); +} + +static __inline uint64_t +be64dec(const void *pp) +{ + uint8_t const *p = (uint8_t const *)pp; + + return (((uint64_t)be32dec(p) << 32) | be32dec(p + 4)); +} + +static __inline uint16_t +le16dec(const void *pp) +{ + uint8_t const *p = (uint8_t const *)pp; + + return ((p[1] << 8) | p[0]); +} + +static __inline uint32_t +le32dec(const void *pp) +{ + uint8_t const *p = (uint8_t const *)pp; + + return (((unsigned)p[3] << 24) | (p[2] << 16) | (p[1] << 8) | p[0]); +} + +static __inline uint64_t +le64dec(const void *pp) +{ + uint8_t const *p = (uint8_t const *)pp; + + return (((uint64_t)le32dec(p + 4) << 32) | le32dec(p)); +} + +static __inline void +be16enc(void *pp, uint16_t u) +{ + uint8_t *p = (uint8_t *)pp; + + p[0] = (u >> 8) & 0xff; + p[1] = u & 0xff; +} + +static __inline void +be32enc(void *pp, uint32_t u) +{ + uint8_t *p = (uint8_t *)pp; + + p[0] = (u >> 24) & 0xff; + p[1] = (u >> 16) & 0xff; + p[2] = (u >> 8) & 0xff; + p[3] = u & 0xff; +} + +static __inline void +be64enc(void *pp, uint64_t u) +{ + uint8_t *p = (uint8_t *)pp; + + be32enc(p, (uint32_t)(u >> 32)); + be32enc(p + 4, (uint32_t)(u & 0xffffffffU)); +} + +static __inline void +le16enc(void *pp, uint16_t u) +{ + uint8_t *p = (uint8_t *)pp; + + p[0] = u & 0xff; + p[1] = (u >> 8) & 0xff; +} + +static __inline void +le32enc(void *pp, uint32_t u) +{ + uint8_t *p = (uint8_t *)pp; + + p[0] = u & 0xff; + p[1] = (u >> 8) & 0xff; + p[2] = (u >> 16) & 0xff; + p[3] = (u >> 24) & 0xff; +} + +static __inline void +le64enc(void *pp, uint64_t u) +{ + uint8_t *p = (uint8_t *)pp; + + le32enc(p, (uint32_t)(u & 0xffffffffU)); + le32enc(p + 4, (uint32_t)(u >> 32)); +} + +#endif /* ENDIAN_H */ diff --git a/drivers/rz/ipl/rza/include/lib/libc/errno.h b/drivers/rz/ipl/rza/include/lib/libc/errno.h new file mode 100644 index 00000000..029912f6 --- /dev/null +++ b/drivers/rz/ipl/rza/include/lib/libc/errno.h @@ -0,0 +1,169 @@ +/*- + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright (c) 1982, 1986, 1989, 1993 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * 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 of the University 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 REGENTS 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 REGENTS 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. + * + * @(#)errno.h 8.5 (Berkeley) 1/21/94 + * $FreeBSD$ + */ +/* + * Portions copyright (c) 2018, ARM Limited and Contributors. + * All rights reserved. + */ + +#ifndef ERRNO_H +#define ERRNO_H + +#define EPERM 1 /* Operation not permitted */ +#define ENOENT 2 /* No such file or directory */ +#define ESRCH 3 /* No such process */ +#define EINTR 4 /* Interrupted system call */ +#define EIO 5 /* Input/output error */ +#define ENXIO 6 /* Device not configured */ +#define E2BIG 7 /* Argument list too long */ +#define ENOEXEC 8 /* Exec format error */ +#define EBADF 9 /* Bad file descriptor */ +#define ECHILD 10 /* No child processes */ +#define EDEADLK 11 /* Resource deadlock avoided */ + /* 11 was EAGAIN */ +#define ENOMEM 12 /* Cannot allocate memory */ +#define EACCES 13 /* Permission denied */ +#define EFAULT 14 /* Bad address */ +#define ENOTBLK 15 /* Block device required */ +#define EBUSY 16 /* Device busy */ +#define EEXIST 17 /* File exists */ +#define EXDEV 18 /* Cross-device link */ +#define ENODEV 19 /* Operation not supported by device */ +#define ENOTDIR 20 /* Not a directory */ +#define EISDIR 21 /* Is a directory */ +#define EINVAL 22 /* Invalid argument */ +#define ENFILE 23 /* Too many open files in system */ +#define EMFILE 24 /* Too many open files */ +#define ENOTTY 25 /* Inappropriate ioctl for device */ +#define ETXTBSY 26 /* Text file busy */ +#define EFBIG 27 /* File too large */ +#define ENOSPC 28 /* No space left on device */ +#define ESPIPE 29 /* Illegal seek */ +#define EROFS 30 /* Read-only filesystem */ +#define EMLINK 31 /* Too many links */ +#define EPIPE 32 /* Broken pipe */ + +/* math software */ +#define EDOM 33 /* Numerical argument out of domain */ +#define ERANGE 34 /* Result too large */ + +/* non-blocking and interrupt i/o */ +#define EAGAIN 35 /* Resource temporarily unavailable */ +#define EWOULDBLOCK EAGAIN /* Operation would block */ +#define EINPROGRESS 36 /* Operation now in progress */ +#define EALREADY 37 /* Operation already in progress */ + +/* ipc/network software -- argument errors */ +#define ENOTSOCK 38 /* Socket operation on non-socket */ +#define EDESTADDRREQ 39 /* Destination address required */ +#define EMSGSIZE 40 /* Message too long */ +#define EPROTOTYPE 41 /* Protocol wrong type for socket */ +#define ENOPROTOOPT 42 /* Protocol not available */ +#define EPROTONOSUPPORT 43 /* Protocol not supported */ +#define ESOCKTNOSUPPORT 44 /* Socket type not supported */ +#define EOPNOTSUPP 45 /* Operation not supported */ +#define ENOTSUP EOPNOTSUPP /* Operation not supported */ +#define EPFNOSUPPORT 46 /* Protocol family not supported */ +#define EAFNOSUPPORT 47 /* Address family not supported by protocol family */ +#define EADDRINUSE 48 /* Address already in use */ +#define EADDRNOTAVAIL 49 /* Can't assign requested address */ + +/* ipc/network software -- operational errors */ +#define ENETDOWN 50 /* Network is down */ +#define ENETUNREACH 51 /* Network is unreachable */ +#define ENETRESET 52 /* Network dropped connection on reset */ +#define ECONNABORTED 53 /* Software caused connection abort */ +#define ECONNRESET 54 /* Connection reset by peer */ +#define ENOBUFS 55 /* No buffer space available */ +#define EISCONN 56 /* Socket is already connected */ +#define ENOTCONN 57 /* Socket is not connected */ +#define ESHUTDOWN 58 /* Can't send after socket shutdown */ +#define ETOOMANYREFS 59 /* Too many references: can't splice */ +#define ETIMEDOUT 60 /* Operation timed out */ +#define ECONNREFUSED 61 /* Connection refused */ + +#define ELOOP 62 /* Too many levels of symbolic links */ +#define ENAMETOOLONG 63 /* File name too long */ + +/* should be rearranged */ +#define EHOSTDOWN 64 /* Host is down */ +#define EHOSTUNREACH 65 /* No route to host */ +#define ENOTEMPTY 66 /* Directory not empty */ + +/* quotas & mush */ +#define EPROCLIM 67 /* Too many processes */ +#define EUSERS 68 /* Too many users */ +#define EDQUOT 69 /* Disc quota exceeded */ + +/* Network File System */ +#define ESTALE 70 /* Stale NFS file handle */ +#define EREMOTE 71 /* Too many levels of remote in path */ +#define EBADRPC 72 /* RPC struct is bad */ +#define ERPCMISMATCH 73 /* RPC version wrong */ +#define EPROGUNAVAIL 74 /* RPC prog. not avail */ +#define EPROGMISMATCH 75 /* Program version wrong */ +#define EPROCUNAVAIL 76 /* Bad procedure for program */ + +#define ENOLCK 77 /* No locks available */ +#define ENOSYS 78 /* Function not implemented */ + +#define EFTYPE 79 /* Inappropriate file type or format */ +#define EAUTH 80 /* Authentication error */ +#define ENEEDAUTH 81 /* Need authenticator */ +#define EIDRM 82 /* Identifier removed */ +#define ENOMSG 83 /* No message of desired type */ +#define EOVERFLOW 84 /* Value too large to be stored in data type */ +#define ECANCELED 85 /* Operation canceled */ +#define EILSEQ 86 /* Illegal byte sequence */ +#define ENOATTR 87 /* Attribute not found */ + +#define EDOOFUS 88 /* Programming error */ + +#define EBADMSG 89 /* Bad message */ +#define EMULTIHOP 90 /* Multihop attempted */ +#define ENOLINK 91 /* Link has been severed */ +#define EPROTO 92 /* Protocol error */ + +#define ENOTCAPABLE 93 /* Capabilities insufficient */ +#define ECAPMODE 94 /* Not permitted in capability mode */ +#define ENOTRECOVERABLE 95 /* State not recoverable */ +#define EOWNERDEAD 96 /* Previous owner died */ + +#define ELAST 96 /* Must be equal largest errno */ + +#endif /* ERRNO_H */ diff --git a/drivers/rz/ipl/rza/include/lib/libc/limits.h b/drivers/rz/ipl/rza/include/lib/libc/limits.h new file mode 100644 index 00000000..41bb6584 --- /dev/null +++ b/drivers/rz/ipl/rza/include/lib/libc/limits.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2012-2017 Roberto E. Vargas Caballero + * + * SPDX-License-Identifier: BSD-3-Clause + */ +/* + * Portions copyright (c) 2018, ARM Limited and Contributors. + * All rights reserved. + */ + +#ifndef LIMITS_H +#define LIMITS_H + +#include + +#define CHAR_BIT 8 +#define MB_LEN_MAX 1 + +#endif /* LIMITS_H */ diff --git a/drivers/rz/ipl/rza/include/lib/libc/setjmp.h b/drivers/rz/ipl/rza/include/lib/libc/setjmp.h new file mode 100644 index 00000000..be8e2c01 --- /dev/null +++ b/drivers/rz/ipl/rza/include/lib/libc/setjmp.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SETJMP_H +#define SETJMP_H + +#include + +#ifndef __ASSEMBLER__ + +#include + +int setjmp(jmp_buf env); +__dead2 void longjmp(jmp_buf env, int val); + +#endif /* __ASSEMBLER__ */ +#endif /* SETJMP_H */ diff --git a/drivers/rz/ipl/rza/include/lib/libc/stdarg.h b/drivers/rz/ipl/rza/include/lib/libc/stdarg.h new file mode 100644 index 00000000..e260b9b5 --- /dev/null +++ b/drivers/rz/ipl/rza/include/lib/libc/stdarg.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2012-2017 Roberto E. Vargas Caballero + * + * SPDX-License-Identifier: BSD-3-Clause + */ +/* + * Portions copyright (c) 2018, ARM Limited and Contributors. + * All rights reserved. + */ + +#ifndef STDARG_H +#define STDARG_H + +#define va_list __builtin_va_list +#define va_start(ap, last) __builtin_va_start(ap, last) +#define va_end(ap) __builtin_va_end(ap) +#define va_copy(to, from) __builtin_va_copy(to, from) +#define va_arg(to, type) __builtin_va_arg(to, type) + +#endif /* STDARG_H */ diff --git a/drivers/rz/ipl/rza/include/lib/libc/stdbool.h b/drivers/rz/ipl/rza/include/lib/libc/stdbool.h new file mode 100644 index 00000000..b58334cd --- /dev/null +++ b/drivers/rz/ipl/rza/include/lib/libc/stdbool.h @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef STDBOOL_H +#define STDBOOL_H + +#define bool _Bool + +#define true (0 < 1) +#define false (0 > 1) + +#define __bool_true_false_are_defined 1 + +#endif /* STDBOOL_H */ diff --git a/drivers/rz/ipl/rza/include/lib/libc/stddef.h b/drivers/rz/ipl/rza/include/lib/libc/stddef.h new file mode 100644 index 00000000..58a519e5 --- /dev/null +++ b/drivers/rz/ipl/rza/include/lib/libc/stddef.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2012-2017 Roberto E. Vargas Caballero + * + * SPDX-License-Identifier: BSD-3-Clause + */ +/* + * Portions copyright (c) 2018-2019, ARM Limited and Contributors. + * All rights reserved. + */ + +#ifndef STDDEF_H +#define STDDEF_H + +#include + +#ifndef _PTRDIFF_T +typedef long ptrdiff_t; +#define _PTRDIFF_T +#endif + +#ifndef NULL +#define NULL ((void *) 0) +#endif + +#define offsetof(st, m) __builtin_offsetof(st, m) + +#endif /* STDDEF_H */ diff --git a/drivers/rz/ipl/rza/include/lib/libc/stdint.h b/drivers/rz/ipl/rza/include/lib/libc/stdint.h new file mode 100644 index 00000000..818870e1 --- /dev/null +++ b/drivers/rz/ipl/rza/include/lib/libc/stdint.h @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2012-2017 Roberto E. Vargas Caballero + * + * SPDX-License-Identifier: BSD-3-Clause + */ +/* + * Portions copyright (c) 2018-2019, ARM Limited and Contributors. + * All rights reserved. + */ + +#ifndef STDINT_H +#define STDINT_H + +#include + +#define INT8_MAX CHAR_MAX +#define INT8_MIN CHAR_MIN +#define UINT8_MAX UCHAR_MAX + +#define INT16_MAX SHRT_MAX +#define INT16_MIN SHRT_MIN +#define UINT16_MAX USHRT_MAX + +#define INT32_MAX INT_MAX +#define INT32_MIN INT_MIN +#define UINT32_MAX UINT_MAX + +#define INT64_MAX LLONG_MAX +#define INT64_MIN LLONG_MIN +#define UINT64_MAX ULLONG_MAX + +#define INT_LEAST8_MIN INT8_MIN +#define INT_LEAST8_MAX INT8_MAX +#define UINT_LEAST8_MAX UINT8_MAX + +#define INT_LEAST16_MIN INT16_MIN +#define INT_LEAST16_MAX INT16_MAX +#define UINT_LEAST16_MAX UINT16_MAX + +#define INT_LEAST32_MIN INT32_MIN +#define INT_LEAST32_MAX INT32_MAX +#define UINT_LEAST32_MAX UINT32_MAX + +#define INT_LEAST64_MIN INT64_MIN +#define INT_LEAST64_MAX INT64_MAX +#define UINT_LEAST64_MAX UINT64_MAX + +#define INT_FAST8_MIN INT32_MIN +#define INT_FAST8_MAX INT32_MAX +#define UINT_FAST8_MAX UINT32_MAX + +#define INT_FAST16_MIN INT32_MIN +#define INT_FAST16_MAX INT32_MAX +#define UINT_FAST16_MAX UINT32_MAX + +#define INT_FAST32_MIN INT32_MIN +#define INT_FAST32_MAX INT32_MAX +#define UINT_FAST32_MAX UINT32_MAX + +#define INT_FAST64_MIN INT64_MIN +#define INT_FAST64_MAX INT64_MAX +#define UINT_FAST64_MAX UINT64_MAX + +#define INTPTR_MIN LONG_MIN +#define INTPTR_MAX LONG_MAX +#define UINTPTR_MAX ULONG_MAX + +#define INTMAX_MIN LLONG_MIN +#define INTMAX_MAX LLONG_MAX +#define UINTMAX_MAX ULLONG_MAX + +#define PTRDIFF_MIN LONG_MIN +#define PTRDIFF_MAX LONG_MAX + +#define SIZE_MAX ULONG_MAX + +#define INT8_C(x) x +#define INT16_C(x) x +#define INT32_C(x) x +#define INT64_C(x) x ## LL + +#define UINT8_C(x) x +#define UINT16_C(x) x +#define UINT32_C(x) x ## U +#define UINT64_C(x) x ## ULL + +#define INTMAX_C(x) x ## LL +#define UINTMAX_C(x) x ## ULL + +typedef signed char int8_t; +typedef short int16_t; +typedef int int32_t; +typedef long long int64_t; + +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; +typedef unsigned int uint32_t; +typedef unsigned long long uint64_t; + +typedef signed char int8_least_t; +typedef short int16_least_t; +typedef int int32_least_t; +typedef long long int64_least_t; + +typedef unsigned char uint8_least_t; +typedef unsigned short uint16_least_t; +typedef unsigned int uint32_least_t; +typedef unsigned long long uint64_least_t; + +typedef int int8_fast_t; +typedef int int16_fast_t; +typedef int int32_fast_t; +typedef long long int64_fast_t; + +typedef unsigned int uint8_fast_t; +typedef unsigned int uint16_fast_t; +typedef unsigned int uint32_fast_t; +typedef unsigned long long uint64_fast_t; + +typedef long intptr_t; +typedef unsigned long uintptr_t; + +/* +* Conceptually, these are supposed to be the largest integers representable in C, +* but GCC and Clang define them as long long for compatibility. +*/ +typedef long long intmax_t; +typedef unsigned long long uintmax_t; + +typedef long register_t; +typedef unsigned long u_register_t; + +#ifdef __aarch64__ +typedef __int128 int128_t; +typedef unsigned __int128 uint128_t; +#endif /* __aarch64__ */ + +#endif /* STDINT_H */ diff --git a/drivers/rz/ipl/rza/include/lib/libc/stdio.h b/drivers/rz/ipl/rza/include/lib/libc/stdio.h new file mode 100644 index 00000000..ba13683e --- /dev/null +++ b/drivers/rz/ipl/rza/include/lib/libc/stdio.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2012-2017 Roberto E. Vargas Caballero + * + * SPDX-License-Identifier: BSD-3-Clause + */ +/* + * Portions copyright (c) 2018-2019, ARM Limited and Contributors. + * All rights reserved. + */ + +#ifndef STDIO_H +#define STDIO_H + +#include +#include +#include + +#define EOF -1 + +int printf(const char *fmt, ...) __printflike(1, 2); +int snprintf(char *s, size_t n, const char *fmt, ...) __printflike(3, 4); + +#ifdef STDARG_H +int vprintf(const char *fmt, va_list args); +int vsnprintf(char *s, size_t n, const char *fmt, va_list args); +#endif + +int putchar(int c); +int puts(const char *s); + +#endif /* STDIO_H */ diff --git a/drivers/rz/ipl/rza/include/lib/libc/stdlib.h b/drivers/rz/ipl/rza/include/lib/libc/stdlib.h new file mode 100644 index 00000000..4641e566 --- /dev/null +++ b/drivers/rz/ipl/rza/include/lib/libc/stdlib.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2012-2021 Roberto E. Vargas Caballero + * + * SPDX-License-Identifier: BSD-3-Clause + */ +/* + * Portions copyright (c) 2018-2019, ARM Limited and Contributors. + * All rights reserved. + */ + +#ifndef STDLIB_H +#define STDLIB_H + +#include + +#define EXIT_FAILURE 1 +#define EXIT_SUCCESS 0 + +#define _ATEXIT_MAX 1 + +#define isspace(x) (((x) == ' ') || ((x) == '\r') || ((x) == '\n') || \ + ((x) == '\t') || ((x) == '\b')) + +extern void abort(void); +extern int atexit(void (*func)(void)); +extern void exit(int status); + +long strtol(const char *nptr, char **endptr, int base); +unsigned long strtoul(const char *nptr, char **endptr, int base); +long long strtoll(const char *nptr, char **endptr, int base); +unsigned long long strtoull(const char *nptr, char **endptr, int base); +#endif /* STDLIB_H */ diff --git a/drivers/rz/ipl/rza/include/lib/libc/string.h b/drivers/rz/ipl/rza/include/lib/libc/string.h new file mode 100644 index 00000000..98944831 --- /dev/null +++ b/drivers/rz/ipl/rza/include/lib/libc/string.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2012-2017 Roberto E. Vargas Caballero + * + * SPDX-License-Identifier: BSD-3-Clause + */ +/* + * Portions copyright (c) 2018-2020, ARM Limited and Contributors. + * All rights reserved. + */ + +#ifndef STRING_H +#define STRING_H + +#include + +void *memcpy(void *dst, const void *src, size_t len); +void *memmove(void *dst, const void *src, size_t len); +int memcmp(const void *s1, const void *s2, size_t len); +int strcmp(const char *s1, const char *s2); +int strncmp(const char *s1, const char *s2, size_t n); +void *memchr(const void *src, int c, size_t len); +void *memrchr(const void *src, int c, size_t len); +char *strchr(const char *s, int c); +void *memset(void *dst, int val, size_t count); +size_t strlen(const char *s); +size_t strnlen(const char *s, size_t maxlen); +char *strrchr(const char *p, int ch); +size_t strlcpy(char * dst, const char * src, size_t dsize); +size_t strlcat(char * dst, const char * src, size_t dsize); +char *strtok_r(char *s, const char *delim, char **last); + +#endif /* STRING_H */ diff --git a/drivers/rz/ipl/rza/include/lib/libc/time.h b/drivers/rz/ipl/rza/include/lib/libc/time.h new file mode 100644 index 00000000..c1c95e58 --- /dev/null +++ b/drivers/rz/ipl/rza/include/lib/libc/time.h @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2012-2017 Roberto E. Vargas Caballero + * + * SPDX-License-Identifier: BSD-3-Clause + */ +/* + * Portions copyright (c) 2018-2019, ARM Limited and Contributors. + * All rights reserved. + */ + +#ifndef TIME_H +#define TIME_H + +#include + +typedef long int time_t; + +#endif /* TIME_H */ diff --git a/drivers/rz/ipl/rza/include/lib/mmio.h b/drivers/rz/ipl/rza/include/lib/mmio.h new file mode 100644 index 00000000..3242a7cc --- /dev/null +++ b/drivers/rz/ipl/rza/include/lib/mmio.h @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MMIO_H +#define MMIO_H + +#include + +static inline void mmio_write_8(uintptr_t addr, uint8_t value) +{ + *(volatile uint8_t*)addr = value; +} + +static inline uint8_t mmio_read_8(uintptr_t addr) +{ + return *(volatile uint8_t*)addr; +} + +static inline void mmio_write_16(uintptr_t addr, uint16_t value) +{ + *(volatile uint16_t*)addr = value; +} + +static inline uint16_t mmio_read_16(uintptr_t addr) +{ + return *(volatile uint16_t*)addr; +} + +static inline void mmio_clrsetbits_16(uintptr_t addr, + uint16_t clear, + uint16_t set) +{ + mmio_write_16(addr, (mmio_read_16(addr) & ~clear) | set); +} + +static inline void mmio_write_32(uintptr_t addr, uint32_t value) +{ + *(volatile uint32_t*)addr = value; +} + +static inline uint32_t mmio_read_32(uintptr_t addr) +{ + return *(volatile uint32_t*)addr; +} + +static inline void mmio_write_64(uintptr_t addr, uint64_t value) +{ + *(volatile uint64_t*)addr = value; +} + +static inline uint64_t mmio_read_64(uintptr_t addr) +{ + return *(volatile uint64_t*)addr; +} + +static inline void mmio_clrbits_32(uintptr_t addr, uint32_t clear) +{ + mmio_write_32(addr, mmio_read_32(addr) & ~clear); +} + +static inline void mmio_setbits_32(uintptr_t addr, uint32_t set) +{ + mmio_write_32(addr, mmio_read_32(addr) | set); +} + +static inline void mmio_clrsetbits_32(uintptr_t addr, + uint32_t clear, + uint32_t set) +{ + mmio_write_32(addr, (mmio_read_32(addr) & ~clear) | set); +} + +#endif /* MMIO_H */ diff --git a/drivers/rz/ipl/rza/include/lib/object_pool.h b/drivers/rz/ipl/rza/include/lib/object_pool.h new file mode 100644 index 00000000..66e8c478 --- /dev/null +++ b/drivers/rz/ipl/rza/include/lib/object_pool.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef OBJECT_POOL_H +#define OBJECT_POOL_H + +#include + +#include +#include + +/* + * Pool of statically allocated objects. + * + * Objects can be reserved but not freed. This is by design and it is not a + * limitation. We do not want to introduce complexity induced by memory freeing, + * such as use-after-free bugs, memory fragmentation and so on. + * + * The object size and capacity of the pool are fixed at build time. So is the + * address of the objects back store. + */ +struct object_pool { + /* Size of 1 object in the pool in byte unit. */ + const size_t obj_size; + + /* Number of objects in the pool. */ + const size_t capacity; + + /* Objects back store. */ + void *const objects; + + /* How many objects are currently allocated. */ + size_t used; +}; + +/* Create a static pool of objects. */ +#define OBJECT_POOL(_pool_name, _obj_backstore, _obj_size, _obj_count) \ + struct object_pool _pool_name = { \ + .objects = (_obj_backstore), \ + .obj_size = (_obj_size), \ + .capacity = (_obj_count), \ + .used = 0U, \ + } + +/* Create a static pool of objects out of an array of pre-allocated objects. */ +#define OBJECT_POOL_ARRAY(_pool_name, _obj_array) \ + OBJECT_POOL(_pool_name, (_obj_array), \ + sizeof((_obj_array)[0]), ARRAY_SIZE(_obj_array)) + +/* + * Allocate 'count' objects from a pool. + * Return the address of the first object. Panic on error. + */ +static inline void *pool_alloc_n(struct object_pool *pool, size_t count) +{ + if ((pool->used + count) > pool->capacity) { + ERROR("Cannot allocate %zu objects out of pool (%zu objects left).\n", + count, pool->capacity - pool->used); + panic(); + } + + void *obj = (char *)(pool->objects) + (pool->obj_size * pool->used); + pool->used += count; + return obj; +} + +/* + * Allocate 1 object from a pool. + * Return the address of the object. Panic on error. + */ +static inline void *pool_alloc(struct object_pool *pool) +{ + return pool_alloc_n(pool, 1U); +} + +#endif /* OBJECT_POOL_H */ diff --git a/drivers/rz/ipl/rza/include/lib/optee_utils.h b/drivers/rz/ipl/rza/include/lib/optee_utils.h new file mode 100644 index 00000000..6067caff --- /dev/null +++ b/drivers/rz/ipl/rza/include/lib/optee_utils.h @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef OPTEE_UTILS_H +#define OPTEE_UTILS_H + +#include + +int parse_optee_header(entry_point_info_t *header_ep, + image_info_t *pager_image_info, + image_info_t *paged_image_info); + +#endif /* OPTEE_UTILS_H */ diff --git a/drivers/rz/ipl/rza/include/lib/psci/psci.h b/drivers/rz/ipl/rza/include/lib/psci/psci.h new file mode 100644 index 00000000..b56e98b5 --- /dev/null +++ b/drivers/rz/ipl/rza/include/lib/psci/psci.h @@ -0,0 +1,355 @@ +/* + * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PSCI_H +#define PSCI_H + +#include /* for PLAT_NUM_PWR_DOMAINS */ + +#include +#include +#include /* To maintain compatibility for SPDs */ +#include + +/******************************************************************************* + * Number of power domains whose state this PSCI implementation can track + ******************************************************************************/ +#ifdef PLAT_NUM_PWR_DOMAINS +#define PSCI_NUM_PWR_DOMAINS PLAT_NUM_PWR_DOMAINS +#else +#define PSCI_NUM_PWR_DOMAINS (U(2) * PLATFORM_CORE_COUNT) +#endif + +#define PSCI_NUM_NON_CPU_PWR_DOMAINS (PSCI_NUM_PWR_DOMAINS - \ + PLATFORM_CORE_COUNT) + +/* This is the power level corresponding to a CPU */ +#define PSCI_CPU_PWR_LVL U(0) + +/* + * The maximum power level supported by PSCI. Since PSCI CPU_SUSPEND + * uses the old power_state parameter format which has 2 bits to specify the + * power level, this constant is defined to be 3. + */ +#define PSCI_MAX_PWR_LVL U(3) + +/******************************************************************************* + * Defines for runtime services function ids + ******************************************************************************/ +#define PSCI_VERSION U(0x84000000) +#define PSCI_CPU_SUSPEND_AARCH32 U(0x84000001) +#define PSCI_CPU_SUSPEND_AARCH64 U(0xc4000001) +#define PSCI_CPU_OFF U(0x84000002) +#define PSCI_CPU_ON_AARCH32 U(0x84000003) +#define PSCI_CPU_ON_AARCH64 U(0xc4000003) +#define PSCI_AFFINITY_INFO_AARCH32 U(0x84000004) +#define PSCI_AFFINITY_INFO_AARCH64 U(0xc4000004) +#define PSCI_MIG_AARCH32 U(0x84000005) +#define PSCI_MIG_AARCH64 U(0xc4000005) +#define PSCI_MIG_INFO_TYPE U(0x84000006) +#define PSCI_MIG_INFO_UP_CPU_AARCH32 U(0x84000007) +#define PSCI_MIG_INFO_UP_CPU_AARCH64 U(0xc4000007) +#define PSCI_SYSTEM_OFF U(0x84000008) +#define PSCI_SYSTEM_RESET U(0x84000009) +#define PSCI_FEATURES U(0x8400000A) +#define PSCI_NODE_HW_STATE_AARCH32 U(0x8400000d) +#define PSCI_NODE_HW_STATE_AARCH64 U(0xc400000d) +#define PSCI_SYSTEM_SUSPEND_AARCH32 U(0x8400000E) +#define PSCI_SYSTEM_SUSPEND_AARCH64 U(0xc400000E) +#define PSCI_STAT_RESIDENCY_AARCH32 U(0x84000010) +#define PSCI_STAT_RESIDENCY_AARCH64 U(0xc4000010) +#define PSCI_STAT_COUNT_AARCH32 U(0x84000011) +#define PSCI_STAT_COUNT_AARCH64 U(0xc4000011) +#define PSCI_SYSTEM_RESET2_AARCH32 U(0x84000012) +#define PSCI_SYSTEM_RESET2_AARCH64 U(0xc4000012) +#define PSCI_MEM_PROTECT U(0x84000013) +#define PSCI_MEM_CHK_RANGE_AARCH32 U(0x84000014) +#define PSCI_MEM_CHK_RANGE_AARCH64 U(0xc4000014) + +/* + * Number of PSCI calls (above) implemented + */ +#if ENABLE_PSCI_STAT +#define PSCI_NUM_CALLS U(22) +#else +#define PSCI_NUM_CALLS U(18) +#endif + +/* The macros below are used to identify PSCI calls from the SMC function ID */ +#define PSCI_FID_MASK U(0xffe0) +#define PSCI_FID_VALUE U(0) +#define is_psci_fid(_fid) \ + (((_fid) & PSCI_FID_MASK) == PSCI_FID_VALUE) + +/******************************************************************************* + * PSCI Migrate and friends + ******************************************************************************/ +#define PSCI_TOS_UP_MIG_CAP 0 +#define PSCI_TOS_NOT_UP_MIG_CAP 1 +#define PSCI_TOS_NOT_PRESENT_MP 2 + +/******************************************************************************* + * PSCI CPU_SUSPEND 'power_state' parameter specific defines + ******************************************************************************/ +#define PSTATE_ID_SHIFT U(0) + +#if PSCI_EXTENDED_STATE_ID +#define PSTATE_VALID_MASK U(0xB0000000) +#define PSTATE_TYPE_SHIFT U(30) +#define PSTATE_ID_MASK U(0xfffffff) +#else +#define PSTATE_VALID_MASK U(0xFCFE0000) +#define PSTATE_TYPE_SHIFT U(16) +#define PSTATE_PWR_LVL_SHIFT U(24) +#define PSTATE_ID_MASK U(0xffff) +#define PSTATE_PWR_LVL_MASK U(0x3) + +#define psci_get_pstate_pwrlvl(pstate) (((pstate) >> PSTATE_PWR_LVL_SHIFT) & \ + PSTATE_PWR_LVL_MASK) +#define psci_make_powerstate(state_id, type, pwrlvl) \ + (((state_id) & PSTATE_ID_MASK) << PSTATE_ID_SHIFT) |\ + (((type) & PSTATE_TYPE_MASK) << PSTATE_TYPE_SHIFT) |\ + (((pwrlvl) & PSTATE_PWR_LVL_MASK) << PSTATE_PWR_LVL_SHIFT) +#endif /* __PSCI_EXTENDED_STATE_ID__ */ + +#define PSTATE_TYPE_STANDBY U(0x0) +#define PSTATE_TYPE_POWERDOWN U(0x1) +#define PSTATE_TYPE_MASK U(0x1) + +/******************************************************************************* + * PSCI CPU_FEATURES feature flag specific defines + ******************************************************************************/ +/* Features flags for CPU SUSPEND power state parameter format. Bits [1:1] */ +#define FF_PSTATE_SHIFT U(1) +#define FF_PSTATE_ORIG U(0) +#define FF_PSTATE_EXTENDED U(1) +#if PSCI_EXTENDED_STATE_ID +#define FF_PSTATE FF_PSTATE_EXTENDED +#else +#define FF_PSTATE FF_PSTATE_ORIG +#endif + +/* Features flags for CPU SUSPEND OS Initiated mode support. Bits [0:0] */ +#define FF_MODE_SUPPORT_SHIFT U(0) +#define FF_SUPPORTS_OS_INIT_MODE U(1) + +/******************************************************************************* + * PSCI version + ******************************************************************************/ +#define PSCI_MAJOR_VER (U(1) << 16) +#define PSCI_MINOR_VER U(0x1) + +/******************************************************************************* + * PSCI error codes + ******************************************************************************/ +#define PSCI_E_SUCCESS 0 +#define PSCI_E_NOT_SUPPORTED -1 +#define PSCI_E_INVALID_PARAMS -2 +#define PSCI_E_DENIED -3 +#define PSCI_E_ALREADY_ON -4 +#define PSCI_E_ON_PENDING -5 +#define PSCI_E_INTERN_FAIL -6 +#define PSCI_E_NOT_PRESENT -7 +#define PSCI_E_DISABLED -8 +#define PSCI_E_INVALID_ADDRESS -9 + +#define PSCI_INVALID_MPIDR ~((u_register_t)0) + +/* + * SYSTEM_RESET2 macros + */ +#define PSCI_RESET2_TYPE_VENDOR_SHIFT U(31) +#define PSCI_RESET2_TYPE_VENDOR (U(1) << PSCI_RESET2_TYPE_VENDOR_SHIFT) +#define PSCI_RESET2_TYPE_ARCH (U(0) << PSCI_RESET2_TYPE_VENDOR_SHIFT) +#define PSCI_RESET2_SYSTEM_WARM_RESET (PSCI_RESET2_TYPE_ARCH | U(0)) + +#ifndef __ASSEMBLER__ + +#include + +/* Function to help build the psci capabilities bitfield */ + +static inline unsigned int define_psci_cap(unsigned int x) +{ + return U(1) << (x & U(0x1f)); +} + + +/* Power state helper functions */ + +static inline unsigned int psci_get_pstate_id(unsigned int power_state) +{ + return ((power_state) >> PSTATE_ID_SHIFT) & PSTATE_ID_MASK; +} + +static inline unsigned int psci_get_pstate_type(unsigned int power_state) +{ + return ((power_state) >> PSTATE_TYPE_SHIFT) & PSTATE_TYPE_MASK; +} + +static inline unsigned int psci_check_power_state(unsigned int power_state) +{ + return ((power_state) & PSTATE_VALID_MASK); +} + +/* + * These are the states reported by the PSCI_AFFINITY_INFO API for the specified + * CPU. The definitions of these states can be found in Section 5.7.1 in the + * PSCI specification (ARM DEN 0022C). + */ +typedef enum { + AFF_STATE_ON = U(0), + AFF_STATE_OFF = U(1), + AFF_STATE_ON_PENDING = U(2) +} aff_info_state_t; + +/* + * These are the power states reported by PSCI_NODE_HW_STATE API for the + * specified CPU. The definitions of these states can be found in Section 5.15.3 + * of PSCI specification (ARM DEN 0022C). + */ +#define HW_ON 0 +#define HW_OFF 1 +#define HW_STANDBY 2 + +/* + * Macro to represent invalid affinity level within PSCI. + */ +#define PSCI_INVALID_PWR_LVL (PLAT_MAX_PWR_LVL + U(1)) + +/* + * Type for representing the local power state at a particular level. + */ +typedef uint8_t plat_local_state_t; + +/* The local state macro used to represent RUN state. */ +#define PSCI_LOCAL_STATE_RUN U(0) + +/* + * Function to test whether the plat_local_state is RUN state + */ +static inline int is_local_state_run(unsigned int plat_local_state) +{ + return (plat_local_state == PSCI_LOCAL_STATE_RUN) ? 1 : 0; +} + +/* + * Function to test whether the plat_local_state is RETENTION state + */ +static inline int is_local_state_retn(unsigned int plat_local_state) +{ + return ((plat_local_state > PSCI_LOCAL_STATE_RUN) && + (plat_local_state <= PLAT_MAX_RET_STATE)) ? 1 : 0; +} + +/* + * Function to test whether the plat_local_state is OFF state + */ +static inline int is_local_state_off(unsigned int plat_local_state) +{ + return ((plat_local_state > PLAT_MAX_RET_STATE) && + (plat_local_state <= PLAT_MAX_OFF_STATE)) ? 1 : 0; +} + +/***************************************************************************** + * This data structure defines the representation of the power state parameter + * for its exchange between the generic PSCI code and the platform port. For + * example, it is used by the platform port to specify the requested power + * states during a power management operation. It is used by the generic code to + * inform the platform about the target power states that each level should + * enter. + ****************************************************************************/ +typedef struct psci_power_state { + /* + * The pwr_domain_state[] stores the local power state at each level + * for the CPU. + */ + plat_local_state_t pwr_domain_state[PLAT_MAX_PWR_LVL + U(1)]; +} psci_power_state_t; + +/******************************************************************************* + * Structure used to store per-cpu information relevant to the PSCI service. + * It is populated in the per-cpu data array. In return we get a guarantee that + * this information will not reside on a cache line shared with another cpu. + ******************************************************************************/ +typedef struct psci_cpu_data { + /* State as seen by PSCI Affinity Info API */ + aff_info_state_t aff_info_state; + + /* + * Highest power level which takes part in a power management + * operation. + */ + unsigned int target_pwrlvl; + + /* The local power state of this CPU */ + plat_local_state_t local_state; +} psci_cpu_data_t; + +/******************************************************************************* + * Structure populated by platform specific code to export routines which + * perform common low level power management functions + ******************************************************************************/ +typedef struct plat_psci_ops { + void (*cpu_standby)(plat_local_state_t cpu_state); + int (*pwr_domain_on)(u_register_t mpidr); + void (*pwr_domain_off)(const psci_power_state_t *target_state); + void (*pwr_domain_suspend_pwrdown_early)( + const psci_power_state_t *target_state); + void (*pwr_domain_suspend)(const psci_power_state_t *target_state); + void (*pwr_domain_on_finish)(const psci_power_state_t *target_state); + void (*pwr_domain_on_finish_late)( + const psci_power_state_t *target_state); + void (*pwr_domain_suspend_finish)( + const psci_power_state_t *target_state); + void __dead2 (*pwr_domain_pwr_down_wfi)( + const psci_power_state_t *target_state); + void __dead2 (*system_off)(void); + void __dead2 (*system_reset)(void); + int (*validate_power_state)(unsigned int power_state, + psci_power_state_t *req_state); + int (*validate_ns_entrypoint)(uintptr_t ns_entrypoint); + void (*get_sys_suspend_power_state)( + psci_power_state_t *req_state); + int (*get_pwr_lvl_state_idx)(plat_local_state_t pwr_domain_state, + int pwrlvl); + int (*translate_power_state_by_mpidr)(u_register_t mpidr, + unsigned int power_state, + psci_power_state_t *output_state); + int (*get_node_hw_state)(u_register_t mpidr, unsigned int power_level); + int (*mem_protect_chk)(uintptr_t base, u_register_t length); + int (*read_mem_protect)(int *val); + int (*write_mem_protect)(int val); + int (*system_reset2)(int is_vendor, + int reset_type, u_register_t cookie); +} plat_psci_ops_t; + +/******************************************************************************* + * Function & Data prototypes + ******************************************************************************/ +unsigned int psci_version(void); +int psci_cpu_on(u_register_t target_cpu, + uintptr_t entrypoint, + u_register_t context_id); +int psci_cpu_suspend(unsigned int power_state, + uintptr_t entrypoint, + u_register_t context_id); +int psci_system_suspend(uintptr_t entrypoint, u_register_t context_id); +int psci_cpu_off(void); +int psci_affinity_info(u_register_t target_affinity, + unsigned int lowest_affinity_level); +int psci_migrate(u_register_t target_cpu); +int psci_migrate_info_type(void); +u_register_t psci_migrate_info_up_cpu(void); +int psci_node_hw_state(u_register_t target_cpu, + unsigned int power_level); +int psci_features(unsigned int psci_fid); +void __dead2 psci_power_down_wfi(void); +void psci_arch_setup(void); + +#endif /*__ASSEMBLER__*/ + +#endif /* PSCI_H */ diff --git a/drivers/rz/ipl/rza/include/lib/psci/psci_lib.h b/drivers/rz/ipl/rza/include/lib/psci/psci_lib.h new file mode 100644 index 00000000..1ac45adf --- /dev/null +++ b/drivers/rz/ipl/rza/include/lib/psci/psci_lib.h @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PSCI_LIB_H +#define PSCI_LIB_H + +#include + +#ifndef __ASSEMBLER__ + +#include +#include + +/******************************************************************************* + * Optional structure populated by the Secure Payload Dispatcher to be given a + * chance to perform any bookkeeping before PSCI executes a power management + * operation. It also allows PSCI to determine certain properties of the SP e.g. + * migrate capability etc. + ******************************************************************************/ +typedef struct spd_pm_ops { + void (*svc_on)(u_register_t target_cpu); + int32_t (*svc_off)(u_register_t __unused unused); + void (*svc_suspend)(u_register_t max_off_pwrlvl); + void (*svc_on_finish)(u_register_t __unused unused); + void (*svc_suspend_finish)(u_register_t max_off_pwrlvl); + int32_t (*svc_migrate)(u_register_t from_cpu, u_register_t to_cpu); + int32_t (*svc_migrate_info)(u_register_t *resident_cpu); + void (*svc_system_off)(void); + void (*svc_system_reset)(void); +} spd_pm_ops_t; + +/* + * Function prototype for the warmboot entrypoint function which will be + * programmed in the mailbox by the platform. + */ +typedef void (*mailbox_entrypoint_t)(void); + +/****************************************************************************** + * Structure to pass PSCI Library arguments. + *****************************************************************************/ +typedef struct psci_lib_args { + /* The version information of PSCI Library Interface */ + param_header_t h; + /* The warm boot entrypoint function */ + mailbox_entrypoint_t mailbox_ep; +} psci_lib_args_t; + +/* Helper macro to set the psci_lib_args_t structure at runtime */ +#define SET_PSCI_LIB_ARGS_V1(_p, _entry) do { \ + SET_PARAM_HEAD(_p, PARAM_PSCI_LIB_ARGS, VERSION_1, 0); \ + (_p)->mailbox_ep = (_entry); \ + } while (0) + +/* Helper macro to define the psci_lib_args_t statically */ +#define DEFINE_STATIC_PSCI_LIB_ARGS_V1(_name, _entry) \ + static const psci_lib_args_t (_name) = { \ + .h.type = (uint8_t)PARAM_PSCI_LIB_ARGS, \ + .h.version = (uint8_t)VERSION_1, \ + .h.size = (uint16_t)sizeof(_name), \ + .h.attr = 0U, \ + .mailbox_ep = (_entry) \ + } + +/* Helper macro to verify the pointer to psci_lib_args_t structure */ +#define VERIFY_PSCI_LIB_ARGS_V1(_p) (((_p) != NULL) \ + && ((_p)->h.type == PARAM_PSCI_LIB_ARGS) \ + && ((_p)->h.version == VERSION_1) \ + && ((_p)->h.size == sizeof(*(_p))) \ + && ((_p)->h.attr == 0) \ + && ((_p)->mailbox_ep != NULL)) + +/****************************************************************************** + * PSCI Library Interfaces + *****************************************************************************/ +u_register_t psci_smc_handler(uint32_t smc_fid, + u_register_t x1, + u_register_t x2, + u_register_t x3, + u_register_t x4, + void *cookie, + void *handle, + u_register_t flags); +int psci_setup(const psci_lib_args_t *lib_args); +int psci_secondaries_brought_up(void); +void psci_warmboot_entrypoint(void); +void psci_register_spd_pm_hook(const spd_pm_ops_t *pm); +void psci_prepare_next_non_secure_ctx( + entry_point_info_t *next_image_info); +int psci_stop_other_cores(unsigned int wait_ms, + void (*stop_func)(u_register_t mpidr)); +#endif /* __ASSEMBLER__ */ + +#endif /* PSCI_LIB_H */ diff --git a/drivers/rz/ipl/rza/include/lib/runtime_instr.h b/drivers/rz/ipl/rza/include/lib/runtime_instr.h new file mode 100644 index 00000000..303f27e5 --- /dev/null +++ b/drivers/rz/ipl/rza/include/lib/runtime_instr.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef RUNTIME_INSTR_H +#define RUNTIME_INSTR_H + +#include + +#define RT_INSTR_ENTER_PSCI U(0) +#define RT_INSTR_EXIT_PSCI U(1) +#define RT_INSTR_ENTER_HW_LOW_PWR U(2) +#define RT_INSTR_EXIT_HW_LOW_PWR U(3) +#define RT_INSTR_ENTER_CFLUSH U(4) +#define RT_INSTR_EXIT_CFLUSH U(5) +#define RT_INSTR_TOTAL_IDS U(6) + +#ifndef __ASSEMBLER__ +PMF_DECLARE_CAPTURE_TIMESTAMP(rt_instr_svc) +PMF_DECLARE_GET_TIMESTAMP(rt_instr_svc) +#endif /* __ASSEMBLER__ */ + +#endif /* RUNTIME_INSTR_H */ diff --git a/drivers/rz/ipl/rza/include/lib/semihosting.h b/drivers/rz/ipl/rza/include/lib/semihosting.h new file mode 100644 index 00000000..24b030cf --- /dev/null +++ b/drivers/rz/ipl/rza/include/lib/semihosting.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SEMIHOSTING_H +#define SEMIHOSTING_H + +#include +#include /* For ssize_t */ + + +#define SEMIHOSTING_SYS_OPEN 0x01 +#define SEMIHOSTING_SYS_CLOSE 0x02 +#define SEMIHOSTING_SYS_WRITE0 0x04 +#define SEMIHOSTING_SYS_WRITEC 0x03 +#define SEMIHOSTING_SYS_WRITE 0x05 +#define SEMIHOSTING_SYS_READ 0x06 +#define SEMIHOSTING_SYS_READC 0x07 +#define SEMIHOSTING_SYS_SEEK 0x0A +#define SEMIHOSTING_SYS_FLEN 0x0C +#define SEMIHOSTING_SYS_REMOVE 0x0E +#define SEMIHOSTING_SYS_SYSTEM 0x12 +#define SEMIHOSTING_SYS_ERRNO 0x13 +#define SEMIHOSTING_SYS_EXIT 0x18 + +#define FOPEN_MODE_R 0x0 +#define FOPEN_MODE_RB 0x1 +#define FOPEN_MODE_RPLUS 0x2 +#define FOPEN_MODE_RPLUSB 0x3 +#define FOPEN_MODE_W 0x4 +#define FOPEN_MODE_WB 0x5 +#define FOPEN_MODE_WPLUS 0x6 +#define FOPEN_MODE_WPLUSB 0x7 +#define FOPEN_MODE_A 0x8 +#define FOPEN_MODE_AB 0x9 +#define FOPEN_MODE_APLUS 0xa +#define FOPEN_MODE_APLUSB 0xb + +long semihosting_connection_supported(void); +long semihosting_file_open(const char *file_name, size_t mode); +long semihosting_file_seek(long file_handle, ssize_t offset); +long semihosting_file_read(long file_handle, size_t *length, uintptr_t buffer); +long semihosting_file_write(long file_handle, + size_t *length, + const uintptr_t buffer); +long semihosting_file_close(long file_handle); +long semihosting_file_length(long file_handle); +long semihosting_system(char *command_line); +long semihosting_get_flen(const char *file_name); +long semihosting_download_file(const char *file_name, + size_t buf_size, + uintptr_t buf); +void semihosting_write_char(char character); +void semihosting_write_string(char *string); +char semihosting_read_char(void); +void semihosting_exit(uint32_t reason, uint32_t subcode); + +#endif /* SEMIHOSTING_H */ diff --git a/drivers/rz/ipl/rza/include/lib/smccc.h b/drivers/rz/ipl/rza/include/lib/smccc.h new file mode 100644 index 00000000..470317dd --- /dev/null +++ b/drivers/rz/ipl/rza/include/lib/smccc.h @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SMCCC_H +#define SMCCC_H + +#include + +#define SMCCC_VERSION_MAJOR_SHIFT U(16) +#define SMCCC_VERSION_MAJOR_MASK U(0x7FFF) +#define SMCCC_VERSION_MINOR_SHIFT U(0) +#define SMCCC_VERSION_MINOR_MASK U(0xFFFF) +#define MAKE_SMCCC_VERSION(_major, _minor) \ + ((((uint32_t)(_major) & SMCCC_VERSION_MAJOR_MASK) << \ + SMCCC_VERSION_MAJOR_SHIFT) \ + | (((uint32_t)(_minor) & SMCCC_VERSION_MINOR_MASK) << \ + SMCCC_VERSION_MINOR_SHIFT)) + +#define SMCCC_MAJOR_VERSION U(1) +#define SMCCC_MINOR_VERSION U(2) + +/******************************************************************************* + * Bit definitions inside the function id as per the SMC calling convention + ******************************************************************************/ +#define FUNCID_TYPE_SHIFT U(31) +#define FUNCID_TYPE_MASK U(0x1) +#define FUNCID_TYPE_WIDTH U(1) + +#define FUNCID_CC_SHIFT U(30) +#define FUNCID_CC_MASK U(0x1) +#define FUNCID_CC_WIDTH U(1) + +#define FUNCID_OEN_SHIFT U(24) +#define FUNCID_OEN_MASK U(0x3f) +#define FUNCID_OEN_WIDTH U(6) + +#define FUNCID_NUM_SHIFT U(0) +#define FUNCID_NUM_MASK U(0xffff) +#define FUNCID_NUM_WIDTH U(16) + +#define GET_SMC_NUM(id) (((id) >> FUNCID_NUM_SHIFT) & \ + FUNCID_NUM_MASK) +#define GET_SMC_TYPE(id) (((id) >> FUNCID_TYPE_SHIFT) & \ + FUNCID_TYPE_MASK) +#define GET_SMC_CC(id) (((id) >> FUNCID_CC_SHIFT) & \ + FUNCID_CC_MASK) +#define GET_SMC_OEN(id) (((id) >> FUNCID_OEN_SHIFT) & \ + FUNCID_OEN_MASK) + +/******************************************************************************* + * Owning entity number definitions inside the function id as per the SMC + * calling convention + ******************************************************************************/ +#define OEN_ARM_START U(0) +#define OEN_ARM_END U(0) +#define OEN_CPU_START U(1) +#define OEN_CPU_END U(1) +#define OEN_SIP_START U(2) +#define OEN_SIP_END U(2) +#define OEN_OEM_START U(3) +#define OEN_OEM_END U(3) +#define OEN_STD_START U(4) /* Standard Service Calls */ +#define OEN_STD_END U(4) +#define OEN_STD_HYP_START U(5) /* Standard Hypervisor Service calls */ +#define OEN_STD_HYP_END U(5) +#define OEN_VEN_HYP_START U(6) /* Vendor Hypervisor Service calls */ +#define OEN_VEN_HYP_END U(6) +#define OEN_TAP_START U(48) /* Trusted Applications */ +#define OEN_TAP_END U(49) +#define OEN_TOS_START U(50) /* Trusted OS */ +#define OEN_TOS_END U(63) +#define OEN_LIMIT U(64) + +/* Flags and error codes */ +#define SMC_64 U(1) +#define SMC_32 U(0) + +#define SMC_TYPE_FAST UL(1) +#define SMC_TYPE_YIELD UL(0) + +#define SMC_OK ULL(0) +#define SMC_UNK -1 +#define SMC_PREEMPTED -2 /* Not defined by the SMCCC */ + +/* Return codes for Arm Architecture Service SMC calls */ +#define SMC_ARCH_CALL_SUCCESS 0 +#define SMC_ARCH_CALL_NOT_SUPPORTED -1 +#define SMC_ARCH_CALL_NOT_REQUIRED -2 +#define SMC_ARCH_CALL_INVAL_PARAM -3 + +/* Various flags passed to SMC handlers */ +#define SMC_FROM_SECURE (U(0) << 0) +#define SMC_FROM_NON_SECURE (U(1) << 0) + +#ifndef __ASSEMBLER__ + +#include + +#include + +#define is_caller_non_secure(_f) (((_f) & SMC_FROM_NON_SECURE) != U(0)) +#define is_caller_secure(_f) (!is_caller_non_secure(_f)) + +/* The macro below is used to identify a Standard Service SMC call */ +#define is_std_svc_call(_fid) (GET_SMC_OEN(_fid) == OEN_STD_START) + +/* The macro below is used to identify a Arm Architectural Service SMC call */ +#define is_arm_arch_svc_call(_fid) (GET_SMC_OEN(_fid) == OEN_ARM_START) + +/* The macro below is used to identify a valid Fast SMC call */ +#define is_valid_fast_smc(_fid) ((!(((_fid) >> 16) & U(0xff))) && \ + (GET_SMC_TYPE(_fid) \ + == (uint32_t)SMC_TYPE_FAST)) + +/* + * Macro to define UUID for services. Apart from defining and initializing a + * uuid_t structure, this macro verifies that the first word of the defined UUID + * does not equal SMC_UNK. This is to ensure that the caller won't mistake the + * returned UUID in x0 for an invalid SMC error return + */ +#define DEFINE_SVC_UUID2(_name, _tl, _tm, _th, _cl, _ch, \ + _n0, _n1, _n2, _n3, _n4, _n5) \ + CASSERT((uint32_t)(_tl) != (uint32_t)SMC_UNK, \ + invalid_svc_uuid_##_name); \ + static const uuid_t _name = { \ + {((_tl) >> 24) & 0xFF, \ + ((_tl) >> 16) & 0xFF, \ + ((_tl) >> 8) & 0xFF, \ + ((_tl) & 0xFF)}, \ + {((_tm) >> 8) & 0xFF, \ + ((_tm) & 0xFF)}, \ + {((_th) >> 8) & 0xFF, \ + ((_th) & 0xFF)}, \ + (_cl), (_ch), \ + { (_n0), (_n1), (_n2), (_n3), (_n4), (_n5) } \ + } + +/* + * Return a UUID in the SMC return registers. + * + * Acccording to section 5.3 of the SMCCC, UUIDs are returned as a single + * 128-bit value using the SMC32 calling convention. This value is mapped to + * argument registers x0-x3 on AArch64 (resp. r0-r3 on AArch32). x0 for example + * shall hold bytes 0 to 3, with byte 0 in the low-order bits. + */ +static inline uint32_t smc_uuid_word(uint8_t b0, uint8_t b1, uint8_t b2, uint8_t b3) +{ + return ((uint32_t) b0) | (((uint32_t) b1) << 8) | + (((uint32_t) b2) << 16) | (((uint32_t) b3) << 24); +} + +#define SMC_UUID_RET(_h, _uuid) \ + SMC_RET4(handle, \ + smc_uuid_word((_uuid).time_low[0], (_uuid).time_low[1], \ + (_uuid).time_low[2], (_uuid).time_low[3]), \ + smc_uuid_word((_uuid).time_mid[0], (_uuid).time_mid[1], \ + (_uuid).time_hi_and_version[0], \ + (_uuid).time_hi_and_version[1]), \ + smc_uuid_word((_uuid).clock_seq_hi_and_reserved, \ + (_uuid).clock_seq_low, (_uuid).node[0], \ + (_uuid).node[1]), \ + smc_uuid_word((_uuid).node[2], (_uuid).node[3], \ + (_uuid).node[4], (_uuid).node[5])) + +#endif /*__ASSEMBLER__*/ +#endif /* SMCCC_H */ diff --git a/drivers/rz/ipl/rza/include/lib/spinlock.h b/drivers/rz/ipl/rza/include/lib/spinlock.h new file mode 100644 index 00000000..0bf3ee06 --- /dev/null +++ b/drivers/rz/ipl/rza/include/lib/spinlock.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SPINLOCK_H +#define SPINLOCK_H + +#ifndef __ASSEMBLER__ + +#include + +typedef struct spinlock { + volatile uint32_t lock; +} spinlock_t; + +void spin_lock(spinlock_t *lock); +void spin_unlock(spinlock_t *lock); + +#else + +/* Spin lock definitions for use in assembly */ +#define SPINLOCK_ASM_ALIGN 2 +#define SPINLOCK_ASM_SIZE 4 + +#endif + +#endif /* SPINLOCK_H */ diff --git a/drivers/rz/ipl/rza/include/lib/utils.h b/drivers/rz/ipl/rza/include/lib/utils.h new file mode 100644 index 00000000..17ee9369 --- /dev/null +++ b/drivers/rz/ipl/rza/include/lib/utils.h @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef UTILS_H +#define UTILS_H + +/* + * C code should be put in this part of the header to avoid breaking ASM files + * or linker scripts including it. + */ +#if !(defined(__LINKER__) || defined(__ASSEMBLER__)) + +#include +#include + +typedef struct mem_region { + uintptr_t base; + size_t nbytes; +} mem_region_t; + +/* + * zero_normalmem all the regions defined in tbl. + */ +void clear_mem_regions(mem_region_t *tbl, size_t nregions); + +/* + * zero_normalmem all the regions defined in region. It dynamically + * maps chunks of 'chunk_size' in 'va' virtual address and clears them. + * For this reason memory regions must be multiple of chunk_size and + * must be aligned to it as well. chunk_size and va can be selected + * in a way that they minimize the number of entries used in the + * translation tables. + */ +void clear_map_dyn_mem_regions(struct mem_region *regions, + size_t nregions, + uintptr_t va, + size_t chunk); + +/* + * checks that a region (addr + nbytes-1) of memory is totally covered by + * one of the regions defined in tbl. Caller must ensure that (addr+nbytes-1) + * doesn't overflow. + */ +int mem_region_in_array_chk(mem_region_t *tbl, size_t nregions, + uintptr_t addr, size_t nbytes); + +/* + * Fill a region of normal memory of size "length" in bytes with zero bytes. + * + * WARNING: This function can only operate on normal memory. This means that + * the MMU must be enabled when using this function. Otherwise, use + * zeromem. + */ +void zero_normalmem(void *mem, u_register_t length); + +/* + * Fill a region of memory of size "length" in bytes with null bytes. + * + * Unlike zero_normalmem, this function has no restriction on the type of + * memory targeted and can be used for any device memory as well as normal + * memory. This function must be used instead of zero_normalmem when MMU is + * disabled. + * + * NOTE: When data cache and MMU are enabled, prefer zero_normalmem for faster + * zeroing. + */ +void zeromem(void *mem, u_register_t length); + +/* + * Utility function to return the address of a symbol. By default, the + * compiler generates adr/adrp instruction pair to return the reference + * to the symbol and this utility is used to override this compiler + * generated to code to use `ldr` instruction. + * + * This helps when Position Independent Executable needs to reference a symbol + * which is constant and does not depend on the execute address of the binary. + */ +#define DEFINE_LOAD_SYM_ADDR(_name) \ +static inline u_register_t load_addr_## _name(void) \ +{ \ + u_register_t v; \ + __asm__ volatile ("ldr %0, =" #_name : "=r" (v) : "X" (#_name));\ + return v; \ +} + +/* Helper to invoke the function defined by DEFINE_LOAD_SYM_ADDR() */ +#define LOAD_ADDR_OF(_name) (typeof(_name) *) load_addr_## _name() + +#endif /* !(defined(__LINKER__) || defined(__ASSEMBLER__)) */ + +#endif /* UTILS_H */ diff --git a/drivers/rz/ipl/rza/include/lib/utils_def.h b/drivers/rz/ipl/rza/include/lib/utils_def.h new file mode 100644 index 00000000..7a7012d3 --- /dev/null +++ b/drivers/rz/ipl/rza/include/lib/utils_def.h @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2020, NVIDIA Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef UTILS_DEF_H +#define UTILS_DEF_H + +#include + +/* Compute the number of elements in the given array */ +#define ARRAY_SIZE(a) \ + (sizeof(a) / sizeof((a)[0])) + +#define IS_POWER_OF_TWO(x) \ + (((x) & ((x) - 1)) == 0) + +#define SIZE_FROM_LOG2_WORDS(n) (U(4) << (n)) + +#define BIT_32(nr) (U(1) << (nr)) +#define BIT_64(nr) (ULL(1) << (nr)) + +#ifdef __aarch64__ +#define BIT BIT_64 +#else +#define BIT BIT_32 +#endif + +/* + * Create a contiguous bitmask starting at bit position @l and ending at + * position @h. For example + * GENMASK_64(39, 21) gives us the 64bit vector 0x000000ffffe00000. + */ +#if defined(__LINKER__) || defined(__ASSEMBLER__) +#define GENMASK_32(h, l) \ + (((0xFFFFFFFF) << (l)) & (0xFFFFFFFF >> (32 - 1 - (h)))) + +#define GENMASK_64(h, l) \ + ((~0 << (l)) & (~0 >> (64 - 1 - (h)))) +#else +#define GENMASK_32(h, l) \ + (((~UINT32_C(0)) << (l)) & (~UINT32_C(0) >> (32 - 1 - (h)))) + +#define GENMASK_64(h, l) \ + (((~UINT64_C(0)) << (l)) & (~UINT64_C(0) >> (64 - 1 - (h)))) +#endif + +#ifdef __aarch64__ +#define GENMASK GENMASK_64 +#else +#define GENMASK GENMASK_32 +#endif + +/* + * This variant of div_round_up can be used in macro definition but should not + * be used in C code as the `div` parameter is evaluated twice. + */ +#define DIV_ROUND_UP_2EVAL(n, d) (((n) + (d) - 1) / (d)) + +#define div_round_up(val, div) __extension__ ({ \ + __typeof__(div) _div = (div); \ + ((val) + _div - (__typeof__(div)) 1) / _div; \ +}) + +#define MIN(x, y) __extension__ ({ \ + __typeof__(x) _x = (x); \ + __typeof__(y) _y = (y); \ + (void)(&_x == &_y); \ + _x < _y ? _x : _y; \ +}) + +#define MAX(x, y) __extension__ ({ \ + __typeof__(x) _x = (x); \ + __typeof__(y) _y = (y); \ + (void)(&_x == &_y); \ + _x > _y ? _x : _y; \ +}) + +#define CLAMP(x, min, max) __extension__ ({ \ + __typeof__(x) _x = (x); \ + __typeof__(min) _min = (min); \ + __typeof__(max) _max = (max); \ + (void)(&_x == &_min); \ + (void)(&_x == &_max); \ + (_x > _max ? _max : (_x < _min ? _min : _x)); \ +}) + +/* + * The round_up() macro rounds up a value to the given boundary in a + * type-agnostic yet type-safe manner. The boundary must be a power of two. + * In other words, it computes the smallest multiple of boundary which is + * greater than or equal to value. + * + * round_down() is similar but rounds the value down instead. + */ +#define round_boundary(value, boundary) \ + ((__typeof__(value))((boundary) - 1)) + +#define round_up(value, boundary) \ + ((((value) - 1) | round_boundary(value, boundary)) + 1) + +#define round_down(value, boundary) \ + ((value) & ~round_boundary(value, boundary)) + +/* + * Evaluates to 1 if (ptr + inc) overflows, 0 otherwise. + * Both arguments must be unsigned pointer values (i.e. uintptr_t). + */ +#define check_uptr_overflow(_ptr, _inc) \ + ((_ptr) > (UINTPTR_MAX - (_inc))) + +/* + * Evaluates to 1 if (u32 + inc) overflows, 0 otherwise. + * Both arguments must be 32-bit unsigned integers (i.e. effectively uint32_t). + */ +#define check_u32_overflow(_u32, _inc) \ + ((_u32) > (UINT32_MAX - (_inc))) + +/* Register size of the current architecture. */ +#ifdef __aarch64__ +#define REGSZ U(8) +#else +#define REGSZ U(4) +#endif + +/* + * Test for the current architecture version to be at least the version + * expected. + */ +#define ARM_ARCH_AT_LEAST(_maj, _min) \ + ((ARM_ARCH_MAJOR > (_maj)) || \ + ((ARM_ARCH_MAJOR == (_maj)) && (ARM_ARCH_MINOR >= (_min)))) + +/* + * Import an assembly or linker symbol as a C expression with the specified + * type + */ +#define IMPORT_SYM(type, sym, name) \ + extern char sym[];\ + static const __attribute__((unused)) type name = (type) sym; + +/* + * When the symbol is used to hold a pointer, its alignment can be asserted + * with this macro. For example, if there is a linker symbol that is going to + * be used as a 64-bit pointer, the value of the linker symbol must also be + * aligned to 64 bit. This macro makes sure this is the case. + */ +#define ASSERT_SYM_PTR_ALIGN(sym) assert(((size_t)(sym) % __alignof__(*(sym))) == 0) + +#define COMPILER_BARRIER() __asm__ volatile ("" ::: "memory") + +/* Compiler builtin of GCC >= 9 and planned in llvm */ +#ifdef __HAVE_SPECULATION_SAFE_VALUE +# define SPECULATION_SAFE_VALUE(var) __builtin_speculation_safe_value(var) +#else +# define SPECULATION_SAFE_VALUE(var) var +#endif + +/* + * Ticks elapsed in one second with a signal of 1 MHz + */ +#define MHZ_TICKS_PER_SEC U(1000000) + +/* + * Ticks elapsed in one second with a signal of 1 KHz + */ +#define KHZ_TICKS_PER_SEC U(1000) + +#endif /* UTILS_DEF_H */ diff --git a/drivers/rz/ipl/rza/include/lib/xlat_tables/aarch64/xlat_tables_aarch64.h b/drivers/rz/ipl/rza/include/lib/xlat_tables/aarch64/xlat_tables_aarch64.h new file mode 100644 index 00000000..3014c8fe --- /dev/null +++ b/drivers/rz/ipl/rza/include/lib/xlat_tables/aarch64/xlat_tables_aarch64.h @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef XLAT_TABLES_AARCH64_H +#define XLAT_TABLES_AARCH64_H + +#include +#include +#include + +#if !defined(PAGE_SIZE) +#error "PAGE_SIZE is not defined." +#endif + +/* + * Encode a Physical Address Space size for its use in TCR_ELx. + */ +unsigned long long tcr_physical_addr_size_bits(unsigned long long max_addr); + +/* + * In AArch64 state, the MMU may support 4 KB, 16 KB and 64 KB page + * granularity. For 4KB granularity, a level 0 table descriptor doesn't support + * block translation. For 16KB, the same thing happens to levels 0 and 1. For + * 64KB, same for level 1. See section D4.3.1 of the ARMv8-A Architecture + * Reference Manual (DDI 0487A.k) for more information. + * + * The define below specifies the first table level that allows block + * descriptors. + */ +#if PAGE_SIZE == PAGE_SIZE_4KB +# define MIN_LVL_BLOCK_DESC U(1) +#elif (PAGE_SIZE == PAGE_SIZE_16KB) || (PAGE_SIZE == PAGE_SIZE_64KB) +# define MIN_LVL_BLOCK_DESC U(2) +#endif + +#define XLAT_TABLE_LEVEL_MIN U(0) + +/* + * Define the architectural limits of the virtual address space in AArch64 + * state. + * + * TCR.TxSZ is calculated as 64 minus the width of said address space. + * The value of TCR.TxSZ must be in the range 16 to 39 [1] or 48 [2], + * depending on Small Translation Table Support which means that + * the virtual address space width must be in the range 48 to 25 or 16 bits. + * + * [1] See the ARMv8-A Architecture Reference Manual (DDI 0487A.j) for more + * information: + * Page 1730: 'Input address size', 'For all translation stages'. + * [2] See section 12.2.55 in the ARMv8-A Architecture Reference Manual + * (DDI 0487D.a) + */ +/* Maximum value of TCR_ELx.T(0,1)SZ is 39 */ +#define MIN_VIRT_ADDR_SPACE_SIZE (ULL(1) << (U(64) - TCR_TxSZ_MAX)) + +/* Maximum value of TCR_ELx.T(0,1)SZ is 48 */ +#define MIN_VIRT_ADDR_SPACE_SIZE_TTST \ + (ULL(1) << (U(64) - TCR_TxSZ_MAX_TTST)) +#define MAX_VIRT_ADDR_SPACE_SIZE (ULL(1) << (U(64) - TCR_TxSZ_MIN)) + +/* + * Here we calculate the initial lookup level from the value of the given + * virtual address space size. For a 4 KB page size, + * - level 0 supports virtual address spaces of widths 48 to 40 bits; + * - level 1 from 39 to 31; + * - level 2 from 30 to 22. + * - level 3 from 21 to 16. + * + * Small Translation Table (Armv8.4-TTST) support allows the starting level + * of the translation table from 3 for 4KB granularity. See section 12.2.55 in + * the ARMv8-A Architecture Reference Manual (DDI 0487D.a). In Armv8.3 and below + * wider or narrower address spaces are not supported. As a result, level 3 + * cannot be used as initial lookup level with 4 KB granularity. See section + * D4.2.5 in the ARMv8-A Architecture Reference Manual (DDI 0487A.j) for more + * information. + * + * For example, for a 35-bit address space (i.e. virt_addr_space_size == + * 1 << 35), TCR.TxSZ will be programmed to (64 - 35) = 29. According to Table + * D4-11 in the ARM ARM, the initial lookup level for an address space like that + * is 1. + * + * Note that this macro assumes that the given virtual address space size is + * valid. + */ +#define GET_XLAT_TABLE_LEVEL_BASE(_virt_addr_space_sz) \ + (((_virt_addr_space_sz) > (ULL(1) << L0_XLAT_ADDRESS_SHIFT)) \ + ? 0U \ + : (((_virt_addr_space_sz) > (ULL(1) << L1_XLAT_ADDRESS_SHIFT)) \ + ? 1U \ + : (((_virt_addr_space_sz) > (ULL(1) << L2_XLAT_ADDRESS_SHIFT)) \ + ? 2U : 3U))) + +#endif /* XLAT_TABLES_AARCH64_H */ diff --git a/drivers/rz/ipl/rza/include/lib/xlat_tables/xlat_mmu_helpers.h b/drivers/rz/ipl/rza/include/lib/xlat_tables/xlat_mmu_helpers.h new file mode 100644 index 00000000..269afd28 --- /dev/null +++ b/drivers/rz/ipl/rza/include/lib/xlat_tables/xlat_mmu_helpers.h @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2014-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef XLAT_MMU_HELPERS_H +#define XLAT_MMU_HELPERS_H + +/* + * The following flags are passed to enable_mmu_xxx() to override the default + * values used to program system registers while enabling the MMU. + */ + +/* + * When this flag is used, all data access to Normal memory from this EL and all + * Normal memory accesses to the translation tables of this EL are non-cacheable + * for all levels of data and unified cache until the caches are enabled by + * setting the bit SCTLR_ELx.C. + */ +#define DISABLE_DCACHE (U(1) << 0) + +/* + * Mark the translation tables as non-cacheable for the MMU table walker, which + * is a different observer from the PE/CPU. If the flag is not specified, the + * tables are cacheable for the MMU table walker. + * + * Note that, as far as the PE/CPU observer is concerned, the attributes used + * are the ones specified in the translation tables themselves. The MAIR + * register specifies the cacheability through the field AttrIndx of the lower + * attributes of the translation tables. The shareability is specified in the SH + * field of the lower attributes. + * + * The MMU table walker uses the attributes specified in the fields ORGNn, IRGNn + * and SHn of the TCR register to access the translation tables. + * + * The attributes specified in the TCR register and the tables can be different + * as there are no checks to prevent that. Special care must be taken to ensure + * that there aren't mismatches. The behaviour in that case is described in the + * sections 'Mismatched memory attributes' in the ARMv8 ARM. + */ +#define XLAT_TABLE_NC (U(1) << 1) + +/* + * Offsets into a mmu_cfg_params array generated by setup_mmu_cfg(). All + * parameters are 64 bits wide. + */ +#define MMU_CFG_MAIR 0 +#define MMU_CFG_TCR 1 +#define MMU_CFG_TTBR0 2 +#define MMU_CFG_PARAM_MAX 3 + +#ifndef __ASSEMBLER__ + +#include +#include +#include + +#include + +/* + * Return the values that the MMU configuration registers must contain for the + * specified translation context. `params` must be a pointer to array of size + * MMU_CFG_PARAM_MAX. + */ +void setup_mmu_cfg(uint64_t *params, unsigned int flags, + const uint64_t *base_table, unsigned long long max_pa, + uintptr_t max_va, int xlat_regime); + +#ifdef __aarch64__ +/* AArch64 specific translation table APIs */ +void enable_mmu_el1(unsigned int flags); +void enable_mmu_el2(unsigned int flags); +void enable_mmu_el3(unsigned int flags); +void enable_mmu(unsigned int flags); + +void enable_mmu_direct_el1(unsigned int flags); +void enable_mmu_direct_el2(unsigned int flags); +void enable_mmu_direct_el3(unsigned int flags); +#else +/* AArch32 specific translation table API */ +void enable_mmu_svc_mon(unsigned int flags); +void enable_mmu_hyp(unsigned int flags); + +void enable_mmu_direct_svc_mon(unsigned int flags); +void enable_mmu_direct_hyp(unsigned int flags); +#endif /* __aarch64__ */ + +bool xlat_arch_is_granule_size_supported(size_t size); +size_t xlat_arch_get_max_supported_granule_size(void); + +#endif /* __ASSEMBLER__ */ + +#endif /* XLAT_MMU_HELPERS_H */ diff --git a/drivers/rz/ipl/rza/include/lib/xlat_tables/xlat_tables.h b/drivers/rz/ipl/rza/include/lib/xlat_tables/xlat_tables.h new file mode 100644 index 00000000..082bb5e4 --- /dev/null +++ b/drivers/rz/ipl/rza/include/lib/xlat_tables/xlat_tables.h @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2014-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef XLAT_TABLES_H +#define XLAT_TABLES_H + +#include + +#ifndef __ASSEMBLER__ +#include +#include + +#include + +/* Helper macro to define entries for mmap_region_t. It creates + * identity mappings for each region. + */ +#define MAP_REGION_FLAT(adr, sz, attr) MAP_REGION(adr, adr, sz, attr) + +/* Helper macro to define entries for mmap_region_t. It allows to + * re-map address mappings from 'pa' to 'va' for each region. + */ +#define MAP_REGION(pa, va, sz, attr) {(pa), (va), (sz), (attr)} + +/* + * Shifts and masks to access fields of an mmap attribute + */ +#define MT_TYPE_MASK U(0x7) +#define MT_TYPE(_attr) ((_attr) & MT_TYPE_MASK) +/* Access permissions (RO/RW) */ +#define MT_PERM_SHIFT U(3) +/* Security state (SECURE/NS) */ +#define MT_SEC_SHIFT U(4) +/* Access permissions for instruction execution (EXECUTE/EXECUTE_NEVER) */ +#define MT_EXECUTE_SHIFT U(5) + +/* + * Memory mapping attributes + */ + +/* + * Memory types supported. + * These are organised so that, going down the list, the memory types are + * getting weaker; conversely going up the list the memory types are getting + * stronger. + */ +#define MT_DEVICE U(0) +#define MT_NON_CACHEABLE U(1) +#define MT_MEMORY U(2) +/* Values up to 7 are reserved to add new memory types in the future */ + +#define MT_RO (U(0) << MT_PERM_SHIFT) +#define MT_RW (U(1) << MT_PERM_SHIFT) + +#define MT_SECURE (U(0) << MT_SEC_SHIFT) +#define MT_NS (U(1) << MT_SEC_SHIFT) + +/* + * Access permissions for instruction execution are only relevant for normal + * read-only memory, i.e. MT_MEMORY | MT_RO. They are ignored (and potentially + * overridden) otherwise: + * - Device memory is always marked as execute-never. + * - Read-write normal memory is always marked as execute-never. + */ +#define MT_EXECUTE (U(0) << MT_EXECUTE_SHIFT) +#define MT_EXECUTE_NEVER (U(1) << MT_EXECUTE_SHIFT) + +/* Compound attributes for most common usages */ +#define MT_CODE (MT_MEMORY | MT_RO | MT_EXECUTE) +#define MT_RO_DATA (MT_MEMORY | MT_RO | MT_EXECUTE_NEVER) + +/* + * Structure for specifying a single region of memory. + */ +typedef struct mmap_region { + unsigned long long base_pa; + uintptr_t base_va; + size_t size; + unsigned int attr; +} mmap_region_t; + +/* Generic translation table APIs */ +void init_xlat_tables(void); +void mmap_add_region(unsigned long long base_pa, uintptr_t base_va, + size_t size, unsigned int attr); +void mmap_add(const mmap_region_t *mm); + +#endif /*__ASSEMBLER__*/ +#endif /* XLAT_TABLES_H */ diff --git a/drivers/rz/ipl/rza/include/lib/xlat_tables/xlat_tables_arch.h b/drivers/rz/ipl/rza/include/lib/xlat_tables/xlat_tables_arch.h new file mode 100644 index 00000000..0ce0cacb --- /dev/null +++ b/drivers/rz/ipl/rza/include/lib/xlat_tables/xlat_tables_arch.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef XLAT_TABLES_ARCH_H +#define XLAT_TABLES_ARCH_H + +#ifdef __aarch64__ +#include "aarch64/xlat_tables_aarch64.h" +#else +#include "aarch32/xlat_tables_aarch32.h" +#endif + +/* + * Evaluates to 1 if the given physical address space size is a power of 2, + * or 0 if it's not. + */ +#define CHECK_PHY_ADDR_SPACE_SIZE(size) \ + (IS_POWER_OF_TWO(size)) + +/* + * Compute the number of entries required at the initial lookup level to address + * the whole virtual address space. + */ +#define GET_NUM_BASE_LEVEL_ENTRIES(addr_space_size) \ + ((addr_space_size) >> \ + XLAT_ADDR_SHIFT(GET_XLAT_TABLE_LEVEL_BASE(addr_space_size))) + +#endif /* XLAT_TABLES_ARCH_H */ diff --git a/drivers/rz/ipl/rza/include/lib/xlat_tables/xlat_tables_compat.h b/drivers/rz/ipl/rza/include/lib/xlat_tables/xlat_tables_compat.h new file mode 100644 index 00000000..90768db5 --- /dev/null +++ b/drivers/rz/ipl/rza/include/lib/xlat_tables/xlat_tables_compat.h @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#if XLAT_TABLES_LIB_V2 +#include +#else +#include +#endif diff --git a/drivers/rz/ipl/rza/include/lib/xlat_tables/xlat_tables_defs.h b/drivers/rz/ipl/rza/include/lib/xlat_tables/xlat_tables_defs.h new file mode 100644 index 00000000..579d8d89 --- /dev/null +++ b/drivers/rz/ipl/rza/include/lib/xlat_tables/xlat_tables_defs.h @@ -0,0 +1,182 @@ +/* + * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef XLAT_TABLES_DEFS_H +#define XLAT_TABLES_DEFS_H + +#include +#include +#include + +/* Miscellaneous MMU related constants */ +#define NUM_2MB_IN_GB (U(1) << 9) +#define NUM_4K_IN_2MB (U(1) << 9) +#define NUM_GB_IN_4GB (U(1) << 2) + +#define TWO_MB_SHIFT U(21) +#define ONE_GB_SHIFT U(30) +#define FOUR_KB_SHIFT U(12) + +#define ONE_GB_INDEX(x) ((x) >> ONE_GB_SHIFT) +#define TWO_MB_INDEX(x) ((x) >> TWO_MB_SHIFT) +#define FOUR_KB_INDEX(x) ((x) >> FOUR_KB_SHIFT) + +#define PAGE_SIZE_4KB U(4096) +#define PAGE_SIZE_16KB U(16384) +#define PAGE_SIZE_64KB U(65536) + +#define INVALID_DESC U(0x0) +/* + * A block descriptor points to a region of memory bigger than the granule size + * (e.g. a 2MB region when the granule size is 4KB). + */ +#define BLOCK_DESC U(0x1) /* Table levels 0-2 */ +/* A table descriptor points to the next level of translation table. */ +#define TABLE_DESC U(0x3) /* Table levels 0-2 */ +/* + * A page descriptor points to a page, i.e. a memory region whose size is the + * translation granule size (e.g. 4KB). + */ +#define PAGE_DESC U(0x3) /* Table level 3 */ + +#define DESC_MASK U(0x3) + +#define FIRST_LEVEL_DESC_N ONE_GB_SHIFT +#define SECOND_LEVEL_DESC_N TWO_MB_SHIFT +#define THIRD_LEVEL_DESC_N FOUR_KB_SHIFT + +/* XN: Translation regimes that support one VA range (EL2 and EL3). */ +#define XN (ULL(1) << 2) +/* UXN, PXN: Translation regimes that support two VA ranges (EL1&0). */ +#define UXN (ULL(1) << 2) +#define PXN (ULL(1) << 1) +#define CONT_HINT (ULL(1) << 0) +#define UPPER_ATTRS(x) (((x) & ULL(0x7)) << 52) + +#define NON_GLOBAL (U(1) << 9) +#define ACCESS_FLAG (U(1) << 8) +#define NSH (U(0x0) << 6) +#define OSH (U(0x2) << 6) +#define ISH (U(0x3) << 6) + +#ifdef __aarch64__ +/* Guarded Page bit */ +#define GP (ULL(1) << 50) +#endif + +#define TABLE_ADDR_MASK ULL(0x0000FFFFFFFFF000) + +/* + * The ARMv8-A architecture allows translation granule sizes of 4KB, 16KB or + * 64KB. However, only 4KB are supported at the moment. + */ +#define PAGE_SIZE_SHIFT FOUR_KB_SHIFT +#define PAGE_SIZE (UL(1) << PAGE_SIZE_SHIFT) +#define PAGE_SIZE_MASK (PAGE_SIZE - UL(1)) +#define IS_PAGE_ALIGNED(addr) (((addr) & PAGE_SIZE_MASK) == U(0)) + +#if (ARM_ARCH_MAJOR == 7) && !ARMV7_SUPPORTS_LARGE_PAGE_ADDRESSING +#define XLAT_ENTRY_SIZE_SHIFT U(2) /* Each MMU table entry is 4 bytes */ +#else +#define XLAT_ENTRY_SIZE_SHIFT U(3) /* Each MMU table entry is 8 bytes */ +#endif +#define XLAT_ENTRY_SIZE (U(1) << XLAT_ENTRY_SIZE_SHIFT) + +#define XLAT_TABLE_SIZE_SHIFT PAGE_SIZE_SHIFT /* Size of one complete table */ +#define XLAT_TABLE_SIZE (U(1) << XLAT_TABLE_SIZE_SHIFT) + +#define XLAT_TABLE_LEVEL_MAX U(3) + +/* Values for number of entries in each MMU translation table */ +#define XLAT_TABLE_ENTRIES_SHIFT (XLAT_TABLE_SIZE_SHIFT - XLAT_ENTRY_SIZE_SHIFT) +#define XLAT_TABLE_ENTRIES (U(1) << XLAT_TABLE_ENTRIES_SHIFT) +#define XLAT_TABLE_ENTRIES_MASK (XLAT_TABLE_ENTRIES - U(1)) + +/* Values to convert a memory address to an index into a translation table */ +#define L3_XLAT_ADDRESS_SHIFT PAGE_SIZE_SHIFT +#define L2_XLAT_ADDRESS_SHIFT (L3_XLAT_ADDRESS_SHIFT + XLAT_TABLE_ENTRIES_SHIFT) +#define L1_XLAT_ADDRESS_SHIFT (L2_XLAT_ADDRESS_SHIFT + XLAT_TABLE_ENTRIES_SHIFT) +#define L0_XLAT_ADDRESS_SHIFT (L1_XLAT_ADDRESS_SHIFT + XLAT_TABLE_ENTRIES_SHIFT) +#define XLAT_ADDR_SHIFT(level) (PAGE_SIZE_SHIFT + \ + ((XLAT_TABLE_LEVEL_MAX - (level)) * XLAT_TABLE_ENTRIES_SHIFT)) + +#define XLAT_BLOCK_SIZE(level) (UL(1) << XLAT_ADDR_SHIFT(level)) +/* Mask to get the bits used to index inside a block of a certain level */ +#define XLAT_BLOCK_MASK(level) (XLAT_BLOCK_SIZE(level) - UL(1)) +/* Mask to get the address bits common to a block of a certain table level*/ +#define XLAT_ADDR_MASK(level) (~XLAT_BLOCK_MASK(level)) +/* + * Extract from the given virtual address the index into the given lookup level. + * This macro assumes the system is using the 4KB translation granule. + */ +#define XLAT_TABLE_IDX(virtual_addr, level) \ + (((virtual_addr) >> XLAT_ADDR_SHIFT(level)) & ULL(0x1FF)) + +/* + * The ARMv8 translation table descriptor format defines AP[2:1] as the Access + * Permissions bits, and does not define an AP[0] bit. + * + * AP[1] is valid only for a stage 1 translation that supports two VA ranges + * (i.e. in the ARMv8A.0 architecture, that is the S-EL1&0 regime). It is RES1 + * when stage 1 translations can only support one VA range. + */ +#define AP2_SHIFT U(0x7) +#define AP2_RO ULL(0x1) +#define AP2_RW ULL(0x0) + +#define AP1_SHIFT U(0x6) +#define AP1_ACCESS_UNPRIVILEGED ULL(0x1) +#define AP1_NO_ACCESS_UNPRIVILEGED ULL(0x0) +#define AP1_RES1 ULL(0x1) + +/* + * The following definitions must all be passed to the LOWER_ATTRS() macro to + * get the right bitmask. + */ +#define AP_RO (AP2_RO << 5) +#define AP_RW (AP2_RW << 5) +#define AP_ACCESS_UNPRIVILEGED (AP1_ACCESS_UNPRIVILEGED << 4) +#define AP_NO_ACCESS_UNPRIVILEGED (AP1_NO_ACCESS_UNPRIVILEGED << 4) +#define AP_ONE_VA_RANGE_RES1 (AP1_RES1 << 4) +#define NS (U(0x1) << 3) +#define ATTR_NON_CACHEABLE_INDEX ULL(0x2) +#define ATTR_DEVICE_INDEX ULL(0x1) +#define ATTR_IWBWA_OWBWA_NTR_INDEX ULL(0x0) +#define LOWER_ATTRS(x) (((x) & U(0xfff)) << 2) + +/* Normal Memory, Outer Write-Through non-transient, Inner Non-cacheable */ +#define ATTR_NON_CACHEABLE MAKE_MAIR_NORMAL_MEMORY(MAIR_NORM_NC, MAIR_NORM_NC) +/* Device-nGnRE */ +#define ATTR_DEVICE MAIR_DEV_nGnRE +/* Normal Memory, Outer Write-Back non-transient, Inner Write-Back non-transient */ +#define ATTR_IWBWA_OWBWA_NTR MAKE_MAIR_NORMAL_MEMORY(MAIR_NORM_WB_NTR_RWA, MAIR_NORM_WB_NTR_RWA) +#define MAIR_ATTR_SET(attr, index) ((attr) << ((index) << 3)) +#define ATTR_INDEX_MASK U(0x3) +#define ATTR_INDEX_GET(attr) (((attr) >> 2) & ATTR_INDEX_MASK) + +/* + * Shift values for the attributes fields in a block or page descriptor. + * See section D4.3.3 in the ARMv8-A ARM (issue B.a). + */ + +/* Memory attributes index field, AttrIndx[2:0]. */ +#define ATTR_INDEX_SHIFT 2 +/* Non-secure bit, NS. */ +#define NS_SHIFT 5 +/* Shareability field, SH[1:0] */ +#define SHAREABILITY_SHIFT 8 +/* The Access Flag, AF. */ +#define ACCESS_FLAG_SHIFT 10 +/* The not global bit, nG. */ +#define NOT_GLOBAL_SHIFT 11 +/* Contiguous hint bit. */ +#define CONT_HINT_SHIFT 52 +/* Execute-never bits, XN. */ +#define PXN_SHIFT 53 +#define XN_SHIFT 54 +#define UXN_SHIFT XN_SHIFT + +#endif /* XLAT_TABLES_DEFS_H */ diff --git a/drivers/rz/ipl/rza/include/lib/xlat_tables/xlat_tables_v2.h b/drivers/rz/ipl/rza/include/lib/xlat_tables/xlat_tables_v2.h new file mode 100644 index 00000000..359b9839 --- /dev/null +++ b/drivers/rz/ipl/rza/include/lib/xlat_tables/xlat_tables_v2.h @@ -0,0 +1,402 @@ +/* + * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef XLAT_TABLES_V2_H +#define XLAT_TABLES_V2_H + +#include +#include + +#ifndef __ASSEMBLER__ +#include +#include + +#include + +/* + * Default granularity size for an mmap_region_t. + * Useful when no specific granularity is required. + * + * By default, choose the biggest possible block size allowed by the + * architectural state and granule size in order to minimize the number of page + * tables required for the mapping. + */ +#define REGION_DEFAULT_GRANULARITY XLAT_BLOCK_SIZE(MIN_LVL_BLOCK_DESC) + +/* Helper macro to define an mmap_region_t. */ +#define MAP_REGION(_pa, _va, _sz, _attr) \ + MAP_REGION_FULL_SPEC(_pa, _va, _sz, _attr, REGION_DEFAULT_GRANULARITY) + +/* Helper macro to define an mmap_region_t with an identity mapping. */ +#define MAP_REGION_FLAT(_adr, _sz, _attr) \ + MAP_REGION(_adr, _adr, _sz, _attr) + +/* + * Helper macro to define entries for mmap_region_t. It allows to define 'pa' + * and sets 'va' to 0 for each region. To be used with mmap_add_alloc_va(). + */ +#define MAP_REGION_ALLOC_VA(pa, sz, attr) MAP_REGION(pa, 0, sz, attr) + +/* + * Helper macro to define an mmap_region_t to map with the desired granularity + * of translation tables. + * + * The granularity value passed to this macro must be a valid block or page + * size. When using a 4KB translation granule, this might be 4KB, 2MB or 1GB. + * Passing REGION_DEFAULT_GRANULARITY is also allowed and means that the library + * is free to choose the granularity for this region. In this case, it is + * equivalent to the MAP_REGION() macro. + */ +#define MAP_REGION2(_pa, _va, _sz, _attr, _gr) \ + MAP_REGION_FULL_SPEC(_pa, _va, _sz, _attr, _gr) + +/* + * Shifts and masks to access fields of an mmap attribute + */ +#define MT_TYPE_MASK U(0x7) +#define MT_TYPE(_attr) ((_attr) & MT_TYPE_MASK) +/* Access permissions (RO/RW) */ +#define MT_PERM_SHIFT U(3) +/* Security state (SECURE/NS) */ +#define MT_SEC_SHIFT U(4) +/* Access permissions for instruction execution (EXECUTE/EXECUTE_NEVER) */ +#define MT_EXECUTE_SHIFT U(5) +/* In the EL1&0 translation regime, User (EL0) or Privileged (EL1). */ +#define MT_USER_SHIFT U(6) + +/* Shareability attribute for the memory region */ +#define MT_SHAREABILITY_SHIFT U(7) +#define MT_SHAREABILITY_MASK (U(3) << MT_SHAREABILITY_SHIFT) +#define MT_SHAREABILITY(_attr) ((_attr) & MT_SHAREABILITY_MASK) +/* All other bits are reserved */ + +/* + * Memory mapping attributes + */ + +/* + * Memory types supported. + * These are organised so that, going down the list, the memory types are + * getting weaker; conversely going up the list the memory types are getting + * stronger. + */ +#define MT_DEVICE U(0) +#define MT_NON_CACHEABLE U(1) +#define MT_MEMORY U(2) +/* Values up to 7 are reserved to add new memory types in the future */ + +#define MT_RO (U(0) << MT_PERM_SHIFT) +#define MT_RW (U(1) << MT_PERM_SHIFT) + +#define MT_SECURE (U(0) << MT_SEC_SHIFT) +#define MT_NS (U(1) << MT_SEC_SHIFT) + +/* + * Access permissions for instruction execution are only relevant for normal + * read-only memory, i.e. MT_MEMORY | MT_RO. They are ignored (and potentially + * overridden) otherwise: + * - Device memory is always marked as execute-never. + * - Read-write normal memory is always marked as execute-never. + */ +#define MT_EXECUTE (U(0) << MT_EXECUTE_SHIFT) +#define MT_EXECUTE_NEVER (U(1) << MT_EXECUTE_SHIFT) + +/* + * When mapping a region at EL0 or EL1, this attribute will be used to determine + * if a User mapping (EL0) will be created or a Privileged mapping (EL1). + */ +#define MT_USER (U(1) << MT_USER_SHIFT) +#define MT_PRIVILEGED (U(0) << MT_USER_SHIFT) + +/* + * Shareability defines the visibility of any cache changes to + * all masters belonging to a shareable domain. + * + * MT_SHAREABILITY_ISH: For inner shareable domain + * MT_SHAREABILITY_OSH: For outer shareable domain + * MT_SHAREABILITY_NSH: For non shareable domain + */ +#define MT_SHAREABILITY_ISH (U(1) << MT_SHAREABILITY_SHIFT) +#define MT_SHAREABILITY_OSH (U(2) << MT_SHAREABILITY_SHIFT) +#define MT_SHAREABILITY_NSH (U(3) << MT_SHAREABILITY_SHIFT) + +/* Compound attributes for most common usages */ +#define MT_CODE (MT_MEMORY | MT_RO | MT_EXECUTE) +#define MT_RO_DATA (MT_MEMORY | MT_RO | MT_EXECUTE_NEVER) +#define MT_RW_DATA (MT_MEMORY | MT_RW | MT_EXECUTE_NEVER) + +/* + * Structure for specifying a single region of memory. + */ +typedef struct mmap_region { + unsigned long long base_pa; + uintptr_t base_va; + size_t size; + unsigned int attr; + /* Desired granularity. See the MAP_REGION2() macro for more details. */ + size_t granularity; +} mmap_region_t; + +/* + * Translation regimes supported by this library. EL_REGIME_INVALID tells the + * library to detect it at runtime. + */ +#define EL1_EL0_REGIME 1 +#define EL2_REGIME 2 +#define EL3_REGIME 3 +#define EL_REGIME_INVALID -1 + +/* + * Declare the translation context type. + * Its definition is private. + */ +typedef struct xlat_ctx xlat_ctx_t; + +/* + * Statically allocate a translation context and associated structures. Also + * initialize them. + * + * _ctx_name: + * Prefix for the translation context variable. + * E.g. If _ctx_name is 'foo', the variable will be called 'foo_xlat_ctx'. + * Useful to distinguish multiple contexts from one another. + * + * _mmap_count: + * Number of mmap_region_t to allocate. + * Would typically be MAX_MMAP_REGIONS for the translation context describing + * the BL image currently executing. + * + * _xlat_tables_count: + * Number of sub-translation tables to allocate. + * Would typically be MAX_XLAT_TABLES for the translation context describing + * the BL image currently executing. + * Note that this is only for sub-tables ; at the initial lookup level, there + * is always a single table. + * + * _virt_addr_space_size, _phy_addr_space_size: + * Size (in bytes) of the virtual (resp. physical) address space. + * Would typically be PLAT_VIRT_ADDR_SPACE_SIZE + * (resp. PLAT_PHY_ADDR_SPACE_SIZE) for the translation context describing the + * BL image currently executing. + */ +#define REGISTER_XLAT_CONTEXT(_ctx_name, _mmap_count, _xlat_tables_count, \ + _virt_addr_space_size, _phy_addr_space_size) \ + REGISTER_XLAT_CONTEXT_FULL_SPEC(_ctx_name, (_mmap_count), \ + (_xlat_tables_count), \ + (_virt_addr_space_size), \ + (_phy_addr_space_size), \ + EL_REGIME_INVALID, \ + "xlat_table", "base_xlat_table") + +/* + * Same as REGISTER_XLAT_CONTEXT plus the additional parameters: + * + * _xlat_regime: + * Specify the translation regime managed by this xlat_ctx_t instance. The + * values are the one from the EL*_REGIME definitions. + * + * _section_name: + * Specify the name of the section where the translation tables have to be + * placed by the linker. + * + * _base_table_section_name: + * Specify the name of the section where the base translation tables have to + * be placed by the linker. + */ +#define REGISTER_XLAT_CONTEXT2(_ctx_name, _mmap_count, _xlat_tables_count, \ + _virt_addr_space_size, _phy_addr_space_size, \ + _xlat_regime, _section_name, _base_table_section_name) \ + REGISTER_XLAT_CONTEXT_FULL_SPEC(_ctx_name, (_mmap_count), \ + (_xlat_tables_count), \ + (_virt_addr_space_size), \ + (_phy_addr_space_size), \ + (_xlat_regime), \ + (_section_name), (_base_table_section_name) \ +) + +/****************************************************************************** + * Generic translation table APIs. + * Each API comes in 2 variants: + * - one that acts on the current translation context for this BL image + * - another that acts on the given translation context instead. This variant + * is named after the 1st version, with an additional '_ctx' suffix. + *****************************************************************************/ + +/* + * Initialize translation tables from the current list of mmap regions. Calling + * this function marks the transition point after which static regions can no + * longer be added. + */ +void init_xlat_tables(void); +void init_xlat_tables_ctx(xlat_ctx_t *ctx); + +/* + * Fill all fields of a dynamic translation tables context. It must be done + * either statically with REGISTER_XLAT_CONTEXT() or at runtime with this + * function. + */ +void xlat_setup_dynamic_ctx(xlat_ctx_t *ctx, unsigned long long pa_max, + uintptr_t va_max, struct mmap_region *mmap, + unsigned int mmap_num, uint64_t **tables, + unsigned int tables_num, uint64_t *base_table, + int xlat_regime, int *mapped_regions); + +/* + * Add a static region with defined base PA and base VA. This function can only + * be used before initializing the translation tables. The region cannot be + * removed afterwards. + */ +void mmap_add_region(unsigned long long base_pa, uintptr_t base_va, + size_t size, unsigned int attr); +void mmap_add_region_ctx(xlat_ctx_t *ctx, const mmap_region_t *mm); + +/* + * Add an array of static regions with defined base PA and base VA. This + * function can only be used before initializing the translation tables. The + * regions cannot be removed afterwards. + */ +void mmap_add(const mmap_region_t *mm); +void mmap_add_ctx(xlat_ctx_t *ctx, const mmap_region_t *mm); + +/* + * Add a region with defined base PA. Returns base VA calculated using the + * highest existing region in the mmap array even if it fails to allocate the + * region. + */ +void mmap_add_region_alloc_va(unsigned long long base_pa, uintptr_t *base_va, + size_t size, unsigned int attr); +void mmap_add_region_alloc_va_ctx(xlat_ctx_t *ctx, mmap_region_t *mm); + +/* + * Add an array of static regions with defined base PA, and fill the base VA + * field on the array of structs. This function can only be used before + * initializing the translation tables. The regions cannot be removed afterwards. + */ +void mmap_add_alloc_va(mmap_region_t *mm); + +#if PLAT_XLAT_TABLES_DYNAMIC +/* + * Add a dynamic region with defined base PA and base VA. This type of region + * can be added and removed even after the translation tables are initialized. + * + * Returns: + * 0: Success. + * EINVAL: Invalid values were used as arguments. + * ERANGE: Memory limits were surpassed. + * ENOMEM: Not enough space in the mmap array or not enough free xlat tables. + * EPERM: It overlaps another region in an invalid way. + */ +int mmap_add_dynamic_region(unsigned long long base_pa, uintptr_t base_va, + size_t size, unsigned int attr); +int mmap_add_dynamic_region_ctx(xlat_ctx_t *ctx, mmap_region_t *mm); + +/* + * Add a dynamic region with defined base PA. Returns base VA calculated using + * the highest existing region in the mmap array even if it fails to allocate + * the region. + * + * mmap_add_dynamic_region_alloc_va() returns the allocated VA in 'base_va'. + * mmap_add_dynamic_region_alloc_va_ctx() returns it in 'mm->base_va'. + * + * It returns the same error values as mmap_add_dynamic_region(). + */ +int mmap_add_dynamic_region_alloc_va(unsigned long long base_pa, + uintptr_t *base_va, + size_t size, unsigned int attr); +int mmap_add_dynamic_region_alloc_va_ctx(xlat_ctx_t *ctx, mmap_region_t *mm); + +/* + * Remove a region with the specified base VA and size. Only dynamic regions can + * be removed, and they can be removed even if the translation tables are + * initialized. + * + * Returns: + * 0: Success. + * EINVAL: The specified region wasn't found. + * EPERM: Trying to remove a static region. + */ +int mmap_remove_dynamic_region(uintptr_t base_va, size_t size); +int mmap_remove_dynamic_region_ctx(xlat_ctx_t *ctx, + uintptr_t base_va, + size_t size); + +#endif /* PLAT_XLAT_TABLES_DYNAMIC */ + +/* + * Change the memory attributes of the memory region starting from a given + * virtual address in a set of translation tables. + * + * This function can only be used after the translation tables have been + * initialized. + * + * The base address of the memory region must be aligned on a page boundary. + * The size of this memory region must be a multiple of a page size. + * The memory region must be already mapped by the given translation tables + * and it must be mapped at the granularity of a page. + * + * Return 0 on success, a negative value on error. + * + * In case of error, the memory attributes remain unchanged and this function + * has no effect. + * + * ctx + * Translation context to work on. + * base_va: + * Virtual address of the 1st page to change the attributes of. + * size: + * Size in bytes of the memory region. + * attr: + * New attributes of the page tables. The attributes that can be changed are + * data access (MT_RO/MT_RW), instruction access (MT_EXECUTE_NEVER/MT_EXECUTE) + * and user/privileged access (MT_USER/MT_PRIVILEGED) in the case of contexts + * that are used in the EL1&0 translation regime. Also, note that this + * function doesn't allow to remap a region as RW and executable, or to remap + * device memory as executable. + * + * NOTE: The caller of this function must be able to write to the translation + * tables, i.e. the memory where they are stored must be mapped with read-write + * access permissions. This function assumes it is the case. If this is not + * the case then this function might trigger a data abort exception. + * + * NOTE2: The caller is responsible for making sure that the targeted + * translation tables are not modified by any other code while this function is + * executing. + */ +int xlat_change_mem_attributes_ctx(const xlat_ctx_t *ctx, uintptr_t base_va, + size_t size, uint32_t attr); +int xlat_change_mem_attributes(uintptr_t base_va, size_t size, uint32_t attr); + +#if PLAT_RO_XLAT_TABLES +/* + * Change the memory attributes of the memory region encompassing the higher + * level translation tables to secure read-only data. + * + * Return 0 on success, a negative error code on error. + */ +int xlat_make_tables_readonly(void); +#endif + +/* + * Query the memory attributes of a memory page in a set of translation tables. + * + * Return 0 on success, a negative error code on error. + * On success, the attributes are stored into *attr. + * + * ctx + * Translation context to work on. + * base_va + * Virtual address of the page to get the attributes of. + * There are no alignment restrictions on this address. The attributes of the + * memory page it lies within are returned. + * attr + * Output parameter where to store the attributes of the targeted memory page. + */ +int xlat_get_mem_attributes_ctx(const xlat_ctx_t *ctx, uintptr_t base_va, + uint32_t *attr); +int xlat_get_mem_attributes(uintptr_t base_va, uint32_t *attr); + +#endif /*__ASSEMBLER__*/ +#endif /* XLAT_TABLES_V2_H */ diff --git a/drivers/rz/ipl/rza/include/lib/xlat_tables/xlat_tables_v2_helpers.h b/drivers/rz/ipl/rza/include/lib/xlat_tables/xlat_tables_v2_helpers.h new file mode 100644 index 00000000..62f853d1 --- /dev/null +++ b/drivers/rz/ipl/rza/include/lib/xlat_tables/xlat_tables_v2_helpers.h @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * This header file contains internal definitions that are not supposed to be + * used outside of this library code. + */ + +#ifndef XLAT_TABLES_V2_HELPERS_H +#define XLAT_TABLES_V2_HELPERS_H + +#ifndef XLAT_TABLES_V2_H +#error "Do not include this header file directly. Include xlat_tables_v2.h instead." +#endif + +#ifndef __ASSEMBLER__ + +#include +#include + +#include + +#include +#include +#include +#include + +/* Forward declaration */ +struct mmap_region; + +/* + * Helper macro to define an mmap_region_t. This macro allows to specify all + * the fields of the structure but its parameter list is not guaranteed to + * remain stable as we add members to mmap_region_t. + */ +#define MAP_REGION_FULL_SPEC(_pa, _va, _sz, _attr, _gr) \ + { \ + .base_pa = (_pa), \ + .base_va = (_va), \ + .size = (_sz), \ + .attr = (_attr), \ + .granularity = (_gr), \ + } + +/* Struct that holds all information about the translation tables. */ +struct xlat_ctx { + /* + * Max allowed Virtual and Physical Addresses. + */ + unsigned long long pa_max_address; + uintptr_t va_max_address; + + /* + * Array of all memory regions stored in order of ascending end address + * and ascending size to simplify the code that allows overlapping + * regions. The list is terminated by the first entry with size == 0. + * The max size of the list is stored in `mmap_num`. `mmap` points to an + * array of mmap_num + 1 elements, so that there is space for the final + * null entry. + */ + struct mmap_region *mmap; + int mmap_num; + + /* + * Array of finer-grain translation tables. + * For example, if the initial lookup level is 1 then this array would + * contain both level-2 and level-3 entries. + */ + uint64_t (*tables)[XLAT_TABLE_ENTRIES]; + int tables_num; +#if PLAT_RO_XLAT_TABLES + bool readonly_tables; +#endif + /* + * Keep track of how many regions are mapped in each table. The base + * table can't be unmapped so it isn't needed to keep track of it. + */ +#if PLAT_XLAT_TABLES_DYNAMIC + int *tables_mapped_regions; +#endif /* PLAT_XLAT_TABLES_DYNAMIC */ + + int next_table; + + /* + * Base translation table. It doesn't need to have the same amount of + * entries as the ones used for other levels. + */ + uint64_t *base_table; + unsigned int base_table_entries; + + /* + * Max Physical and Virtual addresses currently in use by the + * translation tables. These might get updated as we map/unmap memory + * regions but they will never go beyond pa/va_max_address. + */ + unsigned long long max_pa; + uintptr_t max_va; + + /* Level of the base translation table. */ + unsigned int base_level; + + /* Set to true when the translation tables are initialized. */ + bool initialized; + + /* + * Translation regime managed by this xlat_ctx_t. It should be one of + * the EL*_REGIME defines. + */ + int xlat_regime; +}; + +#if PLAT_XLAT_TABLES_DYNAMIC +#define XLAT_ALLOC_DYNMAP_STRUCT(_ctx_name, _xlat_tables_count) \ + static int _ctx_name##_mapped_regions[_xlat_tables_count]; + +#define XLAT_REGISTER_DYNMAP_STRUCT(_ctx_name) \ + .tables_mapped_regions = _ctx_name##_mapped_regions, +#else +#define XLAT_ALLOC_DYNMAP_STRUCT(_ctx_name, _xlat_tables_count) \ + /* do nothing */ + +#define XLAT_REGISTER_DYNMAP_STRUCT(_ctx_name) \ + /* do nothing */ +#endif /* PLAT_XLAT_TABLES_DYNAMIC */ + +#if PLAT_RO_XLAT_TABLES +#define XLAT_CTX_INIT_TABLE_ATTR() \ + .readonly_tables = false, +#else +#define XLAT_CTX_INIT_TABLE_ATTR() + /* do nothing */ +#endif + +#define REGISTER_XLAT_CONTEXT_FULL_SPEC(_ctx_name, _mmap_count, \ + _xlat_tables_count, _virt_addr_space_size, \ + _phy_addr_space_size, _xlat_regime, \ + _table_section, _base_table_section) \ + CASSERT(CHECK_PHY_ADDR_SPACE_SIZE(_phy_addr_space_size), \ + assert_invalid_physical_addr_space_sizefor_##_ctx_name);\ + \ + static mmap_region_t _ctx_name##_mmap[_mmap_count + 1]; \ + \ + static uint64_t _ctx_name##_xlat_tables[_xlat_tables_count] \ + [XLAT_TABLE_ENTRIES] \ + __aligned(XLAT_TABLE_SIZE) __section(_table_section); \ + \ + static uint64_t _ctx_name##_base_xlat_table \ + [GET_NUM_BASE_LEVEL_ENTRIES(_virt_addr_space_size)] \ + __aligned(GET_NUM_BASE_LEVEL_ENTRIES(_virt_addr_space_size)\ + * sizeof(uint64_t)) \ + __section(_base_table_section); \ + \ + XLAT_ALLOC_DYNMAP_STRUCT(_ctx_name, _xlat_tables_count) \ + \ + static xlat_ctx_t _ctx_name##_xlat_ctx = { \ + .pa_max_address = (_phy_addr_space_size) - 1ULL, \ + .va_max_address = (_virt_addr_space_size) - 1UL, \ + .mmap = _ctx_name##_mmap, \ + .mmap_num = (_mmap_count), \ + .tables = _ctx_name##_xlat_tables, \ + .tables_num = ARRAY_SIZE(_ctx_name##_xlat_tables), \ + XLAT_CTX_INIT_TABLE_ATTR() \ + XLAT_REGISTER_DYNMAP_STRUCT(_ctx_name) \ + .next_table = 0, \ + .base_table = _ctx_name##_base_xlat_table, \ + .base_table_entries = \ + ARRAY_SIZE(_ctx_name##_base_xlat_table), \ + .max_pa = 0U, \ + .max_va = 0U, \ + .base_level = GET_XLAT_TABLE_LEVEL_BASE(_virt_addr_space_size),\ + .initialized = false, \ + .xlat_regime = (_xlat_regime) \ + } + +#endif /*__ASSEMBLER__*/ + +#endif /* XLAT_TABLES_V2_HELPERS_H */ diff --git a/drivers/rz/ipl/rza/include/plat/arm/board/common/board_css_def.h b/drivers/rz/ipl/rza/include/plat/arm/board/common/board_css_def.h new file mode 100644 index 00000000..1963bf0c --- /dev/null +++ b/drivers/rz/ipl/rza/include/plat/arm/board/common/board_css_def.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef BOARD_CSS_DEF_H +#define BOARD_CSS_DEF_H + +#include +#include +#include +#include + +/* + * Definitions common to all ARM CSS-based development platforms + */ + +/* Platform ID address */ +#define BOARD_CSS_PLAT_ID_REG_ADDR 0x7ffe00e0 + +/* Platform ID related accessors */ +#define BOARD_CSS_PLAT_ID_REG_ID_MASK 0x0f +#define BOARD_CSS_PLAT_ID_REG_ID_SHIFT 0x0 +#define BOARD_CSS_PLAT_ID_REG_VERSION_MASK 0xf00 +#define BOARD_CSS_PLAT_ID_REG_VERSION_SHIFT 0x8 +#define BOARD_CSS_PLAT_TYPE_RTL 0x00 +#define BOARD_CSS_PLAT_TYPE_FPGA 0x01 +#define BOARD_CSS_PLAT_TYPE_EMULATOR 0x02 +#define BOARD_CSS_PLAT_TYPE_FVP 0x03 + +#ifndef __ASSEMBLER__ + +#include + +#define BOARD_CSS_GET_PLAT_TYPE(addr) \ + ((mmio_read_32(addr) & BOARD_CSS_PLAT_ID_REG_ID_MASK) \ + >> BOARD_CSS_PLAT_ID_REG_ID_SHIFT) + +#endif /* __ASSEMBLER__ */ + + +#define MAX_IO_DEVICES 3 +#define MAX_IO_HANDLES 4 + +/* Reserve the last block of flash for PSCI MEM PROTECT flag */ +#define PLAT_ARM_FLASH_IMAGE_BASE V2M_FLASH0_BASE +#define PLAT_ARM_FLASH_IMAGE_MAX_SIZE (V2M_FLASH0_SIZE - V2M_FLASH_BLOCK_SIZE) + +#if ARM_GPT_SUPPORT +/* + * Offset of the FIP in the GPT image. BL1 component uses this option + * as it does not load the partition table to get the FIP base + * address. At sector 34 by default (i.e. after reserved sectors 0-33) + * Offset = 34 * 512(sector size) = 17408 i.e. 0x4400 + */ +#define PLAT_ARM_FIP_OFFSET_IN_GPT 0x4400 +#endif /* ARM_GPT_SUPPORT */ + +#define PLAT_ARM_NVM_BASE V2M_FLASH0_BASE +#define PLAT_ARM_NVM_SIZE (V2M_FLASH0_SIZE - V2M_FLASH_BLOCK_SIZE) + +/* UART related constants */ +#define PLAT_ARM_BOOT_UART_BASE SOC_CSS_UART0_BASE +#define PLAT_ARM_BOOT_UART_CLK_IN_HZ SOC_CSS_UART0_CLK_IN_HZ + +#define PLAT_ARM_RUN_UART_BASE SOC_CSS_UART1_BASE +#define PLAT_ARM_RUN_UART_CLK_IN_HZ SOC_CSS_UART1_CLK_IN_HZ + +#define PLAT_ARM_SP_MIN_RUN_UART_BASE SOC_CSS_UART1_BASE +#define PLAT_ARM_SP_MIN_RUN_UART_CLK_IN_HZ SOC_CSS_UART1_CLK_IN_HZ + +#define PLAT_ARM_CRASH_UART_BASE PLAT_ARM_RUN_UART_BASE +#define PLAT_ARM_CRASH_UART_CLK_IN_HZ PLAT_ARM_RUN_UART_CLK_IN_HZ + +#define PLAT_ARM_TSP_UART_BASE V2M_IOFPGA_UART0_BASE +#define PLAT_ARM_TSP_UART_CLK_IN_HZ V2M_IOFPGA_UART0_CLK_IN_HZ + +#endif /* BOARD_CSS_DEF_H */ diff --git a/drivers/rz/ipl/rza/include/plat/arm/board/common/v2m_def.h b/drivers/rz/ipl/rza/include/plat/arm/board/common/v2m_def.h new file mode 100644 index 00000000..6a6979c9 --- /dev/null +++ b/drivers/rz/ipl/rza/include/plat/arm/board/common/v2m_def.h @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef V2M_DEF_H +#define V2M_DEF_H + +#include + +/* V2M motherboard system registers & offsets */ +#define V2M_SYSREGS_BASE UL(0x1c010000) +#define V2M_SYS_ID UL(0x0) +#define V2M_SYS_SWITCH UL(0x4) +#define V2M_SYS_LED UL(0x8) +#define V2M_SYS_NVFLAGS UL(0x38) +#define V2M_SYS_NVFLAGSSET UL(0x38) +#define V2M_SYS_NVFLAGSCLR UL(0x3c) +#define V2M_SYS_CFGDATA UL(0xa0) +#define V2M_SYS_CFGCTRL UL(0xa4) +#define V2M_SYS_CFGSTATUS UL(0xa8) + +#define V2M_CFGCTRL_START BIT_32(31) +#define V2M_CFGCTRL_RW BIT_32(30) +#define V2M_CFGCTRL_FUNC_SHIFT 20 +#define V2M_CFGCTRL_FUNC(fn) ((fn) << V2M_CFGCTRL_FUNC_SHIFT) +#define V2M_FUNC_CLK_GEN U(0x01) +#define V2M_FUNC_TEMP U(0x04) +#define V2M_FUNC_DB_RESET U(0x05) +#define V2M_FUNC_SCC_CFG U(0x06) +#define V2M_FUNC_SHUTDOWN U(0x08) +#define V2M_FUNC_REBOOT U(0x09) + +/* NVFLAGS in the V2M motherboard which is preserved after a watchdog reset */ + #define V2M_SYS_NVFLAGS_ADDR (V2M_SYSREGS_BASE + V2M_SYS_NVFLAGS) + +/* + * V2M sysled bit definitions. The values written to this + * register are defined in arch.h & runtime_svc.h. Only + * used by the primary cpu to diagnose any cold boot issues. + * + * SYS_LED[0] - Security state (S=0/NS=1) + * SYS_LED[2:1] - Exception Level (EL3-EL0) + * SYS_LED[7:3] - Exception Class (Sync/Async & origin) + * + */ +#define V2M_SYS_LED_SS_SHIFT 0x0 +#define V2M_SYS_LED_EL_SHIFT 0x1 +#define V2M_SYS_LED_EC_SHIFT 0x3 + +#define V2M_SYS_LED_SS_MASK U(0x1) +#define V2M_SYS_LED_EL_MASK U(0x3) +#define V2M_SYS_LED_EC_MASK U(0x1f) + +/* V2M sysid register bits */ +#define V2M_SYS_ID_REV_SHIFT 28 +#define V2M_SYS_ID_HBI_SHIFT 16 +#define V2M_SYS_ID_BLD_SHIFT 12 +#define V2M_SYS_ID_ARCH_SHIFT 8 +#define V2M_SYS_ID_FPGA_SHIFT 0 + +#define V2M_SYS_ID_REV_MASK U(0xf) +#define V2M_SYS_ID_HBI_MASK U(0xfff) +#define V2M_SYS_ID_BLD_MASK U(0xf) +#define V2M_SYS_ID_ARCH_MASK U(0xf) +#define V2M_SYS_ID_FPGA_MASK U(0xff) + +#define V2M_SYS_ID_BLD_LENGTH 4 + + +/* NOR Flash */ +#define V2M_FLASH0_BASE UL(0x08000000) +#define V2M_FLASH0_SIZE UL(0x04000000) +#define V2M_FLASH_BLOCK_SIZE UL(0x00040000) /* 256 KB */ + +#define V2M_IOFPGA_BASE UL(0x1c000000) +#define V2M_IOFPGA_SIZE UL(0x03000000) + +/* PL011 UART related constants */ +#define V2M_IOFPGA_UART0_BASE UL(0x1c090000) +#define V2M_IOFPGA_UART1_BASE UL(0x1c0a0000) +#define V2M_IOFPGA_UART2_BASE UL(0x1c0b0000) +#define V2M_IOFPGA_UART3_BASE UL(0x1c0c0000) + +#define V2M_IOFPGA_UART0_CLK_IN_HZ 24000000 +#define V2M_IOFPGA_UART1_CLK_IN_HZ 24000000 +#define V2M_IOFPGA_UART2_CLK_IN_HZ 24000000 +#define V2M_IOFPGA_UART3_CLK_IN_HZ 24000000 + +/* SP804 timer related constants */ +#define V2M_SP804_TIMER0_BASE UL(0x1C110000) +#define V2M_SP804_TIMER1_BASE UL(0x1C120000) + +/* SP810 controller */ +#define V2M_SP810_BASE UL(0x1c020000) +#define V2M_SP810_CTRL_TIM0_SEL BIT_32(15) +#define V2M_SP810_CTRL_TIM1_SEL BIT_32(17) +#define V2M_SP810_CTRL_TIM2_SEL BIT_32(19) +#define V2M_SP810_CTRL_TIM3_SEL BIT_32(21) + +/* + * The flash can be mapped either as read-only or read-write. + * + * If it is read-write then it should also be mapped as device memory because + * NOR flash programming involves sending a fixed, ordered sequence of commands. + * + * If it is read-only then it should also be mapped as: + * - Normal memory, because reading from NOR flash is transparent, it is like + * reading from RAM. + * - Non-executable by default. If some parts of the flash need to be executable + * then platform code is responsible for re-mapping the appropriate portion + * of it as executable. + */ +#define V2M_MAP_FLASH0_RW MAP_REGION_FLAT(V2M_FLASH0_BASE,\ + V2M_FLASH0_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +#define V2M_MAP_FLASH0_RO MAP_REGION_FLAT(V2M_FLASH0_BASE,\ + V2M_FLASH0_SIZE, \ + MT_RO_DATA | MT_SECURE) + +#define V2M_MAP_IOFPGA MAP_REGION_FLAT(V2M_IOFPGA_BASE,\ + V2M_IOFPGA_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +/* Region equivalent to V2M_MAP_IOFPGA suitable for mapping at EL0 */ +#define V2M_MAP_IOFPGA_EL0 MAP_REGION_FLAT( \ + V2M_IOFPGA_BASE, \ + V2M_IOFPGA_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE | MT_USER) + + +#endif /* V2M_DEF_H */ diff --git a/drivers/rz/ipl/rza/include/plat/arm/common/aarch64/arm_macros.S b/drivers/rz/ipl/rza/include/plat/arm/common/aarch64/arm_macros.S new file mode 100644 index 00000000..d47e4e09 --- /dev/null +++ b/drivers/rz/ipl/rza/include/plat/arm/common/aarch64/arm_macros.S @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef ARM_MACROS_S +#define ARM_MACROS_S + +#include +#include +#include +#include + +.section .rodata.gic_reg_name, "aS" +/* Applicable only to GICv2 and GICv3 with SRE disabled (legacy mode) */ +gicc_regs: + .asciz "gicc_hppir", "gicc_ahppir", "gicc_ctlr", "" + +/* Applicable only to GICv3 with SRE enabled */ +icc_regs: + .asciz "icc_hppir0_el1", "icc_hppir1_el1", "icc_ctlr_el3", "" + +/* Registers common to both GICv2 and GICv3 */ +gicd_pend_reg: + .asciz "gicd_ispendr regs (Offsets 0x200-0x278)\nOffset\t\t\tValue\n" +newline: + .asciz "\n" +spacer: + .asciz ":\t\t 0x" +prefix: + .asciz "0x" + + /* --------------------------------------------- + * The below utility macro prints out relevant GIC + * registers whenever an unhandled exception is + * taken in BL31 on ARM standard platforms. + * Expects: GICD base in x16, GICC base in x17 + * Clobbers: x0 - x10, sp + * --------------------------------------------- + */ + .macro arm_print_gic_regs + /* Check for GICv3 system register access */ + mrs x7, id_aa64pfr0_el1 + ubfx x7, x7, #ID_AA64PFR0_GIC_SHIFT, #ID_AA64PFR0_GIC_WIDTH + cmp x7, #1 + b.ne print_gicv2 + + /* Check for SRE enable */ + mrs x8, ICC_SRE_EL3 + tst x8, #ICC_SRE_SRE_BIT + b.eq print_gicv2 + + /* Load the icc reg list to x6 */ + adr x6, icc_regs + /* Load the icc regs to gp regs used by str_in_crash_buf_print */ + mrs x8, ICC_HPPIR0_EL1 + mrs x9, ICC_HPPIR1_EL1 + mrs x10, ICC_CTLR_EL3 + /* Store to the crash buf and print to console */ + bl str_in_crash_buf_print + b print_gic_common + +print_gicv2: + /* Load the gicc reg list to x6 */ + adr x6, gicc_regs + /* Load the gicc regs to gp regs used by str_in_crash_buf_print */ + ldr w8, [x17, #GICC_HPPIR] + ldr w9, [x17, #GICC_AHPPIR] + ldr w10, [x17, #GICC_CTLR] + /* Store to the crash buf and print to console */ + bl str_in_crash_buf_print + +print_gic_common: + /* Print the GICD_ISPENDR regs */ + add x7, x16, #GICD_ISPENDR + adr x4, gicd_pend_reg + bl asm_print_str +gicd_ispendr_loop: + sub x4, x7, x16 + cmp x4, #0x280 + b.eq exit_print_gic_regs + + /* Print "0x" */ + adr x4, prefix + bl asm_print_str + + /* Print offset */ + sub x4, x7, x16 + mov x5, #12 + bl asm_print_hex_bits + + adr x4, spacer + bl asm_print_str + + ldr x4, [x7], #8 + bl asm_print_hex + + adr x4, newline + bl asm_print_str + b gicd_ispendr_loop +exit_print_gic_regs: + .endm + +#endif /* ARM_MACROS_S */ diff --git a/drivers/rz/ipl/rza/include/plat/arm/common/aarch64/cci_macros.S b/drivers/rz/ipl/rza/include/plat/arm/common/aarch64/cci_macros.S new file mode 100644 index 00000000..07f7cd39 --- /dev/null +++ b/drivers/rz/ipl/rza/include/plat/arm/common/aarch64/cci_macros.S @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef CCI_MACROS_S +#define CCI_MACROS_S + +#include +#include + +.section .rodata.cci_reg_name, "aS" +cci_iface_regs: + .asciz "cci_snoop_ctrl_cluster0", "cci_snoop_ctrl_cluster1" , "" + + /* ------------------------------------------------ + * The below required platform porting macro prints + * out relevant interconnect registers whenever an + * unhandled exception is taken in BL31. + * Clobbers: x0 - x9, sp + * ------------------------------------------------ + */ + .macro print_cci_regs + adr x6, cci_iface_regs + /* Store in x7 the base address of the first interface */ + mov_imm x7, (PLAT_ARM_CCI_BASE + SLAVE_IFACE_OFFSET( \ + PLAT_ARM_CCI_CLUSTER0_SL_IFACE_IX)) + ldr w8, [x7, #SNOOP_CTRL_REG] + /* Store in x7 the base address of the second interface */ + mov_imm x7, (PLAT_ARM_CCI_BASE + SLAVE_IFACE_OFFSET( \ + PLAT_ARM_CCI_CLUSTER1_SL_IFACE_IX)) + ldr w9, [x7, #SNOOP_CTRL_REG] + /* Store to the crash buf and print to console */ + bl str_in_crash_buf_print + .endm + +#endif /* CCI_MACROS_S */ diff --git a/drivers/rz/ipl/rza/include/plat/arm/common/arm_config.h b/drivers/rz/ipl/rza/include/plat/arm/common/arm_config.h new file mode 100644 index 00000000..c2b28df5 --- /dev/null +++ b/drivers/rz/ipl/rza/include/plat/arm/common/arm_config.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2014-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef ARM_CONFIG_H +#define ARM_CONFIG_H + +#include + +#include + +/* Whether Base memory map is in use */ +#define ARM_CONFIG_BASE_MMAP BIT(1) + +/* Whether TZC should be configured */ +#define ARM_CONFIG_HAS_TZC BIT(2) + +/* FVP model has shifted affinity */ +#define ARM_CONFIG_FVP_SHIFTED_AFF BIT(3) + +/* FVP model has SMMUv3 affinity */ +#define ARM_CONFIG_FVP_HAS_SMMUV3 BIT(4) + +/* FVP model has CCI (400 or 500/550) devices */ +#define ARM_CONFIG_FVP_HAS_CCI400 BIT(5) +#define ARM_CONFIG_FVP_HAS_CCI5XX BIT(6) + +typedef struct arm_config { + unsigned long flags; +} arm_config_t; + + +/* If used, arm_config must be defined and populated in the platform port */ +extern arm_config_t arm_config; + +static inline const arm_config_t *get_arm_config(void) +{ + return &arm_config; +} + + +#endif /* ARM_CONFIG_H */ diff --git a/drivers/rz/ipl/rza/include/plat/arm/common/arm_def.h b/drivers/rz/ipl/rza/include/plat/arm/common/arm_def.h new file mode 100644 index 00000000..00746c6d --- /dev/null +++ b/drivers/rz/ipl/rza/include/plat/arm/common/arm_def.h @@ -0,0 +1,605 @@ +/* + * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef ARM_DEF_H +#define ARM_DEF_H + +#include +#include +#include +#include +#include +#include +#include +#include + +/****************************************************************************** + * Definitions common to all ARM standard platforms + *****************************************************************************/ + +/* + * Root of trust key hash lengths + */ +#define ARM_ROTPK_HEADER_LEN 19 +#define ARM_ROTPK_HASH_LEN 32 + +/* Special value used to verify platform parameters from BL2 to BL31 */ +#define ARM_BL31_PLAT_PARAM_VAL ULL(0x0f1e2d3c4b5a6978) + +#define ARM_SYSTEM_COUNT U(1) + +#define ARM_CACHE_WRITEBACK_SHIFT 6 + +/* + * Macros mapping the MPIDR Affinity levels to ARM Platform Power levels. The + * power levels have a 1:1 mapping with the MPIDR affinity levels. + */ +#define ARM_PWR_LVL0 MPIDR_AFFLVL0 +#define ARM_PWR_LVL1 MPIDR_AFFLVL1 +#define ARM_PWR_LVL2 MPIDR_AFFLVL2 +#define ARM_PWR_LVL3 MPIDR_AFFLVL3 + +/* + * Macros for local power states in ARM platforms encoded by State-ID field + * within the power-state parameter. + */ +/* Local power state for power domains in Run state. */ +#define ARM_LOCAL_STATE_RUN U(0) +/* Local power state for retention. Valid only for CPU power domains */ +#define ARM_LOCAL_STATE_RET U(1) +/* Local power state for OFF/power-down. Valid for CPU and cluster power + domains */ +#define ARM_LOCAL_STATE_OFF U(2) + +/* Memory location options for TSP */ +#define ARM_TRUSTED_SRAM_ID 0 +#define ARM_TRUSTED_DRAM_ID 1 +#define ARM_DRAM_ID 2 + +/* The first 4KB of Trusted SRAM are used as shared memory */ +#define ARM_TRUSTED_SRAM_BASE UL(0x04000000) +#define ARM_SHARED_RAM_BASE ARM_TRUSTED_SRAM_BASE +#define ARM_SHARED_RAM_SIZE UL(0x00001000) /* 4 KB */ + +/* The remaining Trusted SRAM is used to load the BL images */ +#define ARM_BL_RAM_BASE (ARM_SHARED_RAM_BASE + \ + ARM_SHARED_RAM_SIZE) +#define ARM_BL_RAM_SIZE (PLAT_ARM_TRUSTED_SRAM_SIZE - \ + ARM_SHARED_RAM_SIZE) + +/* + * The top 16MB of DRAM1 is configured as secure access only using the TZC + * - SCP TZC DRAM: If present, DRAM reserved for SCP use + * - AP TZC DRAM: The remaining TZC secured DRAM reserved for AP use + */ +#define ARM_TZC_DRAM1_SIZE UL(0x01000000) + +#define ARM_SCP_TZC_DRAM1_BASE (ARM_DRAM1_BASE + \ + ARM_DRAM1_SIZE - \ + ARM_SCP_TZC_DRAM1_SIZE) +#define ARM_SCP_TZC_DRAM1_SIZE PLAT_ARM_SCP_TZC_DRAM1_SIZE +#define ARM_SCP_TZC_DRAM1_END (ARM_SCP_TZC_DRAM1_BASE + \ + ARM_SCP_TZC_DRAM1_SIZE - 1U) + +/* + * Define a 2MB region within the TZC secured DRAM for use by EL3 runtime + * firmware. This region is meant to be NOLOAD and will not be zero + * initialized. Data sections with the attribute `arm_el3_tzc_dram` will be + * placed here. + */ +#define ARM_EL3_TZC_DRAM1_BASE (ARM_SCP_TZC_DRAM1_BASE - ARM_EL3_TZC_DRAM1_SIZE) +#define ARM_EL3_TZC_DRAM1_SIZE UL(0x00200000) /* 2 MB */ +#define ARM_EL3_TZC_DRAM1_END (ARM_EL3_TZC_DRAM1_BASE + \ + ARM_EL3_TZC_DRAM1_SIZE - 1U) + +#define ARM_AP_TZC_DRAM1_BASE (ARM_DRAM1_BASE + \ + ARM_DRAM1_SIZE - \ + ARM_TZC_DRAM1_SIZE) +#define ARM_AP_TZC_DRAM1_SIZE (ARM_TZC_DRAM1_SIZE - \ + (ARM_SCP_TZC_DRAM1_SIZE + \ + ARM_EL3_TZC_DRAM1_SIZE)) +#define ARM_AP_TZC_DRAM1_END (ARM_AP_TZC_DRAM1_BASE + \ + ARM_AP_TZC_DRAM1_SIZE - 1U) + +/* Define the Access permissions for Secure peripherals to NS_DRAM */ +#if ARM_CRYPTOCELL_INTEG +/* + * Allow Secure peripheral to read NS DRAM when integrated with CryptoCell. + * This is required by CryptoCell to authenticate BL33 which is loaded + * into the Non Secure DDR. + */ +#define ARM_TZC_NS_DRAM_S_ACCESS TZC_REGION_S_RD +#else +#define ARM_TZC_NS_DRAM_S_ACCESS TZC_REGION_S_NONE +#endif + +#ifdef SPD_opteed +/* + * BL2 needs to map 4MB at the end of TZC_DRAM1 in order to + * load/authenticate the trusted os extra image. The first 512KB of + * TZC_DRAM1 are reserved for trusted os (OPTEE). The extra image loading + * for OPTEE is paged image which only include the paging part using + * virtual memory but without "init" data. OPTEE will copy the "init" data + * (from pager image) to the first 512KB of TZC_DRAM, and then copy the + * extra image behind the "init" data. + */ +#define ARM_OPTEE_PAGEABLE_LOAD_BASE (ARM_AP_TZC_DRAM1_BASE + \ + ARM_AP_TZC_DRAM1_SIZE - \ + ARM_OPTEE_PAGEABLE_LOAD_SIZE) +#define ARM_OPTEE_PAGEABLE_LOAD_SIZE UL(0x400000) +#define ARM_OPTEE_PAGEABLE_LOAD_MEM MAP_REGION_FLAT( \ + ARM_OPTEE_PAGEABLE_LOAD_BASE, \ + ARM_OPTEE_PAGEABLE_LOAD_SIZE, \ + MT_MEMORY | MT_RW | MT_SECURE) + +/* + * Map the memory for the OP-TEE core (also known as OP-TEE pager when paging + * support is enabled). + */ +#define ARM_MAP_OPTEE_CORE_MEM MAP_REGION_FLAT( \ + BL32_BASE, \ + BL32_LIMIT - BL32_BASE, \ + MT_MEMORY | MT_RW | MT_SECURE) +#endif /* SPD_opteed */ + +#define ARM_NS_DRAM1_BASE ARM_DRAM1_BASE +#define ARM_NS_DRAM1_SIZE (ARM_DRAM1_SIZE - \ + ARM_TZC_DRAM1_SIZE) +#define ARM_NS_DRAM1_END (ARM_NS_DRAM1_BASE + \ + ARM_NS_DRAM1_SIZE - 1U) + +#define ARM_DRAM1_BASE ULL(0x80000000) +#define ARM_DRAM1_SIZE ULL(0x80000000) +#define ARM_DRAM1_END (ARM_DRAM1_BASE + \ + ARM_DRAM1_SIZE - 1U) + +#define ARM_DRAM2_BASE PLAT_ARM_DRAM2_BASE +#define ARM_DRAM2_SIZE PLAT_ARM_DRAM2_SIZE +#define ARM_DRAM2_END (ARM_DRAM2_BASE + \ + ARM_DRAM2_SIZE - 1U) + +#define ARM_IRQ_SEC_PHY_TIMER 29 + +#define ARM_IRQ_SEC_SGI_0 8 +#define ARM_IRQ_SEC_SGI_1 9 +#define ARM_IRQ_SEC_SGI_2 10 +#define ARM_IRQ_SEC_SGI_3 11 +#define ARM_IRQ_SEC_SGI_4 12 +#define ARM_IRQ_SEC_SGI_5 13 +#define ARM_IRQ_SEC_SGI_6 14 +#define ARM_IRQ_SEC_SGI_7 15 + +/* + * Define a list of Group 1 Secure and Group 0 interrupt properties as per GICv3 + * terminology. On a GICv2 system or mode, the lists will be merged and treated + * as Group 0 interrupts. + */ +#define ARM_G1S_IRQ_PROPS(grp) \ + INTR_PROP_DESC(ARM_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, (grp), \ + GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_1, GIC_HIGHEST_SEC_PRIORITY, (grp), \ + GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_2, GIC_HIGHEST_SEC_PRIORITY, (grp), \ + GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_3, GIC_HIGHEST_SEC_PRIORITY, (grp), \ + GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_4, GIC_HIGHEST_SEC_PRIORITY, (grp), \ + GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_5, GIC_HIGHEST_SEC_PRIORITY, (grp), \ + GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY, (grp), \ + GIC_INTR_CFG_EDGE) + +#define ARM_G0_IRQ_PROPS(grp) \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_0, PLAT_SDEI_NORMAL_PRI, (grp), \ + GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY, (grp), \ + GIC_INTR_CFG_EDGE) + +#define ARM_MAP_SHARED_RAM MAP_REGION_FLAT( \ + ARM_SHARED_RAM_BASE, \ + ARM_SHARED_RAM_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +#define ARM_MAP_NS_DRAM1 MAP_REGION_FLAT( \ + ARM_NS_DRAM1_BASE, \ + ARM_NS_DRAM1_SIZE, \ + MT_MEMORY | MT_RW | MT_NS) + +#define ARM_MAP_DRAM2 MAP_REGION_FLAT( \ + ARM_DRAM2_BASE, \ + ARM_DRAM2_SIZE, \ + MT_MEMORY | MT_RW | MT_NS) + +#define ARM_MAP_TSP_SEC_MEM MAP_REGION_FLAT( \ + TSP_SEC_MEM_BASE, \ + TSP_SEC_MEM_SIZE, \ + MT_MEMORY | MT_RW | MT_SECURE) + +#if ARM_BL31_IN_DRAM +#define ARM_MAP_BL31_SEC_DRAM MAP_REGION_FLAT( \ + BL31_BASE, \ + PLAT_ARM_MAX_BL31_SIZE, \ + MT_MEMORY | MT_RW | MT_SECURE) +#endif + +#define ARM_MAP_EL3_TZC_DRAM MAP_REGION_FLAT( \ + ARM_EL3_TZC_DRAM1_BASE, \ + ARM_EL3_TZC_DRAM1_SIZE, \ + MT_MEMORY | MT_RW | MT_SECURE) + +#if defined(SPD_spmd) +#define ARM_MAP_TRUSTED_DRAM MAP_REGION_FLAT( \ + PLAT_ARM_TRUSTED_DRAM_BASE, \ + PLAT_ARM_TRUSTED_DRAM_SIZE, \ + MT_MEMORY | MT_RW | MT_SECURE) +#endif + + +/* + * Mapping for the BL1 RW region. This mapping is needed by BL2 in order to + * share the Mbed TLS heap. Since the heap is allocated inside BL1, it resides + * in the BL1 RW region. Hence, BL2 needs access to the BL1 RW region in order + * to be able to access the heap. + */ +#define ARM_MAP_BL1_RW MAP_REGION_FLAT( \ + BL1_RW_BASE, \ + BL1_RW_LIMIT - BL1_RW_BASE, \ + MT_MEMORY | MT_RW | MT_SECURE) + +/* + * If SEPARATE_CODE_AND_RODATA=1 we define a region for each section + * otherwise one region is defined containing both. + */ +#if SEPARATE_CODE_AND_RODATA +#define ARM_MAP_BL_RO MAP_REGION_FLAT( \ + BL_CODE_BASE, \ + BL_CODE_END - BL_CODE_BASE, \ + MT_CODE | MT_SECURE), \ + MAP_REGION_FLAT( \ + BL_RO_DATA_BASE, \ + BL_RO_DATA_END \ + - BL_RO_DATA_BASE, \ + MT_RO_DATA | MT_SECURE) +#else +#define ARM_MAP_BL_RO MAP_REGION_FLAT( \ + BL_CODE_BASE, \ + BL_CODE_END - BL_CODE_BASE, \ + MT_CODE | MT_SECURE) +#endif +#if USE_COHERENT_MEM +#define ARM_MAP_BL_COHERENT_RAM MAP_REGION_FLAT( \ + BL_COHERENT_RAM_BASE, \ + BL_COHERENT_RAM_END \ + - BL_COHERENT_RAM_BASE, \ + MT_DEVICE | MT_RW | MT_SECURE) +#endif +#if USE_ROMLIB +#define ARM_MAP_ROMLIB_CODE MAP_REGION_FLAT( \ + ROMLIB_RO_BASE, \ + ROMLIB_RO_LIMIT - ROMLIB_RO_BASE,\ + MT_CODE | MT_SECURE) + +#define ARM_MAP_ROMLIB_DATA MAP_REGION_FLAT( \ + ROMLIB_RW_BASE, \ + ROMLIB_RW_END - ROMLIB_RW_BASE,\ + MT_MEMORY | MT_RW | MT_SECURE) +#endif + +/* + * Map mem_protect flash region with read and write permissions + */ +#define ARM_V2M_MAP_MEM_PROTECT MAP_REGION_FLAT(PLAT_ARM_MEM_PROT_ADDR, \ + V2M_FLASH_BLOCK_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) +/* + * Map the region for device tree configuration with read and write permissions + */ +#define ARM_MAP_BL_CONFIG_REGION MAP_REGION_FLAT(ARM_BL_RAM_BASE, \ + (ARM_FW_CONFIGS_LIMIT \ + - ARM_BL_RAM_BASE), \ + MT_MEMORY | MT_RW | MT_SECURE) + +/* + * The max number of regions like RO(code), coherent and data required by + * different BL stages which need to be mapped in the MMU. + */ +#define ARM_BL_REGIONS 6 + +#define MAX_MMAP_REGIONS (PLAT_ARM_MMAP_ENTRIES + \ + ARM_BL_REGIONS) + +/* Memory mapped Generic timer interfaces */ +#define ARM_SYS_CNTCTL_BASE UL(0x2a430000) +#define ARM_SYS_CNTREAD_BASE UL(0x2a800000) +#define ARM_SYS_TIMCTL_BASE UL(0x2a810000) +#define ARM_SYS_CNT_BASE_S UL(0x2a820000) +#define ARM_SYS_CNT_BASE_NS UL(0x2a830000) + +#define ARM_CONSOLE_BAUDRATE 115200 + +/* Trusted Watchdog constants */ +#define ARM_SP805_TWDG_BASE UL(0x2a490000) +#define ARM_SP805_TWDG_CLK_HZ 32768 +/* The TBBR document specifies a watchdog timeout of 256 seconds. SP805 + * asserts reset after two consecutive countdowns (2 x 128 = 256 sec) */ +#define ARM_TWDG_TIMEOUT_SEC 128 +#define ARM_TWDG_LOAD_VAL (ARM_SP805_TWDG_CLK_HZ * \ + ARM_TWDG_TIMEOUT_SEC) + +/****************************************************************************** + * Required platform porting definitions common to all ARM standard platforms + *****************************************************************************/ + +/* + * This macro defines the deepest retention state possible. A higher state + * id will represent an invalid or a power down state. + */ +#define PLAT_MAX_RET_STATE ARM_LOCAL_STATE_RET + +/* + * This macro defines the deepest power down states possible. Any state ID + * higher than this is invalid. + */ +#define PLAT_MAX_OFF_STATE ARM_LOCAL_STATE_OFF + +/* + * Some data must be aligned on the biggest cache line size in the platform. + * This is known only to the platform as it might have a combination of + * integrated and external caches. + */ +#define CACHE_WRITEBACK_GRANULE (U(1) << ARM_CACHE_WRITEBACK_SHIFT) + +/* + * To enable FW_CONFIG to be loaded by BL1, define the corresponding base + * and limit. Leave enough space of BL2 meminfo. + */ +#define ARM_FW_CONFIG_BASE (ARM_BL_RAM_BASE + sizeof(meminfo_t)) +#define ARM_FW_CONFIG_LIMIT ((ARM_BL_RAM_BASE + PAGE_SIZE) \ + + (PAGE_SIZE / 2U)) + +/* + * Boot parameters passed from BL2 to BL31/BL32 are stored here + */ +#define ARM_BL2_MEM_DESC_BASE (ARM_FW_CONFIG_LIMIT) +#define ARM_BL2_MEM_DESC_LIMIT (ARM_BL2_MEM_DESC_BASE \ + + (PAGE_SIZE / 2U)) + +/* + * Define limit of firmware configuration memory: + * ARM_FW_CONFIG + ARM_BL2_MEM_DESC memory + */ +#define ARM_FW_CONFIGS_LIMIT (ARM_BL_RAM_BASE + (PAGE_SIZE * 2)) + +/******************************************************************************* + * BL1 specific defines. + * BL1 RW data is relocated from ROM to RAM at runtime so we need 2 sets of + * addresses. + ******************************************************************************/ +#define BL1_RO_BASE PLAT_ARM_TRUSTED_ROM_BASE +#define BL1_RO_LIMIT (PLAT_ARM_TRUSTED_ROM_BASE \ + + (PLAT_ARM_TRUSTED_ROM_SIZE - \ + PLAT_ARM_MAX_ROMLIB_RO_SIZE)) +/* + * Put BL1 RW at the top of the Trusted SRAM. + */ +#define BL1_RW_BASE (ARM_BL_RAM_BASE + \ + ARM_BL_RAM_SIZE - \ + (PLAT_ARM_MAX_BL1_RW_SIZE +\ + PLAT_ARM_MAX_ROMLIB_RW_SIZE)) +#define BL1_RW_LIMIT (ARM_BL_RAM_BASE + \ + (ARM_BL_RAM_SIZE - PLAT_ARM_MAX_ROMLIB_RW_SIZE)) + +#define ROMLIB_RO_BASE BL1_RO_LIMIT +#define ROMLIB_RO_LIMIT (PLAT_ARM_TRUSTED_ROM_BASE + PLAT_ARM_TRUSTED_ROM_SIZE) + +#define ROMLIB_RW_BASE (BL1_RW_BASE + PLAT_ARM_MAX_BL1_RW_SIZE) +#define ROMLIB_RW_END (ROMLIB_RW_BASE + PLAT_ARM_MAX_ROMLIB_RW_SIZE) + +/******************************************************************************* + * BL2 specific defines. + ******************************************************************************/ +#if BL2_AT_EL3 +/* Put BL2 towards the middle of the Trusted SRAM */ +#define BL2_BASE (ARM_TRUSTED_SRAM_BASE + \ + (PLAT_ARM_TRUSTED_SRAM_SIZE >> 1) + 0x2000) +#define BL2_LIMIT (ARM_BL_RAM_BASE + ARM_BL_RAM_SIZE) + +#else +/* + * Put BL2 just below BL1. + */ +#define BL2_BASE (BL1_RW_BASE - PLAT_ARM_MAX_BL2_SIZE) +#define BL2_LIMIT BL1_RW_BASE +#endif + +/******************************************************************************* + * BL31 specific defines. + ******************************************************************************/ +#if ARM_BL31_IN_DRAM || SEPARATE_NOBITS_REGION +/* + * Put BL31 at the bottom of TZC secured DRAM + */ +#define BL31_BASE ARM_AP_TZC_DRAM1_BASE +#define BL31_LIMIT (ARM_AP_TZC_DRAM1_BASE + \ + PLAT_ARM_MAX_BL31_SIZE) +/* + * For SEPARATE_NOBITS_REGION, BL31 PROGBITS are loaded in TZC secured DRAM. + * And BL31 NOBITS are loaded in Trusted SRAM such that BL2 is overwritten. + */ +#if SEPARATE_NOBITS_REGION +#define BL31_NOBITS_BASE BL2_BASE +#define BL31_NOBITS_LIMIT BL2_LIMIT +#endif /* SEPARATE_NOBITS_REGION */ +#elif (RESET_TO_BL31) +/* Ensure Position Independent support (PIE) is enabled for this config.*/ +# if !ENABLE_PIE +# error "BL31 must be a PIE if RESET_TO_BL31=1." +#endif +/* + * Since this is PIE, we can define BL31_BASE to 0x0 since this macro is solely + * used for building BL31 and not used for loading BL31. + */ +# define BL31_BASE 0x0 +# define BL31_LIMIT PLAT_ARM_MAX_BL31_SIZE +#else +/* Put BL31 below BL2 in the Trusted SRAM.*/ +#define BL31_BASE ((ARM_BL_RAM_BASE + ARM_BL_RAM_SIZE)\ + - PLAT_ARM_MAX_BL31_SIZE) +#define BL31_PROGBITS_LIMIT BL2_BASE +/* + * For BL2_AT_EL3 make sure the BL31 can grow up until BL2_BASE. This is + * because in the BL2_AT_EL3 configuration, BL2 is always resident. + */ +#if BL2_AT_EL3 +#define BL31_LIMIT BL2_BASE +#else +#define BL31_LIMIT (ARM_BL_RAM_BASE + ARM_BL_RAM_SIZE) +#endif +#endif + +#if !defined(__aarch64__) || JUNO_AARCH32_EL3_RUNTIME +/******************************************************************************* + * BL32 specific defines for EL3 runtime in AArch32 mode + ******************************************************************************/ +# if RESET_TO_SP_MIN && !JUNO_AARCH32_EL3_RUNTIME +/* + * SP_MIN is the only BL image in SRAM. Allocate the whole of SRAM (excluding + * the page reserved for fw_configs) to BL32 + */ +# define BL32_BASE ARM_FW_CONFIGS_LIMIT +# define BL32_LIMIT (ARM_BL_RAM_BASE + ARM_BL_RAM_SIZE) +# else +/* Put BL32 below BL2 in the Trusted SRAM.*/ +# define BL32_BASE ((ARM_BL_RAM_BASE + ARM_BL_RAM_SIZE)\ + - PLAT_ARM_MAX_BL32_SIZE) +# define BL32_PROGBITS_LIMIT BL2_BASE +# define BL32_LIMIT (ARM_BL_RAM_BASE + ARM_BL_RAM_SIZE) +# endif /* RESET_TO_SP_MIN && !JUNO_AARCH32_EL3_RUNTIME */ + +#else +/******************************************************************************* + * BL32 specific defines for EL3 runtime in AArch64 mode + ******************************************************************************/ +/* + * On ARM standard platforms, the TSP can execute from Trusted SRAM, + * Trusted DRAM (if available) or the DRAM region secured by the TrustZone + * controller. + */ +# if SPM_MM +# define TSP_SEC_MEM_BASE (ARM_AP_TZC_DRAM1_BASE + ULL(0x200000)) +# define TSP_SEC_MEM_SIZE (ARM_AP_TZC_DRAM1_SIZE - ULL(0x200000)) +# define BL32_BASE (ARM_AP_TZC_DRAM1_BASE + ULL(0x200000)) +# define BL32_LIMIT (ARM_AP_TZC_DRAM1_BASE + \ + ARM_AP_TZC_DRAM1_SIZE) +# elif defined(SPD_spmd) +# define TSP_SEC_MEM_BASE (ARM_AP_TZC_DRAM1_BASE + ULL(0x200000)) +# define TSP_SEC_MEM_SIZE (ARM_AP_TZC_DRAM1_SIZE - ULL(0x200000)) +# define BL32_BASE PLAT_ARM_SPMC_BASE +# define BL32_LIMIT (PLAT_ARM_SPMC_BASE + \ + PLAT_ARM_SPMC_SIZE) +# elif ARM_BL31_IN_DRAM +# define TSP_SEC_MEM_BASE (ARM_AP_TZC_DRAM1_BASE + \ + PLAT_ARM_MAX_BL31_SIZE) +# define TSP_SEC_MEM_SIZE (ARM_AP_TZC_DRAM1_SIZE - \ + PLAT_ARM_MAX_BL31_SIZE) +# define BL32_BASE (ARM_AP_TZC_DRAM1_BASE + \ + PLAT_ARM_MAX_BL31_SIZE) +# define BL32_LIMIT (ARM_AP_TZC_DRAM1_BASE + \ + ARM_AP_TZC_DRAM1_SIZE) +# elif ARM_TSP_RAM_LOCATION_ID == ARM_TRUSTED_SRAM_ID +# define TSP_SEC_MEM_BASE ARM_BL_RAM_BASE +# define TSP_SEC_MEM_SIZE ARM_BL_RAM_SIZE +# define TSP_PROGBITS_LIMIT BL31_BASE +# define BL32_BASE ARM_FW_CONFIGS_LIMIT +# define BL32_LIMIT BL31_BASE +# elif ARM_TSP_RAM_LOCATION_ID == ARM_TRUSTED_DRAM_ID +# define TSP_SEC_MEM_BASE PLAT_ARM_TRUSTED_DRAM_BASE +# define TSP_SEC_MEM_SIZE PLAT_ARM_TRUSTED_DRAM_SIZE +# define BL32_BASE PLAT_ARM_TRUSTED_DRAM_BASE +# define BL32_LIMIT (PLAT_ARM_TRUSTED_DRAM_BASE \ + + (UL(1) << 21)) +# elif ARM_TSP_RAM_LOCATION_ID == ARM_DRAM_ID +# define TSP_SEC_MEM_BASE ARM_AP_TZC_DRAM1_BASE +# define TSP_SEC_MEM_SIZE ARM_AP_TZC_DRAM1_SIZE +# define BL32_BASE ARM_AP_TZC_DRAM1_BASE +# define BL32_LIMIT (ARM_AP_TZC_DRAM1_BASE + \ + ARM_AP_TZC_DRAM1_SIZE) +# else +# error "Unsupported ARM_TSP_RAM_LOCATION_ID value" +# endif +#endif /* !__aarch64__ || JUNO_AARCH32_EL3_RUNTIME */ + +/* + * BL32 is mandatory in AArch32. In AArch64, undefine BL32_BASE if there is no + * SPD and no SPM-MM, as they are the only ones that can be used as BL32. + */ +#if defined(__aarch64__) && !JUNO_AARCH32_EL3_RUNTIME +# if defined(SPD_none) && !SPM_MM +# undef BL32_BASE +# endif /* defined(SPD_none) && !SPM_MM */ +#endif /* defined(__aarch64__) && !JUNO_AARCH32_EL3_RUNTIME */ + +/******************************************************************************* + * FWU Images: NS_BL1U, BL2U & NS_BL2U defines. + ******************************************************************************/ +#define BL2U_BASE BL2_BASE +#define BL2U_LIMIT BL2_LIMIT + +#define NS_BL2U_BASE ARM_NS_DRAM1_BASE +#define NS_BL1U_BASE (PLAT_ARM_NVM_BASE + UL(0x03EB8000)) + +/* + * ID of the secure physical generic timer interrupt used by the TSP. + */ +#define TSP_IRQ_SEC_PHY_TIMER ARM_IRQ_SEC_PHY_TIMER + + +/* + * One cache line needed for bakery locks on ARM platforms + */ +#define PLAT_PERCPU_BAKERY_LOCK_SIZE (1 * CACHE_WRITEBACK_GRANULE) + +/* Priority levels for ARM platforms */ +#define PLAT_RAS_PRI 0x10 +#define PLAT_SDEI_CRITICAL_PRI 0x60 +#define PLAT_SDEI_NORMAL_PRI 0x70 + +/* ARM platforms use 3 upper bits of secure interrupt priority */ +#define PLAT_PRI_BITS 3 + +/* SGI used for SDEI signalling */ +#define ARM_SDEI_SGI ARM_IRQ_SEC_SGI_0 + +#if SDEI_IN_FCONF +/* ARM SDEI dynamic private event max count */ +#define ARM_SDEI_DP_EVENT_MAX_CNT 3 + +/* ARM SDEI dynamic shared event max count */ +#define ARM_SDEI_DS_EVENT_MAX_CNT 3 +#else +/* ARM SDEI dynamic private event numbers */ +#define ARM_SDEI_DP_EVENT_0 1000 +#define ARM_SDEI_DP_EVENT_1 1001 +#define ARM_SDEI_DP_EVENT_2 1002 + +/* ARM SDEI dynamic shared event numbers */ +#define ARM_SDEI_DS_EVENT_0 2000 +#define ARM_SDEI_DS_EVENT_1 2001 +#define ARM_SDEI_DS_EVENT_2 2002 + +#define ARM_SDEI_PRIVATE_EVENTS \ + SDEI_DEFINE_EVENT_0(ARM_SDEI_SGI), \ + SDEI_PRIVATE_EVENT(ARM_SDEI_DP_EVENT_0, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC), \ + SDEI_PRIVATE_EVENT(ARM_SDEI_DP_EVENT_1, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC), \ + SDEI_PRIVATE_EVENT(ARM_SDEI_DP_EVENT_2, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC) + +#define ARM_SDEI_SHARED_EVENTS \ + SDEI_SHARED_EVENT(ARM_SDEI_DS_EVENT_0, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC), \ + SDEI_SHARED_EVENT(ARM_SDEI_DS_EVENT_1, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC), \ + SDEI_SHARED_EVENT(ARM_SDEI_DS_EVENT_2, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC) +#endif /* SDEI_IN_FCONF */ + +#endif /* ARM_DEF_H */ diff --git a/drivers/rz/ipl/rza/include/plat/arm/common/arm_dyn_cfg_helpers.h b/drivers/rz/ipl/rza/include/plat/arm/common/arm_dyn_cfg_helpers.h new file mode 100644 index 00000000..34bf07c0 --- /dev/null +++ b/drivers/rz/ipl/rza/include/plat/arm/common/arm_dyn_cfg_helpers.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef ARM_DYN_CFG_HELPERS_H +#define ARM_DYN_CFG_HELPERS_H + +#include +#include + +/* Function declarations */ +int arm_dyn_tb_fw_cfg_init(void *dtb, int *node); +int arm_set_dtb_mbedtls_heap_info(void *dtb, void *heap_addr, + size_t heap_size); + +#if MEASURED_BOOT +int arm_set_bl2_hash_info(void *dtb, void *data); +#endif + +#endif /* ARM_DYN_CFG_HELPERS_H */ diff --git a/drivers/rz/ipl/rza/include/plat/arm/common/arm_fconf_getter.h b/drivers/rz/ipl/rza/include/plat/arm/common/arm_fconf_getter.h new file mode 100644 index 00000000..8fd8c7ad --- /dev/null +++ b/drivers/rz/ipl/rza/include/plat/arm/common/arm_fconf_getter.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2019-2020, ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef ARM_FCONF_GETTER +#define ARM_FCONF_GETTER + +#include + +#include + +/* ARM io policies */ +#define arm__io_policies_getter(id) __extension__ ({ \ + assert((id) < MAX_NUMBER_IDS); \ + &policies[id]; \ +}) + +struct plat_io_policy { + uintptr_t *dev_handle; + uintptr_t image_spec; + int (*check)(const uintptr_t spec); +}; + +extern struct plat_io_policy policies[]; +int fconf_populate_arm_io_policies(uintptr_t config); + +#endif /* ARM_FCONF_GETTER */ diff --git a/drivers/rz/ipl/rza/include/plat/arm/common/arm_fconf_io_storage.h b/drivers/rz/ipl/rza/include/plat/arm/common/arm_fconf_io_storage.h new file mode 100644 index 00000000..02ee66c3 --- /dev/null +++ b/drivers/rz/ipl/rza/include/plat/arm/common/arm_fconf_io_storage.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2020, ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef ARM_FCONF_IO_STORAGE_H +#define ARM_FCONF_IO_STORAGE_H + +#include + +/* IO devices handle */ +extern uintptr_t memmap_dev_handle; +extern uintptr_t fip_dev_handle; + +/* Function declarations */ +int open_fip(const uintptr_t spec); +int open_memmap(const uintptr_t spec); + +#endif /* ARM_FCONF_IO_STORAGE_H */ diff --git a/drivers/rz/ipl/rza/include/plat/arm/common/arm_reclaim_init.ld.S b/drivers/rz/ipl/rza/include/plat/arm/common/arm_reclaim_init.ld.S new file mode 100644 index 00000000..717f65e2 --- /dev/null +++ b/drivers/rz/ipl/rza/include/plat/arm/common/arm_reclaim_init.ld.S @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef ARM_RECLAIM_INIT_LD_S +#define ARM_RECLAIM_INIT_LD_S + +SECTIONS +{ + .init __STACKS_START__ : { + . = . + PLATFORM_STACK_SIZE; + . = ALIGN(PAGE_SIZE); + __INIT_CODE_START__ = .; + *(*text.init*); + __INIT_CODE_END__ = .; + INIT_CODE_END_ALIGNED = ALIGN(PAGE_SIZE); + } >RAM + +#ifdef BL31_PROGBITS_LIMIT + ASSERT(__INIT_CODE_END__ <= BL31_PROGBITS_LIMIT, + "BL31 init has exceeded progbits limit.") +#endif +} + +#define ABS ABSOLUTE + +#define STACK_SECTION \ + stacks (NOLOAD) : { \ + __STACKS_START__ = .; \ + *(tzfw_normal_stacks) \ + __STACKS_END__ = .; \ + /* Allow room for the init section where necessary. */ \ + OFFSET = ABS(SIZEOF(.init) - (. - __STACKS_START__)); \ + /* Offset sign */ \ + SIGN = ABS(OFFSET) & (1 << 63); \ + /* Offset mask */ \ + MASK = ABS(SIGN >> 63) - 1; \ + . += ABS(OFFSET) & ABS(MASK); \ + . = ALIGN(PAGE_SIZE); \ + } + +#endif /* ARM_RECLAIM_INIT_LD_S */ diff --git a/drivers/rz/ipl/rza/include/plat/arm/common/arm_sip_svc.h b/drivers/rz/ipl/rza/include/plat/arm/common/arm_sip_svc.h new file mode 100644 index 00000000..2eeed95f --- /dev/null +++ b/drivers/rz/ipl/rza/include/plat/arm/common/arm_sip_svc.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2016-2019,2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef ARM_SIP_SVC_H +#define ARM_SIP_SVC_H + +#include + +/* SMC function IDs for SiP Service queries */ + +#define ARM_SIP_SVC_CALL_COUNT U(0x8200ff00) +#define ARM_SIP_SVC_UID U(0x8200ff01) +/* U(0x8200ff02) is reserved */ +#define ARM_SIP_SVC_VERSION U(0x8200ff03) + +/* PMF_SMC_GET_TIMESTAMP_32 0x82000010 */ +/* PMF_SMC_GET_TIMESTAMP_64 0xC2000010 */ + +/* Function ID for requesting state switch of lower EL */ +#define ARM_SIP_SVC_EXE_STATE_SWITCH U(0x82000020) + +/* DEBUGFS_SMC_32 0x82000030U */ +/* DEBUGFS_SMC_64 0xC2000030U */ + +/* + * Arm Ethos-N NPU SiP SMC function IDs + * 0xC2000050-0xC200005F + * 0x82000050-0x8200005F + */ + +/* ARM SiP Service Calls version numbers */ +#define ARM_SIP_SVC_VERSION_MAJOR U(0x0) +#define ARM_SIP_SVC_VERSION_MINOR U(0x2) + +#endif /* ARM_SIP_SVC_H */ diff --git a/drivers/rz/ipl/rza/include/plat/arm/common/arm_spm_def.h b/drivers/rz/ipl/rza/include/plat/arm/common/arm_spm_def.h new file mode 100644 index 00000000..c43583de --- /dev/null +++ b/drivers/rz/ipl/rza/include/plat/arm/common/arm_spm_def.h @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef ARM_SPM_DEF_H +#define ARM_SPM_DEF_H + +#include +#include + +/* + * If BL31 is placed in DRAM, place the Secure Partition in DRAM right after the + * region used by BL31. If BL31 it is placed in SRAM, put the Secure Partition + * at the base of DRAM. + */ +#define ARM_SP_IMAGE_BASE BL32_BASE +#define ARM_SP_IMAGE_LIMIT BL32_LIMIT +/* The maximum size of the S-EL0 payload can be 3MB */ +#define ARM_SP_IMAGE_SIZE ULL(0x300000) + +#ifdef IMAGE_BL2 +/* SPM Payload memory. Mapped as RW in BL2. */ +#define ARM_SP_IMAGE_MMAP MAP_REGION_FLAT( \ + ARM_SP_IMAGE_BASE, \ + ARM_SP_IMAGE_SIZE, \ + MT_MEMORY | MT_RW | MT_SECURE) +#endif + +#ifdef IMAGE_BL31 +/* SPM Payload memory. Mapped as code in S-EL1 */ +#define ARM_SP_IMAGE_MMAP MAP_REGION2( \ + ARM_SP_IMAGE_BASE, \ + ARM_SP_IMAGE_BASE, \ + ARM_SP_IMAGE_SIZE, \ + MT_CODE | MT_SECURE | MT_USER, \ + PAGE_SIZE) +#endif + +/* + * Memory shared between EL3 and S-EL0. It is used by EL3 to push data into + * S-EL0, so it is mapped with RW permission from EL3 and with RO permission + * from S-EL0. Placed after SPM Payload memory. + */ +#define PLAT_SPM_BUF_BASE (ARM_SP_IMAGE_BASE + ARM_SP_IMAGE_SIZE) +#define PLAT_SPM_BUF_SIZE ULL(0x100000) + +#define ARM_SPM_BUF_EL3_MMAP MAP_REGION_FLAT( \ + PLAT_SPM_BUF_BASE, \ + PLAT_SPM_BUF_SIZE, \ + MT_RW_DATA | MT_SECURE) +#define ARM_SPM_BUF_EL0_MMAP MAP_REGION2( \ + PLAT_SPM_BUF_BASE, \ + PLAT_SPM_BUF_BASE, \ + PLAT_SPM_BUF_SIZE, \ + MT_RO_DATA | MT_SECURE | MT_USER,\ + PAGE_SIZE) + +/* + * Memory shared between Normal world and S-EL0 for passing data during service + * requests. Mapped as RW and NS. Placed after the shared memory between EL3 and + * S-EL0. + */ +#define PLAT_SP_IMAGE_NS_BUF_BASE (PLAT_SPM_BUF_BASE + PLAT_SPM_BUF_SIZE) +#define PLAT_SP_IMAGE_NS_BUF_SIZE ULL(0x10000) +#define ARM_SP_IMAGE_NS_BUF_MMAP MAP_REGION2( \ + PLAT_SP_IMAGE_NS_BUF_BASE, \ + PLAT_SP_IMAGE_NS_BUF_BASE, \ + PLAT_SP_IMAGE_NS_BUF_SIZE, \ + MT_RW_DATA | MT_NS | MT_USER, \ + PAGE_SIZE) + +/* + * RW memory, which uses the remaining Trusted DRAM. Placed after the memory + * shared between Secure and Non-secure worlds, or after the platform specific + * buffers, if defined. First there is the stack memory for all CPUs and then + * there is the common heap memory. Both are mapped with RW permissions. + */ +#define PLAT_SP_IMAGE_STACK_BASE PLAT_ARM_SP_IMAGE_STACK_BASE +#define PLAT_SP_IMAGE_STACK_PCPU_SIZE ULL(0x2000) +#define ARM_SP_IMAGE_STACK_TOTAL_SIZE (PLATFORM_CORE_COUNT * \ + PLAT_SP_IMAGE_STACK_PCPU_SIZE) + +#define ARM_SP_IMAGE_HEAP_BASE (PLAT_SP_IMAGE_STACK_BASE + \ + ARM_SP_IMAGE_STACK_TOTAL_SIZE) +#define ARM_SP_IMAGE_HEAP_SIZE (ARM_SP_IMAGE_LIMIT - ARM_SP_IMAGE_HEAP_BASE) + +#define ARM_SP_IMAGE_RW_MMAP MAP_REGION2( \ + PLAT_SP_IMAGE_STACK_BASE, \ + PLAT_SP_IMAGE_STACK_BASE, \ + (ARM_SP_IMAGE_LIMIT - \ + PLAT_SP_IMAGE_STACK_BASE), \ + MT_RW_DATA | MT_SECURE | MT_USER,\ + PAGE_SIZE) + +/* Total number of memory regions with distinct properties */ +#define ARM_SP_IMAGE_NUM_MEM_REGIONS 6 + +/* Cookies passed to the Secure Partition at boot. Not used by ARM platforms. */ +#define PLAT_SPM_COOKIE_0 ULL(0) +#define PLAT_SPM_COOKIE_1 ULL(0) + +#endif /* ARM_SPM_DEF_H */ diff --git a/drivers/rz/ipl/rza/include/plat/arm/common/arm_tzc_dram.ld.S b/drivers/rz/ipl/rza/include/plat/arm/common/arm_tzc_dram.ld.S new file mode 100644 index 00000000..6dcea0b6 --- /dev/null +++ b/drivers/rz/ipl/rza/include/plat/arm/common/arm_tzc_dram.ld.S @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef ARM_TZC_DRAM_LD_S +#define ARM_TZC_DRAM_LD_S + +#include + +MEMORY { + EL3_SEC_DRAM (rw): ORIGIN = ARM_EL3_TZC_DRAM1_BASE, LENGTH = ARM_EL3_TZC_DRAM1_SIZE +} + +SECTIONS +{ + . = ARM_EL3_TZC_DRAM1_BASE; + ASSERT(. == ALIGN(PAGE_SIZE), + "ARM_EL3_TZC_DRAM_BASE address is not aligned on a page boundary.") + el3_tzc_dram (NOLOAD) : ALIGN(PAGE_SIZE) { + __EL3_SEC_DRAM_START__ = .; + *(arm_el3_tzc_dram) + __EL3_SEC_DRAM_UNALIGNED_END__ = .; + + . = ALIGN(PAGE_SIZE); + __EL3_SEC_DRAM_END__ = .; + } >EL3_SEC_DRAM +} + +#endif /* ARM_TZC_DRAM_LD_S */ diff --git a/drivers/rz/ipl/rza/include/plat/arm/common/fconf_arm_sp_getter.h b/drivers/rz/ipl/rza/include/plat/arm/common/fconf_arm_sp_getter.h new file mode 100644 index 00000000..aa628dfd --- /dev/null +++ b/drivers/rz/ipl/rza/include/plat/arm/common/fconf_arm_sp_getter.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef FCONF_ARM_SP_GETTER_H +#define FCONF_ARM_SP_GETTER_H + +#include +#include + +/* arm_sp getter */ +#define arm__sp_getter(prop) arm_sp.prop + +#define ARM_SP_MAX_SIZE U(0xb0000) +#define ARM_SP_OWNER_NAME_LEN U(8) + +struct arm_sp_t { + unsigned int number_of_sp; + union uuid_helper_t uuids[MAX_SP_IDS]; + uintptr_t load_addr[MAX_SP_IDS]; + char owner[MAX_SP_IDS][ARM_SP_OWNER_NAME_LEN]; +}; + +int fconf_populate_arm_sp(uintptr_t config); + +extern struct arm_sp_t arm_sp; + +extern bl_mem_params_node_t sp_mem_params_descs[MAX_SP_IDS]; + +#endif /* FCONF_ARM_SP_GETTER_H */ diff --git a/drivers/rz/ipl/rza/include/plat/arm/common/fconf_ethosn_getter.h b/drivers/rz/ipl/rza/include/plat/arm/common/fconf_ethosn_getter.h new file mode 100644 index 00000000..0fd1f025 --- /dev/null +++ b/drivers/rz/ipl/rza/include/plat/arm/common/fconf_ethosn_getter.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef FCONF_ETHOSN_GETTER_H +#define FCONF_ETHOSN_GETTER_H + +#include + +#include + +#define hw_config__ethosn_config_getter(prop) ethosn_config.prop +#define hw_config__ethosn_core_addr_getter(idx) __extension__ ({ \ + assert(idx < ethosn_config.num_cores); \ + ethosn_config.core_addr[idx]; \ +}) + +#define ETHOSN_STATUS_DISABLED U(0) +#define ETHOSN_STATUS_ENABLED U(1) + +#define ETHOSN_CORE_NUM_MAX U(64) + +struct ethosn_config_t { + uint8_t status; + uint32_t num_cores; + uint64_t core_addr[ETHOSN_CORE_NUM_MAX]; +}; + +int fconf_populate_arm_ethosn(uintptr_t config); + +extern struct ethosn_config_t ethosn_config; + +#endif /* FCONF_ETHOSN_GETTER_H */ diff --git a/drivers/rz/ipl/rza/include/plat/arm/common/fconf_nv_cntr_getter.h b/drivers/rz/ipl/rza/include/plat/arm/common/fconf_nv_cntr_getter.h new file mode 100644 index 00000000..80a60004 --- /dev/null +++ b/drivers/rz/ipl/rza/include/plat/arm/common/fconf_nv_cntr_getter.h @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef FCONF_NV_CNTR_GETTER_H +#define FCONF_NV_CNTR_GETTER_H + +#include +#include + +#define cot__nv_cntr_addr_getter(id) nv_cntr_base_addr[id] + +extern uintptr_t nv_cntr_base_addr[MAX_NV_CTR_IDS]; + +#endif /* FCONF_NV_CNTR_GETTER_H */ diff --git a/drivers/rz/ipl/rza/include/plat/arm/common/fconf_sdei_getter.h b/drivers/rz/ipl/rza/include/plat/arm/common/fconf_sdei_getter.h new file mode 100644 index 00000000..e0a97a6f --- /dev/null +++ b/drivers/rz/ipl/rza/include/plat/arm/common/fconf_sdei_getter.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef FCONF_SDEI_GETTER_H +#define FCONF_SDEI_GETTER_H + +#include + +#include + +#define sdei__dyn_config_getter(id) sdei_dyn_config.id + +struct sdei_dyn_config_t { + uint32_t private_ev_cnt; + int32_t private_ev_nums[PLAT_SDEI_DP_EVENT_MAX_CNT]; + unsigned int private_ev_intrs[PLAT_SDEI_DP_EVENT_MAX_CNT]; + unsigned int private_ev_flags[PLAT_SDEI_DP_EVENT_MAX_CNT]; + uint32_t shared_ev_cnt; + int32_t shared_ev_nums[PLAT_SDEI_DS_EVENT_MAX_CNT]; + unsigned int shared_ev_intrs[PLAT_SDEI_DS_EVENT_MAX_CNT]; + unsigned int shared_ev_flags[PLAT_SDEI_DS_EVENT_MAX_CNT]; +}; + +int fconf_populate_sdei_dyn_config(uintptr_t config); + +extern struct sdei_dyn_config_t sdei_dyn_config; + +#endif /* FCONF_SDEI_GETTER_H */ diff --git a/drivers/rz/ipl/rza/include/plat/arm/common/fconf_sec_intr_config.h b/drivers/rz/ipl/rza/include/plat/arm/common/fconf_sec_intr_config.h new file mode 100644 index 00000000..5d6b594a --- /dev/null +++ b/drivers/rz/ipl/rza/include/plat/arm/common/fconf_sec_intr_config.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef FCONF_SEC_INTR_CONFIG_H +#define FCONF_SEC_INTR_CONFIG_H + +#include + +#include + +#define hw_config__sec_intr_prop_getter(id) sec_intr_prop.id + +#define SEC_INT_COUNT_MAX U(15) + +struct sec_intr_prop_t { + interrupt_prop_t descriptor[SEC_INT_COUNT_MAX]; + uint32_t count; +}; + +int fconf_populate_sec_intr_config(uintptr_t config); + +extern struct sec_intr_prop_t sec_intr_prop; + +#endif /* FCONF_SEC_INTR_CONFIG_H */ diff --git a/drivers/rz/ipl/rza/include/plat/arm/common/plat_arm.h b/drivers/rz/ipl/rza/include/plat/arm/common/plat_arm.h new file mode 100644 index 00000000..846c9a44 --- /dev/null +++ b/drivers/rz/ipl/rza/include/plat/arm/common/plat_arm.h @@ -0,0 +1,350 @@ +/* + * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef PLAT_ARM_H +#define PLAT_ARM_H + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +/******************************************************************************* + * Forward declarations + ******************************************************************************/ +struct meminfo; +struct image_info; +struct bl_params; + +typedef struct arm_tzc_regions_info { + unsigned long long base; + unsigned long long end; + unsigned int sec_attr; + unsigned int nsaid_permissions; +} arm_tzc_regions_info_t; + +/******************************************************************************* + * Default mapping definition of the TrustZone Controller for ARM standard + * platforms. + * Configure: + * - Region 0 with no access; + * - Region 1 with secure access only; + * - the remaining DRAM regions access from the given Non-Secure masters. + ******************************************************************************/ +#if SPM_MM +#define ARM_TZC_REGIONS_DEF \ + {ARM_AP_TZC_DRAM1_BASE, ARM_EL3_TZC_DRAM1_END, \ + TZC_REGION_S_RDWR, 0}, \ + {ARM_NS_DRAM1_BASE, ARM_NS_DRAM1_END, ARM_TZC_NS_DRAM_S_ACCESS, \ + PLAT_ARM_TZC_NS_DEV_ACCESS}, \ + {ARM_DRAM2_BASE, ARM_DRAM2_END, ARM_TZC_NS_DRAM_S_ACCESS, \ + PLAT_ARM_TZC_NS_DEV_ACCESS}, \ + {PLAT_SP_IMAGE_NS_BUF_BASE, (PLAT_SP_IMAGE_NS_BUF_BASE + \ + PLAT_SP_IMAGE_NS_BUF_SIZE) - 1, TZC_REGION_S_NONE, \ + PLAT_ARM_TZC_NS_DEV_ACCESS} + +#else +#define ARM_TZC_REGIONS_DEF \ + {ARM_AP_TZC_DRAM1_BASE, ARM_EL3_TZC_DRAM1_END, \ + TZC_REGION_S_RDWR, 0}, \ + {ARM_NS_DRAM1_BASE, ARM_NS_DRAM1_END, ARM_TZC_NS_DRAM_S_ACCESS, \ + PLAT_ARM_TZC_NS_DEV_ACCESS}, \ + {ARM_DRAM2_BASE, ARM_DRAM2_END, ARM_TZC_NS_DRAM_S_ACCESS, \ + PLAT_ARM_TZC_NS_DEV_ACCESS} +#endif + +#define ARM_CASSERT_MMAP \ + CASSERT((ARRAY_SIZE(plat_arm_mmap) - 1) <= PLAT_ARM_MMAP_ENTRIES, \ + assert_plat_arm_mmap_mismatch); \ + CASSERT((PLAT_ARM_MMAP_ENTRIES + ARM_BL_REGIONS) \ + <= MAX_MMAP_REGIONS, \ + assert_max_mmap_regions); + +void arm_setup_romlib(void); + +#if defined(IMAGE_BL31) || (!defined(__aarch64__) && defined(IMAGE_BL32)) +/* + * Use this macro to instantiate lock before it is used in below + * arm_lock_xxx() macros + */ +#define ARM_INSTANTIATE_LOCK static DEFINE_BAKERY_LOCK(arm_lock) +#define ARM_LOCK_GET_INSTANCE (&arm_lock) + +#if !HW_ASSISTED_COHERENCY +#define ARM_SCMI_INSTANTIATE_LOCK DEFINE_BAKERY_LOCK(arm_scmi_lock) +#else +#define ARM_SCMI_INSTANTIATE_LOCK spinlock_t arm_scmi_lock +#endif +#define ARM_SCMI_LOCK_GET_INSTANCE (&arm_scmi_lock) + +/* + * These are wrapper macros to the Coherent Memory Bakery Lock API. + */ +#define arm_lock_init() bakery_lock_init(&arm_lock) +#define arm_lock_get() bakery_lock_get(&arm_lock) +#define arm_lock_release() bakery_lock_release(&arm_lock) + +#else + +/* + * Empty macros for all other BL stages other than BL31 and BL32 + */ +#define ARM_INSTANTIATE_LOCK static int arm_lock __unused +#define ARM_LOCK_GET_INSTANCE 0 +#define arm_lock_init() +#define arm_lock_get() +#define arm_lock_release() + +#endif /* defined(IMAGE_BL31) || (!defined(__aarch64__) && defined(IMAGE_BL32)) */ + +#if ARM_RECOM_STATE_ID_ENC +/* + * Macros used to parse state information from State-ID if it is using the + * recommended encoding for State-ID. + */ +#define ARM_LOCAL_PSTATE_WIDTH 4 +#define ARM_LOCAL_PSTATE_MASK ((1 << ARM_LOCAL_PSTATE_WIDTH) - 1) + +/* Macros to construct the composite power state */ + +/* Make composite power state parameter till power level 0 */ +#if PSCI_EXTENDED_STATE_ID + +#define arm_make_pwrstate_lvl0(lvl0_state, pwr_lvl, type) \ + (((lvl0_state) << PSTATE_ID_SHIFT) | ((type) << PSTATE_TYPE_SHIFT)) +#else +#define arm_make_pwrstate_lvl0(lvl0_state, pwr_lvl, type) \ + (((lvl0_state) << PSTATE_ID_SHIFT) | \ + ((pwr_lvl) << PSTATE_PWR_LVL_SHIFT) | \ + ((type) << PSTATE_TYPE_SHIFT)) +#endif /* __PSCI_EXTENDED_STATE_ID__ */ + +/* Make composite power state parameter till power level 1 */ +#define arm_make_pwrstate_lvl1(lvl1_state, lvl0_state, pwr_lvl, type) \ + (((lvl1_state) << ARM_LOCAL_PSTATE_WIDTH) | \ + arm_make_pwrstate_lvl0(lvl0_state, pwr_lvl, type)) + +/* Make composite power state parameter till power level 2 */ +#define arm_make_pwrstate_lvl2(lvl2_state, lvl1_state, lvl0_state, pwr_lvl, type) \ + (((lvl2_state) << (ARM_LOCAL_PSTATE_WIDTH * 2)) | \ + arm_make_pwrstate_lvl1(lvl1_state, lvl0_state, pwr_lvl, type)) + +#endif /* __ARM_RECOM_STATE_ID_ENC__ */ + +/* ARM State switch error codes */ +#define STATE_SW_E_PARAM (-2) +#define STATE_SW_E_DENIED (-3) + +/* plat_get_rotpk_info() flags */ +#define ARM_ROTPK_REGS_ID 1 +#define ARM_ROTPK_DEVEL_RSA_ID 2 +#define ARM_ROTPK_DEVEL_ECDSA_ID 3 + + +/* IO storage utility functions */ +int arm_io_setup(void); + +/* Set image specification in IO block policy */ +int arm_set_image_source(unsigned int image_id, const char *part_name); + +/* Security utility functions */ +void arm_tzc400_setup(uintptr_t tzc_base, + const arm_tzc_regions_info_t *tzc_regions); +struct tzc_dmc500_driver_data; +void arm_tzc_dmc500_setup(struct tzc_dmc500_driver_data *plat_driver_data, + const arm_tzc_regions_info_t *tzc_regions); + +/* Console utility functions */ +void arm_console_boot_init(void); +void arm_console_boot_end(void); +void arm_console_runtime_init(void); +void arm_console_runtime_end(void); + +/* Systimer utility function */ +void arm_configure_sys_timer(void); + +/* PM utility functions */ +int arm_validate_power_state(unsigned int power_state, + psci_power_state_t *req_state); +int arm_validate_psci_entrypoint(uintptr_t entrypoint); +int arm_validate_ns_entrypoint(uintptr_t entrypoint); +void arm_system_pwr_domain_save(void); +void arm_system_pwr_domain_resume(void); +int arm_psci_read_mem_protect(int *enabled); +int arm_nor_psci_write_mem_protect(int val); +void arm_nor_psci_do_static_mem_protect(void); +void arm_nor_psci_do_dyn_mem_protect(void); +int arm_psci_mem_protect_chk(uintptr_t base, u_register_t length); + +/* Topology utility function */ +int arm_check_mpidr(u_register_t mpidr); + +/* BL1 utility functions */ +void arm_bl1_early_platform_setup(void); +void arm_bl1_platform_setup(void); +void arm_bl1_plat_arch_setup(void); + +/* BL2 utility functions */ +void arm_bl2_early_platform_setup(uintptr_t fw_config, struct meminfo *mem_layout); +void arm_bl2_platform_setup(void); +void arm_bl2_plat_arch_setup(void); +uint32_t arm_get_spsr_for_bl32_entry(void); +uint32_t arm_get_spsr_for_bl33_entry(void); +int arm_bl2_plat_handle_post_image_load(unsigned int image_id); +int arm_bl2_handle_post_image_load(unsigned int image_id); +struct bl_params *arm_get_next_bl_params(void); + +/* BL2 at EL3 functions */ +void arm_bl2_el3_early_platform_setup(void); +void arm_bl2_el3_plat_arch_setup(void); + +/* BL2U utility functions */ +void arm_bl2u_early_platform_setup(struct meminfo *mem_layout, + void *plat_info); +void arm_bl2u_platform_setup(void); +void arm_bl2u_plat_arch_setup(void); + +/* BL31 utility functions */ +void arm_bl31_early_platform_setup(void *from_bl2, uintptr_t soc_fw_config, + uintptr_t hw_config, void *plat_params_from_bl2); +void arm_bl31_platform_setup(void); +void arm_bl31_plat_runtime_setup(void); +void arm_bl31_plat_arch_setup(void); + +/* TSP utility functions */ +void arm_tsp_early_platform_setup(void); + +/* SP_MIN utility functions */ +void arm_sp_min_early_platform_setup(void *from_bl2, uintptr_t tos_fw_config, + uintptr_t hw_config, void *plat_params_from_bl2); +void arm_sp_min_plat_runtime_setup(void); +void arm_sp_min_plat_arch_setup(void); + +/* FIP TOC validity check */ +bool arm_io_is_toc_valid(void); + +/* Utility functions for Dynamic Config */ +void arm_bl2_dyn_cfg_init(void); +void arm_bl1_set_mbedtls_heap(void); +int arm_get_mbedtls_heap(void **heap_addr, size_t *heap_size); + +#if MEASURED_BOOT +/* Measured boot related functions */ +void arm_bl1_set_bl2_hash(const image_desc_t *image_desc); +void arm_bl2_get_hash(void *data); +int arm_set_tos_fw_info(uintptr_t config_base, uintptr_t log_addr, + size_t log_size); +int arm_set_nt_fw_info(uintptr_t config_base, +/* + * Currently OP-TEE does not support reading DTBs from Secure memory + * and this option should be removed when feature is supported. + */ +#ifdef SPD_opteed + uintptr_t log_addr, +#endif + size_t log_size, uintptr_t *ns_log_addr); +#endif /* MEASURED_BOOT */ + +/* + * Free the memory storing initialization code only used during an images boot + * time so it can be reclaimed for runtime data + */ +void arm_free_init_memory(void); + +/* + * Make the higher level translation tables read-only + */ +void arm_xlat_make_tables_readonly(void); + +/* + * Mandatory functions required in ARM standard platforms + */ +unsigned int plat_arm_get_cluster_core_count(u_register_t mpidr); +void plat_arm_gic_driver_init(void); +void plat_arm_gic_init(void); +void plat_arm_gic_cpuif_enable(void); +void plat_arm_gic_cpuif_disable(void); +void plat_arm_gic_redistif_on(void); +void plat_arm_gic_redistif_off(void); +void plat_arm_gic_pcpu_init(void); +void plat_arm_gic_save(void); +void plat_arm_gic_resume(void); +void plat_arm_security_setup(void); +void plat_arm_pwrc_setup(void); +void plat_arm_interconnect_init(void); +void plat_arm_interconnect_enter_coherency(void); +void plat_arm_interconnect_exit_coherency(void); +void plat_arm_program_trusted_mailbox(uintptr_t address); +bool plat_arm_bl1_fwu_needed(void); +__dead2 void plat_arm_error_handler(int err); + +/* + * Optional functions in ARM standard platforms + */ +void plat_arm_override_gicr_frames(const uintptr_t *plat_gicr_frames); +int arm_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len, + unsigned int *flags); +int arm_get_rotpk_info_regs(void **key_ptr, unsigned int *key_len, + unsigned int *flags); +int arm_get_rotpk_info_cc(void **key_ptr, unsigned int *key_len, + unsigned int *flags); +int arm_get_rotpk_info_dev(void **key_ptr, unsigned int *key_len, + unsigned int *flags); + +#if ARM_PLAT_MT +unsigned int plat_arm_get_cpu_pe_count(u_register_t mpidr); +#endif + +/* + * This function is called after loading SCP_BL2 image and it is used to perform + * any platform-specific actions required to handle the SCP firmware. + */ +int plat_arm_bl2_handle_scp_bl2(struct image_info *scp_bl2_image_info); + +/* + * Optional functions required in ARM standard platforms + */ +void plat_arm_io_setup(void); +int plat_arm_get_alt_image_source( + unsigned int image_id, + uintptr_t *dev_handle, + uintptr_t *image_spec); +unsigned int plat_arm_calc_core_pos(u_register_t mpidr); +const mmap_region_t *plat_arm_get_mmap(void); + +/* Allow platform to override psci_pm_ops during runtime */ +const plat_psci_ops_t *plat_arm_psci_override_pm_ops(plat_psci_ops_t *ops); + +/* Execution state switch in ARM platforms */ +int arm_execution_state_switch(unsigned int smc_fid, + uint32_t pc_hi, + uint32_t pc_lo, + uint32_t cookie_hi, + uint32_t cookie_lo, + void *handle); + +/* Optional functions for SP_MIN */ +void plat_arm_sp_min_early_platform_setup(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3); + +/* global variables */ +extern plat_psci_ops_t plat_arm_psci_pm_ops; +extern const mmap_region_t plat_arm_mmap[]; +extern const unsigned int arm_pm_idle_states[]; + +/* secure watchdog */ +void plat_arm_secure_wdt_start(void); +void plat_arm_secure_wdt_stop(void); + +/* Get SOC-ID of ARM platform */ +uint32_t plat_arm_get_soc_id(void); + +#endif /* PLAT_ARM_H */ diff --git a/drivers/rz/ipl/rza/include/plat/arm/common/smccc_def.h b/drivers/rz/ipl/rza/include/plat/arm/common/smccc_def.h new file mode 100644 index 00000000..6e698e5d --- /dev/null +++ b/drivers/rz/ipl/rza/include/plat/arm/common/smccc_def.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef SMCCC_DEF_H +#define SMCCC_DEF_H + +/* Defines used to retrieve ARM SOC revision */ +#define ARM_SOC_CONTINUATION_CODE U(0x4) +#define ARM_SOC_IDENTIFICATION_CODE U(0x3B) +#define ARM_SOC_CONTINUATION_SHIFT U(24) +#define ARM_SOC_IDENTIFICATION_SHIFT U(16) + +#endif /* SMCCC_DEF_H */ diff --git a/drivers/rz/ipl/rza/include/plat/arm/css/common/aarch64/css_macros.S b/drivers/rz/ipl/rza/include/plat/arm/css/common/aarch64/css_macros.S new file mode 100644 index 00000000..85a7044d --- /dev/null +++ b/drivers/rz/ipl/rza/include/plat/arm/css/common/aarch64/css_macros.S @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef CSS_MACROS_S +#define CSS_MACROS_S + +#include +#include + + /* --------------------------------------------- + * The below required platform porting macro + * prints out relevant GIC registers whenever an + * unhandled exception is taken in BL31. + * Clobbers: x0 - x10, x16, x17, sp + * --------------------------------------------- + */ + .macro css_print_gic_regs + mov_imm x16, PLAT_ARM_GICD_BASE + mov_imm x17, PLAT_ARM_GICC_BASE + arm_print_gic_regs + .endm + +#endif /* CSS_MACROS_S */ diff --git a/drivers/rz/ipl/rza/include/plat/arm/css/common/css_def.h b/drivers/rz/ipl/rza/include/plat/arm/css/common/css_def.h new file mode 100644 index 00000000..d5993526 --- /dev/null +++ b/drivers/rz/ipl/rza/include/plat/arm/css/common/css_def.h @@ -0,0 +1,203 @@ +/* + * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CSS_DEF_H +#define CSS_DEF_H + +#include +#include +#include + +/************************************************************************* + * Definitions common to all ARM Compute SubSystems (CSS) + *************************************************************************/ +#define NSROM_BASE 0x1f000000 +#define NSROM_SIZE 0x00001000 + +/* Following covers CSS Peripherals excluding NSROM and NSRAM */ +#define CSS_DEVICE_BASE 0x20000000 +#define CSS_DEVICE_SIZE 0x0e000000 + +/* System Security Control Registers */ +#define SSC_REG_BASE 0x2a420000 +#define SSC_GPRETN (SSC_REG_BASE + 0x030) + +/* System ID Registers Unit */ +#define SID_REG_BASE 0x2a4a0000 +#define SID_SYSTEM_ID_OFFSET 0x40 +#define SID_SYSTEM_CFG_OFFSET 0x70 +#define SID_NODE_ID_OFFSET 0x60 +#define SID_CHIP_ID_MASK 0xFF +#define SID_MULTI_CHIP_MODE_MASK 0x100 +#define SID_MULTI_CHIP_MODE_SHIFT 8 + +/* The slave_bootsecure controls access to GPU, DMC and CS. */ +#define CSS_NIC400_SLAVE_BOOTSECURE 8 + +/* Interrupt handling constants */ +#define CSS_IRQ_MHU 69 +#define CSS_IRQ_GPU_SMMU_0 71 +#define CSS_IRQ_TZC 80 +#define CSS_IRQ_TZ_WDOG 86 +#define CSS_IRQ_SEC_SYS_TIMER 91 + +/* MHU register offsets */ +#define MHU_CPU_INTR_S_SET_OFFSET 0x308 + +/* + * Define a list of Group 1 Secure interrupt properties as per GICv3 + * terminology. On a GICv2 system or mode, the interrupts will be treated as + * Group 0 interrupts. + */ +#define CSS_G1S_IRQ_PROPS(grp) \ + INTR_PROP_DESC(CSS_IRQ_MHU, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(CSS_IRQ_GPU_SMMU_0, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(CSS_IRQ_TZC, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(CSS_IRQ_TZ_WDOG, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(CSS_IRQ_SEC_SYS_TIMER, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_LEVEL) + +#if CSS_USE_SCMI_SDS_DRIVER +/* Memory region for shared data storage */ +#define PLAT_ARM_SDS_MEM_BASE ARM_SHARED_RAM_BASE +#define PLAT_ARM_SDS_MEM_SIZE_MAX 0xDC0 /* 3520 bytes */ +/* + * The SCMI Channel is placed right after the SDS region + */ +#define CSS_SCMI_PAYLOAD_BASE (PLAT_ARM_SDS_MEM_BASE + PLAT_ARM_SDS_MEM_SIZE_MAX) +#define CSS_SCMI_MHU_DB_REG_OFF MHU_CPU_INTR_S_SET_OFFSET + +/* Trusted mailbox base address common to all CSS */ +/* If SDS is present, then mailbox is at top of SRAM */ +#define PLAT_ARM_TRUSTED_MAILBOX_BASE (ARM_SHARED_RAM_BASE + ARM_SHARED_RAM_SIZE - 0x8) + +/* Number of retries for SCP_RAM_READY flag */ +#define CSS_SCP_READY_10US_RETRIES 1000000 /* Effective timeout of 10000 ms */ + +#else +/* + * SCP <=> AP boot configuration + * + * The SCP/AP boot configuration is a 32-bit word located at a known offset from + * the start of the Trusted SRAM. + * + * Note that the value stored at this address is only valid at boot time, before + * the SCP_BL2 image is transferred to SCP. + */ +#define SCP_BOOT_CFG_ADDR PLAT_CSS_SCP_COM_SHARED_MEM_BASE + +/* Trusted mailbox base address common to all CSS */ +/* If SDS is not present, then the mailbox is at the bottom of SRAM */ +#define PLAT_ARM_TRUSTED_MAILBOX_BASE ARM_TRUSTED_SRAM_BASE + +#endif /* CSS_USE_SCMI_SDS_DRIVER */ + +#define CSS_MAP_DEVICE MAP_REGION_FLAT( \ + CSS_DEVICE_BASE, \ + CSS_DEVICE_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +#define CSS_MAP_NSRAM MAP_REGION_FLAT( \ + NSRAM_BASE, \ + NSRAM_SIZE, \ + MT_DEVICE | MT_RW | MT_NS) + +#if defined(IMAGE_BL2U) +#define CSS_MAP_SCP_BL2U MAP_REGION_FLAT( \ + SCP_BL2U_BASE, \ + SCP_BL2U_LIMIT \ + - SCP_BL2U_BASE,\ + MT_RW_DATA | MT_SECURE) +#endif + +/* Platform ID address */ +#define SSC_VERSION_OFFSET 0x040 + +#define SSC_VERSION_CONFIG_SHIFT 28 +#define SSC_VERSION_MAJOR_REV_SHIFT 24 +#define SSC_VERSION_MINOR_REV_SHIFT 20 +#define SSC_VERSION_DESIGNER_ID_SHIFT 12 +#define SSC_VERSION_PART_NUM_SHIFT 0x0 +#define SSC_VERSION_CONFIG_MASK 0xf +#define SSC_VERSION_MAJOR_REV_MASK 0xf +#define SSC_VERSION_MINOR_REV_MASK 0xf +#define SSC_VERSION_DESIGNER_ID_MASK 0xff +#define SSC_VERSION_PART_NUM_MASK 0xfff + +#define SID_SYSTEM_ID_PART_NUM_MASK 0xfff + +/* SSC debug configuration registers */ +#define SSC_DBGCFG_SET 0x14 +#define SSC_DBGCFG_CLR 0x18 + +#define SPIDEN_INT_CLR_SHIFT 6 +#define SPIDEN_SEL_SET_SHIFT 7 + +#ifndef __ASSEMBLER__ + +/* SSC_VERSION related accessors */ + +/* Returns the part number of the platform */ +#define GET_SSC_VERSION_PART_NUM(val) \ + (((val) >> SSC_VERSION_PART_NUM_SHIFT) & \ + SSC_VERSION_PART_NUM_MASK) + +/* Returns the configuration number of the platform */ +#define GET_SSC_VERSION_CONFIG(val) \ + (((val) >> SSC_VERSION_CONFIG_SHIFT) & \ + SSC_VERSION_CONFIG_MASK) + +#endif /* __ASSEMBLER__ */ + +/************************************************************************* + * Required platform porting definitions common to all + * ARM Compute SubSystems (CSS) + ************************************************************************/ + +/* + * The loading of SCP images(SCP_BL2 or SCP_BL2U) is done if there + * respective base addresses are defined (i.e SCP_BL2_BASE, SCP_BL2U_BASE). + * Hence, `CSS_LOAD_SCP_IMAGES` needs to be set to 1 if BL2 needs to load + * an SCP_BL2/SCP_BL2U image. + */ +#if CSS_LOAD_SCP_IMAGES + +#if ARM_BL31_IN_DRAM +#error "SCP_BL2 is not expected to be loaded by BL2 for ARM_BL31_IN_DRAM config" +#endif + +/* + * Load address of SCP_BL2 in CSS platform ports + * SCP_BL2 is loaded to the same place as BL31 but it shouldn't overwrite BL1 + * rw data or BL2. Once SCP_BL2 is transferred to the SCP, it is discarded and + * BL31 is loaded over the top. + */ +#define SCP_BL2_BASE (BL2_BASE - PLAT_CSS_MAX_SCP_BL2_SIZE) +#define SCP_BL2_LIMIT BL2_BASE + +#define SCP_BL2U_BASE (BL2_BASE - PLAT_CSS_MAX_SCP_BL2U_SIZE) +#define SCP_BL2U_LIMIT BL2_BASE +#endif /* CSS_LOAD_SCP_IMAGES */ + +/* Load address of Non-Secure Image for CSS platform ports */ +#define PLAT_ARM_NS_IMAGE_BASE U(0xE0000000) + +/* + * Parsing of CPU and Cluster states, as returned by 'Get CSS Power State' SCP + * command + */ +#define CSS_CLUSTER_PWR_STATE_ON 0 +#define CSS_CLUSTER_PWR_STATE_OFF 3 + +#define CSS_CPU_PWR_STATE_ON 1 +#define CSS_CPU_PWR_STATE_OFF 0 +#define CSS_CPU_PWR_STATE(state, n) (((state) >> (n)) & 1) + +#endif /* CSS_DEF_H */ diff --git a/drivers/rz/ipl/rza/include/plat/arm/css/common/css_pm.h b/drivers/rz/ipl/rza/include/plat/arm/css/common/css_pm.h new file mode 100644 index 00000000..e5357f50 --- /dev/null +++ b/drivers/rz/ipl/rza/include/plat/arm/css/common/css_pm.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CSS_PM_H +#define CSS_PM_H + +#include +#include + +#include + +/* Macros to read the CSS power domain state */ +#define CSS_CORE_PWR_STATE(state) (state)->pwr_domain_state[ARM_PWR_LVL0] +#define CSS_CLUSTER_PWR_STATE(state) (state)->pwr_domain_state[ARM_PWR_LVL1] + +static inline unsigned int css_system_pwr_state(const psci_power_state_t *state) +{ +#if (PLAT_MAX_PWR_LVL == CSS_SYSTEM_PWR_DMN_LVL) + return state->pwr_domain_state[CSS_SYSTEM_PWR_DMN_LVL]; +#else + return 0; +#endif +} + +int css_pwr_domain_on(u_register_t mpidr); +void css_pwr_domain_on_finish(const psci_power_state_t *target_state); +void css_pwr_domain_on_finish_late(const psci_power_state_t *target_state); +void css_pwr_domain_off(const psci_power_state_t *target_state); +void css_pwr_domain_suspend(const psci_power_state_t *target_state); +void css_pwr_domain_suspend_finish( + const psci_power_state_t *target_state); +void __dead2 css_system_off(void); +void __dead2 css_system_reset(void); +void css_cpu_standby(plat_local_state_t cpu_state); +void css_get_sys_suspend_power_state(psci_power_state_t *req_state); +int css_node_hw_state(u_register_t mpidr, unsigned int power_level); + +/* + * This mapping array has to be exported by the platform. Each element at + * a given index maps that core to an SCMI power domain. + */ +extern const uint32_t plat_css_core_pos_to_scmi_dmn_id_map[]; + +#define SCMI_DOMAIN_ID_MASK U(0xFFFF) +#define SCMI_CHANNEL_ID_MASK U(0xFFFF) +#define SCMI_CHANNEL_ID_SHIFT U(16) + +#define SET_SCMI_CHANNEL_ID(n) (((n) & SCMI_CHANNEL_ID_MASK) << \ + SCMI_CHANNEL_ID_SHIFT) +#define SET_SCMI_DOMAIN_ID(n) ((n) & SCMI_DOMAIN_ID_MASK) +#define GET_SCMI_CHANNEL_ID(n) (((n) >> SCMI_CHANNEL_ID_SHIFT) & \ + SCMI_CHANNEL_ID_MASK) +#define GET_SCMI_DOMAIN_ID(n) ((n) & SCMI_DOMAIN_ID_MASK) + +#endif /* CSS_PM_H */ diff --git a/drivers/rz/ipl/rza/include/plat/arm/soc/common/soc_css.h b/drivers/rz/ipl/rza/include/plat/arm/soc/common/soc_css.h new file mode 100644 index 00000000..469928d8 --- /dev/null +++ b/drivers/rz/ipl/rza/include/plat/arm/soc/common/soc_css.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SOC_CSS_H +#define SOC_CSS_H + +/* + * Utility functions for ARM CSS SoCs + */ +void soc_css_init_nic400(void); +void soc_css_init_pcie(void); + +static inline void soc_css_security_setup(void) +{ + soc_css_init_nic400(); + soc_css_init_pcie(); +} + +#endif /* SOC_CSS_H */ diff --git a/drivers/rz/ipl/rza/include/plat/arm/soc/common/soc_css_def.h b/drivers/rz/ipl/rza/include/plat/arm/soc/common/soc_css_def.h new file mode 100644 index 00000000..b4b6ba8e --- /dev/null +++ b/drivers/rz/ipl/rza/include/plat/arm/soc/common/soc_css_def.h @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SOC_CSS_DEF_H +#define SOC_CSS_DEF_H + +#include +#include + +/* + * Definitions common to all ARM CSS SoCs + */ + +/* Following covers ARM CSS SoC Peripherals and PCIe expansion area */ +#define SOC_CSS_DEVICE_BASE 0x40000000 +#define SOC_CSS_DEVICE_SIZE 0x40000000 +#define SOC_CSS_PCIE_CONTROL_BASE 0x7ff20000 + +/* PL011 UART related constants */ +#define SOC_CSS_UART0_BASE 0x7ff80000 +#define SOC_CSS_UART1_BASE 0x7ff70000 + +#define SOC_CSS_UART0_CLK_IN_HZ 7372800 +#define SOC_CSS_UART1_CLK_IN_HZ 7372800 + +/* SoC NIC-400 Global Programmers View (GPV) */ +#define SOC_CSS_NIC400_BASE 0x7fd00000 + +#define SOC_CSS_NIC400_USB_EHCI 0 +#define SOC_CSS_NIC400_TLX_MASTER 1 +#define SOC_CSS_NIC400_USB_OHCI 2 +#define SOC_CSS_NIC400_PL354_SMC 3 +/* + * The apb4_bridge controls access to: + * - the PCIe configuration registers + * - the MMU units for USB, HDLCD and DMA + */ +#define SOC_CSS_NIC400_APB4_BRIDGE 4 + +/* Non-volatile counters */ +#define SOC_TRUSTED_NVCTR_BASE 0x7fe70000 +#define TFW_NVCTR_BASE (SOC_TRUSTED_NVCTR_BASE + 0x0000) +#define TFW_NVCTR_SIZE 4 +#define NTFW_CTR_BASE (SOC_TRUSTED_NVCTR_BASE + 0x0004) +#define NTFW_CTR_SIZE 4 + +/* Keys */ +#define SOC_KEYS_BASE 0x7fe80000 +#define TZ_PUB_KEY_HASH_BASE (SOC_KEYS_BASE + 0x0000) +#define TZ_PUB_KEY_HASH_SIZE 32 +#define HU_KEY_BASE (SOC_KEYS_BASE + 0x0020) +#define HU_KEY_SIZE 16 +#define END_KEY_BASE (SOC_KEYS_BASE + 0x0044) +#define END_KEY_SIZE 32 + +#define SOC_CSS_MAP_DEVICE MAP_REGION_FLAT( \ + SOC_CSS_DEVICE_BASE, \ + SOC_CSS_DEVICE_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + + +/* + * The bootsec_bridge controls access to a bunch of peripherals, e.g. the UARTs. + */ +#define SOC_CSS_NIC400_BOOTSEC_BRIDGE 5 +#define SOC_CSS_NIC400_BOOTSEC_BRIDGE_UART1 (1 << 12) + +/* + * Required platform porting definitions common to all ARM CSS SoCs + */ +#if JUNO_AARCH32_EL3_RUNTIME +/* + * Following change is required to initialize TZC + * for enabling access to the HI_VECTOR (0xFFFF0000) + * location needed for JUNO AARCH32 support. + */ +#define PLAT_ARM_SCP_TZC_DRAM1_SIZE ULL(0x8000) +#else +/* 2MB used for SCP DDR retraining */ +#define PLAT_ARM_SCP_TZC_DRAM1_SIZE ULL(0x00200000) +#endif + +#endif /* SOC_CSS_DEF_H */ diff --git a/drivers/rz/ipl/rza/include/plat/common/common_def.h b/drivers/rz/ipl/rza/include/plat/common/common_def.h new file mode 100644 index 00000000..14ae603b --- /dev/null +++ b/drivers/rz/ipl/rza/include/plat/common/common_def.h @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef COMMON_DEF_H +#define COMMON_DEF_H + +#include + +#include +#include +#include + +/****************************************************************************** + * Required platform porting definitions that are expected to be common to + * all platforms + *****************************************************************************/ + +/* + * Platform binary types for linking + */ +#ifdef __aarch64__ +#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64" +#define PLATFORM_LINKER_ARCH aarch64 +#else +#define PLATFORM_LINKER_FORMAT "elf32-littlearm" +#define PLATFORM_LINKER_ARCH arm +#endif /* __aarch64__ */ + +/* + * Generic platform constants + */ +#define FIRMWARE_WELCOME_STR "Booting Trusted Firmware\n" + +#define BL2_IMAGE_DESC { \ + .image_id = BL2_IMAGE_ID, \ + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, \ + VERSION_2, image_info_t, 0), \ + .image_info.image_base = BL2_BASE, \ + .image_info.image_max_size = BL2_LIMIT - BL2_BASE,\ + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, \ + VERSION_2, entry_point_info_t, SECURE | EXECUTABLE),\ + .ep_info.pc = BL2_BASE, \ +} + +/* + * The following constants identify the extents of the code & read-only data + * regions. These addresses are used by the MMU setup code and therefore they + * must be page-aligned. + * + * When the code and read-only data are mapped as a single atomic section + * (i.e. when SEPARATE_CODE_AND_RODATA=0) then we treat the whole section as + * code by specifying the read-only data section as empty. + * + * BL1 is different than the other images in the sense that its read-write data + * originally lives in Trusted ROM and needs to be relocated in Trusted SRAM at + * run-time. Therefore, the read-write data in ROM can be mapped with the same + * memory attributes as the read-only data region. For this reason, BL1 uses + * different macros. + * + * Note that BL1_ROM_END is not necessarily aligned on a page boundary as it + * just points to the end of BL1's actual content in Trusted ROM. Therefore it + * needs to be rounded up to the next page size in order to map the whole last + * page of it with the right memory attributes. + */ +#if SEPARATE_CODE_AND_RODATA + +#define BL1_CODE_END BL_CODE_END +#define BL1_RO_DATA_BASE BL_RO_DATA_BASE +#define BL1_RO_DATA_END round_up(BL1_ROM_END, PAGE_SIZE) +#if BL2_IN_XIP_MEM +#define BL2_CODE_END BL_CODE_END +#define BL2_RO_DATA_BASE BL_RO_DATA_BASE +#define BL2_RO_DATA_END round_up(BL2_ROM_END, PAGE_SIZE) +#endif /* BL2_IN_XIP_MEM */ +#else +#define BL_RO_DATA_BASE UL(0) +#define BL_RO_DATA_END UL(0) +#define BL1_CODE_END round_up(BL1_ROM_END, PAGE_SIZE) +#if BL2_IN_XIP_MEM +#define BL2_RO_DATA_BASE UL(0) +#define BL2_RO_DATA_END UL(0) +#define BL2_CODE_END round_up(BL2_ROM_END, PAGE_SIZE) +#endif /* BL2_IN_XIP_MEM */ +#endif /* SEPARATE_CODE_AND_RODATA */ + +#endif /* COMMON_DEF_H */ diff --git a/drivers/rz/ipl/rza/include/plat/common/plat_trng.h b/drivers/rz/ipl/rza/include/plat/common/plat_trng.h new file mode 100644 index 00000000..a9f73b67 --- /dev/null +++ b/drivers/rz/ipl/rza/include/plat/common/plat_trng.h @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2021, ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_TRNG_H +#define PLAT_TRNG_H + +#include + +/* TRNG platform functions */ + +extern uuid_t plat_trng_uuid; +void plat_entropy_setup(void); +bool plat_get_entropy(uint64_t *out); + +#endif /* PLAT_TRNG_H */ diff --git a/drivers/rz/ipl/rza/include/plat/common/platform.h b/drivers/rz/ipl/rza/include/plat/common/platform.h new file mode 100644 index 00000000..1def86ea --- /dev/null +++ b/drivers/rz/ipl/rza/include/plat/common/platform.h @@ -0,0 +1,352 @@ +/* + * Copyright (c) 2013-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_H +#define PLATFORM_H + +#include + +#include +#if defined(SPD_spmd) + #include +#endif +#if TRNG_SUPPORT +#include "plat_trng.h" +#endif + +/******************************************************************************* + * Forward declarations + ******************************************************************************/ +struct auth_img_desc_s; +struct meminfo; +struct image_info; +struct entry_point_info; +struct image_desc; +struct bl_load_info; +struct bl_params; +struct mmap_region; +struct spm_mm_boot_info; +struct sp_res_desc; +enum fw_enc_status_t; + +/******************************************************************************* + * plat_get_rotpk_info() flags + ******************************************************************************/ +#define ROTPK_IS_HASH (1 << 0) +/* Flag used to skip verification of the certificate ROTPK while the platform + ROTPK is not deployed */ +#define ROTPK_NOT_DEPLOYED (1 << 1) + +/******************************************************************************* + * plat_get_enc_key_info() flags + ******************************************************************************/ +/* + * Flag used to notify caller that information provided in key buffer is an + * identifier rather than an actual key. + */ +#define ENC_KEY_IS_IDENTIFIER (1 << 0) + +/******************************************************************************* + * Function declarations + ******************************************************************************/ +/******************************************************************************* + * Mandatory common functions + ******************************************************************************/ +unsigned int plat_get_syscnt_freq2(void); + +int plat_get_image_source(unsigned int image_id, + uintptr_t *dev_handle, + uintptr_t *image_spec); +uintptr_t plat_get_ns_image_entrypoint(void); +unsigned int plat_my_core_pos(void); +int plat_core_pos_by_mpidr(u_register_t mpidr); +int plat_get_mbedtls_heap(void **heap_addr, size_t *heap_size); + +#if STACK_PROTECTOR_ENABLED +/* + * Return a new value to be used for the stack protection's canary. + * + * Ideally, this value is a random number that is impossible to predict by an + * attacker. + */ +u_register_t plat_get_stack_protector_canary(void); +#endif /* STACK_PROTECTOR_ENABLED */ + +/******************************************************************************* + * Mandatory interrupt management functions + ******************************************************************************/ +uint32_t plat_ic_get_pending_interrupt_id(void); +uint32_t plat_ic_get_pending_interrupt_type(void); +uint32_t plat_ic_acknowledge_interrupt(void); +uint32_t plat_ic_get_interrupt_type(uint32_t id); +void plat_ic_end_of_interrupt(uint32_t id); +uint32_t plat_interrupt_type_to_line(uint32_t type, + uint32_t security_state); + +/******************************************************************************* + * Optional interrupt management functions, depending on chosen EL3 components. + ******************************************************************************/ +unsigned int plat_ic_get_running_priority(void); +int plat_ic_is_spi(unsigned int id); +int plat_ic_is_ppi(unsigned int id); +int plat_ic_is_sgi(unsigned int id); +unsigned int plat_ic_get_interrupt_active(unsigned int id); +void plat_ic_disable_interrupt(unsigned int id); +void plat_ic_enable_interrupt(unsigned int id); +int plat_ic_has_interrupt_type(unsigned int type); +void plat_ic_set_interrupt_type(unsigned int id, unsigned int type); +void plat_ic_set_interrupt_priority(unsigned int id, unsigned int priority); +void plat_ic_raise_el3_sgi(int sgi_num, u_register_t target); +void plat_ic_set_spi_routing(unsigned int id, unsigned int routing_mode, + u_register_t mpidr); +void plat_ic_set_interrupt_pending(unsigned int id); +void plat_ic_clear_interrupt_pending(unsigned int id); +unsigned int plat_ic_set_priority_mask(unsigned int mask); +unsigned int plat_ic_get_interrupt_id(unsigned int raw); + +/******************************************************************************* + * Optional common functions (may be overridden) + ******************************************************************************/ +uintptr_t plat_get_my_stack(void); +void plat_report_exception(unsigned int exception_type); +int plat_crash_console_init(void); +int plat_crash_console_putc(int c); +void plat_crash_console_flush(void); +void plat_error_handler(int err) __dead2; +void plat_panic_handler(void) __dead2; +const char *plat_log_get_prefix(unsigned int log_level); +void bl2_plat_preload_setup(void); +int plat_try_next_boot_source(void); + +/******************************************************************************* + * Mandatory BL1 functions + ******************************************************************************/ +void bl1_early_platform_setup(void); +void bl1_plat_arch_setup(void); +void bl1_platform_setup(void); +struct meminfo *bl1_plat_sec_mem_layout(void); + +/******************************************************************************* + * Optional EL3 component functions in BL31 + ******************************************************************************/ + +/* SDEI platform functions */ +#if SDEI_SUPPORT +void plat_sdei_setup(void); +int plat_sdei_validate_entry_point(uintptr_t ep, unsigned int client_mode); +void plat_sdei_handle_masked_trigger(uint64_t mpidr, unsigned int intr); +#endif + +void plat_ea_handler(unsigned int ea_reason, uint64_t syndrome, void *cookie, + void *handle, uint64_t flags); + +/* + * The following function is mandatory when the + * firmware update feature is used. + */ +int bl1_plat_mem_check(uintptr_t mem_base, unsigned int mem_size, + unsigned int flags); + +/******************************************************************************* + * Optional BL1 functions (may be overridden) + ******************************************************************************/ +/* + * The following functions are used for image loading process in BL1. + */ +void bl1_plat_set_ep_info(unsigned int image_id, + struct entry_point_info *ep_info); +/* + * The following functions are mandatory when firmware update + * feature is used and optional otherwise. + */ +unsigned int bl1_plat_get_next_image_id(void); +struct image_desc *bl1_plat_get_image_desc(unsigned int image_id); + +/* + * The following functions are used by firmware update + * feature and may optionally be overridden. + */ +__dead2 void bl1_plat_fwu_done(void *client_cookie, void *reserved); + +/* + * This BL1 function can be used by the platforms to update/use image + * information for a given `image_id`. + */ +int bl1_plat_handle_pre_image_load(unsigned int image_id); +int bl1_plat_handle_post_image_load(unsigned int image_id); + +#if MEASURED_BOOT +/* + * Calculates and writes BL2 hash data to the platform's defined location. + * For ARM platforms the data are written to TB_FW_CONFIG DTB. + */ +void bl1_plat_set_bl2_hash(const image_desc_t *image_desc); +#endif + +/******************************************************************************* + * Mandatory BL2 functions + ******************************************************************************/ +void bl2_early_platform_setup2(u_register_t arg0, u_register_t arg1, u_register_t arg2, u_register_t arg3); +void bl2_plat_arch_setup(void); +void bl2_platform_setup(void); +struct meminfo *bl2_plat_sec_mem_layout(void); + +/* + * This function can be used by the platforms to update/use image + * information for given `image_id`. + */ +int bl2_plat_handle_pre_image_load(unsigned int image_id); +int bl2_plat_handle_post_image_load(unsigned int image_id); + +/******************************************************************************* + * Optional BL2 functions (may be overridden) + ******************************************************************************/ +#if MEASURED_BOOT +/* Read TCG_DIGEST_SIZE bytes of BL2 hash data */ +void bl2_plat_get_hash(void *data); +#endif + +/******************************************************************************* + * Mandatory BL2 at EL3 functions: Must be implemented if BL2_AT_EL3 image is + * supported + ******************************************************************************/ +void bl2_el3_early_platform_setup(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3); +void bl2_el3_plat_arch_setup(void); + +/******************************************************************************* + * Optional BL2 at EL3 functions (may be overridden) + ******************************************************************************/ +void bl2_el3_plat_prepare_exit(void); + +/******************************************************************************* + * Mandatory BL2U functions. + ******************************************************************************/ +void bl2u_early_platform_setup(struct meminfo *mem_layout, + void *plat_info); +void bl2u_plat_arch_setup(void); +void bl2u_platform_setup(void); + +/******************************************************************************* + * Conditionally mandatory BL2U functions for CSS platforms. + ******************************************************************************/ +/* + * This function is used to perform any platform-specific actions required to + * handle the BL2U_SCP firmware. + */ +int bl2u_plat_handle_scp_bl2u(void); + +/******************************************************************************* + * Mandatory BL31 functions + ******************************************************************************/ +void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3); +void bl31_plat_arch_setup(void); +void bl31_platform_setup(void); +void bl31_plat_runtime_setup(void); +struct entry_point_info *bl31_plat_get_next_image_ep_info(uint32_t type); + +/******************************************************************************* + * Mandatory PSCI functions (BL31) + ******************************************************************************/ +int plat_setup_psci_ops(uintptr_t sec_entrypoint, + const struct plat_psci_ops **psci_ops); +const unsigned char *plat_get_power_domain_tree_desc(void); + +/******************************************************************************* + * Optional PSCI functions (BL31). + ******************************************************************************/ +void plat_psci_stat_accounting_start(const psci_power_state_t *state_info); +void plat_psci_stat_accounting_stop(const psci_power_state_t *state_info); +u_register_t plat_psci_stat_get_residency(unsigned int lvl, + const psci_power_state_t *state_info, + unsigned int last_cpu_idx); +plat_local_state_t plat_get_target_pwr_state(unsigned int lvl, + const plat_local_state_t *states, + unsigned int ncpu); + +/******************************************************************************* + * Optional BL31 functions (may be overridden) + ******************************************************************************/ +void bl31_plat_enable_mmu(uint32_t flags); + +/******************************************************************************* + * Optional BL32 functions (may be overridden) + ******************************************************************************/ +void bl32_plat_enable_mmu(uint32_t flags); + +/******************************************************************************* + * Trusted Board Boot functions + ******************************************************************************/ +int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len, + unsigned int *flags); +int plat_get_nv_ctr(void *cookie, unsigned int *nv_ctr); +int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr); +int plat_set_nv_ctr2(void *cookie, const struct auth_img_desc_s *img_desc, + unsigned int nv_ctr); +int get_mbedtls_heap_helper(void **heap_addr, size_t *heap_size); +int plat_get_enc_key_info(enum fw_enc_status_t fw_enc_status, uint8_t *key, + size_t *key_len, unsigned int *flags, + const uint8_t *img_id, size_t img_id_len); + +/******************************************************************************* + * Secure Partitions functions + ******************************************************************************/ +const struct mmap_region *plat_get_secure_partition_mmap(void *cookie); +const struct spm_mm_boot_info *plat_get_secure_partition_boot_info( + void *cookie); +int plat_spm_sp_rd_load(struct sp_res_desc *rd, const void *ptr, size_t size); +int plat_spm_sp_get_next_address(void **sp_base, size_t *sp_size, + void **rd_base, size_t *rd_size); +#if defined(SPD_spmd) +int plat_spm_core_manifest_load(spmc_manifest_attribute_t *manifest, + const void *pm_addr); +#endif +/******************************************************************************* + * Mandatory BL image load functions(may be overridden). + ******************************************************************************/ +/* + * This function returns pointer to the list of images that the + * platform has populated to load. + */ +struct bl_load_info *plat_get_bl_image_load_info(void); + +/* + * This function returns a pointer to the shared memory that the + * platform has kept aside to pass trusted firmware related + * information that next BL image could need. + */ +struct bl_params *plat_get_next_bl_params(void); + +/* + * This function flushes to main memory all the params that are + * passed to next image. + */ +void plat_flush_next_bl_params(void); + +/* + * The below function enable Trusted Firmware components like SPDs which + * haven't migrated to the new platform API to compile on platforms which + * have the compatibility layer disabled. + */ +unsigned int platform_core_pos_helper(unsigned long mpidr); + +/* + * Optional function to get SOC version + */ +int32_t plat_get_soc_version(void); + +/* + * Optional function to get SOC revision + */ +int32_t plat_get_soc_revision(void); + +/* + * Optional function to check for SMCCC function availability for platform + */ +int32_t plat_is_smccc_feature_available(u_register_t fid); + +#endif /* PLATFORM_H */ diff --git a/drivers/rz/ipl/rza/include/services/arm_arch_svc.h b/drivers/rz/ipl/rza/include/services/arm_arch_svc.h new file mode 100644 index 00000000..5bbd8bb6 --- /dev/null +++ b/drivers/rz/ipl/rza/include/services/arm_arch_svc.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef ARM_ARCH_SVC_H +#define ARM_ARCH_SVC_H + +#define SMCCC_VERSION U(0x80000000) +#define SMCCC_ARCH_FEATURES U(0x80000001) +#define SMCCC_ARCH_SOC_ID U(0x80000002) +#define SMCCC_ARCH_WORKAROUND_1 U(0x80008000) +#define SMCCC_ARCH_WORKAROUND_2 U(0x80007FFF) + +#define SMCCC_GET_SOC_VERSION U(0) +#define SMCCC_GET_SOC_REVISION U(1) + +#endif /* ARM_ARCH_SVC_H */ diff --git a/drivers/rz/ipl/rza/include/services/ffa_svc.h b/drivers/rz/ipl/rza/include/services/ffa_svc.h new file mode 100644 index 00000000..ec75bc93 --- /dev/null +++ b/drivers/rz/ipl/rza/include/services/ffa_svc.h @@ -0,0 +1,184 @@ +/* + * Copyright (c) 2020-2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef FFA_SVC_H +#define FFA_SVC_H + +#include +#include +#include + +/* FFA error codes. */ +#define FFA_ERROR_NOT_SUPPORTED -1 +#define FFA_ERROR_INVALID_PARAMETER -2 +#define FFA_ERROR_NO_MEMORY -3 +#define FFA_ERROR_BUSY -4 +#define FFA_ERROR_INTERRUPTED -5 +#define FFA_ERROR_DENIED -6 +#define FFA_ERROR_RETRY -7 + +/* The macros below are used to identify FFA calls from the SMC function ID */ +#define FFA_FNUM_MIN_VALUE U(0x60) +#define FFA_FNUM_MAX_VALUE U(0x84) +#define is_ffa_fid(fid) __extension__ ({ \ + __typeof__(fid) _fid = (fid); \ + ((GET_SMC_NUM(_fid) >= FFA_FNUM_MIN_VALUE) && \ + (GET_SMC_NUM(_fid) <= FFA_FNUM_MAX_VALUE)); }) + +/* FFA_VERSION helpers */ +#define FFA_VERSION_MAJOR U(1) +#define FFA_VERSION_MAJOR_SHIFT 16 +#define FFA_VERSION_MAJOR_MASK U(0x7FFF) +#define FFA_VERSION_MINOR U(0) +#define FFA_VERSION_MINOR_SHIFT 0 +#define FFA_VERSION_MINOR_MASK U(0xFFFF) +#define FFA_VERSION_BIT31_MASK U(0x1u << 31) + + +#define MAKE_FFA_VERSION(major, minor) \ + ((((major) & FFA_VERSION_MAJOR_MASK) << FFA_VERSION_MAJOR_SHIFT) | \ + (((minor) & FFA_VERSION_MINOR_MASK) << FFA_VERSION_MINOR_SHIFT)) +#define FFA_VERSION_COMPILED MAKE_FFA_VERSION(FFA_VERSION_MAJOR, \ + FFA_VERSION_MINOR) + +/* FFA_MSG_SEND helpers */ +#define FFA_MSG_SEND_ATTRS_BLK_SHIFT U(0) +#define FFA_MSG_SEND_ATTRS_BLK_MASK U(0x1) +#define FFA_MSG_SEND_ATTRS_BLK U(0) +#define FFA_MSG_SEND_ATTRS_BLK_NOT U(1) +#define FFA_MSG_SEND_ATTRS(blk) \ + (((blk) & FFA_MSG_SEND_ATTRS_BLK_MASK) \ + << FFA_MSG_SEND_ATTRS_BLK_SHIFT) + +/* Get FFA fastcall std FID from function number */ +#define FFA_FID(smc_cc, func_num) \ + ((SMC_TYPE_FAST << FUNCID_TYPE_SHIFT) | \ + ((smc_cc) << FUNCID_CC_SHIFT) | \ + (OEN_STD_START << FUNCID_OEN_SHIFT) | \ + ((func_num) << FUNCID_NUM_SHIFT)) + +/* FFA function numbers */ +#define FFA_FNUM_ERROR U(0x60) +#define FFA_FNUM_SUCCESS U(0x61) +#define FFA_FNUM_INTERRUPT U(0x62) +#define FFA_FNUM_VERSION U(0x63) +#define FFA_FNUM_FEATURES U(0x64) +#define FFA_FNUM_RX_RELEASE U(0x65) +#define FFA_FNUM_RXTX_MAP U(0x66) +#define FFA_FNUM_RXTX_UNMAP U(0x67) +#define FFA_FNUM_PARTITION_INFO_GET U(0x68) +#define FFA_FNUM_ID_GET U(0x69) +#define FFA_FNUM_MSG_POLL U(0x6A) +#define FFA_FNUM_MSG_WAIT U(0x6B) +#define FFA_FNUM_MSG_YIELD U(0x6C) +#define FFA_FNUM_MSG_RUN U(0x6D) +#define FFA_FNUM_MSG_SEND U(0x6E) +#define FFA_FNUM_MSG_SEND_DIRECT_REQ U(0x6F) +#define FFA_FNUM_MSG_SEND_DIRECT_RESP U(0x70) +#define FFA_FNUM_MEM_DONATE U(0x71) +#define FFA_FNUM_MEM_LEND U(0x72) +#define FFA_FNUM_MEM_SHARE U(0x73) +#define FFA_FNUM_MEM_RETRIEVE_REQ U(0x74) +#define FFA_FNUM_MEM_RETRIEVE_RESP U(0x75) +#define FFA_FNUM_MEM_RELINQUISH U(0x76) +#define FFA_FNUM_MEM_RECLAIM U(0x77) +#define FFA_FNUM_SECONDARY_EP_REGISTER U(0x84) + +/* FFA SMC32 FIDs */ +#define FFA_ERROR FFA_FID(SMC_32, FFA_FNUM_ERROR) +#define FFA_SUCCESS_SMC32 FFA_FID(SMC_32, FFA_FNUM_SUCCESS) +#define FFA_INTERRUPT FFA_FID(SMC_32, FFA_FNUM_INTERRUPT) +#define FFA_VERSION FFA_FID(SMC_32, FFA_FNUM_VERSION) +#define FFA_FEATURES FFA_FID(SMC_32, FFA_FNUM_FEATURES) +#define FFA_RX_RELEASE FFA_FID(SMC_32, FFA_FNUM_RX_RELEASE) +#define FFA_RXTX_MAP_SMC32 FFA_FID(SMC_32, FFA_FNUM_RXTX_MAP) +#define FFA_RXTX_UNMAP FFA_FID(SMC_32, FFA_FNUM_RXTX_UNMAP) +#define FFA_PARTITION_INFO_GET FFA_FID(SMC_32, FFA_FNUM_PARTITION_INFO_GET) +#define FFA_ID_GET FFA_FID(SMC_32, FFA_FNUM_ID_GET) +#define FFA_MSG_POLL FFA_FID(SMC_32, FFA_FNUM_MSG_POLL) +#define FFA_MSG_WAIT FFA_FID(SMC_32, FFA_FNUM_MSG_WAIT) +#define FFA_MSG_YIELD FFA_FID(SMC_32, FFA_FNUM_MSG_YIELD) +#define FFA_MSG_RUN FFA_FID(SMC_32, FFA_FNUM_MSG_RUN) +#define FFA_MSG_SEND FFA_FID(SMC_32, FFA_FNUM_MSG_SEND) +#define FFA_MSG_SEND_DIRECT_REQ_SMC32 \ + FFA_FID(SMC_32, FFA_FNUM_MSG_SEND_DIRECT_REQ) +#define FFA_MSG_SEND_DIRECT_RESP_SMC32 \ + FFA_FID(SMC_32, FFA_FNUM_MSG_SEND_DIRECT_RESP) +#define FFA_MEM_DONATE_SMC32 FFA_FID(SMC_32, FFA_FNUM_MEM_DONATE) +#define FFA_MEM_LEND_SMC32 FFA_FID(SMC_32, FFA_FNUM_MEM_LEND) +#define FFA_MEM_SHARE_SMC32 FFA_FID(SMC_32, FFA_FNUM_MEM_SHARE) +#define FFA_MEM_RETRIEVE_REQ_SMC32 \ + FFA_FID(SMC_32, FFA_FNUM_MEM_RETRIEVE_REQ) +#define FFA_MEM_RETRIEVE_RESP FFA_FID(SMC_32, FFA_FNUM_MEM_RETRIEVE_RESP) +#define FFA_MEM_RELINQUISH FFA_FID(SMC_32, FFA_FNUM_MEM_RELINQUISH) +#define FFA_MEM_RECLAIM FFA_FID(SMC_32, FFA_FNUM_MEM_RECLAIM) + +/* FFA SMC64 FIDs */ +#define FFA_ERROR_SMC64 FFA_FID(SMC_64, FFA_FNUM_ERROR) +#define FFA_SUCCESS_SMC64 FFA_FID(SMC_64, FFA_FNUM_SUCCESS) +#define FFA_RXTX_MAP_SMC64 FFA_FID(SMC_64, FFA_FNUM_RXTX_MAP) +#define FFA_MSG_SEND_DIRECT_REQ_SMC64 \ + FFA_FID(SMC_64, FFA_FNUM_MSG_SEND_DIRECT_REQ) +#define FFA_MSG_SEND_DIRECT_RESP_SMC64 \ + FFA_FID(SMC_64, FFA_FNUM_MSG_SEND_DIRECT_RESP) +#define FFA_MEM_DONATE_SMC64 FFA_FID(SMC_64, FFA_FNUM_MEM_DONATE) +#define FFA_MEM_LEND_SMC64 FFA_FID(SMC_64, FFA_FNUM_MEM_LEND) +#define FFA_MEM_SHARE_SMC64 FFA_FID(SMC_64, FFA_FNUM_MEM_SHARE) +#define FFA_MEM_RETRIEVE_REQ_SMC64 \ + FFA_FID(SMC_64, FFA_FNUM_MEM_RETRIEVE_REQ) +#define FFA_SECONDARY_EP_REGISTER_SMC64 \ + FFA_FID(SMC_64, FFA_FNUM_SECONDARY_EP_REGISTER) + +/* + * Reserve a special value for traffic targeted to the Hypervisor or SPM. + */ +#define FFA_TARGET_INFO_MBZ U(0x0) + +/* + * Reserve a special value for MBZ parameters. + */ +#define FFA_PARAM_MBZ U(0x0) + +/* + * Maximum FF-A endpoint id value + */ +#define FFA_ENDPOINT_ID_MAX U(1 << 16) + +/* + * Mask for source and destination endpoint id in + * a direct message request/response. + */ +#define FFA_DIRECT_MSG_ENDPOINT_ID_MASK U(0xffff) + +/* + * Bit shift for destination endpoint id in a direct message request/response. + */ +#define FFA_DIRECT_MSG_DESTINATION_SHIFT U(0) + +/* + * Bit shift for source endpoint id in a direct message request/response. + */ +#define FFA_DIRECT_MSG_SOURCE_SHIFT U(16) + +/****************************************************************************** + * ffa_endpoint_destination + *****************************************************************************/ +static inline uint16_t ffa_endpoint_destination(unsigned int ep) +{ + return (ep >> FFA_DIRECT_MSG_DESTINATION_SHIFT) & + FFA_DIRECT_MSG_ENDPOINT_ID_MASK; +} + +/****************************************************************************** + * ffa_endpoint_source + *****************************************************************************/ +static inline uint16_t ffa_endpoint_source(unsigned int ep) +{ + return (ep >> FFA_DIRECT_MSG_SOURCE_SHIFT) & + FFA_DIRECT_MSG_ENDPOINT_ID_MASK; +} + +#endif /* FFA_SVC_H */ diff --git a/drivers/rz/ipl/rza/include/services/sdei.h b/drivers/rz/ipl/rza/include/services/sdei.h new file mode 100644 index 00000000..063ed6f2 --- /dev/null +++ b/drivers/rz/ipl/rza/include/services/sdei.h @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SDEI_H +#define SDEI_H + +#include +#include +#include + +/* Range 0xC4000020 - 0xC400003F reserved for SDE 64bit smc calls */ +#define SDEI_VERSION 0xC4000020U +#define SDEI_EVENT_REGISTER 0xC4000021U +#define SDEI_EVENT_ENABLE 0xC4000022U +#define SDEI_EVENT_DISABLE 0xC4000023U +#define SDEI_EVENT_CONTEXT 0xC4000024U +#define SDEI_EVENT_COMPLETE 0xC4000025U +#define SDEI_EVENT_COMPLETE_AND_RESUME 0xC4000026U + +#define SDEI_EVENT_UNREGISTER 0xC4000027U +#define SDEI_EVENT_STATUS 0xC4000028U +#define SDEI_EVENT_GET_INFO 0xC4000029U +#define SDEI_EVENT_ROUTING_SET 0xC400002AU +#define SDEI_PE_MASK 0xC400002BU +#define SDEI_PE_UNMASK 0xC400002CU + +#define SDEI_INTERRUPT_BIND 0xC400002DU +#define SDEI_INTERRUPT_RELEASE 0xC400002EU +#define SDEI_EVENT_SIGNAL 0xC400002FU +#define SDEI_FEATURES 0xC4000030U +#define SDEI_PRIVATE_RESET 0xC4000031U +#define SDEI_SHARED_RESET 0xC4000032U + +/* SDEI_EVENT_REGISTER flags */ +#define SDEI_REGF_RM_ANY 0ULL +#define SDEI_REGF_RM_PE 1ULL + +/* SDEI_EVENT_COMPLETE status flags */ +#define SDEI_EV_HANDLED 0U +#define SDEI_EV_FAILED 1U + +/* Indices of private and shared mappings */ +#define SDEI_MAP_IDX_PRIV_ 0U +#define SDEI_MAP_IDX_SHRD_ 1U +#define SDEI_MAP_IDX_MAX_ 2U + +/* The macros below are used to identify SDEI calls from the SMC function ID */ +#define SDEI_FID_MASK U(0xffe0) +#define SDEI_FID_VALUE U(0x20) +#define is_sdei_fid(_fid) \ + ((((_fid) & SDEI_FID_MASK) == SDEI_FID_VALUE) && \ + (((_fid >> FUNCID_CC_SHIFT) & FUNCID_CC_MASK) == SMC_64)) + +#define SDEI_EVENT_MAP(_event, _intr, _flags) \ + { \ + .ev_num = (_event), \ + .intr = (_intr), \ + .map_flags = (_flags) \ + } + +#define SDEI_SHARED_EVENT(_event, _intr, _flags) \ + SDEI_EVENT_MAP(_event, _intr, _flags) + +#define SDEI_PRIVATE_EVENT(_event, _intr, _flags) \ + SDEI_EVENT_MAP(_event, _intr, (_flags) | SDEI_MAPF_PRIVATE) + +#define SDEI_DEFINE_EVENT_0(_intr) \ + SDEI_PRIVATE_EVENT(SDEI_EVENT_0, (_intr), SDEI_MAPF_SIGNALABLE) + +#define SDEI_EXPLICIT_EVENT(_event, _pri) \ + SDEI_EVENT_MAP((_event), 0, (_pri) | SDEI_MAPF_EXPLICIT | SDEI_MAPF_PRIVATE) + +/* + * Declare shared and private entries for each core. Also declare a global + * structure containing private and share entries. + * + * This macro must be used in the same file as the platform SDEI mappings are + * declared. Only then would ARRAY_SIZE() yield a meaningful value. + */ +#define REGISTER_SDEI_MAP(_private, _shared) \ + sdei_entry_t sdei_private_event_table \ + [PLATFORM_CORE_COUNT * ARRAY_SIZE(_private)]; \ + sdei_entry_t sdei_shared_event_table[ARRAY_SIZE(_shared)]; \ + const sdei_mapping_t sdei_global_mappings[] = { \ + [SDEI_MAP_IDX_PRIV_] = { \ + .map = (_private), \ + .num_maps = ARRAY_SIZE(_private) \ + }, \ + [SDEI_MAP_IDX_SHRD_] = { \ + .map = (_shared), \ + .num_maps = ARRAY_SIZE(_shared) \ + }, \ + } + +typedef uint8_t sdei_state_t; + +/* Runtime data of SDEI event */ +typedef struct sdei_entry { + uint64_t ep; /* Entry point */ + uint64_t arg; /* Entry point argument */ + uint64_t affinity; /* Affinity of shared event */ + unsigned int reg_flags; /* Registration flags */ + + /* Event handler states: registered, enabled, running */ + sdei_state_t state; +} sdei_entry_t; + +/* Mapping of SDEI events to interrupts, and associated data */ +typedef struct sdei_ev_map { + int32_t ev_num; /* Event number */ + unsigned int intr; /* Physical interrupt number for a bound map */ + unsigned int map_flags; /* Mapping flags, see SDEI_MAPF_* */ + int reg_count; /* Registration count */ + spinlock_t lock; /* Per-event lock */ +} sdei_ev_map_t; + +typedef struct sdei_mapping { + sdei_ev_map_t *map; + size_t num_maps; +} sdei_mapping_t; + +/* Handler to be called to handle SDEI smc calls */ +uint64_t sdei_smc_handler(uint32_t smc_fid, + uint64_t x1, + uint64_t x2, + uint64_t x3, + uint64_t x4, + void *cookie, + void *handle, + uint64_t flags); + +void sdei_init(void); + +/* Public API to dispatch an event to Normal world */ +int sdei_dispatch_event(int ev_num); + +#endif /* SDEI_H */ diff --git a/drivers/rz/ipl/rza/include/services/sdei_flags.h b/drivers/rz/ipl/rza/include/services/sdei_flags.h new file mode 100644 index 00000000..d1308f82 --- /dev/null +++ b/drivers/rz/ipl/rza/include/services/sdei_flags.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SDEI_FLAGS_H +#define SDEI_FLAGS_H + +#include + +/* Internal: SDEI flag bit positions */ +#define SDEI_MAPF_DYNAMIC_SHIFT_ 1U +#define SDEI_MAPF_BOUND_SHIFT_ 2U +#define SDEI_MAPF_SIGNALABLE_SHIFT_ 3U +#define SDEI_MAPF_PRIVATE_SHIFT_ 4U +#define SDEI_MAPF_CRITICAL_SHIFT_ 5U +#define SDEI_MAPF_EXPLICIT_SHIFT_ 6U + +/* SDEI event 0 */ +#define SDEI_EVENT_0 0 + +/* Placeholder interrupt for dynamic mapping */ +#define SDEI_DYN_IRQ 0U + +/* SDEI flags */ + +/* + * These flags determine whether or not an event can be associated with an + * interrupt. Static events are permanently associated with an interrupt, and + * can't be changed at runtime. Association of dynamic events with interrupts + * can be changed at run time using the SDEI_INTERRUPT_BIND and + * SDEI_INTERRUPT_RELEASE calls. + * + * SDEI_MAPF_DYNAMIC only indicates run time configurability, where as + * SDEI_MAPF_BOUND indicates interrupt association. For example: + * + * - Calling SDEI_INTERRUPT_BIND on a dynamic event will have both + * SDEI_MAPF_DYNAMIC and SDEI_MAPF_BOUND set. + * + * - Statically-bound events will always have SDEI_MAPF_BOUND set, and neither + * SDEI_INTERRUPT_BIND nor SDEI_INTERRUPT_RELEASE can be called on them. + * + * See also the is_map_bound() macro. + */ +#define SDEI_MAPF_DYNAMIC BIT(SDEI_MAPF_DYNAMIC_SHIFT_) +#define SDEI_MAPF_BOUND BIT(SDEI_MAPF_BOUND_SHIFT_) +#define SDEI_MAPF_EXPLICIT BIT(SDEI_MAPF_EXPLICIT_SHIFT_) + +#define SDEI_MAPF_SIGNALABLE BIT(SDEI_MAPF_SIGNALABLE_SHIFT_) +#define SDEI_MAPF_PRIVATE BIT(SDEI_MAPF_PRIVATE_SHIFT_) + +#define SDEI_MAPF_NORMAL 0 +#define SDEI_MAPF_CRITICAL BIT(SDEI_MAPF_CRITICAL_SHIFT_) + +#endif /* SDEI_FLAGS_H */ diff --git a/drivers/rz/ipl/rza/include/services/spm_core_manifest.h b/drivers/rz/ipl/rza/include/services/spm_core_manifest.h new file mode 100644 index 00000000..453b21c0 --- /dev/null +++ b/drivers/rz/ipl/rza/include/services/spm_core_manifest.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SPM_CORE_MANIFEST_H +#define SPM_CORE_MANIFEST_H + +#include + +/******************************************************************************* + * Attribute Section + ******************************************************************************/ + +typedef struct spm_core_manifest_sect_attribute { + /* + * FFA version (mandatory). + */ + uint32_t major_version; + uint32_t minor_version; + + /* + * Run-Time Execution state (optional): + * - 0: AArch64 (default) + * - 1: AArch32 + */ + uint32_t exec_state; + + /* + * Address of binary image containing SPM Core (optional). + */ + uint64_t load_address; + + /* + * Offset from the base of the partition's binary image to the entry + * point of the partition (optional). + */ + uint64_t entrypoint; + + /* + * Size of binary image containing SPM Core in bytes (mandatory). + */ + uint32_t binary_size; + + /* + * ID of the SPMC (mandatory) + */ + uint16_t spmc_id; + +} spmc_manifest_attribute_t; + +#endif /* SPM_CORE_MANIFEST_H */ diff --git a/drivers/rz/ipl/rza/include/services/spm_mm_partition.h b/drivers/rz/ipl/rza/include/services/spm_mm_partition.h new file mode 100644 index 00000000..ad5ceefb --- /dev/null +++ b/drivers/rz/ipl/rza/include/services/spm_mm_partition.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SPM_MM_PARTITION_H +#define SPM_MM_PARTITION_H + +#include + +#include + +/* + * Flags used by the spm_mm_mp_info structure to describe the + * characteristics of a cpu. Only a single flag is defined at the moment to + * indicate the primary cpu. + */ +#define MP_INFO_FLAG_PRIMARY_CPU U(0x00000001) + +/* + * This structure is used to provide information required to initialise a S-EL0 + * partition. + */ +typedef struct spm_mm_mp_info { + uint64_t mpidr; + uint32_t linear_id; + uint32_t flags; +} spm_mm_mp_info_t; + +typedef struct spm_mm_boot_info { + param_header_t h; + uint64_t sp_mem_base; + uint64_t sp_mem_limit; + uint64_t sp_image_base; + uint64_t sp_stack_base; + uint64_t sp_heap_base; + uint64_t sp_ns_comm_buf_base; + uint64_t sp_shared_buf_base; + uint64_t sp_image_size; + uint64_t sp_pcpu_stack_size; + uint64_t sp_heap_size; + uint64_t sp_ns_comm_buf_size; + uint64_t sp_shared_buf_size; + uint32_t num_sp_mem_regions; + uint32_t num_cpus; + spm_mm_mp_info_t *mp_info; +} spm_mm_boot_info_t; + +#endif /* SPM_MM_PARTITION_H */ diff --git a/drivers/rz/ipl/rza/include/services/spm_mm_svc.h b/drivers/rz/ipl/rza/include/services/spm_mm_svc.h new file mode 100644 index 00000000..3148beb8 --- /dev/null +++ b/drivers/rz/ipl/rza/include/services/spm_mm_svc.h @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SPM_MM_SVC_H +#define SPM_MM_SVC_H + +#include + +/* + * The MM_VERSION_XXX definitions are used when responding to the + * MM_VERSION_AARCH32 service request. The version returned is different between + * this request and the SPM_MM_VERSION_AARCH32 request - both have been retained + * for compatibility. + */ +#define MM_VERSION_MAJOR U(1) +#define MM_VERSION_MAJOR_SHIFT 16 +#define MM_VERSION_MAJOR_MASK U(0x7FFF) +#define MM_VERSION_MINOR U(0) +#define MM_VERSION_MINOR_SHIFT 0 +#define MM_VERSION_MINOR_MASK U(0xFFFF) +#define MM_VERSION_FORM(major, minor) ((major << MM_VERSION_MAJOR_SHIFT) | \ + (minor)) +#define MM_VERSION_COMPILED MM_VERSION_FORM(MM_VERSION_MAJOR, \ + MM_VERSION_MINOR) + +#define SPM_MM_VERSION_MAJOR U(0) +#define SPM_MM_VERSION_MAJOR_SHIFT 16 +#define SPM_MM_VERSION_MAJOR_MASK U(0x7FFF) +#define SPM_MM_VERSION_MINOR U(1) +#define SPM_MM_VERSION_MINOR_SHIFT 0 +#define SPM_MM_VERSION_MINOR_MASK U(0xFFFF) +#define SPM_MM_VERSION_FORM(major, minor) ((major << \ + SPM_MM_VERSION_MAJOR_SHIFT) | \ + (minor)) +#define SPM_MM_VERSION_COMPILED SPM_MM_VERSION_FORM(SPM_MM_VERSION_MAJOR, \ + SPM_MM_VERSION_MINOR) + +/* These macros are used to identify SPM-MM calls using the SMC function ID */ +#define SPM_MM_FID_MASK U(0xffff) +#define SPM_MM_FID_MIN_VALUE U(0x40) +#define SPM_MM_FID_MAX_VALUE U(0x7f) +#define is_spm_mm_fid(_fid) \ + ((((_fid) & SPM_MM_FID_MASK) >= SPM_MM_FID_MIN_VALUE) && \ + (((_fid) & SPM_MM_FID_MASK) <= SPM_MM_FID_MAX_VALUE)) + +/* + * SMC IDs defined in [1] for accessing MM services from the Non-secure world. + * These FIDs occupy the range 0x40 - 0x5f. + * [1] DEN0060A_ARM_MM_Interface_Specification.pdf + */ +#define MM_VERSION_AARCH32 U(0x84000040) +#define MM_COMMUNICATE_AARCH64 U(0xC4000041) +#define MM_COMMUNICATE_AARCH32 U(0x84000041) + +/* + * SMC IDs defined for accessing services implemented by the Secure Partition + * Manager from the Secure Partition(s). These services enable a partition to + * handle delegated events and request privileged operations from the manager. + * They occupy the range 0x60-0x7f. + */ +#define SPM_MM_VERSION_AARCH32 U(0x84000060) +#define MM_SP_EVENT_COMPLETE_AARCH64 U(0xC4000061) +#define MM_SP_MEMORY_ATTRIBUTES_GET_AARCH64 U(0xC4000064) +#define MM_SP_MEMORY_ATTRIBUTES_SET_AARCH64 U(0xC4000065) + +/* + * Macros used by MM_SP_MEMORY_ATTRIBUTES_SET_AARCH64. + */ + +#define MM_SP_MEMORY_ATTRIBUTES_ACCESS_NOACCESS U(0) +#define MM_SP_MEMORY_ATTRIBUTES_ACCESS_RW U(1) +/* Value U(2) is reserved. */ +#define MM_SP_MEMORY_ATTRIBUTES_ACCESS_RO U(3) +#define MM_SP_MEMORY_ATTRIBUTES_ACCESS_MASK U(3) +#define MM_SP_MEMORY_ATTRIBUTES_ACCESS_SHIFT 0 + +#define MM_SP_MEMORY_ATTRIBUTES_EXEC (U(0) << 2) +#define MM_SP_MEMORY_ATTRIBUTES_NON_EXEC (U(1) << 2) + + +/* SPM error codes. */ +#define SPM_MM_SUCCESS 0 +#define SPM_MM_NOT_SUPPORTED -1 +#define SPM_MM_INVALID_PARAMETER -2 +#define SPM_MM_DENIED -3 +#define SPM_MM_NO_MEMORY -5 + +#ifndef __ASSEMBLER__ + +#include + +int32_t spm_mm_setup(void); + +uint64_t spm_mm_smc_handler(uint32_t smc_fid, + uint64_t x1, + uint64_t x2, + uint64_t x3, + uint64_t x4, + void *cookie, + void *handle, + uint64_t flags); + +/* Helper to enter a secure partition */ +uint64_t spm_mm_sp_call(uint32_t smc_fid, + uint64_t x1, + uint64_t x2, + uint64_t x3); + +#endif /* __ASSEMBLER__ */ + +#endif /* SPM_MM_SVC_H */ diff --git a/drivers/rz/ipl/rza/include/services/spmd_svc.h b/drivers/rz/ipl/rza/include/services/spmd_svc.h new file mode 100644 index 00000000..1e7e6aa8 --- /dev/null +++ b/drivers/rz/ipl/rza/include/services/spmd_svc.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SPMD_SVC_H +#define SPMD_SVC_H + +#ifndef __ASSEMBLER__ +#include +#include + +int spmd_setup(void); +uint64_t spmd_smc_handler(uint32_t smc_fid, + uint64_t x1, + uint64_t x2, + uint64_t x3, + uint64_t x4, + void *cookie, + void *handle, + uint64_t flags); +#endif /* __ASSEMBLER__ */ + +#endif /* SPMD_SVC_H */ diff --git a/drivers/rz/ipl/rza/include/services/std_svc.h b/drivers/rz/ipl/rza/include/services/std_svc.h new file mode 100644 index 00000000..b0614fb4 --- /dev/null +++ b/drivers/rz/ipl/rza/include/services/std_svc.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2014-2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef STD_SVC_H +#define STD_SVC_H + +/* SMC function IDs for Standard Service queries */ + +#define ARM_STD_SVC_CALL_COUNT 0x8400ff00 +#define ARM_STD_SVC_UID 0x8400ff01 +/* 0x8400ff02 is reserved */ +#define ARM_STD_SVC_VERSION 0x8400ff03 + +/* ARM Standard Service Calls version numbers */ +#define STD_SVC_VERSION_MAJOR 0x0 +#define STD_SVC_VERSION_MINOR 0x1 + +/* + * Get the ARM Standard Service argument from EL3 Runtime. + * This function must be implemented by EL3 Runtime and the + * `svc_mask` identifies the service. `svc_mask` is a bit + * mask identifying the range of SMC function IDs available + * to the service. + */ +uintptr_t get_arm_std_svc_args(unsigned int svc_mask); + +#endif /* STD_SVC_H */ diff --git a/drivers/rz/ipl/rza/include/services/trng_svc.h b/drivers/rz/ipl/rza/include/services/trng_svc.h new file mode 100644 index 00000000..ed4d557c --- /dev/null +++ b/drivers/rz/ipl/rza/include/services/trng_svc.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2021, ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TRNG_SVC_H +#define TRNG_SVC_H + +#include +#include + +#include + +/* SMC function IDs for TRNG queries */ +#define ARM_TRNG_VERSION U(0x84000050) +#define ARM_TRNG_FEATURES U(0x84000051) +#define ARM_TRNG_GET_UUID U(0x84000052) +#define ARM_TRNG_RND32 U(0x84000053) +#define ARM_TRNG_RND64 U(0xc4000053) + +/* TRNG version numbers */ +#define TRNG_VERSION_MAJOR (0x1) +#define TRNG_VERSION_MINOR (0x0) + +/* TRNG Error Numbers */ +#define TRNG_E_SUCCESS (0) +#define TRNG_E_NOT_SUPPORTED (-1) +#define TRNG_E_INVALID_PARAMS (-2) +#define TRNG_E_NO_ENTROPY (-3) +#define TRNG_E_NOT_IMPLEMENTED (-4) + +#if TRNG_SUPPORT +void trng_setup(void); +bool is_trng_fid(uint32_t smc_fid); +#else +static inline void trng_setup(void) +{ +} + +static inline bool is_trng_fid(uint32_t smc_fid) +{ + return false; +} +#endif +uintptr_t trng_smc_handler( + uint32_t smc_fid, + u_register_t x1, + u_register_t x2, + u_register_t x3, + u_register_t x4, + void *cookie, + void *handle, + u_register_t flags +); + +#endif /* TRNG_SVC_H */ diff --git a/drivers/rz/ipl/rza/include/tools_share/dualroot_oid.h b/drivers/rz/ipl/rza/include/tools_share/dualroot_oid.h new file mode 100644 index 00000000..3e88a6d2 --- /dev/null +++ b/drivers/rz/ipl/rza/include/tools_share/dualroot_oid.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef DUALROOT_OID_H +#define DUALROOT_OID_H + +/* Reuse the Object IDs defined by TBBR for certificate extensions. */ +#include "tbbr_oid.h" + +/* + * Platform root-of-trust public key. + * Arbitrary value that does not conflict with any of the TBBR reserved OIDs. + */ +#define PROT_PK_OID "1.3.6.1.4.1.4128.2100.1102" + +#endif /* DUALROOT_OID_H */ diff --git a/drivers/rz/ipl/rza/include/tools_share/firmware_encrypted.h b/drivers/rz/ipl/rza/include/tools_share/firmware_encrypted.h new file mode 100644 index 00000000..7ca634f5 --- /dev/null +++ b/drivers/rz/ipl/rza/include/tools_share/firmware_encrypted.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2020, Linaro Limited. All rights reserved. + * Author: Sumit Garg + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef FIRMWARE_ENCRYPTED_H +#define FIRMWARE_ENCRYPTED_H + +#include + +/* This is used as a signature to validate the encryption header */ +#define ENC_HEADER_MAGIC 0xAA640001U + +/* Firmware encryption status flag mask */ +#define FW_ENC_STATUS_FLAG_MASK 0x1 + +/* + * SSK: Secret Symmetric Key + * BSSK: Binding Secret Symmetric Key + */ +enum fw_enc_status_t { + FW_ENC_WITH_SSK = 0, + FW_ENC_WITH_BSSK = 1, +}; + +#define ENC_MAX_IV_SIZE 16U +#define ENC_MAX_TAG_SIZE 16U +#define ENC_MAX_KEY_SIZE 32U + +struct fw_enc_hdr { + uint32_t magic; + uint16_t dec_algo; + uint16_t flags; + uint16_t iv_len; + uint16_t tag_len; + uint8_t iv[ENC_MAX_IV_SIZE]; + uint8_t tag[ENC_MAX_TAG_SIZE]; +}; + +#endif /* FIRMWARE_ENCRYPTED_H */ diff --git a/drivers/rz/ipl/rza/include/tools_share/firmware_image_package.h b/drivers/rz/ipl/rza/include/tools_share/firmware_image_package.h new file mode 100644 index 00000000..dc65cc62 --- /dev/null +++ b/drivers/rz/ipl/rza/include/tools_share/firmware_image_package.h @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2014-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef FIRMWARE_IMAGE_PACKAGE_H +#define FIRMWARE_IMAGE_PACKAGE_H + +#include + +#include "uuid.h" + +/* This is used as a signature to validate the blob header */ +#define TOC_HEADER_NAME 0xAA640001 + + +/* ToC Entry UUIDs */ +#define UUID_TRUSTED_UPDATE_FIRMWARE_SCP_BL2U \ + {{0x65, 0x92, 0x27, 0x03}, {0x2f, 0x74}, {0xe6, 0x44}, 0x8d, 0xff, {0x57, 0x9a, 0xc1, 0xff, 0x06, 0x10} } +#define UUID_TRUSTED_UPDATE_FIRMWARE_BL2U \ + {{0x60, 0xb3, 0xeb, 0x37}, {0xc1, 0xe5}, {0xea, 0x41}, 0x9d, 0xf3, {0x19, 0xed, 0xa1, 0x1f, 0x68, 0x01} } +#define UUID_TRUSTED_UPDATE_FIRMWARE_NS_BL2U \ + {{0x4f, 0x51, 0x1d, 0x11}, {0x2b, 0xe5}, {0x4e, 0x49}, 0xb4, 0xc5, {0x83, 0xc2, 0xf7, 0x15, 0x84, 0x0a} } +#define UUID_TRUSTED_FWU_CERT \ + {{0x71, 0x40, 0x8a, 0xb2}, {0x18, 0xd6}, {0x87, 0x4c}, 0x8b, 0x2e, {0xc6, 0xdc, 0xcd, 0x50, 0xf0, 0x96} } +#define UUID_TRUSTED_BOOT_FIRMWARE_BL2 \ + {{0x5f, 0xf9, 0xec, 0x0b}, {0x4d, 0x22}, {0x3e, 0x4d}, 0xa5, 0x44, {0xc3, 0x9d, 0x81, 0xc7, 0x3f, 0x0a} } +#define UUID_SCP_FIRMWARE_SCP_BL2 \ + {{0x97, 0x66, 0xfd, 0x3d}, {0x89, 0xbe}, {0xe8, 0x49}, 0xae, 0x5d, {0x78, 0xa1, 0x40, 0x60, 0x82, 0x13} } +#define UUID_EL3_RUNTIME_FIRMWARE_BL31 \ + {{0x47, 0xd4, 0x08, 0x6d}, {0x4c, 0xfe}, {0x98, 0x46}, 0x9b, 0x95, {0x29, 0x50, 0xcb, 0xbd, 0x5a, 0x00} } +#define UUID_SECURE_PAYLOAD_BL32 \ + {{0x05, 0xd0, 0xe1, 0x89}, {0x53, 0xdc}, {0x13, 0x47}, 0x8d, 0x2b, {0x50, 0x0a, 0x4b, 0x7a, 0x3e, 0x38} } +#define UUID_SECURE_PAYLOAD_BL32_EXTRA1 \ + {{0x0b, 0x70, 0xc2, 0x9b}, {0x2a, 0x5a}, {0x78, 0x40}, 0x9f, 0x65, {0x0a, 0x56, 0x82, 0x73, 0x82, 0x88} } +#define UUID_SECURE_PAYLOAD_BL32_EXTRA2 \ + {{0x8e, 0xa8, 0x7b, 0xb1}, {0xcf, 0xa2}, {0x3f, 0x4d}, 0x85, 0xfd, {0xe7, 0xbb, 0xa5, 0x02, 0x20, 0xd9} } +#define UUID_NON_TRUSTED_FIRMWARE_BL33 \ + {{0xd6, 0xd0, 0xee, 0xa7}, {0xfc, 0xea}, {0xd5, 0x4b}, 0x97, 0x82, {0x99, 0x34, 0xf2, 0x34, 0xb6, 0xe4} } +/* Key certificates */ +#define UUID_ROT_KEY_CERT \ + {{0x86, 0x2d, 0x1d, 0x72}, {0xf8, 0x60}, {0xe4, 0x11}, 0x92, 0x0b, {0x8b, 0xe7, 0x62, 0x16, 0x0f, 0x24} } +#define UUID_TRUSTED_KEY_CERT \ + {{0x82, 0x7e, 0xe8, 0x90}, {0xf8, 0x60}, {0xe4, 0x11}, 0xa1, 0xb4, {0x77, 0x7a, 0x21, 0xb4, 0xf9, 0x4c} } +#define UUID_NON_TRUSTED_WORLD_KEY_CERT \ + {{0x1c, 0x67, 0x87, 0x3d}, {0x5f, 0x63}, {0xe4, 0x11}, 0x97, 0x8d, {0x27, 0xc0, 0xc7, 0x14, 0x8a, 0xbd} } +#define UUID_SCP_FW_KEY_CERT \ + {{0x02, 0x42, 0x21, 0xa1}, {0xf8, 0x60}, {0xe4, 0x11}, 0x8d, 0x9b, {0xf3, 0x3c, 0x0e, 0x15, 0xa0, 0x14} } +#define UUID_SOC_FW_KEY_CERT \ + {{0x8a, 0xb8, 0xbe, 0xcc}, {0xf9, 0x60}, {0xe4, 0x11}, 0x9a, 0xd0, {0xeb, 0x48, 0x22, 0xd8, 0xdc, 0xf8} } +#define UUID_TRUSTED_OS_FW_KEY_CERT \ + {{0x94, 0x77, 0xd6, 0x03}, {0xfb, 0x60}, {0xe4, 0x11}, 0x85, 0xdd, {0xb7, 0x10, 0x5b, 0x8c, 0xee, 0x04} } +#define UUID_NON_TRUSTED_FW_KEY_CERT \ + {{0x8a, 0xd5, 0x83, 0x2a}, {0xfb, 0x60}, {0xe4, 0x11}, 0x8a, 0xaf, {0xdf, 0x30, 0xbb, 0xc4, 0x98, 0x59} } +/* Content certificates */ +#define UUID_TRUSTED_BOOT_FW_CERT \ + {{0xd6, 0xe2, 0x69, 0xea}, {0x5d, 0x63}, {0xe4, 0x11}, 0x8d, 0x8c, {0x9f, 0xba, 0xbe, 0x99, 0x56, 0xa5} } +#define UUID_SCP_FW_CONTENT_CERT \ + {{0x44, 0xbe, 0x6f, 0x04}, {0x5e, 0x63}, {0xe4, 0x11}, 0xb2, 0x8b, {0x73, 0xd8, 0xea, 0xae, 0x96, 0x56} } +#define UUID_SOC_FW_CONTENT_CERT \ + {{0xe2, 0xb2, 0x0c, 0x20}, {0x5e, 0x63}, {0xe4, 0x11}, 0x9c, 0xe8, {0xab, 0xcc, 0xf9, 0x2b, 0xb6, 0x66} } +#define UUID_TRUSTED_OS_FW_CONTENT_CERT \ + {{0xa4, 0x9f, 0x44, 0x11}, {0x5e, 0x63}, {0xe4, 0x11}, 0x87, 0x28, {0x3f, 0x05, 0x72, 0x2a, 0xf3, 0x3d} } +#define UUID_NON_TRUSTED_FW_CONTENT_CERT \ + {{0x8e, 0xc4, 0xc1, 0xf3}, {0x5d, 0x63}, {0xe4, 0x11}, 0xa7, 0xa9, {0x87, 0xee, 0x40, 0xb2, 0x3f, 0xa7} } +#define UUID_SIP_SECURE_PARTITION_CONTENT_CERT \ + {{0x77, 0x6d, 0xfd, 0x44}, {0x86, 0x97}, {0x4c, 0x3b}, 0x91, 0xeb, {0xc1, 0x3e, 0x02, 0x5a, 0x2a, 0x6f} } +#define UUID_PLAT_SECURE_PARTITION_CONTENT_CERT \ + {{0xdd, 0xcb, 0xbf, 0x4a}, {0xca, 0xd6}, {0x11, 0xea}, 0x87, 0xd0, {0x02, 0x42, 0xac, 0x13, 0x00, 0x03} } +/* Dynamic configs */ +#define UUID_HW_CONFIG \ + {{0x08, 0xb8, 0xf1, 0xd9}, {0xc9, 0xcf}, {0x93, 0x49}, 0xa9, 0x62, {0x6f, 0xbc, 0x6b, 0x72, 0x65, 0xcc} } +#define UUID_TB_FW_CONFIG \ + {{0x6c, 0x04, 0x58, 0xff}, {0xaf, 0x6b}, {0x7d, 0x4f}, 0x82, 0xed, {0xaa, 0x27, 0xbc, 0x69, 0xbf, 0xd2} } +#define UUID_SOC_FW_CONFIG \ + {{0x99, 0x79, 0x81, 0x4b}, {0x03, 0x76}, {0xfb, 0x46}, 0x8c, 0x8e, {0x8d, 0x26, 0x7f, 0x78, 0x59, 0xe0} } +#define UUID_TOS_FW_CONFIG \ + {{0x26, 0x25, 0x7c, 0x1a}, {0xdb, 0xc6}, {0x7f, 0x47}, 0x8d, 0x96, {0xc4, 0xc4, 0xb0, 0x24, 0x80, 0x21} } +#define UUID_NT_FW_CONFIG \ + {{0x28, 0xda, 0x98, 0x15}, {0x93, 0xe8}, {0x7e, 0x44}, 0xac, 0x66, {0x1a, 0xaf, 0x80, 0x15, 0x50, 0xf9} } +#define UUID_FW_CONFIG \ + {{0x58, 0x07, 0xe1, 0x6a}, {0x84, 0x59}, {0x47, 0xbe}, 0x8e, 0xd5, {0x64, 0x8e, 0x8d, 0xdd, 0xab, 0x0e} } + +#ifdef PLAT_DEF_FIP_UUID +#include +#endif + +typedef struct fip_toc_header { + uint32_t name; + uint32_t serial_number; + uint64_t flags; +} fip_toc_header_t; + +typedef struct fip_toc_entry { + uuid_t uuid; + uint64_t offset_address; + uint64_t size; + uint64_t flags; +} fip_toc_entry_t; + +#endif /* FIRMWARE_IMAGE_PACKAGE_H */ diff --git a/drivers/rz/ipl/rza/include/tools_share/sptool.h b/drivers/rz/ipl/rza/include/tools_share/sptool.h new file mode 100644 index 00000000..53668e09 --- /dev/null +++ b/drivers/rz/ipl/rza/include/tools_share/sptool.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2018-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SPTOOL_H +#define SPTOOL_H + +#include + +/* 4 Byte magic name "SPKG" */ +#define SECURE_PARTITION_MAGIC 0x474B5053 + +/* Header for a secure partition package. */ +struct sp_pkg_header { + uint32_t magic; + uint32_t version; + uint32_t pm_offset; + uint32_t pm_size; + uint32_t img_offset; + uint32_t img_size; +}; + +#endif /* SPTOOL_H */ diff --git a/drivers/rz/ipl/rza/include/tools_share/tbbr_oid.h b/drivers/rz/ipl/rza/include/tools_share/tbbr_oid.h new file mode 100644 index 00000000..52b43ab3 --- /dev/null +++ b/drivers/rz/ipl/rza/include/tools_share/tbbr_oid.h @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TBBR_OID_H +#define TBBR_OID_H + +#define MAX_OID_NAME_LEN 30 + +/* + * The following is a list of OID values defined and reserved by ARM, which + * are used to define the extension fields of the certificate structure, as + * defined in the Trusted Board Boot Requirements (TBBR) specification, + * ARM DEN0006C-1. + */ + + +/* TrustedFirmwareNVCounter - Non-volatile counter extension */ +#define TRUSTED_FW_NVCOUNTER_OID "1.3.6.1.4.1.4128.2100.1" +/* NonTrustedFirmwareNVCounter - Non-volatile counter extension */ +#define NON_TRUSTED_FW_NVCOUNTER_OID "1.3.6.1.4.1.4128.2100.2" + + +/* + * Non-Trusted Firmware Updater Certificate + */ + +/* APFirmwareUpdaterConfigHash - BL2U */ +#define AP_FWU_CFG_HASH_OID "1.3.6.1.4.1.4128.2100.101" +/* SCPFirmwareUpdaterConfigHash - SCP_BL2U */ +#define SCP_FWU_CFG_HASH_OID "1.3.6.1.4.1.4128.2100.102" +/* FirmwareUpdaterHash - NS_BL2U */ +#define FWU_HASH_OID "1.3.6.1.4.1.4128.2100.103" +/* TrustedWatchdogRefreshTime */ +#define TRUSTED_WATCHDOG_TIME_OID "1.3.6.1.4.1.4128.2100.104" + + +/* + * Trusted Boot Firmware Certificate + */ + +/* TrustedBootFirmwareHash - BL2 */ +#define TRUSTED_BOOT_FW_HASH_OID "1.3.6.1.4.1.4128.2100.201" +#define TRUSTED_BOOT_FW_CONFIG_HASH_OID "1.3.6.1.4.1.4128.2100.202" +#define HW_CONFIG_HASH_OID "1.3.6.1.4.1.4128.2100.203" +#define FW_CONFIG_HASH_OID "1.3.6.1.4.1.4128.2100.204" + +/* + * Trusted Key Certificate + */ + +/* PrimaryDebugCertificatePK */ +#define PRIMARY_DEBUG_PK_OID "1.3.6.1.4.1.4128.2100.301" +/* TrustedWorldPK */ +#define TRUSTED_WORLD_PK_OID "1.3.6.1.4.1.4128.2100.302" +/* NonTrustedWorldPK */ +#define NON_TRUSTED_WORLD_PK_OID "1.3.6.1.4.1.4128.2100.303" + + +/* + * Trusted Debug Certificate + */ + +/* DebugScenario */ +#define TRUSTED_DEBUG_SCENARIO_OID "1.3.6.1.4.1.4128.2100.401" +/* SoC Specific */ +#define TRUSTED_DEBUG_SOC_SPEC_OID "1.3.6.1.4.1.4128.2100.402" +/* SecondaryDebugCertPK */ +#define SECONDARY_DEBUG_PK_OID "1.3.6.1.4.1.4128.2100.403" + + +/* + * SoC Firmware Key Certificate + */ + +/* SoCFirmwareContentCertPK */ +#define SOC_FW_CONTENT_CERT_PK_OID "1.3.6.1.4.1.4128.2100.501" + +/* + * SoC Firmware Content Certificate + */ + +/* APRomPatchHash - BL1_PATCH */ +#define APROM_PATCH_HASH_OID "1.3.6.1.4.1.4128.2100.601" +/* SoCConfigHash */ +#define SOC_CONFIG_HASH_OID "1.3.6.1.4.1.4128.2100.602" +/* SoCAPFirmwareHash - BL31 */ +#define SOC_AP_FW_HASH_OID "1.3.6.1.4.1.4128.2100.603" +/* SoCFirmwareConfigHash = SOC_FW_CONFIG */ +#define SOC_FW_CONFIG_HASH_OID "1.3.6.1.4.1.4128.2100.604" + +/* + * SCP Firmware Key Certificate + */ + +/* SCPFirmwareContentCertPK */ +#define SCP_FW_CONTENT_CERT_PK_OID "1.3.6.1.4.1.4128.2100.701" + + +/* + * SCP Firmware Content Certificate + */ + +/* SCPFirmwareHash - SCP_BL2 */ +#define SCP_FW_HASH_OID "1.3.6.1.4.1.4128.2100.801" +/* SCPRomPatchHash - SCP_BL1_PATCH */ +#define SCP_ROM_PATCH_HASH_OID "1.3.6.1.4.1.4128.2100.802" + + +/* + * Trusted OS Firmware Key Certificate + */ + +/* TrustedOSFirmwareContentCertPK */ +#define TRUSTED_OS_FW_CONTENT_CERT_PK_OID "1.3.6.1.4.1.4128.2100.901" + + +/* + * Trusted OS Firmware Content Certificate + */ + +/* TrustedOSFirmwareHash - BL32 */ +#define TRUSTED_OS_FW_HASH_OID "1.3.6.1.4.1.4128.2100.1001" +/* TrustedOSExtra1FirmwareHash - BL32 Extra1 */ +#define TRUSTED_OS_FW_EXTRA1_HASH_OID "1.3.6.1.4.1.4128.2100.1002" +/* TrustedOSExtra2FirmwareHash - BL32 Extra2 */ +#define TRUSTED_OS_FW_EXTRA2_HASH_OID "1.3.6.1.4.1.4128.2100.1003" +/* TrustedOSFirmwareConfigHash - TOS_FW_CONFIG */ +#define TRUSTED_OS_FW_CONFIG_HASH_OID "1.3.6.1.4.1.4128.2100.1004" + + +/* + * Non-Trusted Firmware Key Certificate + */ + +/* NonTrustedFirmwareContentCertPK */ +#define NON_TRUSTED_FW_CONTENT_CERT_PK_OID "1.3.6.1.4.1.4128.2100.1101" + + +/* + * Non-Trusted Firmware Content Certificate + */ + +/* NonTrustedWorldBootloaderHash - BL33 */ +#define NON_TRUSTED_WORLD_BOOTLOADER_HASH_OID "1.3.6.1.4.1.4128.2100.1201" +/* NonTrustedFirmwareConfigHash - NT_FW_CONFIG */ +#define NON_TRUSTED_FW_CONFIG_HASH_OID "1.3.6.1.4.1.4128.2100.1202" + +/* + * Secure Partitions Content Certificate + */ +#define SP_PKG1_HASH_OID "1.3.6.1.4.1.4128.2100.1301" +#define SP_PKG2_HASH_OID "1.3.6.1.4.1.4128.2100.1302" +#define SP_PKG3_HASH_OID "1.3.6.1.4.1.4128.2100.1303" +#define SP_PKG4_HASH_OID "1.3.6.1.4.1.4128.2100.1304" +#define SP_PKG5_HASH_OID "1.3.6.1.4.1.4128.2100.1305" +#define SP_PKG6_HASH_OID "1.3.6.1.4.1.4128.2100.1306" +#define SP_PKG7_HASH_OID "1.3.6.1.4.1.4128.2100.1307" +#define SP_PKG8_HASH_OID "1.3.6.1.4.1.4128.2100.1308" + +#ifdef PLAT_DEF_OID +#include +#endif +#endif /* TBBR_OID_H */ diff --git a/drivers/rz/ipl/rza/include/tools_share/uuid.h b/drivers/rz/ipl/rza/include/tools_share/uuid.h new file mode 100644 index 00000000..2ced3a3f --- /dev/null +++ b/drivers/rz/ipl/rza/include/tools_share/uuid.h @@ -0,0 +1,74 @@ +/*- + * Copyright (c) 2002 Marcel Moolenaar + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * $FreeBSD$ + */ + +/* + * Portions copyright (c) 2014-2020, ARM Limited and Contributors. + * All rights reserved. + */ + +#ifndef UUID_H +#define UUID_H + +/* Length of a node address (an IEEE 802 address). */ +#define _UUID_NODE_LEN 6 + +/* Length of UUID string including dashes. */ +#define _UUID_STR_LEN 36 + +/* + * See also: + * http://www.opengroup.org/dce/info/draft-leach-uuids-guids-01.txt + * http://www.opengroup.org/onlinepubs/009629399/apdxa.htm + * + * A DCE 1.1 compatible source representation of UUIDs. + */ +struct uuid { + uint8_t time_low[4]; + uint8_t time_mid[2]; + uint8_t time_hi_and_version[2]; + uint8_t clock_seq_hi_and_reserved; + uint8_t clock_seq_low; + uint8_t node[_UUID_NODE_LEN]; +}; + +struct efi_guid { + uint32_t time_low; + uint16_t time_mid; + uint16_t time_hi_and_version; + uint8_t clock_seq_and_node[8]; +}; + +union uuid_helper_t { + struct uuid uuid_struct; + struct efi_guid efi_guid; +}; + +/* XXX namespace pollution? */ +typedef struct uuid uuid_t; + +#endif /* UUID_H */ diff --git a/drivers/rz/ipl/rza/lib/aarch64/armclang_printf.S b/drivers/rz/ipl/rza/lib/aarch64/armclang_printf.S new file mode 100644 index 00000000..52a69769 --- /dev/null +++ b/drivers/rz/ipl/rza/lib/aarch64/armclang_printf.S @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +/* Symbols needed by armclang */ + + .globl __0printf + .globl __1printf + .globl __2printf + +func __0printf + b printf +endfunc __0printf + +func __1printf + b printf +endfunc __1printf + +func __2printf + b printf +endfunc __2printf diff --git a/drivers/rz/ipl/rza/lib/aarch64/cache_helpers.S b/drivers/rz/ipl/rza/lib/aarch64/cache_helpers.S new file mode 100644 index 00000000..de9c8e4f --- /dev/null +++ b/drivers/rz/ipl/rza/lib/aarch64/cache_helpers.S @@ -0,0 +1,209 @@ +/* + * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + + .globl flush_dcache_range + .globl clean_dcache_range + .globl inv_dcache_range + .globl dcsw_op_louis + .globl dcsw_op_all + .globl dcsw_op_level1 + .globl dcsw_op_level2 + .globl dcsw_op_level3 + +/* + * This macro can be used for implementing various data cache operations `op` + */ +.macro do_dcache_maintenance_by_mva op + /* Exit early if size is zero */ + cbz x1, exit_loop_\op + dcache_line_size x2, x3 + add x1, x0, x1 + sub x3, x2, #1 + bic x0, x0, x3 +loop_\op: + dc \op, x0 + add x0, x0, x2 + cmp x0, x1 + b.lo loop_\op + dsb sy +exit_loop_\op: + ret +.endm + /* ------------------------------------------ + * Clean+Invalidate from base address till + * size. 'x0' = addr, 'x1' = size + * ------------------------------------------ + */ +func flush_dcache_range + do_dcache_maintenance_by_mva civac +endfunc flush_dcache_range + + /* ------------------------------------------ + * Clean from base address till size. + * 'x0' = addr, 'x1' = size + * ------------------------------------------ + */ +func clean_dcache_range + do_dcache_maintenance_by_mva cvac +endfunc clean_dcache_range + + /* ------------------------------------------ + * Invalidate from base address till + * size. 'x0' = addr, 'x1' = size + * ------------------------------------------ + */ +func inv_dcache_range + do_dcache_maintenance_by_mva ivac +endfunc inv_dcache_range + + + /* --------------------------------------------------------------- + * Data cache operations by set/way to the level specified + * + * The main function, do_dcsw_op requires: + * x0: The operation type (0-2), as defined in arch.h + * x3: The last cache level to operate on + * x9: clidr_el1 + * x10: The cache level to begin operation from + * and will carry out the operation on each data cache from level 0 + * to the level in x3 in sequence + * + * The dcsw_op macro sets up the x3 and x9 parameters based on + * clidr_el1 cache information before invoking the main function + * --------------------------------------------------------------- + */ + + .macro dcsw_op shift, fw, ls + mrs x9, clidr_el1 + ubfx x3, x9, \shift, \fw + lsl x3, x3, \ls + mov x10, xzr + b do_dcsw_op + .endm + +func do_dcsw_op + cbz x3, exit + adr x14, dcsw_loop_table // compute inner loop address + add x14, x14, x0, lsl #5 // inner loop is 8x32-bit instructions +#if ENABLE_BTI + add x14, x14, x0, lsl #2 // inner loop is + "bti j" instruction +#endif + mov x0, x9 + mov w8, #1 +loop1: + add x2, x10, x10, lsr #1 // work out 3x current cache level + lsr x1, x0, x2 // extract cache type bits from clidr + and x1, x1, #7 // mask the bits for current cache only + cmp x1, #2 // see what cache we have at this level + b.lo level_done // nothing to do if no cache or icache + + msr csselr_el1, x10 // select current cache level in csselr + isb // isb to sych the new cssr&csidr + mrs x1, ccsidr_el1 // read the new ccsidr + and x2, x1, #7 // extract the length of the cache lines + add x2, x2, #4 // add 4 (line length offset) + ubfx x4, x1, #3, #10 // maximum way number + clz w5, w4 // bit position of way size increment + lsl w9, w4, w5 // w9 = aligned max way number + lsl w16, w8, w5 // w16 = way number loop decrement + orr w9, w10, w9 // w9 = combine way and cache number + ubfx w6, w1, #13, #15 // w6 = max set number + lsl w17, w8, w2 // w17 = set number loop decrement + dsb sy // barrier before we start this level + br x14 // jump to DC operation specific loop + + .macro dcsw_loop _op +#if ENABLE_BTI + bti j +#endif +loop2_\_op: + lsl w7, w6, w2 // w7 = aligned max set number + +loop3_\_op: + orr w11, w9, w7 // combine cache, way and set number + dc \_op, x11 + subs w7, w7, w17 // decrement set number + b.hs loop3_\_op + + subs x9, x9, x16 // decrement way number + b.hs loop2_\_op + + b level_done + .endm + +level_done: + add x10, x10, #2 // increment cache number + cmp x3, x10 + b.hi loop1 + msr csselr_el1, xzr // select cache level 0 in csselr + dsb sy // barrier to complete final cache operation + isb +exit: + ret +endfunc do_dcsw_op + +dcsw_loop_table: + dcsw_loop isw + dcsw_loop cisw + dcsw_loop csw + + +func dcsw_op_louis + dcsw_op #LOUIS_SHIFT, #CLIDR_FIELD_WIDTH, #LEVEL_SHIFT +endfunc dcsw_op_louis + + +func dcsw_op_all + dcsw_op #LOC_SHIFT, #CLIDR_FIELD_WIDTH, #LEVEL_SHIFT +endfunc dcsw_op_all + + /* --------------------------------------------------------------- + * Helper macro for data cache operations by set/way for the + * level specified + * --------------------------------------------------------------- + */ + .macro dcsw_op_level level + mrs x9, clidr_el1 + mov x3, \level + sub x10, x3, #2 + b do_dcsw_op + .endm + + /* --------------------------------------------------------------- + * Data cache operations by set/way for level 1 cache + * + * The main function, do_dcsw_op requires: + * x0: The operation type (0-2), as defined in arch.h + * --------------------------------------------------------------- + */ +func dcsw_op_level1 + dcsw_op_level #(1 << LEVEL_SHIFT) +endfunc dcsw_op_level1 + + /* --------------------------------------------------------------- + * Data cache operations by set/way for level 2 cache + * + * The main function, do_dcsw_op requires: + * x0: The operation type (0-2), as defined in arch.h + * --------------------------------------------------------------- + */ +func dcsw_op_level2 + dcsw_op_level #(2 << LEVEL_SHIFT) +endfunc dcsw_op_level2 + + /* --------------------------------------------------------------- + * Data cache operations by set/way for level 3 cache + * + * The main function, do_dcsw_op requires: + * x0: The operation type (0-2), as defined in arch.h + * --------------------------------------------------------------- + */ +func dcsw_op_level3 + dcsw_op_level #(3 << LEVEL_SHIFT) +endfunc dcsw_op_level3 diff --git a/drivers/rz/ipl/rza/lib/aarch64/misc_helpers.S b/drivers/rz/ipl/rza/lib/aarch64/misc_helpers.S new file mode 100644 index 00000000..b6f6c9d8 --- /dev/null +++ b/drivers/rz/ipl/rza/lib/aarch64/misc_helpers.S @@ -0,0 +1,594 @@ +/* + * Copyright (c) 2013-2021, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + + .globl smc + + .globl zero_normalmem + .globl zeromem + .globl memcpy16 + + .globl disable_mmu_el1 + .globl disable_mmu_el3 + .globl disable_mmu_icache_el1 + .globl disable_mmu_icache_el3 + .globl fixup_gdt_reloc +#if SUPPORT_VFP + .globl enable_vfp +#endif + +func smc + smc #0 +endfunc smc + +/* ----------------------------------------------------------------------- + * void zero_normalmem(void *mem, unsigned int length); + * + * Initialise a region in normal memory to 0. This functions complies with the + * AAPCS and can be called from C code. + * + * NOTE: MMU must be enabled when using this function as it can only operate on + * normal memory. It is intended to be mainly used from C code when MMU + * is usually enabled. + * ----------------------------------------------------------------------- + */ +.equ zero_normalmem, zeromem_dczva + +/* ----------------------------------------------------------------------- + * void zeromem(void *mem, unsigned int length); + * + * Initialise a region of device memory to 0. This functions complies with the + * AAPCS and can be called from C code. + * + * NOTE: When data caches and MMU are enabled, zero_normalmem can usually be + * used instead for faster zeroing. + * + * ----------------------------------------------------------------------- + */ +func zeromem + /* x2 is the address past the last zeroed address */ + add x2, x0, x1 + /* + * Uses the fallback path that does not use DC ZVA instruction and + * therefore does not need enabled MMU + */ + b .Lzeromem_dczva_fallback_entry +endfunc zeromem + +/* ----------------------------------------------------------------------- + * void zeromem_dczva(void *mem, unsigned int length); + * + * Fill a region of normal memory of size "length" in bytes with null bytes. + * MMU must be enabled and the memory be of + * normal type. This is because this function internally uses the DC ZVA + * instruction, which generates an Alignment fault if used on any type of + * Device memory (see section D3.4.9 of the ARMv8 ARM, issue k). When the MMU + * is disabled, all memory behaves like Device-nGnRnE memory (see section + * D4.2.8), hence the requirement on the MMU being enabled. + * NOTE: The code assumes that the block size as defined in DCZID_EL0 + * register is at least 16 bytes. + * + * ----------------------------------------------------------------------- + */ +func zeromem_dczva + + /* + * The function consists of a series of loops that zero memory one byte + * at a time, 16 bytes at a time or using the DC ZVA instruction to + * zero aligned block of bytes, which is assumed to be more than 16. + * In the case where the DC ZVA instruction cannot be used or if the + * first 16 bytes loop would overflow, there is fallback path that does + * not use DC ZVA. + * Note: The fallback path is also used by the zeromem function that + * branches to it directly. + * + * +---------+ zeromem_dczva + * | entry | + * +----+----+ + * | + * v + * +---------+ + * | checks |>o-------+ (If any check fails, fallback) + * +----+----+ | + * | |---------------+ + * v | Fallback path | + * +------+------+ |---------------+ + * | 1 byte loop | | + * +------+------+ .Lzeromem_dczva_initial_1byte_aligned_end + * | | + * v | + * +-------+-------+ | + * | 16 bytes loop | | + * +-------+-------+ | + * | | + * v | + * +------+------+ .Lzeromem_dczva_blocksize_aligned + * | DC ZVA loop | | + * +------+------+ | + * +--------+ | | + * | | | | + * | v v | + * | +-------+-------+ .Lzeromem_dczva_final_16bytes_aligned + * | | 16 bytes loop | | + * | +-------+-------+ | + * | | | + * | v | + * | +------+------+ .Lzeromem_dczva_final_1byte_aligned + * | | 1 byte loop | | + * | +-------------+ | + * | | | + * | v | + * | +---+--+ | + * | | exit | | + * | +------+ | + * | | + * | +--------------+ +------------------+ zeromem + * | | +----------------| zeromem function | + * | | | +------------------+ + * | v v + * | +-------------+ .Lzeromem_dczva_fallback_entry + * | | 1 byte loop | + * | +------+------+ + * | | + * +-----------+ + */ + + /* + * Readable names for registers + * + * Registers x0, x1 and x2 are also set by zeromem which + * branches into the fallback path directly, so cursor, length and + * stop_address should not be retargeted to other registers. + */ + cursor .req x0 /* Start address and then current address */ + length .req x1 /* Length in bytes of the region to zero out */ + /* Reusing x1 as length is never used after block_mask is set */ + block_mask .req x1 /* Bitmask of the block size read in DCZID_EL0 */ + stop_address .req x2 /* Address past the last zeroed byte */ + block_size .req x3 /* Size of a block in bytes as read in DCZID_EL0 */ + tmp1 .req x4 + tmp2 .req x5 + +#if ENABLE_ASSERTIONS + /* + * Check for M bit (MMU enabled) of the current SCTLR_EL(1|3) + * register value and panic if the MMU is disabled. + */ +#if defined(IMAGE_BL1) || defined(IMAGE_BL31) || (defined(IMAGE_BL2) && BL2_AT_EL3) + mrs tmp1, sctlr_el3 +#else + mrs tmp1, sctlr_el1 +#endif + + tst tmp1, #SCTLR_M_BIT + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + + /* stop_address is the address past the last to zero */ + add stop_address, cursor, length + + /* + * Get block_size = (log2() >> 2) (see encoding of + * dczid_el0 reg) + */ + mrs block_size, dczid_el0 + + /* + * Select the 4 lowest bits and convert the extracted log2() to + */ + ubfx block_size, block_size, #0, #4 + mov tmp2, #(1 << 2) + lsl block_size, tmp2, block_size + +#if ENABLE_ASSERTIONS + /* + * Assumes block size is at least 16 bytes to avoid manual realignment + * of the cursor at the end of the DCZVA loop. + */ + cmp block_size, #16 + ASM_ASSERT(hs) +#endif + /* + * Not worth doing all the setup for a region less than a block and + * protects against zeroing a whole block when the area to zero is + * smaller than that. Also, as it is assumed that the block size is at + * least 16 bytes, this also protects the initial aligning loops from + * trying to zero 16 bytes when length is less than 16. + */ + cmp length, block_size + b.lo .Lzeromem_dczva_fallback_entry + + /* + * Calculate the bitmask of the block alignment. It will never + * underflow as the block size is between 4 bytes and 2kB. + * block_mask = block_size - 1 + */ + sub block_mask, block_size, #1 + + /* + * length alias should not be used after this point unless it is + * defined as a register other than block_mask's. + */ + .unreq length + + /* + * If the start address is already aligned to zero block size, go + * straight to the cache zeroing loop. This is safe because at this + * point, the length cannot be smaller than a block size. + */ + tst cursor, block_mask + b.eq .Lzeromem_dczva_blocksize_aligned + + /* + * Calculate the first block-size-aligned address. It is assumed that + * the zero block size is at least 16 bytes. This address is the last + * address of this initial loop. + */ + orr tmp1, cursor, block_mask + add tmp1, tmp1, #1 + + /* + * If the addition overflows, skip the cache zeroing loops. This is + * quite unlikely however. + */ + cbz tmp1, .Lzeromem_dczva_fallback_entry + + /* + * If the first block-size-aligned address is past the last address, + * fallback to the simpler code. + */ + cmp tmp1, stop_address + b.hi .Lzeromem_dczva_fallback_entry + + /* + * If the start address is already aligned to 16 bytes, skip this loop. + * It is safe to do this because tmp1 (the stop address of the initial + * 16 bytes loop) will never be greater than the final stop address. + */ + tst cursor, #0xf + b.eq .Lzeromem_dczva_initial_1byte_aligned_end + + /* Calculate the next address aligned to 16 bytes */ + orr tmp2, cursor, #0xf + add tmp2, tmp2, #1 + /* If it overflows, fallback to the simple path (unlikely) */ + cbz tmp2, .Lzeromem_dczva_fallback_entry + /* + * Next aligned address cannot be after the stop address because the + * length cannot be smaller than 16 at this point. + */ + + /* First loop: zero byte per byte */ +1: + strb wzr, [cursor], #1 + cmp cursor, tmp2 + b.ne 1b +.Lzeromem_dczva_initial_1byte_aligned_end: + + /* + * Second loop: we need to zero 16 bytes at a time from cursor to tmp1 + * before being able to use the code that deals with block-size-aligned + * addresses. + */ + cmp cursor, tmp1 + b.hs 2f +1: + stp xzr, xzr, [cursor], #16 + cmp cursor, tmp1 + b.lo 1b +2: + + /* + * Third loop: zero a block at a time using DC ZVA cache block zeroing + * instruction. + */ +.Lzeromem_dczva_blocksize_aligned: + /* + * Calculate the last block-size-aligned address. If the result equals + * to the start address, the loop will exit immediately. + */ + bic tmp1, stop_address, block_mask + + cmp cursor, tmp1 + b.hs 2f +1: + /* Zero the block containing the cursor */ + dc zva, cursor + /* Increment the cursor by the size of a block */ + add cursor, cursor, block_size + cmp cursor, tmp1 + b.lo 1b +2: + + /* + * Fourth loop: zero 16 bytes at a time and then byte per byte the + * remaining area + */ +.Lzeromem_dczva_final_16bytes_aligned: + /* + * Calculate the last 16 bytes aligned address. It is assumed that the + * block size will never be smaller than 16 bytes so that the current + * cursor is aligned to at least 16 bytes boundary. + */ + bic tmp1, stop_address, #15 + + cmp cursor, tmp1 + b.hs 2f +1: + stp xzr, xzr, [cursor], #16 + cmp cursor, tmp1 + b.lo 1b +2: + + /* Fifth and final loop: zero byte per byte */ +.Lzeromem_dczva_final_1byte_aligned: + cmp cursor, stop_address + b.eq 2f +1: + strb wzr, [cursor], #1 + cmp cursor, stop_address + b.ne 1b +2: + ret + + /* Fallback for unaligned start addresses */ +.Lzeromem_dczva_fallback_entry: + /* + * If the start address is already aligned to 16 bytes, skip this loop. + */ + tst cursor, #0xf + b.eq .Lzeromem_dczva_final_16bytes_aligned + + /* Calculate the next address aligned to 16 bytes */ + orr tmp1, cursor, #15 + add tmp1, tmp1, #1 + /* If it overflows, fallback to byte per byte zeroing */ + cbz tmp1, .Lzeromem_dczva_final_1byte_aligned + /* If the next aligned address is after the stop address, fall back */ + cmp tmp1, stop_address + b.hs .Lzeromem_dczva_final_1byte_aligned + + /* Fallback entry loop: zero byte per byte */ +1: + strb wzr, [cursor], #1 + cmp cursor, tmp1 + b.ne 1b + + b .Lzeromem_dczva_final_16bytes_aligned + + .unreq cursor + /* + * length is already unreq'ed to reuse the register for another + * variable. + */ + .unreq stop_address + .unreq block_size + .unreq block_mask + .unreq tmp1 + .unreq tmp2 +endfunc zeromem_dczva + +/* -------------------------------------------------------------------------- + * void memcpy16(void *dest, const void *src, unsigned int length) + * + * Copy length bytes from memory area src to memory area dest. + * The memory areas should not overlap. + * Destination and source addresses must be 16-byte aligned. + * -------------------------------------------------------------------------- + */ +func memcpy16 +#if ENABLE_ASSERTIONS + orr x3, x0, x1 + tst x3, #0xf + ASM_ASSERT(eq) +#endif +/* copy 16 bytes at a time */ +m_loop16: + cmp x2, #16 + b.lo m_loop1 + ldp x3, x4, [x1], #16 + stp x3, x4, [x0], #16 + sub x2, x2, #16 + b m_loop16 +/* copy byte per byte */ +m_loop1: + cbz x2, m_end + ldrb w3, [x1], #1 + strb w3, [x0], #1 + subs x2, x2, #1 + b.ne m_loop1 +m_end: + ret +endfunc memcpy16 + +/* --------------------------------------------------------------------------- + * Disable the MMU at EL3 + * --------------------------------------------------------------------------- + */ + +func disable_mmu_el3 + mov x1, #(SCTLR_M_BIT | SCTLR_C_BIT) +do_disable_mmu_el3: + mrs x0, sctlr_el3 + bic x0, x0, x1 + msr sctlr_el3, x0 + isb /* ensure MMU is off */ + dsb sy + ret +endfunc disable_mmu_el3 + + +func disable_mmu_icache_el3 + mov x1, #(SCTLR_M_BIT | SCTLR_C_BIT | SCTLR_I_BIT) + b do_disable_mmu_el3 +endfunc disable_mmu_icache_el3 + +/* --------------------------------------------------------------------------- + * Disable the MMU at EL1 + * --------------------------------------------------------------------------- + */ + +func disable_mmu_el1 + mov x1, #(SCTLR_M_BIT | SCTLR_C_BIT) +do_disable_mmu_el1: + mrs x0, sctlr_el1 + bic x0, x0, x1 + msr sctlr_el1, x0 + isb /* ensure MMU is off */ + dsb sy + ret +endfunc disable_mmu_el1 + + +func disable_mmu_icache_el1 + mov x1, #(SCTLR_M_BIT | SCTLR_C_BIT | SCTLR_I_BIT) + b do_disable_mmu_el1 +endfunc disable_mmu_icache_el1 + +/* --------------------------------------------------------------------------- + * Enable the use of VFP at EL3 + * --------------------------------------------------------------------------- + */ +#if SUPPORT_VFP +func enable_vfp + mrs x0, cpacr_el1 + orr x0, x0, #CPACR_VFP_BITS + msr cpacr_el1, x0 + mrs x0, cptr_el3 + mov x1, #AARCH64_CPTR_TFP + bic x0, x0, x1 + msr cptr_el3, x0 + isb + ret +endfunc enable_vfp +#endif + +/* --------------------------------------------------------------------------- + * Helper to fixup Global Descriptor table (GDT) and dynamic relocations + * (.rela.dyn) at runtime. + * + * This function is meant to be used when the firmware is compiled with -fpie + * and linked with -pie options. We rely on the linker script exporting + * appropriate markers for start and end of the section. For GOT, we + * expect __GOT_START__ and __GOT_END__. Similarly for .rela.dyn, we expect + * __RELA_START__ and __RELA_END__. + * + * The function takes the limits of the memory to apply fixups to as + * arguments (which is usually the limits of the relocable BL image). + * x0 - the start of the fixup region + * x1 - the limit of the fixup region + * These addresses have to be 4KB page aligned. + * --------------------------------------------------------------------------- + */ + +/* Relocation codes */ +#define R_AARCH64_NONE 0 +#define R_AARCH64_RELATIVE 1027 + +func fixup_gdt_reloc + mov x6, x0 + mov x7, x1 + +#if ENABLE_ASSERTIONS + /* Test if the limits are 4KB aligned */ + orr x0, x0, x1 + tst x0, #(PAGE_SIZE_MASK) + ASM_ASSERT(eq) +#endif + /* + * Calculate the offset based on return address in x30. + * Assume that this function is called within a page at the start of + * fixup region. + */ + and x2, x30, #~(PAGE_SIZE_MASK) + subs x0, x2, x6 /* Diff(S) = Current Address - Compiled Address */ + b.eq 3f /* Diff(S) = 0. No relocation needed */ + + adrp x1, __GOT_START__ + add x1, x1, :lo12:__GOT_START__ + adrp x2, __GOT_END__ + add x2, x2, :lo12:__GOT_END__ + + /* + * GOT is an array of 64_bit addresses which must be fixed up as + * new_addr = old_addr + Diff(S). + * The new_addr is the address currently the binary is executing from + * and old_addr is the address at compile time. + */ +1: ldr x3, [x1] + + /* Skip adding offset if address is < lower limit */ + cmp x3, x6 + b.lo 2f + + /* Skip adding offset if address is >= upper limit */ + cmp x3, x7 + b.hs 2f + add x3, x3, x0 + str x3, [x1] + +2: add x1, x1, #8 + cmp x1, x2 + b.lo 1b + + /* Starting dynamic relocations. Use adrp/adr to get RELA_START and END */ +3: adrp x1, __RELA_START__ + add x1, x1, :lo12:__RELA_START__ + adrp x2, __RELA_END__ + add x2, x2, :lo12:__RELA_END__ + + /* + * According to ELF-64 specification, the RELA data structure is as + * follows: + * typedef struct { + * Elf64_Addr r_offset; + * Elf64_Xword r_info; + * Elf64_Sxword r_addend; + * } Elf64_Rela; + * + * r_offset is address of reference + * r_info is symbol index and type of relocation (in this case + * code 1027 which corresponds to R_AARCH64_RELATIVE). + * r_addend is constant part of expression. + * + * Size of Elf64_Rela structure is 24 bytes. + */ + + /* Skip R_AARCH64_NONE entry with code 0 */ +1: ldr x3, [x1, #8] + cbz x3, 2f + +#if ENABLE_ASSERTIONS + /* Assert that the relocation type is R_AARCH64_RELATIVE */ + cmp x3, #R_AARCH64_RELATIVE + ASM_ASSERT(eq) +#endif + ldr x3, [x1] /* r_offset */ + add x3, x0, x3 + ldr x4, [x1, #16] /* r_addend */ + + /* Skip adding offset if r_addend is < lower limit */ + cmp x4, x6 + b.lo 2f + + /* Skip adding offset if r_addend entry is >= upper limit */ + cmp x4, x7 + b.hs 2f + + add x4, x0, x4 /* Diff(S) + r_addend */ + str x4, [x3] + +2: add x1, x1, #24 + cmp x1, x2 + b.lo 1b + ret +endfunc fixup_gdt_reloc diff --git a/drivers/rz/ipl/rza/lib/compiler-rt/LICENSE.TXT b/drivers/rz/ipl/rza/lib/compiler-rt/LICENSE.TXT new file mode 100644 index 00000000..a17dc12b --- /dev/null +++ b/drivers/rz/ipl/rza/lib/compiler-rt/LICENSE.TXT @@ -0,0 +1,91 @@ +============================================================================== +compiler_rt License +============================================================================== + +The compiler_rt library is dual licensed under both the University of Illinois +"BSD-Like" license and the MIT license. As a user of this code you may choose +to use it under either license. As a contributor, you agree to allow your code +to be used under both. + +Full text of the relevant licenses is included below. + +============================================================================== + +University of Illinois/NCSA +Open Source License + +Copyright (c) 2009-2016 by the contributors listed in CREDITS.TXT + +All rights reserved. + +Developed by: + + LLVM Team + + University of Illinois at Urbana-Champaign + + http://llvm.org + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal with +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimers. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimers in the + documentation and/or other materials provided with the distribution. + + * Neither the names of the LLVM Team, University of Illinois at + Urbana-Champaign, nor the names of its contributors may be used to + endorse or promote products derived from this Software without specific + prior written permission. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE +SOFTWARE. + +============================================================================== + +Copyright (c) 2009-2015 by the contributors listed in CREDITS.TXT + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +============================================================================== +Copyrights and Licenses for Third Party Software Distributed with LLVM: +============================================================================== +The LLVM software contains code written by third parties. Such software will +have its own individual LICENSE.TXT file in the directory in which it appears. +This file will describe the copyrights, license, and restrictions which apply +to that code. + +The disclaimer of warranty in the University of Illinois Open Source License +applies to all code in the LLVM Distribution, and nothing in any of the +other licenses gives permission to use the names of the LLVM Team or the +University of Illinois to endorse or promote products derived from this +Software. + diff --git a/drivers/rz/ipl/rza/lib/compiler-rt/builtins/arm/aeabi_ldivmod.S b/drivers/rz/ipl/rza/lib/compiler-rt/builtins/arm/aeabi_ldivmod.S new file mode 100644 index 00000000..038ae5d7 --- /dev/null +++ b/drivers/rz/ipl/rza/lib/compiler-rt/builtins/arm/aeabi_ldivmod.S @@ -0,0 +1,46 @@ +//===-- aeabi_ldivmod.S - EABI ldivmod implementation ---------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "../assembly.h" + +// struct { int64_t quot, int64_t rem} +// __aeabi_ldivmod(int64_t numerator, int64_t denominator) { +// int64_t rem, quot; +// quot = __divmoddi4(numerator, denominator, &rem); +// return {quot, rem}; +// } + +#if defined(__MINGW32__) +#define __aeabi_ldivmod __rt_sdiv64 +#endif + + .syntax unified + .p2align 2 +DEFINE_COMPILERRT_FUNCTION(__aeabi_ldivmod) + push {r6, lr} + sub sp, sp, #16 + add r6, sp, #8 + str r6, [sp] +#if defined(__MINGW32__) + movs r6, r0 + movs r0, r2 + movs r2, r6 + movs r6, r1 + movs r1, r3 + movs r3, r6 +#endif + bl SYMBOL_NAME(__divmoddi4) + ldr r2, [sp, #8] + ldr r3, [sp, #12] + add sp, sp, #16 + pop {r6, pc} +END_COMPILERRT_FUNCTION(__aeabi_ldivmod) + +NO_EXEC_STACK_DIRECTIVE + diff --git a/drivers/rz/ipl/rza/lib/compiler-rt/builtins/arm/aeabi_uldivmod.S b/drivers/rz/ipl/rza/lib/compiler-rt/builtins/arm/aeabi_uldivmod.S new file mode 100644 index 00000000..be343b6b --- /dev/null +++ b/drivers/rz/ipl/rza/lib/compiler-rt/builtins/arm/aeabi_uldivmod.S @@ -0,0 +1,46 @@ +//===-- aeabi_uldivmod.S - EABI uldivmod implementation -------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "../assembly.h" + +// struct { uint64_t quot, uint64_t rem} +// __aeabi_uldivmod(uint64_t numerator, uint64_t denominator) { +// uint64_t rem, quot; +// quot = __udivmoddi4(numerator, denominator, &rem); +// return {quot, rem}; +// } + +#if defined(__MINGW32__) +#define __aeabi_uldivmod __rt_udiv64 +#endif + + .syntax unified + .p2align 2 +DEFINE_COMPILERRT_FUNCTION(__aeabi_uldivmod) + push {r6, lr} + sub sp, sp, #16 + add r6, sp, #8 + str r6, [sp] +#if defined(__MINGW32__) + movs r6, r0 + movs r0, r2 + movs r2, r6 + movs r6, r1 + movs r1, r3 + movs r3, r6 +#endif + bl SYMBOL_NAME(__udivmoddi4) + ldr r2, [sp, #8] + ldr r3, [sp, #12] + add sp, sp, #16 + pop {r6, pc} +END_COMPILERRT_FUNCTION(__aeabi_uldivmod) + +NO_EXEC_STACK_DIRECTIVE + diff --git a/drivers/rz/ipl/rza/lib/compiler-rt/builtins/assembly.h b/drivers/rz/ipl/rza/lib/compiler-rt/builtins/assembly.h new file mode 100644 index 00000000..29d9f884 --- /dev/null +++ b/drivers/rz/ipl/rza/lib/compiler-rt/builtins/assembly.h @@ -0,0 +1,169 @@ +/* ===-- assembly.h - compiler-rt assembler support macros -----------------=== + * + * The LLVM Compiler Infrastructure + * + * This file is dual licensed under the MIT and the University of Illinois Open + * Source Licenses. See LICENSE.TXT for details. + * + * ===----------------------------------------------------------------------=== + * + * This file defines macros for use in compiler-rt assembler source. + * This file is not part of the interface of this library. + * + * ===----------------------------------------------------------------------=== + */ + +#ifndef COMPILERRT_ASSEMBLY_H +#define COMPILERRT_ASSEMBLY_H + +#if defined(__POWERPC__) || defined(__powerpc__) || defined(__ppc__) +#define SEPARATOR @ +#else +#define SEPARATOR ; +#endif + +#if defined(__APPLE__) +#define HIDDEN(name) .private_extern name +#define LOCAL_LABEL(name) L_##name +// tell linker it can break up file at label boundaries +#define FILE_LEVEL_DIRECTIVE .subsections_via_symbols +#define SYMBOL_IS_FUNC(name) +#define CONST_SECTION .const + +#define NO_EXEC_STACK_DIRECTIVE + +#elif defined(__ELF__) + +#define HIDDEN(name) .hidden name +#define LOCAL_LABEL(name) .L_##name +#define FILE_LEVEL_DIRECTIVE +#if defined(__arm__) +#define SYMBOL_IS_FUNC(name) .type name,%function +#else +#define SYMBOL_IS_FUNC(name) .type name,@function +#endif +#define CONST_SECTION .section .rodata + +#if defined(__GNU__) || defined(__ANDROID__) || defined(__FreeBSD__) +#define NO_EXEC_STACK_DIRECTIVE .section .note.GNU-stack,"",%progbits +#else +#define NO_EXEC_STACK_DIRECTIVE +#endif + +#else // !__APPLE__ && !__ELF__ + +#define HIDDEN(name) +#define LOCAL_LABEL(name) .L ## name +#define FILE_LEVEL_DIRECTIVE +#define SYMBOL_IS_FUNC(name) \ + .def name SEPARATOR \ + .scl 2 SEPARATOR \ + .type 32 SEPARATOR \ + .endef +#define CONST_SECTION .section .rdata,"rd" + +#define NO_EXEC_STACK_DIRECTIVE + +#endif + +#if defined(__arm__) +#if defined(__ARM_ARCH_4T__) || __ARM_ARCH >= 5 +#define ARM_HAS_BX +#endif +#if !defined(__ARM_FEATURE_CLZ) && __ARM_ARCH_ISA_THUMB != 1 && \ + (__ARM_ARCH >= 6 || (__ARM_ARCH == 5 && !defined(__ARM_ARCH_5__))) +#define __ARM_FEATURE_CLZ +#endif + +#ifdef ARM_HAS_BX +#define JMP(r) bx r +#define JMPc(r, c) bx##c r +#else +#define JMP(r) mov pc, r +#define JMPc(r, c) mov##c pc, r +#endif + +// pop {pc} can't switch Thumb mode on ARMv4T +#if __ARM_ARCH >= 5 +#define POP_PC() pop {pc} +#else +#define POP_PC() \ + pop {ip}; \ + JMP(ip) +#endif + +#if __ARM_ARCH_ISA_THUMB == 2 +#define IT(cond) it cond +#define ITT(cond) itt cond +#else +#define IT(cond) +#define ITT(cond) +#endif + +#if __ARM_ARCH_ISA_THUMB == 2 +#define WIDE(op) op.w +#else +#define WIDE(op) op +#endif +#endif + +#define GLUE2(a, b) a##b +#define GLUE(a, b) GLUE2(a, b) +#define SYMBOL_NAME(name) GLUE(__USER_LABEL_PREFIX__, name) + +#ifdef VISIBILITY_HIDDEN +#define DECLARE_SYMBOL_VISIBILITY(name) \ + HIDDEN(SYMBOL_NAME(name)) SEPARATOR +#else +#define DECLARE_SYMBOL_VISIBILITY(name) +#endif + +#define DEFINE_COMPILERRT_FUNCTION(name) \ + FILE_LEVEL_DIRECTIVE SEPARATOR \ + .globl SYMBOL_NAME(name) SEPARATOR \ + SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR \ + DECLARE_SYMBOL_VISIBILITY(name) \ + SYMBOL_NAME(name): + +#define DEFINE_COMPILERRT_THUMB_FUNCTION(name) \ + FILE_LEVEL_DIRECTIVE SEPARATOR \ + .globl SYMBOL_NAME(name) SEPARATOR \ + SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR \ + DECLARE_SYMBOL_VISIBILITY(name) SEPARATOR \ + .thumb_func SEPARATOR \ + SYMBOL_NAME(name): + +#define DEFINE_COMPILERRT_PRIVATE_FUNCTION(name) \ + FILE_LEVEL_DIRECTIVE SEPARATOR \ + .globl SYMBOL_NAME(name) SEPARATOR \ + SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR \ + HIDDEN(SYMBOL_NAME(name)) SEPARATOR \ + SYMBOL_NAME(name): + +#define DEFINE_COMPILERRT_PRIVATE_FUNCTION_UNMANGLED(name) \ + .globl name SEPARATOR \ + SYMBOL_IS_FUNC(name) SEPARATOR \ + HIDDEN(name) SEPARATOR \ + name: + +#define DEFINE_COMPILERRT_FUNCTION_ALIAS(name, target) \ + .globl SYMBOL_NAME(name) SEPARATOR \ + SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR \ + DECLARE_SYMBOL_VISIBILITY(SYMBOL_NAME(name)) SEPARATOR \ + .set SYMBOL_NAME(name), SYMBOL_NAME(target) SEPARATOR + +#if defined(__ARM_EABI__) +#define DEFINE_AEABI_FUNCTION_ALIAS(aeabi_name, name) \ + DEFINE_COMPILERRT_FUNCTION_ALIAS(aeabi_name, name) +#else +#define DEFINE_AEABI_FUNCTION_ALIAS(aeabi_name, name) +#endif + +#ifdef __ELF__ +#define END_COMPILERRT_FUNCTION(name) \ + .size SYMBOL_NAME(name), . - SYMBOL_NAME(name) +#else +#define END_COMPILERRT_FUNCTION(name) +#endif + +#endif /* COMPILERRT_ASSEMBLY_H */ diff --git a/drivers/rz/ipl/rza/lib/compiler-rt/builtins/ctzdi2.c b/drivers/rz/ipl/rza/lib/compiler-rt/builtins/ctzdi2.c new file mode 100644 index 00000000..db3c6fdc --- /dev/null +++ b/drivers/rz/ipl/rza/lib/compiler-rt/builtins/ctzdi2.c @@ -0,0 +1,29 @@ +/* ===-- ctzdi2.c - Implement __ctzdi2 -------------------------------------=== + * + * The LLVM Compiler Infrastructure + * + * This file is dual licensed under the MIT and the University of Illinois Open + * Source Licenses. See LICENSE.TXT for details. + * + * ===----------------------------------------------------------------------=== + * + * This file implements __ctzdi2 for the compiler_rt library. + * + * ===----------------------------------------------------------------------=== + */ + +#include "int_lib.h" + +/* Returns: the number of trailing 0-bits */ + +/* Precondition: a != 0 */ + +COMPILER_RT_ABI si_int +__ctzdi2(di_int a) +{ + dwords x; + x.all = a; + const si_int f = -(x.s.low == 0); + return __builtin_ctz((x.s.high & f) | (x.s.low & ~f)) + + (f & ((si_int)(sizeof(si_int) * CHAR_BIT))); +} diff --git a/drivers/rz/ipl/rza/lib/compiler-rt/builtins/divdi3.c b/drivers/rz/ipl/rza/lib/compiler-rt/builtins/divdi3.c new file mode 100644 index 00000000..b8eebcb2 --- /dev/null +++ b/drivers/rz/ipl/rza/lib/compiler-rt/builtins/divdi3.c @@ -0,0 +1,29 @@ +/* ===-- divdi3.c - Implement __divdi3 -------------------------------------=== + * + * The LLVM Compiler Infrastructure + * + * This file is dual licensed under the MIT and the University of Illinois Open + * Source Licenses. See LICENSE.TXT for details. + * + * ===----------------------------------------------------------------------=== + * + * This file implements __divdi3 for the compiler_rt library. + * + * ===----------------------------------------------------------------------=== + */ + +#include "int_lib.h" + +/* Returns: a / b */ + +COMPILER_RT_ABI di_int +__divdi3(di_int a, di_int b) +{ + const int bits_in_dword_m1 = (int)(sizeof(di_int) * CHAR_BIT) - 1; + di_int s_a = a >> bits_in_dword_m1; /* s_a = a < 0 ? -1 : 0 */ + di_int s_b = b >> bits_in_dword_m1; /* s_b = b < 0 ? -1 : 0 */ + a = (a ^ s_a) - s_a; /* negate if s_a == -1 */ + b = (b ^ s_b) - s_b; /* negate if s_b == -1 */ + s_a ^= s_b; /*sign of quotient */ + return (__udivmoddi4(a, b, (du_int*)0) ^ s_a) - s_a; /* negate if s_a == -1 */ +} diff --git a/drivers/rz/ipl/rza/lib/compiler-rt/builtins/divmoddi4.c b/drivers/rz/ipl/rza/lib/compiler-rt/builtins/divmoddi4.c new file mode 100644 index 00000000..0d4df67a --- /dev/null +++ b/drivers/rz/ipl/rza/lib/compiler-rt/builtins/divmoddi4.c @@ -0,0 +1,25 @@ +/*===-- divmoddi4.c - Implement __divmoddi4 --------------------------------=== + * + * The LLVM Compiler Infrastructure + * + * This file is dual licensed under the MIT and the University of Illinois Open + * Source Licenses. See LICENSE.TXT for details. + * + * ===----------------------------------------------------------------------=== + * + * This file implements __divmoddi4 for the compiler_rt library. + * + * ===----------------------------------------------------------------------=== + */ + +#include "int_lib.h" + +/* Returns: a / b, *rem = a % b */ + +COMPILER_RT_ABI di_int +__divmoddi4(di_int a, di_int b, di_int* rem) +{ + di_int d = __divdi3(a,b); + *rem = a - (d*b); + return d; +} diff --git a/drivers/rz/ipl/rza/lib/compiler-rt/builtins/int_endianness.h b/drivers/rz/ipl/rza/lib/compiler-rt/builtins/int_endianness.h new file mode 100644 index 00000000..7995ddbb --- /dev/null +++ b/drivers/rz/ipl/rza/lib/compiler-rt/builtins/int_endianness.h @@ -0,0 +1,116 @@ +/* ===-- int_endianness.h - configuration header for compiler-rt ------------=== + * + * The LLVM Compiler Infrastructure + * + * This file is dual licensed under the MIT and the University of Illinois Open + * Source Licenses. See LICENSE.TXT for details. + * + * ===----------------------------------------------------------------------=== + * + * This file is a configuration header for compiler-rt. + * This file is not part of the interface of this library. + * + * ===----------------------------------------------------------------------=== + */ + +#ifndef INT_ENDIANNESS_H +#define INT_ENDIANNESS_H + +#if defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && \ + defined(__ORDER_LITTLE_ENDIAN__) + +/* Clang and GCC provide built-in endianness definitions. */ +#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ +#define _YUGA_LITTLE_ENDIAN 0 +#define _YUGA_BIG_ENDIAN 1 +#elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +#define _YUGA_LITTLE_ENDIAN 1 +#define _YUGA_BIG_ENDIAN 0 +#endif /* __BYTE_ORDER__ */ + +#else /* Compilers other than Clang or GCC. */ + +#if defined(__SVR4) && defined(__sun) +#include + +#if defined(_BIG_ENDIAN) +#define _YUGA_LITTLE_ENDIAN 0 +#define _YUGA_BIG_ENDIAN 1 +#elif defined(_LITTLE_ENDIAN) +#define _YUGA_LITTLE_ENDIAN 1 +#define _YUGA_BIG_ENDIAN 0 +#else /* !_LITTLE_ENDIAN */ +#error "unknown endianness" +#endif /* !_LITTLE_ENDIAN */ + +#endif /* Solaris and AuroraUX. */ + +/* .. */ + +#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || \ + defined(__minix) +#include + +#if _BYTE_ORDER == _BIG_ENDIAN +#define _YUGA_LITTLE_ENDIAN 0 +#define _YUGA_BIG_ENDIAN 1 +#elif _BYTE_ORDER == _LITTLE_ENDIAN +#define _YUGA_LITTLE_ENDIAN 1 +#define _YUGA_BIG_ENDIAN 0 +#endif /* _BYTE_ORDER */ + +#endif /* *BSD */ + +#if defined(__OpenBSD__) || defined(__Bitrig__) +#include + +#if _BYTE_ORDER == _BIG_ENDIAN +#define _YUGA_LITTLE_ENDIAN 0 +#define _YUGA_BIG_ENDIAN 1 +#elif _BYTE_ORDER == _LITTLE_ENDIAN +#define _YUGA_LITTLE_ENDIAN 1 +#define _YUGA_BIG_ENDIAN 0 +#endif /* _BYTE_ORDER */ + +#endif /* OpenBSD and Bitrig. */ + +/* .. */ + +/* Mac OSX has __BIG_ENDIAN__ or __LITTLE_ENDIAN__ automatically set by the + * compiler (at least with GCC) */ +#if defined(__APPLE__) || defined(__ellcc__ ) + +#ifdef __BIG_ENDIAN__ +#if __BIG_ENDIAN__ +#define _YUGA_LITTLE_ENDIAN 0 +#define _YUGA_BIG_ENDIAN 1 +#endif +#endif /* __BIG_ENDIAN__ */ + +#ifdef __LITTLE_ENDIAN__ +#if __LITTLE_ENDIAN__ +#define _YUGA_LITTLE_ENDIAN 1 +#define _YUGA_BIG_ENDIAN 0 +#endif +#endif /* __LITTLE_ENDIAN__ */ + +#endif /* Mac OSX */ + +/* .. */ + +#if defined(_WIN32) + +#define _YUGA_LITTLE_ENDIAN 1 +#define _YUGA_BIG_ENDIAN 0 + +#endif /* Windows */ + +#endif /* Clang or GCC. */ + +/* . */ + +#if !defined(_YUGA_LITTLE_ENDIAN) || !defined(_YUGA_BIG_ENDIAN) +#error Unable to determine endian +#endif /* Check we found an endianness correctly. */ + +#endif /* INT_ENDIANNESS_H */ diff --git a/drivers/rz/ipl/rza/lib/compiler-rt/builtins/int_lib.h b/drivers/rz/ipl/rza/lib/compiler-rt/builtins/int_lib.h new file mode 100644 index 00000000..80a7c41a --- /dev/null +++ b/drivers/rz/ipl/rza/lib/compiler-rt/builtins/int_lib.h @@ -0,0 +1,127 @@ +/* ===-- int_lib.h - configuration header for compiler-rt -----------------=== + * + * The LLVM Compiler Infrastructure + * + * This file is dual licensed under the MIT and the University of Illinois Open + * Source Licenses. See LICENSE.TXT for details. + * + * ===----------------------------------------------------------------------=== + * + * This file is a configuration header for compiler-rt. + * This file is not part of the interface of this library. + * + * ===----------------------------------------------------------------------=== + */ + +/* + * Portions copyright (c) 2017-2018, ARM Limited and Contributors. + * All rights reserved. + */ + +#ifndef INT_LIB_H +#define INT_LIB_H + +/* Assumption: Signed integral is 2's complement. */ +/* Assumption: Right shift of signed negative is arithmetic shift. */ +/* Assumption: Endianness is little or big (not mixed). */ + +#if defined(__ELF__) +#define FNALIAS(alias_name, original_name) \ + void alias_name() __attribute__((__alias__(#original_name))) +#define COMPILER_RT_ALIAS(aliasee) __attribute__((__alias__(#aliasee))) +#else +#define FNALIAS(alias, name) _Pragma("GCC error(\"alias unsupported on this file format\")") +#define COMPILER_RT_ALIAS(aliasee) _Pragma("GCC error(\"alias unsupported on this file format\")") +#endif + +/* ABI macro definitions */ + +#if __ARM_EABI__ +# ifdef COMPILER_RT_ARMHF_TARGET +# define COMPILER_RT_ABI +# else +# define COMPILER_RT_ABI __attribute__((__pcs__("aapcs"))) +# endif +#else +# define COMPILER_RT_ABI +#endif + +#define AEABI_RTABI __attribute__((__pcs__("aapcs"))) + +#if defined(_MSC_VER) && !defined(__clang__) +#define ALWAYS_INLINE __forceinline +#define NOINLINE __declspec(noinline) +#define NORETURN __declspec(noreturn) +#define UNUSED +#else +#define ALWAYS_INLINE __attribute__((always_inline)) +#define NOINLINE __attribute__((noinline)) +#define NORETURN __attribute__((noreturn)) +#define UNUSED __attribute__((unused)) +#endif + +/* + * Kernel and boot environment can't use normal headers, + * so use the equivalent system headers. + */ +# include +# include + +/* Include the commonly used internal type definitions. */ +#include "int_types.h" + +COMPILER_RT_ABI si_int __paritysi2(si_int a); +COMPILER_RT_ABI si_int __paritydi2(di_int a); + +COMPILER_RT_ABI di_int __divdi3(di_int a, di_int b); +COMPILER_RT_ABI si_int __divsi3(si_int a, si_int b); +COMPILER_RT_ABI su_int __udivsi3(su_int n, su_int d); + +COMPILER_RT_ABI su_int __udivmodsi4(su_int a, su_int b, su_int* rem); +COMPILER_RT_ABI du_int __udivmoddi4(du_int a, du_int b, du_int* rem); +#ifdef CRT_HAS_128BIT +COMPILER_RT_ABI si_int __clzti2(ti_int a); +COMPILER_RT_ABI tu_int __udivmodti4(tu_int a, tu_int b, tu_int* rem); +#endif + +/* Definitions for builtins unavailable on MSVC */ +#if defined(_MSC_VER) && !defined(__clang__) +#include + +uint32_t __inline __builtin_ctz(uint32_t value) { + unsigned long trailing_zero = 0; + if (_BitScanForward(&trailing_zero, value)) + return trailing_zero; + return 32; +} + +uint32_t __inline __builtin_clz(uint32_t value) { + unsigned long leading_zero = 0; + if (_BitScanReverse(&leading_zero, value)) + return 31 - leading_zero; + return 32; +} + +#if defined(_M_ARM) || defined(_M_X64) +uint32_t __inline __builtin_clzll(uint64_t value) { + unsigned long leading_zero = 0; + if (_BitScanReverse64(&leading_zero, value)) + return 63 - leading_zero; + return 64; +} +#else +uint32_t __inline __builtin_clzll(uint64_t value) { + if (value == 0) + return 64; + uint32_t msh = (uint32_t)(value >> 32); + uint32_t lsh = (uint32_t)(value & 0xFFFFFFFF); + if (msh != 0) + return __builtin_clz(msh); + return 32 + __builtin_clz(lsh); +} +#endif + +#define __builtin_clzl __builtin_clzll +#endif /* defined(_MSC_VER) && !defined(__clang__) */ + +#endif /* INT_LIB_H */ diff --git a/drivers/rz/ipl/rza/lib/compiler-rt/builtins/int_math.h b/drivers/rz/ipl/rza/lib/compiler-rt/builtins/int_math.h new file mode 100644 index 00000000..fc81fb7f --- /dev/null +++ b/drivers/rz/ipl/rza/lib/compiler-rt/builtins/int_math.h @@ -0,0 +1,114 @@ +/* ===-- int_math.h - internal math inlines ---------------------------------=== + * + * The LLVM Compiler Infrastructure + * + * This file is dual licensed under the MIT and the University of Illinois Open + * Source Licenses. See LICENSE.TXT for details. + * + * ===-----------------------------------------------------------------------=== + * + * This file is not part of the interface of this library. + * + * This file defines substitutes for the libm functions used in some of the + * compiler-rt implementations, defined in such a way that there is not a direct + * dependency on libm or math.h. Instead, we use the compiler builtin versions + * where available. This reduces our dependencies on the system SDK by foisting + * the responsibility onto the compiler. + * + * ===-----------------------------------------------------------------------=== + */ + +#ifndef INT_MATH_H +#define INT_MATH_H + +#ifndef __has_builtin +# define __has_builtin(x) 0 +#endif + +#if defined(_MSC_VER) && !defined(__clang__) +#include +#include +#include +#endif + +#if defined(_MSC_VER) && !defined(__clang__) +#define CRT_INFINITY INFINITY +#else +#define CRT_INFINITY __builtin_huge_valf() +#endif + +#if defined(_MSC_VER) && !defined(__clang__) +#define crt_isfinite(x) _finite((x)) +#define crt_isinf(x) !_finite((x)) +#define crt_isnan(x) _isnan((x)) +#else +/* Define crt_isfinite in terms of the builtin if available, otherwise provide + * an alternate version in terms of our other functions. This supports some + * versions of GCC which didn't have __builtin_isfinite. + */ +#if __has_builtin(__builtin_isfinite) +# define crt_isfinite(x) __builtin_isfinite((x)) +#elif defined(__GNUC__) +# define crt_isfinite(x) \ + __extension__(({ \ + __typeof((x)) x_ = (x); \ + !crt_isinf(x_) && !crt_isnan(x_); \ + })) +#else +# error "Do not know how to check for infinity" +#endif /* __has_builtin(__builtin_isfinite) */ +#define crt_isinf(x) __builtin_isinf((x)) +#define crt_isnan(x) __builtin_isnan((x)) +#endif /* _MSC_VER */ + +#if defined(_MSC_VER) && !defined(__clang__) +#define crt_copysign(x, y) copysign((x), (y)) +#define crt_copysignf(x, y) copysignf((x), (y)) +#define crt_copysignl(x, y) copysignl((x), (y)) +#else +#define crt_copysign(x, y) __builtin_copysign((x), (y)) +#define crt_copysignf(x, y) __builtin_copysignf((x), (y)) +#define crt_copysignl(x, y) __builtin_copysignl((x), (y)) +#endif + +#if defined(_MSC_VER) && !defined(__clang__) +#define crt_fabs(x) fabs((x)) +#define crt_fabsf(x) fabsf((x)) +#define crt_fabsl(x) fabs((x)) +#else +#define crt_fabs(x) __builtin_fabs((x)) +#define crt_fabsf(x) __builtin_fabsf((x)) +#define crt_fabsl(x) __builtin_fabsl((x)) +#endif + +#if defined(_MSC_VER) && !defined(__clang__) +#define crt_fmax(x, y) __max((x), (y)) +#define crt_fmaxf(x, y) __max((x), (y)) +#define crt_fmaxl(x, y) __max((x), (y)) +#else +#define crt_fmax(x, y) __builtin_fmax((x), (y)) +#define crt_fmaxf(x, y) __builtin_fmaxf((x), (y)) +#define crt_fmaxl(x, y) __builtin_fmaxl((x), (y)) +#endif + +#if defined(_MSC_VER) && !defined(__clang__) +#define crt_logb(x) logb((x)) +#define crt_logbf(x) logbf((x)) +#define crt_logbl(x) logbl((x)) +#else +#define crt_logb(x) __builtin_logb((x)) +#define crt_logbf(x) __builtin_logbf((x)) +#define crt_logbl(x) __builtin_logbl((x)) +#endif + +#if defined(_MSC_VER) && !defined(__clang__) +#define crt_scalbn(x, y) scalbn((x), (y)) +#define crt_scalbnf(x, y) scalbnf((x), (y)) +#define crt_scalbnl(x, y) scalbnl((x), (y)) +#else +#define crt_scalbn(x, y) __builtin_scalbn((x), (y)) +#define crt_scalbnf(x, y) __builtin_scalbnf((x), (y)) +#define crt_scalbnl(x, y) __builtin_scalbnl((x), (y)) +#endif + +#endif /* INT_MATH_H */ diff --git a/drivers/rz/ipl/rza/lib/compiler-rt/builtins/int_types.h b/drivers/rz/ipl/rza/lib/compiler-rt/builtins/int_types.h new file mode 100644 index 00000000..660385ec --- /dev/null +++ b/drivers/rz/ipl/rza/lib/compiler-rt/builtins/int_types.h @@ -0,0 +1,166 @@ +/* ===-- int_lib.h - configuration header for compiler-rt -----------------=== + * + * The LLVM Compiler Infrastructure + * + * This file is dual licensed under the MIT and the University of Illinois Open + * Source Licenses. See LICENSE.TXT for details. + * + * ===----------------------------------------------------------------------=== + * + * This file is not part of the interface of this library. + * + * This file defines various standard types, most importantly a number of unions + * used to access parts of larger types. + * + * ===----------------------------------------------------------------------=== + */ + +#ifndef INT_TYPES_H +#define INT_TYPES_H + +#include "int_endianness.h" + +/* si_int is defined in Linux sysroot's asm-generic/siginfo.h */ +#ifdef si_int +#undef si_int +#endif +typedef int si_int; +typedef unsigned su_int; + +typedef long long di_int; +typedef unsigned long long du_int; + +typedef union +{ + di_int all; + struct + { +#if _YUGA_LITTLE_ENDIAN + su_int low; + si_int high; +#else + si_int high; + su_int low; +#endif /* _YUGA_LITTLE_ENDIAN */ + }s; +} dwords; + +typedef union +{ + du_int all; + struct + { +#if _YUGA_LITTLE_ENDIAN + su_int low; + su_int high; +#else + su_int high; + su_int low; +#endif /* _YUGA_LITTLE_ENDIAN */ + }s; +} udwords; + +/* MIPS64 issue: PR 20098 */ +#if (defined(__LP64__) || defined(__wasm__)) && \ + !(defined(__mips__) && defined(__clang__)) +#define CRT_HAS_128BIT +#endif + +#ifdef CRT_HAS_128BIT +typedef int ti_int __attribute__ ((mode (TI))); +typedef unsigned tu_int __attribute__ ((mode (TI))); + +typedef union +{ + ti_int all; + struct + { +#if _YUGA_LITTLE_ENDIAN + du_int low; + di_int high; +#else + di_int high; + du_int low; +#endif /* _YUGA_LITTLE_ENDIAN */ + }s; +} twords; + +typedef union +{ + tu_int all; + struct + { +#if _YUGA_LITTLE_ENDIAN + du_int low; + du_int high; +#else + du_int high; + du_int low; +#endif /* _YUGA_LITTLE_ENDIAN */ + }s; +} utwords; + +static __inline ti_int make_ti(di_int h, di_int l) { + twords r; + r.s.high = h; + r.s.low = l; + return r.all; +} + +static __inline tu_int make_tu(du_int h, du_int l) { + utwords r; + r.s.high = h; + r.s.low = l; + return r.all; +} + +#endif /* CRT_HAS_128BIT */ + +typedef union +{ + su_int u; + float f; +} float_bits; + +typedef union +{ + udwords u; + double f; +} double_bits; + +typedef struct +{ +#if _YUGA_LITTLE_ENDIAN + udwords low; + udwords high; +#else + udwords high; + udwords low; +#endif /* _YUGA_LITTLE_ENDIAN */ +} uqwords; + +typedef union +{ + uqwords u; + long double f; +} long_double_bits; + +#if __STDC_VERSION__ >= 199901L +typedef float _Complex Fcomplex; +typedef double _Complex Dcomplex; +typedef long double _Complex Lcomplex; + +#define COMPLEX_REAL(x) __real__(x) +#define COMPLEX_IMAGINARY(x) __imag__(x) +#else +typedef struct { float real, imaginary; } Fcomplex; + +typedef struct { double real, imaginary; } Dcomplex; + +typedef struct { long double real, imaginary; } Lcomplex; + +#define COMPLEX_REAL(x) (x).real +#define COMPLEX_IMAGINARY(x) (x).imaginary +#endif +#endif /* INT_TYPES_H */ + diff --git a/drivers/rz/ipl/rza/lib/compiler-rt/builtins/lshrdi3.c b/drivers/rz/ipl/rza/lib/compiler-rt/builtins/lshrdi3.c new file mode 100644 index 00000000..67b2a766 --- /dev/null +++ b/drivers/rz/ipl/rza/lib/compiler-rt/builtins/lshrdi3.c @@ -0,0 +1,45 @@ +/* ===-- lshrdi3.c - Implement __lshrdi3 -----------------------------------=== + * + * The LLVM Compiler Infrastructure + * + * This file is dual licensed under the MIT and the University of Illinois Open + * Source Licenses. See LICENSE.TXT for details. + * + * ===----------------------------------------------------------------------=== + * + * This file implements __lshrdi3 for the compiler_rt library. + * + * ===----------------------------------------------------------------------=== + */ + +#include "int_lib.h" + +/* Returns: logical a >> b */ + +/* Precondition: 0 <= b < bits_in_dword */ + +COMPILER_RT_ABI di_int +__lshrdi3(di_int a, si_int b) +{ + const int bits_in_word = (int)(sizeof(si_int) * CHAR_BIT); + udwords input; + udwords result; + input.all = a; + if (b & bits_in_word) /* bits_in_word <= b < bits_in_dword */ + { + result.s.high = 0; + result.s.low = input.s.high >> (b - bits_in_word); + } + else /* 0 <= b < bits_in_word */ + { + if (b == 0) + return a; + result.s.high = input.s.high >> b; + result.s.low = (input.s.high << (bits_in_word - b)) | (input.s.low >> b); + } + return result.all; +} + +#if defined(__ARM_EABI__) +AEABI_RTABI di_int __aeabi_llsr(di_int a, si_int b) COMPILER_RT_ALIAS(__lshrdi3); +#endif diff --git a/drivers/rz/ipl/rza/lib/compiler-rt/builtins/popcountdi2.c b/drivers/rz/ipl/rza/lib/compiler-rt/builtins/popcountdi2.c new file mode 100644 index 00000000..5e8a62f0 --- /dev/null +++ b/drivers/rz/ipl/rza/lib/compiler-rt/builtins/popcountdi2.c @@ -0,0 +1,36 @@ +/* ===-- popcountdi2.c - Implement __popcountdi2 ----------------------------=== + * + * The LLVM Compiler Infrastructure + * + * This file is dual licensed under the MIT and the University of Illinois Open + * Source Licenses. See LICENSE.TXT for details. + * + * ===----------------------------------------------------------------------=== + * + * This file implements __popcountdi2 for the compiler_rt library. + * + * ===----------------------------------------------------------------------=== + */ + +#include "int_lib.h" + +/* Returns: count of 1 bits */ + +COMPILER_RT_ABI si_int +__popcountdi2(di_int a) +{ + du_int x2 = (du_int)a; + x2 = x2 - ((x2 >> 1) & 0x5555555555555555uLL); + /* Every 2 bits holds the sum of every pair of bits (32) */ + x2 = ((x2 >> 2) & 0x3333333333333333uLL) + (x2 & 0x3333333333333333uLL); + /* Every 4 bits holds the sum of every 4-set of bits (3 significant bits) (16) */ + x2 = (x2 + (x2 >> 4)) & 0x0F0F0F0F0F0F0F0FuLL; + /* Every 8 bits holds the sum of every 8-set of bits (4 significant bits) (8) */ + su_int x = (su_int)(x2 + (x2 >> 32)); + /* The lower 32 bits hold four 16 bit sums (5 significant bits). */ + /* Upper 32 bits are garbage */ + x = x + (x >> 16); + /* The lower 16 bits hold two 32 bit sums (6 significant bits). */ + /* Upper 16 bits are garbage */ + return (x + (x >> 8)) & 0x0000007F; /* (7 significant bits) */ +} diff --git a/drivers/rz/ipl/rza/lib/compiler-rt/builtins/popcountsi2.c b/drivers/rz/ipl/rza/lib/compiler-rt/builtins/popcountsi2.c new file mode 100644 index 00000000..44544ff4 --- /dev/null +++ b/drivers/rz/ipl/rza/lib/compiler-rt/builtins/popcountsi2.c @@ -0,0 +1,33 @@ +/* ===-- popcountsi2.c - Implement __popcountsi2 ---------------------------=== + * + * The LLVM Compiler Infrastructure + * + * This file is dual licensed under the MIT and the University of Illinois Open + * Source Licenses. See LICENSE.TXT for details. + * + * ===----------------------------------------------------------------------=== + * + * This file implements __popcountsi2 for the compiler_rt library. + * + * ===----------------------------------------------------------------------=== + */ + +#include "int_lib.h" + +/* Returns: count of 1 bits */ + +COMPILER_RT_ABI si_int +__popcountsi2(si_int a) +{ + su_int x = (su_int)a; + x = x - ((x >> 1) & 0x55555555); + /* Every 2 bits holds the sum of every pair of bits */ + x = ((x >> 2) & 0x33333333) + (x & 0x33333333); + /* Every 4 bits holds the sum of every 4-set of bits (3 significant bits) */ + x = (x + (x >> 4)) & 0x0F0F0F0F; + /* Every 8 bits holds the sum of every 8-set of bits (4 significant bits) */ + x = (x + (x >> 16)); + /* The lower 16 bits hold two 8 bit sums (5 significant bits).*/ + /* Upper 16 bits are garbage */ + return (x + (x >> 8)) & 0x0000003F; /* (6 significant bits) */ +} diff --git a/drivers/rz/ipl/rza/lib/compiler-rt/builtins/udivmoddi4.c b/drivers/rz/ipl/rza/lib/compiler-rt/builtins/udivmoddi4.c new file mode 100644 index 00000000..0c8b4ff4 --- /dev/null +++ b/drivers/rz/ipl/rza/lib/compiler-rt/builtins/udivmoddi4.c @@ -0,0 +1,231 @@ +/* ===-- udivmoddi4.c - Implement __udivmoddi4 -----------------------------=== + * + * The LLVM Compiler Infrastructure + * + * This file is dual licensed under the MIT and the University of Illinois Open + * Source Licenses. See LICENSE.TXT for details. + * + * ===----------------------------------------------------------------------=== + * + * This file implements __udivmoddi4 for the compiler_rt library. + * + * ===----------------------------------------------------------------------=== + */ + +#include "int_lib.h" + +/* Effects: if rem != 0, *rem = a % b + * Returns: a / b + */ + +/* Translated from Figure 3-40 of The PowerPC Compiler Writer's Guide */ + +COMPILER_RT_ABI du_int +__udivmoddi4(du_int a, du_int b, du_int* rem) +{ + const unsigned n_uword_bits = sizeof(su_int) * CHAR_BIT; + const unsigned n_udword_bits = sizeof(du_int) * CHAR_BIT; + udwords n; + n.all = a; + udwords d; + d.all = b; + udwords q; + udwords r; + unsigned sr; + /* special cases, X is unknown, K != 0 */ + if (n.s.high == 0) + { + if (d.s.high == 0) + { + /* 0 X + * --- + * 0 X + */ + if (rem) + *rem = n.s.low % d.s.low; + return n.s.low / d.s.low; + } + /* 0 X + * --- + * K X + */ + if (rem) + *rem = n.s.low; + return 0; + } + /* n.s.high != 0 */ + if (d.s.low == 0) + { + if (d.s.high == 0) + { + /* K X + * --- + * 0 0 + */ + if (rem) + *rem = n.s.high % d.s.low; + return n.s.high / d.s.low; + } + /* d.s.high != 0 */ + if (n.s.low == 0) + { + /* K 0 + * --- + * K 0 + */ + if (rem) + { + r.s.high = n.s.high % d.s.high; + r.s.low = 0; + *rem = r.all; + } + return n.s.high / d.s.high; + } + /* K K + * --- + * K 0 + */ + if ((d.s.high & (d.s.high - 1)) == 0) /* if d is a power of 2 */ + { + if (rem) + { + r.s.low = n.s.low; + r.s.high = n.s.high & (d.s.high - 1); + *rem = r.all; + } + return n.s.high >> __builtin_ctz(d.s.high); + } + /* K K + * --- + * K 0 + */ + sr = __builtin_clz(d.s.high) - __builtin_clz(n.s.high); + /* 0 <= sr <= n_uword_bits - 2 or sr large */ + if (sr > n_uword_bits - 2) + { + if (rem) + *rem = n.all; + return 0; + } + ++sr; + /* 1 <= sr <= n_uword_bits - 1 */ + /* q.all = n.all << (n_udword_bits - sr); */ + q.s.low = 0; + q.s.high = n.s.low << (n_uword_bits - sr); + /* r.all = n.all >> sr; */ + r.s.high = n.s.high >> sr; + r.s.low = (n.s.high << (n_uword_bits - sr)) | (n.s.low >> sr); + } + else /* d.s.low != 0 */ + { + if (d.s.high == 0) + { + /* K X + * --- + * 0 K + */ + if ((d.s.low & (d.s.low - 1)) == 0) /* if d is a power of 2 */ + { + if (rem) + *rem = n.s.low & (d.s.low - 1); + if (d.s.low == 1) + return n.all; + sr = __builtin_ctz(d.s.low); + q.s.high = n.s.high >> sr; + q.s.low = (n.s.high << (n_uword_bits - sr)) | (n.s.low >> sr); + return q.all; + } + /* K X + * --- + * 0 K + */ + sr = 1 + n_uword_bits + __builtin_clz(d.s.low) - __builtin_clz(n.s.high); + /* 2 <= sr <= n_udword_bits - 1 + * q.all = n.all << (n_udword_bits - sr); + * r.all = n.all >> sr; + */ + if (sr == n_uword_bits) + { + q.s.low = 0; + q.s.high = n.s.low; + r.s.high = 0; + r.s.low = n.s.high; + } + else if (sr < n_uword_bits) // 2 <= sr <= n_uword_bits - 1 + { + q.s.low = 0; + q.s.high = n.s.low << (n_uword_bits - sr); + r.s.high = n.s.high >> sr; + r.s.low = (n.s.high << (n_uword_bits - sr)) | (n.s.low >> sr); + } + else // n_uword_bits + 1 <= sr <= n_udword_bits - 1 + { + q.s.low = n.s.low << (n_udword_bits - sr); + q.s.high = (n.s.high << (n_udword_bits - sr)) | + (n.s.low >> (sr - n_uword_bits)); + r.s.high = 0; + r.s.low = n.s.high >> (sr - n_uword_bits); + } + } + else + { + /* K X + * --- + * K K + */ + sr = __builtin_clz(d.s.high) - __builtin_clz(n.s.high); + /* 0 <= sr <= n_uword_bits - 1 or sr large */ + if (sr > n_uword_bits - 1) + { + if (rem) + *rem = n.all; + return 0; + } + ++sr; + /* 1 <= sr <= n_uword_bits */ + /* q.all = n.all << (n_udword_bits - sr); */ + q.s.low = 0; + if (sr == n_uword_bits) + { + q.s.high = n.s.low; + r.s.high = 0; + r.s.low = n.s.high; + } + else + { + q.s.high = n.s.low << (n_uword_bits - sr); + r.s.high = n.s.high >> sr; + r.s.low = (n.s.high << (n_uword_bits - sr)) | (n.s.low >> sr); + } + } + } + /* Not a special case + * q and r are initialized with: + * q.all = n.all << (n_udword_bits - sr); + * r.all = n.all >> sr; + * 1 <= sr <= n_udword_bits - 1 + */ + su_int carry = 0; + for (; sr > 0; --sr) + { + /* r:q = ((r:q) << 1) | carry */ + r.s.high = (r.s.high << 1) | (r.s.low >> (n_uword_bits - 1)); + r.s.low = (r.s.low << 1) | (q.s.high >> (n_uword_bits - 1)); + q.s.high = (q.s.high << 1) | (q.s.low >> (n_uword_bits - 1)); + q.s.low = (q.s.low << 1) | carry; + /* carry = 0; + * if (r.all >= d.all) + * { + * r.all -= d.all; + * carry = 1; + * } + */ + const di_int s = (di_int)(d.all - r.all - 1) >> (n_udword_bits - 1); + carry = s & 1; + r.all -= d.all & s; + } + q.all = (q.all << 1) | carry; + if (rem) + *rem = r.all; + return q.all; +} diff --git a/drivers/rz/ipl/rza/lib/compiler-rt/compiler-rt.mk b/drivers/rz/ipl/rza/lib/compiler-rt/compiler-rt.mk new file mode 100644 index 00000000..40c669f9 --- /dev/null +++ b/drivers/rz/ipl/rza/lib/compiler-rt/compiler-rt.mk @@ -0,0 +1,42 @@ +# +# Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# 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. +# +# Neither the name of ARM 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. +# + +COMPILER_RT_SRCS := lib/compiler-rt/builtins/popcountdi2.c \ + lib/compiler-rt/builtins/popcountsi2.c + +ifeq (${ARCH},aarch32) +COMPILER_RT_SRCS += lib/compiler-rt/builtins/arm/aeabi_ldivmod.S \ + lib/compiler-rt/builtins/arm/aeabi_uldivmod.S \ + lib/compiler-rt/builtins/ctzdi2.c \ + lib/compiler-rt/builtins/divdi3.c \ + lib/compiler-rt/builtins/divmoddi4.c \ + lib/compiler-rt/builtins/lshrdi3.c \ + lib/compiler-rt/builtins/udivmoddi4.c +endif diff --git a/drivers/rz/ipl/rza/lib/cpus/aarch64/cortex_a55.S b/drivers/rz/ipl/rza/lib/cpus/aarch64/cortex_a55.S new file mode 100644 index 00000000..78383045 --- /dev/null +++ b/drivers/rz/ipl/rza/lib/cpus/aarch64/cortex_a55.S @@ -0,0 +1,351 @@ +/* + * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include + +/* Hardware handled coherency */ +#if HW_ASSISTED_COHERENCY == 0 +#error "Cortex-A55 must be compiled with HW_ASSISTED_COHERENCY enabled" +#endif + + /* -------------------------------------------------- + * Errata Workaround for Cortex A55 Errata #768277. + * This applies only to revision r0p0 of Cortex A55. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_a55_768277_wa + /* + * Compare x0 against revision r0p0 + */ + mov x17, x30 + bl check_errata_768277 + cbz x0, 1f + mrs x1, CORTEX_A55_CPUACTLR_EL1 + orr x1, x1, #CORTEX_A55_CPUACTLR_EL1_DISABLE_DUAL_ISSUE + msr CORTEX_A55_CPUACTLR_EL1, x1 + isb +1: + ret x17 +endfunc errata_a55_768277_wa + +func check_errata_768277 + mov x1, #0x00 + b cpu_rev_var_ls +endfunc check_errata_768277 + + /* ------------------------------------------------------------------ + * Errata Workaround for Cortex A55 Errata #778703. + * This applies only to revision r0p0 of Cortex A55 where L2 cache is + * not configured. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * ------------------------------------------------------------------ + */ +func errata_a55_778703_wa + /* + * Compare x0 against revision r0p0 and check that no private L2 cache + * is configured + */ + mov x17, x30 + bl check_errata_778703 + cbz x0, 1f + mrs x1, CORTEX_A55_CPUECTLR_EL1 + orr x1, x1, #CORTEX_A55_CPUECTLR_EL1_L1WSCTL + msr CORTEX_A55_CPUECTLR_EL1, x1 + mrs x1, CORTEX_A55_CPUACTLR_EL1 + orr x1, x1, #CORTEX_A55_CPUACTLR_EL1_DISABLE_WRITE_STREAMING + msr CORTEX_A55_CPUACTLR_EL1, x1 + isb +1: + ret x17 +endfunc errata_a55_778703_wa + +func check_errata_778703 + mov x16, x30 + mov x1, #0x00 + bl cpu_rev_var_ls + /* + * Check that no private L2 cache is configured + */ + mrs x1, CORTEX_A55_CLIDR_EL1 + and x1, x1, CORTEX_A55_CLIDR_EL1_CTYPE3 + cmp x1, #0 + mov x2, #ERRATA_NOT_APPLIES + csel x0, x0, x2, eq + ret x16 +endfunc check_errata_778703 + + /* -------------------------------------------------- + * Errata Workaround for Cortex A55 Errata #798797. + * This applies only to revision r0p0 of Cortex A55. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_a55_798797_wa + /* + * Compare x0 against revision r0p0 + */ + mov x17, x30 + bl check_errata_798797 + cbz x0, 1f + mrs x1, CORTEX_A55_CPUACTLR_EL1 + orr x1, x1, #CORTEX_A55_CPUACTLR_EL1_DISABLE_L1_PAGEWALKS + msr CORTEX_A55_CPUACTLR_EL1, x1 + isb +1: + ret x17 +endfunc errata_a55_798797_wa + +func check_errata_798797 + mov x1, #0x00 + b cpu_rev_var_ls +endfunc check_errata_798797 + + /* -------------------------------------------------------------------- + * Errata Workaround for Cortex A55 Errata #846532. + * This applies only to revisions <= r0p1 of Cortex A55. + * Disabling dual-issue has a small impact on performance. Disabling a + * power optimization feature is an alternate workaround with no impact + * on performance but with an increase in power consumption (see errata + * notice). + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------------------------- + */ +func errata_a55_846532_wa + /* + * Compare x0 against revision r0p1 + */ + mov x17, x30 + bl check_errata_846532 + cbz x0, 1f + mrs x1, CORTEX_A55_CPUACTLR_EL1 + orr x1, x1, #CORTEX_A55_CPUACTLR_EL1_DISABLE_DUAL_ISSUE + msr CORTEX_A55_CPUACTLR_EL1, x1 + isb +1: + ret x17 +endfunc errata_a55_846532_wa + +func check_errata_846532 + mov x1, #0x01 + b cpu_rev_var_ls +endfunc check_errata_846532 + + /* ----------------------------------------------------- + * Errata Workaround for Cortex A55 Errata #903758. + * This applies only to revisions <= r0p1 of Cortex A55. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * ----------------------------------------------------- + */ +func errata_a55_903758_wa + /* + * Compare x0 against revision r0p1 + */ + mov x17, x30 + bl check_errata_903758 + cbz x0, 1f + mrs x1, CORTEX_A55_CPUACTLR_EL1 + orr x1, x1, #CORTEX_A55_CPUACTLR_EL1_DISABLE_L1_PAGEWALKS + msr CORTEX_A55_CPUACTLR_EL1, x1 + isb +1: + ret x17 +endfunc errata_a55_903758_wa + +func check_errata_903758 + mov x1, #0x01 + b cpu_rev_var_ls +endfunc check_errata_903758 + + /* ----------------------------------------------------- + * Errata Workaround for Cortex A55 Errata #1221012. + * This applies only to revisions <= r1p0 of Cortex A55. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * ----------------------------------------------------- + */ +func errata_a55_1221012_wa + /* + * Compare x0 against revision r1p0 + */ + mov x17, x30 + bl check_errata_1221012 + cbz x0, 1f + mov x0, #0x0020 + movk x0, #0x0850, lsl #16 + msr CPUPOR_EL3, x0 + mov x0, #0x0000 + movk x0, #0x1FF0, lsl #16 + movk x0, #0x2, lsl #32 + msr CPUPMR_EL3, x0 + mov x0, #0x03fd + movk x0, #0x0110, lsl #16 + msr CPUPCR_EL3, x0 + mov x0, #0x1 + msr CPUPSELR_EL3, x0 + mov x0, #0x0040 + movk x0, #0x08D0, lsl #16 + msr CPUPOR_EL3, x0 + mov x0, #0x0040 + movk x0, #0x1FF0, lsl #16 + movk x0, #0x2, lsl #32 + msr CPUPMR_EL3, x0 + mov x0, #0x03fd + movk x0, #0x0110, lsl #16 + msr CPUPCR_EL3, x0 + isb +1: + ret x17 +endfunc errata_a55_1221012_wa + +func check_errata_1221012 + mov x1, #0x10 + b cpu_rev_var_ls +endfunc check_errata_1221012 + + /* -------------------------------------------------- + * Errata workaround for Cortex A55 Errata #1530923. + * This applies to all revisions of Cortex A55. + * -------------------------------------------------- + */ +func check_errata_1530923 +#if ERRATA_A55_1530923 + mov x0, #ERRATA_APPLIES +#else + mov x0, #ERRATA_MISSING +#endif + ret +endfunc check_errata_1530923 + +func cortex_a55_reset_func + mov x19, x30 + +#if ERRATA_DSU_798953 + bl errata_dsu_798953_wa +#endif + +#if ERRATA_DSU_936184 + bl errata_dsu_936184_wa +#endif + + bl cpu_get_rev_var + mov x18, x0 + +#if ERRATA_A55_768277 + mov x0, x18 + bl errata_a55_768277_wa +#endif + +#if ERRATA_A55_778703 + mov x0, x18 + bl errata_a55_778703_wa +#endif + +#if ERRATA_A55_798797 + mov x0, x18 + bl errata_a55_798797_wa +#endif + +#if ERRATA_A55_846532 + mov x0, x18 + bl errata_a55_846532_wa +#endif + +#if ERRATA_A55_903758 + mov x0, x18 + bl errata_a55_903758_wa +#endif + +#if ERRATA_A55_1221012 + mov x0, x18 + bl errata_a55_1221012_wa +#endif + + ret x19 +endfunc cortex_a55_reset_func + + /* --------------------------------------------- + * HW will do the cache maintenance while powering down + * --------------------------------------------- + */ +func cortex_a55_core_pwr_dwn + /* --------------------------------------------- + * Enable CPU power down bit in power control register + * --------------------------------------------- + */ + mrs x0, CORTEX_A55_CPUPWRCTLR_EL1 + orr x0, x0, #CORTEX_A55_CORE_PWRDN_EN_MASK + msr CORTEX_A55_CPUPWRCTLR_EL1, x0 + isb + ret +endfunc cortex_a55_core_pwr_dwn + +#if REPORT_ERRATA +/* + * Errata printing function for Cortex A55. Must follow AAPCS & can use stack. + */ +func cortex_a55_errata_report + stp x8, x30, [sp, #-16]! + bl cpu_get_rev_var + mov x8, x0 + + /* + * Report all errata. The revision variant information is at x8, where + * "report_errata" is expecting it and it doesn't corrupt it. + */ + report_errata ERRATA_DSU_798953, cortex_a55, dsu_798953 + report_errata ERRATA_DSU_936184, cortex_a55, dsu_936184 + report_errata ERRATA_A55_768277, cortex_a55, 768277 + report_errata ERRATA_A55_778703, cortex_a55, 778703 + report_errata ERRATA_A55_798797, cortex_a55, 798797 + report_errata ERRATA_A55_846532, cortex_a55, 846532 + report_errata ERRATA_A55_903758, cortex_a55, 903758 + report_errata ERRATA_A55_1221012, cortex_a55, 1221012 + report_errata ERRATA_A55_1530923, cortex_a55, 1530923 + + ldp x8, x30, [sp], #16 + ret +endfunc cortex_a55_errata_report +#endif + + /* --------------------------------------------- + * This function provides cortex_a55 specific + * register information for crash reporting. + * It needs to return with x6 pointing to + * a list of register names in ascii and + * x8 - x15 having values of registers to be + * reported. + * --------------------------------------------- + */ +.section .rodata.cortex_a55_regs, "aS" +cortex_a55_regs: /* The ascii list of register names to be reported */ + .asciz "cpuectlr_el1", "" + +func cortex_a55_cpu_reg_dump + adr x6, cortex_a55_regs + mrs x8, CORTEX_A55_CPUECTLR_EL1 + ret +endfunc cortex_a55_cpu_reg_dump + +declare_cpu_ops cortex_a55, CORTEX_A55_MIDR, \ + cortex_a55_reset_func, \ + cortex_a55_core_pwr_dwn diff --git a/drivers/rz/ipl/rza/lib/cpus/aarch64/cpu_helpers.S b/drivers/rz/ipl/rza/lib/cpus/aarch64/cpu_helpers.S new file mode 100644 index 00000000..730b09be --- /dev/null +++ b/drivers/rz/ipl/rza/lib/cpus/aarch64/cpu_helpers.S @@ -0,0 +1,418 @@ +/* + * Copyright (c) 2014-2020, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include + + /* Reset fn is needed in BL at reset vector */ +#if defined(IMAGE_BL1) || defined(IMAGE_BL31) || (defined(IMAGE_BL2) && BL2_AT_EL3) + /* + * The reset handler common to all platforms. After a matching + * cpu_ops structure entry is found, the correponding reset_handler + * in the cpu_ops is invoked. + * Clobbers: x0 - x19, x30 + */ + .globl reset_handler +func reset_handler + mov x19, x30 + + /* The plat_reset_handler can clobber x0 - x18, x30 */ + bl plat_reset_handler + + /* Get the matching cpu_ops pointer */ + bl get_cpu_ops_ptr +#if ENABLE_ASSERTIONS + cmp x0, #0 + ASM_ASSERT(ne) +#endif + + /* Get the cpu_ops reset handler */ + ldr x2, [x0, #CPU_RESET_FUNC] + mov x30, x19 + cbz x2, 1f + + /* The cpu_ops reset handler can clobber x0 - x19, x30 */ + br x2 +1: + ret +endfunc reset_handler + +#endif + +#ifdef IMAGE_BL31 /* The power down core and cluster is needed only in BL31 */ + /* + * void prepare_cpu_pwr_dwn(unsigned int power_level) + * + * Prepare CPU power down function for all platforms. The function takes + * a domain level to be powered down as its parameter. After the cpu_ops + * pointer is retrieved from cpu_data, the handler for requested power + * level is called. + */ + .globl prepare_cpu_pwr_dwn +func prepare_cpu_pwr_dwn + /* + * If the given power level exceeds CPU_MAX_PWR_DWN_OPS, we call the + * power down handler for the last power level + */ + mov_imm x2, (CPU_MAX_PWR_DWN_OPS - 1) + cmp x0, x2 + csel x2, x2, x0, hi + + mrs x1, tpidr_el3 + ldr x0, [x1, #CPU_DATA_CPU_OPS_PTR] +#if ENABLE_ASSERTIONS + cmp x0, #0 + ASM_ASSERT(ne) +#endif + + /* Get the appropriate power down handler */ + mov x1, #CPU_PWR_DWN_OPS + add x1, x1, x2, lsl #3 + ldr x1, [x0, x1] +#if ENABLE_ASSERTIONS + cmp x1, #0 + ASM_ASSERT(ne) +#endif + br x1 +endfunc prepare_cpu_pwr_dwn + + + /* + * Initializes the cpu_ops_ptr if not already initialized + * in cpu_data. This can be called without a runtime stack, but may + * only be called after the MMU is enabled. + * clobbers: x0 - x6, x10 + */ + .globl init_cpu_ops +func init_cpu_ops + mrs x6, tpidr_el3 + ldr x0, [x6, #CPU_DATA_CPU_OPS_PTR] + cbnz x0, 1f + mov x10, x30 + bl get_cpu_ops_ptr +#if ENABLE_ASSERTIONS + cmp x0, #0 + ASM_ASSERT(ne) +#endif + str x0, [x6, #CPU_DATA_CPU_OPS_PTR]! + mov x30, x10 +1: + ret +endfunc init_cpu_ops +#endif /* IMAGE_BL31 */ + +#if defined(IMAGE_BL31) && CRASH_REPORTING + /* + * The cpu specific registers which need to be reported in a crash + * are reported via cpu_ops cpu_reg_dump function. After a matching + * cpu_ops structure entry is found, the correponding cpu_reg_dump + * in the cpu_ops is invoked. + */ + .globl do_cpu_reg_dump +func do_cpu_reg_dump + mov x16, x30 + + /* Get the matching cpu_ops pointer */ + bl get_cpu_ops_ptr + cbz x0, 1f + + /* Get the cpu_ops cpu_reg_dump */ + ldr x2, [x0, #CPU_REG_DUMP] + cbz x2, 1f + blr x2 +1: + mov x30, x16 + ret +endfunc do_cpu_reg_dump +#endif + + /* + * The below function returns the cpu_ops structure matching the + * midr of the core. It reads the MIDR_EL1 and finds the matching + * entry in cpu_ops entries. Only the implementation and part number + * are used to match the entries. + * + * If cpu_ops for the MIDR_EL1 cannot be found and + * SUPPORT_UNKNOWN_MPID is enabled, it will try to look for a + * default cpu_ops with an MIDR value of 0. + * (Implementation number 0x0 should be reseverd for software use + * and therefore no clashes should happen with that default value). + * + * Return : + * x0 - The matching cpu_ops pointer on Success + * x0 - 0 on failure. + * Clobbers : x0 - x5 + */ + .globl get_cpu_ops_ptr +func get_cpu_ops_ptr + /* Read the MIDR_EL1 */ + mrs x2, midr_el1 + mov_imm x3, CPU_IMPL_PN_MASK + + /* Retain only the implementation and part number using mask */ + and w2, w2, w3 + + /* Get the cpu_ops end location */ + adr x5, (__CPU_OPS_END__ + CPU_MIDR) + + /* Initialize the return parameter */ + mov x0, #0 +1: + /* Get the cpu_ops start location */ + adr x4, (__CPU_OPS_START__ + CPU_MIDR) + +2: + /* Check if we have reached end of list */ + cmp x4, x5 + b.eq search_def_ptr + + /* load the midr from the cpu_ops */ + ldr x1, [x4], #CPU_OPS_SIZE + and w1, w1, w3 + + /* Check if midr matches to midr of this core */ + cmp w1, w2 + b.ne 2b + + /* Subtract the increment and offset to get the cpu-ops pointer */ + sub x0, x4, #(CPU_OPS_SIZE + CPU_MIDR) +#if ENABLE_ASSERTIONS + cmp x0, #0 + ASM_ASSERT(ne) +#endif +#ifdef SUPPORT_UNKNOWN_MPID + cbnz x2, exit_mpid_found + /* Mark the unsupported MPID flag */ + adrp x1, unsupported_mpid_flag + add x1, x1, :lo12:unsupported_mpid_flag + str w2, [x1] +exit_mpid_found: +#endif + ret + + /* + * Search again for a default pointer (MIDR = 0x0) + * or return error if already searched. + */ +search_def_ptr: +#ifdef SUPPORT_UNKNOWN_MPID + cbz x2, error_exit + mov x2, #0 + b 1b +error_exit: +#endif + ret +endfunc get_cpu_ops_ptr + +/* + * Extract CPU revision and variant, and combine them into a single numeric for + * easier comparison. + */ + .globl cpu_get_rev_var +func cpu_get_rev_var + mrs x1, midr_el1 + + /* + * Extract the variant[23:20] and revision[3:0] from MIDR, and pack them + * as variant[7:4] and revision[3:0] of x0. + * + * First extract x1[23:16] to x0[7:0] and zero fill the rest. Then + * extract x1[3:0] into x0[3:0] retaining other bits. + */ + ubfx x0, x1, #(MIDR_VAR_SHIFT - MIDR_REV_BITS), #(MIDR_REV_BITS + MIDR_VAR_BITS) + bfxil x0, x1, #MIDR_REV_SHIFT, #MIDR_REV_BITS + ret +endfunc cpu_get_rev_var + +/* + * Compare the CPU's revision-variant (x0) with a given value (x1), for errata + * application purposes. If the revision-variant is less than or same as a given + * value, indicates that errata applies; otherwise not. + * + * Shall clobber: x0-x3 + */ + .globl cpu_rev_var_ls +func cpu_rev_var_ls + mov x2, #ERRATA_APPLIES + mov x3, #ERRATA_NOT_APPLIES + cmp x0, x1 + csel x0, x2, x3, ls + ret +endfunc cpu_rev_var_ls + +/* + * Compare the CPU's revision-variant (x0) with a given value (x1), for errata + * application purposes. If the revision-variant is higher than or same as a + * given value, indicates that errata applies; otherwise not. + * + * Shall clobber: x0-x3 + */ + .globl cpu_rev_var_hs +func cpu_rev_var_hs + mov x2, #ERRATA_APPLIES + mov x3, #ERRATA_NOT_APPLIES + cmp x0, x1 + csel x0, x2, x3, hs + ret +endfunc cpu_rev_var_hs + +/* + * Compare the CPU's revision-variant (x0) with a given range (x1 - x2), for errata + * application purposes. If the revision-variant is between or includes the given + * values, this indicates that errata applies; otherwise not. + * + * Shall clobber: x0-x4 + */ + .globl cpu_rev_var_range +func cpu_rev_var_range + mov x3, #ERRATA_APPLIES + mov x4, #ERRATA_NOT_APPLIES + cmp x0, x1 + csel x1, x3, x4, hs + cbz x1, 1f + cmp x0, x2 + csel x1, x3, x4, ls +1: + mov x0, x1 + ret +endfunc cpu_rev_var_range + +#if REPORT_ERRATA +/* + * void print_errata_status(void); + * + * Function to print errata status for CPUs of its class. Must be called only: + * + * - with MMU and data caches are enabled; + * - after cpu_ops have been initialized in per-CPU data. + */ + .globl print_errata_status +func print_errata_status +#ifdef IMAGE_BL1 + /* + * BL1 doesn't have per-CPU data. So retrieve the CPU operations + * directly. + */ + stp xzr, x30, [sp, #-16]! + bl get_cpu_ops_ptr + ldp xzr, x30, [sp], #16 + ldr x1, [x0, #CPU_ERRATA_FUNC] + cbnz x1, .Lprint +#else + /* + * Retrieve pointer to cpu_ops from per-CPU data, and further, the + * errata printing function. If it's non-NULL, jump to the function in + * turn. + */ + mrs x0, tpidr_el3 +#if ENABLE_ASSERTIONS + cmp x0, #0 + ASM_ASSERT(ne) +#endif + ldr x1, [x0, #CPU_DATA_CPU_OPS_PTR] +#if ENABLE_ASSERTIONS + cmp x1, #0 + ASM_ASSERT(ne) +#endif + ldr x0, [x1, #CPU_ERRATA_FUNC] + cbz x0, .Lnoprint + + /* + * Printing errata status requires atomically testing the printed flag. + */ + stp x19, x30, [sp, #-16]! + mov x19, x0 + + /* + * Load pointers to errata lock and printed flag. Call + * errata_needs_reporting to check whether this CPU needs to report + * errata status pertaining to its class. + */ + ldr x0, [x1, #CPU_ERRATA_LOCK] + ldr x1, [x1, #CPU_ERRATA_PRINTED] + bl errata_needs_reporting + mov x1, x19 + ldp x19, x30, [sp], #16 + cbnz x0, .Lprint +#endif +.Lnoprint: + ret +.Lprint: + /* Jump to errata reporting function for this CPU */ + br x1 +endfunc print_errata_status +#endif + +/* + * int check_wa_cve_2017_5715(void); + * + * This function returns: + * - ERRATA_APPLIES when firmware mitigation is required. + * - ERRATA_NOT_APPLIES when firmware mitigation is _not_ required. + * - ERRATA_MISSING when firmware mitigation would be required but + * is not compiled in. + * + * NOTE: Must be called only after cpu_ops have been initialized + * in per-CPU data. + */ + .globl check_wa_cve_2017_5715 +func check_wa_cve_2017_5715 + mrs x0, tpidr_el3 +#if ENABLE_ASSERTIONS + cmp x0, #0 + ASM_ASSERT(ne) +#endif + ldr x0, [x0, #CPU_DATA_CPU_OPS_PTR] +#if ENABLE_ASSERTIONS + cmp x0, #0 + ASM_ASSERT(ne) +#endif + ldr x0, [x0, #CPU_EXTRA1_FUNC] + /* + * If the reserved function pointer is NULL, this CPU + * is unaffected by CVE-2017-5715 so bail out. + */ + cmp x0, #0 + beq 1f + br x0 +1: + mov x0, #ERRATA_NOT_APPLIES + ret +endfunc check_wa_cve_2017_5715 + +/* + * void *wa_cve_2018_3639_get_disable_ptr(void); + * + * Returns a function pointer which is used to disable mitigation + * for CVE-2018-3639. + * The function pointer is only returned on cores that employ + * dynamic mitigation. If the core uses static mitigation or is + * unaffected by CVE-2018-3639 this function returns NULL. + * + * NOTE: Must be called only after cpu_ops have been initialized + * in per-CPU data. + */ + .globl wa_cve_2018_3639_get_disable_ptr +func wa_cve_2018_3639_get_disable_ptr + mrs x0, tpidr_el3 +#if ENABLE_ASSERTIONS + cmp x0, #0 + ASM_ASSERT(ne) +#endif + ldr x0, [x0, #CPU_DATA_CPU_OPS_PTR] +#if ENABLE_ASSERTIONS + cmp x0, #0 + ASM_ASSERT(ne) +#endif + ldr x0, [x0, #CPU_EXTRA2_FUNC] + ret +endfunc wa_cve_2018_3639_get_disable_ptr diff --git a/drivers/rz/ipl/rza/lib/cpus/aarch64/dsu_helpers.S b/drivers/rz/ipl/rza/lib/cpus/aarch64/dsu_helpers.S new file mode 100644 index 00000000..da052d5c --- /dev/null +++ b/drivers/rz/ipl/rza/lib/cpus/aarch64/dsu_helpers.S @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + + /* ----------------------------------------------------------------------- + * DSU erratum 798953 check function + * Checks the DSU variant, revision and configuration to determine if + * the erratum applies. Erratum applies on all configurations of the + * DSU and if revision-variant is r0p0. + * + * The erratum was fixed in r0p1. + * + * This function is called from both assembly and C environment. So it + * follows AAPCS. + * + * Clobbers: x0-x3 + * ----------------------------------------------------------------------- + */ + .globl check_errata_dsu_798953 + .globl errata_dsu_798953_wa + +func check_errata_dsu_798953 + mov x2, #ERRATA_APPLIES + mov x3, #ERRATA_NOT_APPLIES + + /* Check if DSU is equal to r0p0 */ + mrs x1, CLUSTERIDR_EL1 + + /* DSU variant and revision bitfields in CLUSTERIDR are adjacent */ + ubfx x0, x1, #CLUSTERIDR_REV_SHIFT,\ + #(CLUSTERIDR_REV_BITS + CLUSTERIDR_VAR_BITS) + mov x1, #(0x0 << CLUSTERIDR_REV_SHIFT) + cmp x0, x1 + csel x0, x2, x3, EQ + ret +endfunc check_errata_dsu_798953 + + /* -------------------------------------------------- + * Errata Workaround for DSU erratum #798953. + * + * Can clobber only: x0-x17 + * -------------------------------------------------- + */ +func errata_dsu_798953_wa + mov x17, x30 + bl check_errata_dsu_798953 + cbz x0, 1f + + /* If erratum applies, disable high-level clock gating */ + mrs x0, CLUSTERACTLR_EL1 + orr x0, x0, #CLUSTERACTLR_EL1_DISABLE_CLOCK_GATING + msr CLUSTERACTLR_EL1, x0 + isb +1: + ret x17 +endfunc errata_dsu_798953_wa + + /* ----------------------------------------------------------------------- + * DSU erratum 936184 check function + * Checks the DSU variant, revision and configuration to determine if + * the erratum applies. Erratum applies if ACP interface is present + * in the DSU and revision-variant < r2p0. + * + * The erratum was fixed in r2p0. + * + * This function is called from both assembly and C environment. So it + * follows AAPCS. + * + * Clobbers: x0-x15 + * ----------------------------------------------------------------------- + */ + .globl check_errata_dsu_936184 + .globl errata_dsu_936184_wa + .weak is_scu_present_in_dsu + + /* -------------------------------------------------------------------- + * Default behaviour respresents SCU is always present with DSU. + * CPUs can override this definition if required. + * + * Can clobber only: x0-x14 + * -------------------------------------------------------------------- + */ +func is_scu_present_in_dsu + mov x0, #1 + ret +endfunc is_scu_present_in_dsu + +func check_errata_dsu_936184 + mov x15, x30 + bl is_scu_present_in_dsu + cmp x0, xzr + /* Default error status */ + mov x0, #ERRATA_NOT_APPLIES + + /* If SCU is not present, return without applying patch */ + b.eq 1f + + /* Erratum applies only if DSU has the ACP interface */ + mrs x1, CLUSTERCFR_EL1 + ubfx x1, x1, #CLUSTERCFR_ACP_SHIFT, #1 + cbz x1, 1f + + /* If ACP is present, check if DSU is older than r2p0 */ + mrs x1, CLUSTERIDR_EL1 + + /* DSU variant and revision bitfields in CLUSTERIDR are adjacent */ + ubfx x2, x1, #CLUSTERIDR_REV_SHIFT,\ + #(CLUSTERIDR_REV_BITS + CLUSTERIDR_VAR_BITS) + cmp x2, #(0x2 << CLUSTERIDR_VAR_SHIFT) + b.hs 1f + mov x0, #ERRATA_APPLIES +1: + ret x15 +endfunc check_errata_dsu_936184 + + /* -------------------------------------------------- + * Errata Workaround for DSU erratum #936184. + * + * Can clobber only: x0-x17 + * -------------------------------------------------- + */ +func errata_dsu_936184_wa + mov x17, x30 + bl check_errata_dsu_936184 + cbz x0, 1f + + /* If erratum applies, we set a mask to a DSU control register */ + mrs x0, CLUSTERACTLR_EL1 + ldr x1, =DSU_ERRATA_936184_MASK + orr x0, x0, x1 + msr CLUSTERACTLR_EL1, x0 + isb +1: + ret x17 +endfunc errata_dsu_936184_wa diff --git a/drivers/rz/ipl/rza/lib/cpus/cpu-ops.mk b/drivers/rz/ipl/rza/lib/cpus/cpu-ops.mk new file mode 100644 index 00000000..fb333467 --- /dev/null +++ b/drivers/rz/ipl/rza/lib/cpus/cpu-ops.mk @@ -0,0 +1,687 @@ +# +# Copyright (c) 2014-2021, ARM Limited and Contributors. All rights reserved. +# Copyright (c) 2020, NVIDIA Corporation. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# Cortex A57 specific optimisation to skip L1 cache flush when +# cluster is powered down. +SKIP_A57_L1_FLUSH_PWR_DWN ?=0 + +# Flag to disable the cache non-temporal hint. +# It is enabled by default. +A53_DISABLE_NON_TEMPORAL_HINT ?=1 + +# Flag to disable the cache non-temporal hint. +# It is enabled by default. +A57_DISABLE_NON_TEMPORAL_HINT ?=1 + +# Flag to enable higher performance non-cacheable load forwarding. +# It is disabled by default. +A57_ENABLE_NONCACHEABLE_LOAD_FWD ?= 0 + +WORKAROUND_CVE_2017_5715 ?=1 +WORKAROUND_CVE_2018_3639 ?=1 +DYNAMIC_WORKAROUND_CVE_2018_3639 ?=0 + +# Flags to indicate internal or external Last level cache +# By default internal +NEOVERSE_Nx_EXTERNAL_LLC ?=0 + +# Process A57_ENABLE_NONCACHEABLE_LOAD_FWD flag +$(eval $(call assert_boolean,A57_ENABLE_NONCACHEABLE_LOAD_FWD)) +$(eval $(call add_define,A57_ENABLE_NONCACHEABLE_LOAD_FWD)) + +# Process SKIP_A57_L1_FLUSH_PWR_DWN flag +$(eval $(call assert_boolean,SKIP_A57_L1_FLUSH_PWR_DWN)) +$(eval $(call add_define,SKIP_A57_L1_FLUSH_PWR_DWN)) + +# Process A53_DISABLE_NON_TEMPORAL_HINT flag +$(eval $(call assert_boolean,A53_DISABLE_NON_TEMPORAL_HINT)) +$(eval $(call add_define,A53_DISABLE_NON_TEMPORAL_HINT)) + +# Process A57_DISABLE_NON_TEMPORAL_HINT flag +$(eval $(call assert_boolean,A57_DISABLE_NON_TEMPORAL_HINT)) +$(eval $(call add_define,A57_DISABLE_NON_TEMPORAL_HINT)) + +# Process WORKAROUND_CVE_2017_5715 flag +$(eval $(call assert_boolean,WORKAROUND_CVE_2017_5715)) +$(eval $(call add_define,WORKAROUND_CVE_2017_5715)) + +# Process WORKAROUND_CVE_2018_3639 flag +$(eval $(call assert_boolean,WORKAROUND_CVE_2018_3639)) +$(eval $(call add_define,WORKAROUND_CVE_2018_3639)) + +$(eval $(call assert_boolean,DYNAMIC_WORKAROUND_CVE_2018_3639)) +$(eval $(call add_define,DYNAMIC_WORKAROUND_CVE_2018_3639)) + +$(eval $(call assert_boolean,NEOVERSE_Nx_EXTERNAL_LLC)) +$(eval $(call add_define,NEOVERSE_Nx_EXTERNAL_LLC)) + +ifneq (${DYNAMIC_WORKAROUND_CVE_2018_3639},0) + ifeq (${WORKAROUND_CVE_2018_3639},0) + $(error "Error: WORKAROUND_CVE_2018_3639 must be 1 if DYNAMIC_WORKAROUND_CVE_2018_3639 is 1") + endif +endif + +# CPU Errata Build flags. +# These should be enabled by the platform if the erratum workaround needs to be +# applied. + +# Flag to apply erratum 794073 workaround when disabling mmu. +ERRATA_A9_794073 ?=0 + +# Flag to apply erratum 816470 workaround during power down. This erratum +# applies only to revision >= r3p0 of the Cortex A15 cpu. +ERRATA_A15_816470 ?=0 + +# Flag to apply erratum 827671 workaround during reset. This erratum applies +# only to revision >= r3p0 of the Cortex A15 cpu. +ERRATA_A15_827671 ?=0 + +# Flag to apply erratum 852421 workaround during reset. This erratum applies +# only to revision <= r1p2 of the Cortex A17 cpu. +ERRATA_A17_852421 ?=0 + +# Flag to apply erratum 852423 workaround during reset. This erratum applies +# only to revision <= r1p2 of the Cortex A17 cpu. +ERRATA_A17_852423 ?=0 + +# Flag to apply erratum 855472 workaround during reset. This erratum applies +# only to revision r0p0 of the Cortex A35 cpu. +ERRATA_A35_855472 ?=0 + +# Flag to apply erratum 819472 workaround during reset. This erratum applies +# only to revision <= r0p1 of the Cortex A53 cpu. +ERRATA_A53_819472 ?=0 + +# Flag to apply erratum 824069 workaround during reset. This erratum applies +# only to revision <= r0p2 of the Cortex A53 cpu. +ERRATA_A53_824069 ?=0 + +# Flag to apply erratum 826319 workaround during reset. This erratum applies +# only to revision <= r0p2 of the Cortex A53 cpu. +ERRATA_A53_826319 ?=0 + +# Flag to apply erratum 827319 workaround during reset. This erratum applies +# only to revision <= r0p2 of the Cortex A53 cpu. +ERRATA_A53_827319 ?=0 + +# Flag to apply erratum 835769 workaround at compile and link time. This +# erratum applies to revision <= r0p4 of the Cortex A53 cpu. Enabling this +# workaround can lead the linker to create "*.stub" sections. +ERRATA_A53_835769 ?=0 + +# Flag to apply erratum 836870 workaround during reset. This erratum applies +# only to revision <= r0p3 of the Cortex A53 cpu. From r0p4 and onwards, this +# erratum workaround is enabled by default in hardware. +ERRATA_A53_836870 ?=0 + +# Flag to apply erratum 843419 workaround at link time. +# This erratum applies to revision <= r0p4 of the Cortex A53 cpu. Enabling this +# workaround could lead the linker to emit "*.stub" sections which are 4kB +# aligned. +ERRATA_A53_843419 ?=0 + +# Flag to apply errata 855873 during reset. This errata applies to all +# revisions of the Cortex A53 CPU, but this firmware workaround only works +# for revisions r0p3 and higher. Earlier revisions are taken care +# of by the rich OS. +ERRATA_A53_855873 ?=0 + +# Flag to apply erratum 1530924 workaround during reset. This erratum applies +# to all revisions of Cortex A53 cpu. +ERRATA_A53_1530924 ?=0 + +# Flag to apply erratum 768277 workaround during reset. This erratum applies +# only to revision r0p0 of the Cortex A55 cpu. +ERRATA_A55_768277 ?=0 + +# Flag to apply erratum 778703 workaround during reset. This erratum applies +# only to revision r0p0 of the Cortex A55 cpu. +ERRATA_A55_778703 ?=0 + +# Flag to apply erratum 798797 workaround during reset. This erratum applies +# only to revision r0p0 of the Cortex A55 cpu. +ERRATA_A55_798797 ?=0 + +# Flag to apply erratum 846532 workaround during reset. This erratum applies +# only to revision <= r0p1 of the Cortex A55 cpu. +ERRATA_A55_846532 ?=0 + +# Flag to apply erratum 903758 workaround during reset. This erratum applies +# only to revision <= r0p1 of the Cortex A55 cpu. +ERRATA_A55_903758 ?=0 + +# Flag to apply erratum 1221012 workaround during reset. This erratum applies +# only to revision <= r1p0 of the Cortex A55 cpu. +ERRATA_A55_1221012 ?=0 + +# Flag to apply erratum 1530923 workaround during reset. This erratum applies +# to all revisions of Cortex A55 cpu. +ERRATA_A55_1530923 ?=0 + +# Flag to apply erratum 806969 workaround during reset. This erratum applies +# only to revision r0p0 of the Cortex A57 cpu. +ERRATA_A57_806969 ?=0 + +# Flag to apply erratum 813419 workaround during reset. This erratum applies +# only to revision r0p0 of the Cortex A57 cpu. +ERRATA_A57_813419 ?=0 + +# Flag to apply erratum 813420 workaround during reset. This erratum applies +# only to revision r0p0 of the Cortex A57 cpu. +ERRATA_A57_813420 ?=0 + +# Flag to apply erratum 814670 workaround during reset. This erratum applies +# only to revision r0p0 of the Cortex A57 cpu. +ERRATA_A57_814670 ?=0 + +# Flag to apply erratum 817169 workaround during power down. This erratum +# applies only to revision <= r0p1 of the Cortex A57 cpu. +ERRATA_A57_817169 ?=0 + +# Flag to apply erratum 826974 workaround during reset. This erratum applies +# only to revision <= r1p1 of the Cortex A57 cpu. +ERRATA_A57_826974 ?=0 + +# Flag to apply erratum 826977 workaround during reset. This erratum applies +# only to revision <= r1p1 of the Cortex A57 cpu. +ERRATA_A57_826977 ?=0 + +# Flag to apply erratum 828024 workaround during reset. This erratum applies +# only to revision <= r1p1 of the Cortex A57 cpu. +ERRATA_A57_828024 ?=0 + +# Flag to apply erratum 829520 workaround during reset. This erratum applies +# only to revision <= r1p2 of the Cortex A57 cpu. +ERRATA_A57_829520 ?=0 + +# Flag to apply erratum 833471 workaround during reset. This erratum applies +# only to revision <= r1p2 of the Cortex A57 cpu. +ERRATA_A57_833471 ?=0 + +# Flag to apply erratum 855972 workaround during reset. This erratum applies +# only to revision <= r1p3 of the Cortex A57 cpu. +ERRATA_A57_859972 ?=0 + +# Flag to apply erratum 1319537 workaround during reset. This erratum applies +# to all revisions of Cortex A57 cpu. +ERRATA_A57_1319537 ?=0 + +# Flag to apply erratum 855971 workaround during reset. This erratum applies +# only to revision <= r0p3 of the Cortex A72 cpu. +ERRATA_A72_859971 ?=0 + +# Flag to apply erratum 1319367 workaround during reset. This erratum applies +# to all revisions of Cortex A72 cpu. +ERRATA_A72_1319367 ?=0 + +# Flag to apply erratum 852427 workaround during reset. This erratum applies +# only to revision r0p0 of the Cortex A73 cpu. +ERRATA_A73_852427 ?=0 + +# Flag to apply erratum 855423 workaround during reset. This erratum applies +# only to revision <= r0p1 of the Cortex A73 cpu. +ERRATA_A73_855423 ?=0 + +# Flag to apply erratum 764081 workaround during reset. This erratum applies +# only to revision <= r0p0 of the Cortex A75 cpu. +ERRATA_A75_764081 ?=0 + +# Flag to apply erratum 790748 workaround during reset. This erratum applies +# only to revision <= r0p0 of the Cortex A75 cpu. +ERRATA_A75_790748 ?=0 + +# Flag to apply erratum 1073348 workaround during reset. This erratum applies +# only to revision <= r1p0 of the Cortex A76 cpu. +ERRATA_A76_1073348 ?=0 + +# Flag to apply erratum 1130799 workaround during reset. This erratum applies +# only to revision <= r2p0 of the Cortex A76 cpu. +ERRATA_A76_1130799 ?=0 + +# Flag to apply erratum 1220197 workaround during reset. This erratum applies +# only to revision <= r2p0 of the Cortex A76 cpu. +ERRATA_A76_1220197 ?=0 + +# Flag to apply erratum 1257314 workaround during reset. This erratum applies +# only to revision <= r3p0 of the Cortex A76 cpu. +ERRATA_A76_1257314 ?=0 + +# Flag to apply erratum 1262606 workaround during reset. This erratum applies +# only to revision <= r3p0 of the Cortex A76 cpu. +ERRATA_A76_1262606 ?=0 + +# Flag to apply erratum 1262888 workaround during reset. This erratum applies +# only to revision <= r3p0 of the Cortex A76 cpu. +ERRATA_A76_1262888 ?=0 + +# Flag to apply erratum 1275112 workaround during reset. This erratum applies +# only to revision <= r3p0 of the Cortex A76 cpu. +ERRATA_A76_1275112 ?=0 + +# Flag to apply erratum 1286807 workaround during reset. This erratum applies +# only to revision <= r3p0 of the Cortex A76 cpu. +ERRATA_A76_1286807 ?=0 + +# Flag to apply erratum 1791580 workaround during reset. This erratum applies +# only to revision <= r4p0 of the Cortex A76 cpu. +ERRATA_A76_1791580 ?=0 + +# Flag to apply erratum 1165522 workaround during reset. This erratum applies +# to all revisions of Cortex A76 cpu. +ERRATA_A76_1165522 ?=0 + +# Flag to apply erratum 1868343 workaround during reset. This erratum applies +# only to revision <= r4p0 of the Cortex A76 cpu. +ERRATA_A76_1868343 ?=0 + +# Flag to apply erratum 1946160 workaround during reset. This erratum applies +# only to revisions r3p0 - r4p1 of the Cortex A76 cpu. +ERRATA_A76_1946160 ?=0 + +# Flag to apply erratum 1508412 workaround during reset. This erratum applies +# only to revision <= r1p0 of the Cortex A77 cpu. +ERRATA_A77_1508412 ?=0 + +# Flag to apply erratum 1925769 workaround during reset. This erratum applies +# only to revision <= r1p1 of the Cortex A77 cpu. +ERRATA_A77_1925769 ?=0 + +# Flag to apply erratum 1946167 workaround during reset. This erratum applies +# only to revision <= r1p1 of the Cortex A77 cpu. +ERRATA_A77_1946167 ?=0 + +# Flag to apply erratum 1688305 workaround during reset. This erratum applies +# to revisions r0p0 - r1p0 of the A78 cpu. +ERRATA_A78_1688305 ?=0 + +# Flag to apply erratum 1941498 workaround during reset. This erratum applies +# to revisions r0p0, r1p0, and r1p1 of the A78 cpu. +ERRATA_A78_1941498 ?=0 + +# Flag to apply erratum 1951500 workaround during reset. This erratum applies +# to revisions r1p0 and r1p1 of the A78 cpu. The issue is present in r0p0 as +# well but there is no workaround for that revision. +ERRATA_A78_1951500 ?=0 + +# Flag to apply T32 CLREX workaround during reset. This erratum applies +# only to r0p0 and r1p0 of the Neoverse N1 cpu. +ERRATA_N1_1043202 ?=0 + +# Flag to apply erratum 1073348 workaround during reset. This erratum applies +# only to revision r0p0 and r1p0 of the Neoverse N1 cpu. +ERRATA_N1_1073348 ?=0 + +# Flag to apply erratum 1130799 workaround during reset. This erratum applies +# only to revision <= r2p0 of the Neoverse N1 cpu. +ERRATA_N1_1130799 ?=0 + +# Flag to apply erratum 1165347 workaround during reset. This erratum applies +# only to revision <= r2p0 of the Neoverse N1 cpu. +ERRATA_N1_1165347 ?=0 + +# Flag to apply erratum 1207823 workaround during reset. This erratum applies +# only to revision <= r2p0 of the Neoverse N1 cpu. +ERRATA_N1_1207823 ?=0 + +# Flag to apply erratum 1220197 workaround during reset. This erratum applies +# only to revision <= r2p0 of the Neoverse N1 cpu. +ERRATA_N1_1220197 ?=0 + +# Flag to apply erratum 1257314 workaround during reset. This erratum applies +# only to revision <= r3p0 of the Neoverse N1 cpu. +ERRATA_N1_1257314 ?=0 + +# Flag to apply erratum 1262606 workaround during reset. This erratum applies +# only to revision <= r3p0 of the Neoverse N1 cpu. +ERRATA_N1_1262606 ?=0 + +# Flag to apply erratum 1262888 workaround during reset. This erratum applies +# only to revision <= r3p0 of the Neoverse N1 cpu. +ERRATA_N1_1262888 ?=0 + +# Flag to apply erratum 1275112 workaround during reset. This erratum applies +# only to revision <= r3p0 of the Neoverse N1 cpu. +ERRATA_N1_1275112 ?=0 + +# Flag to apply erratum 1315703 workaround during reset. This erratum applies +# to revisions before r3p1 of the Neoverse N1 cpu. +ERRATA_N1_1315703 ?=0 + +# Flag to apply erratum 1542419 workaround during reset. This erratum applies +# to revisions r3p0 - r4p0 of the Neoverse N1 cpu. +ERRATA_N1_1542419 ?=0 + +# Flag to apply erratum 1868343 workaround during reset. This erratum applies +# to revision <= r4p0 of the Neoverse N1 cpu. +ERRATA_N1_1868343 ?=0 + +# Flag to apply erratum 1946160 workaround during reset. This erratum applies +# to revisions r3p0, r3p1, r4p0, and r4p1 of the Neoverse N1 cpu. The issue +# exists in revisions r0p0, r1p0, and r2p0 as well but there is no workaround. +ERRATA_N1_1946160 ?=0 + +# Flag to apply DSU erratum 798953. This erratum applies to DSUs revision r0p0. +# Applying the workaround results in higher DSU power consumption on idle. +ERRATA_DSU_798953 ?=0 + +# Flag to apply DSU erratum 936184. This erratum applies to DSUs containing +# the ACP interface and revision < r2p0. Applying the workaround results in +# higher DSU power consumption on idle. +ERRATA_DSU_936184 ?=0 + +# Process ERRATA_A9_794073 flag +$(eval $(call assert_boolean,ERRATA_A9_794073)) +$(eval $(call add_define,ERRATA_A9_794073)) + +# Process ERRATA_A15_816470 flag +$(eval $(call assert_boolean,ERRATA_A15_816470)) +$(eval $(call add_define,ERRATA_A15_816470)) + +# Process ERRATA_A15_827671 flag +$(eval $(call assert_boolean,ERRATA_A15_827671)) +$(eval $(call add_define,ERRATA_A15_827671)) + +# Process ERRATA_A17_852421 flag +$(eval $(call assert_boolean,ERRATA_A17_852421)) +$(eval $(call add_define,ERRATA_A17_852421)) + +# Process ERRATA_A17_852423 flag +$(eval $(call assert_boolean,ERRATA_A17_852423)) +$(eval $(call add_define,ERRATA_A17_852423)) + +# Process ERRATA_A35_855472 flag +$(eval $(call assert_boolean,ERRATA_A35_855472)) +$(eval $(call add_define,ERRATA_A35_855472)) + +# Process ERRATA_A53_819472 flag +$(eval $(call assert_boolean,ERRATA_A53_819472)) +$(eval $(call add_define,ERRATA_A53_819472)) + +# Process ERRATA_A53_824069 flag +$(eval $(call assert_boolean,ERRATA_A53_824069)) +$(eval $(call add_define,ERRATA_A53_824069)) + +# Process ERRATA_A53_826319 flag +$(eval $(call assert_boolean,ERRATA_A53_826319)) +$(eval $(call add_define,ERRATA_A53_826319)) + +# Process ERRATA_A53_827319 flag +$(eval $(call assert_boolean,ERRATA_A53_827319)) +$(eval $(call add_define,ERRATA_A53_827319)) + +# Process ERRATA_A53_835769 flag +$(eval $(call assert_boolean,ERRATA_A53_835769)) +$(eval $(call add_define,ERRATA_A53_835769)) + +# Process ERRATA_A53_836870 flag +$(eval $(call assert_boolean,ERRATA_A53_836870)) +$(eval $(call add_define,ERRATA_A53_836870)) + +# Process ERRATA_A53_843419 flag +$(eval $(call assert_boolean,ERRATA_A53_843419)) +$(eval $(call add_define,ERRATA_A53_843419)) + +# Process ERRATA_A53_855873 flag +$(eval $(call assert_boolean,ERRATA_A53_855873)) +$(eval $(call add_define,ERRATA_A53_855873)) + +# Process ERRATA_A53_1530924 flag +$(eval $(call assert_boolean,ERRATA_A53_1530924)) +$(eval $(call add_define,ERRATA_A53_1530924)) + +# Process ERRATA_A55_768277 flag +$(eval $(call assert_boolean,ERRATA_A55_768277)) +$(eval $(call add_define,ERRATA_A55_768277)) + +# Process ERRATA_A55_778703 flag +$(eval $(call assert_boolean,ERRATA_A55_778703)) +$(eval $(call add_define,ERRATA_A55_778703)) + +# Process ERRATA_A55_798797 flag +$(eval $(call assert_boolean,ERRATA_A55_798797)) +$(eval $(call add_define,ERRATA_A55_798797)) + +# Process ERRATA_A55_846532 flag +$(eval $(call assert_boolean,ERRATA_A55_846532)) +$(eval $(call add_define,ERRATA_A55_846532)) + +# Process ERRATA_A55_903758 flag +$(eval $(call assert_boolean,ERRATA_A55_903758)) +$(eval $(call add_define,ERRATA_A55_903758)) + +# Process ERRATA_A55_1221012 flag +$(eval $(call assert_boolean,ERRATA_A55_1221012)) +$(eval $(call add_define,ERRATA_A55_1221012)) + +# Process ERRATA_A55_1530923 flag +$(eval $(call assert_boolean,ERRATA_A55_1530923)) +$(eval $(call add_define,ERRATA_A55_1530923)) + +# Process ERRATA_A57_806969 flag +$(eval $(call assert_boolean,ERRATA_A57_806969)) +$(eval $(call add_define,ERRATA_A57_806969)) + +# Process ERRATA_A57_813419 flag +$(eval $(call assert_boolean,ERRATA_A57_813419)) +$(eval $(call add_define,ERRATA_A57_813419)) + +# Process ERRATA_A57_813420 flag +$(eval $(call assert_boolean,ERRATA_A57_813420)) +$(eval $(call add_define,ERRATA_A57_813420)) + +# Process ERRATA_A57_814670 flag +$(eval $(call assert_boolean,ERRATA_A57_814670)) +$(eval $(call add_define,ERRATA_A57_814670)) + +# Process ERRATA_A57_817169 flag +$(eval $(call assert_boolean,ERRATA_A57_817169)) +$(eval $(call add_define,ERRATA_A57_817169)) + +# Process ERRATA_A57_826974 flag +$(eval $(call assert_boolean,ERRATA_A57_826974)) +$(eval $(call add_define,ERRATA_A57_826974)) + +# Process ERRATA_A57_826977 flag +$(eval $(call assert_boolean,ERRATA_A57_826977)) +$(eval $(call add_define,ERRATA_A57_826977)) + +# Process ERRATA_A57_828024 flag +$(eval $(call assert_boolean,ERRATA_A57_828024)) +$(eval $(call add_define,ERRATA_A57_828024)) + +# Process ERRATA_A57_829520 flag +$(eval $(call assert_boolean,ERRATA_A57_829520)) +$(eval $(call add_define,ERRATA_A57_829520)) + +# Process ERRATA_A57_833471 flag +$(eval $(call assert_boolean,ERRATA_A57_833471)) +$(eval $(call add_define,ERRATA_A57_833471)) + +# Process ERRATA_A57_859972 flag +$(eval $(call assert_boolean,ERRATA_A57_859972)) +$(eval $(call add_define,ERRATA_A57_859972)) + +# Process ERRATA_A57_1319537 flag +$(eval $(call assert_boolean,ERRATA_A57_1319537)) +$(eval $(call add_define,ERRATA_A57_1319537)) + +# Process ERRATA_A72_859971 flag +$(eval $(call assert_boolean,ERRATA_A72_859971)) +$(eval $(call add_define,ERRATA_A72_859971)) + +# Process ERRATA_A72_1319367 flag +$(eval $(call assert_boolean,ERRATA_A72_1319367)) +$(eval $(call add_define,ERRATA_A72_1319367)) + +# Process ERRATA_A73_852427 flag +$(eval $(call assert_boolean,ERRATA_A73_852427)) +$(eval $(call add_define,ERRATA_A73_852427)) + +# Process ERRATA_A73_855423 flag +$(eval $(call assert_boolean,ERRATA_A73_855423)) +$(eval $(call add_define,ERRATA_A73_855423)) + +# Process ERRATA_A75_764081 flag +$(eval $(call assert_boolean,ERRATA_A75_764081)) +$(eval $(call add_define,ERRATA_A75_764081)) + +# Process ERRATA_A75_790748 flag +$(eval $(call assert_boolean,ERRATA_A75_790748)) +$(eval $(call add_define,ERRATA_A75_790748)) + +# Process ERRATA_A76_1073348 flag +$(eval $(call assert_boolean,ERRATA_A76_1073348)) +$(eval $(call add_define,ERRATA_A76_1073348)) + +# Process ERRATA_A76_1130799 flag +$(eval $(call assert_boolean,ERRATA_A76_1130799)) +$(eval $(call add_define,ERRATA_A76_1130799)) + +# Process ERRATA_A76_1220197 flag +$(eval $(call assert_boolean,ERRATA_A76_1220197)) +$(eval $(call add_define,ERRATA_A76_1220197)) + +# Process ERRATA_A76_1257314 flag +$(eval $(call assert_boolean,ERRATA_A76_1257314)) +$(eval $(call add_define,ERRATA_A76_1257314)) + +# Process ERRATA_A76_1262606 flag +$(eval $(call assert_boolean,ERRATA_A76_1262606)) +$(eval $(call add_define,ERRATA_A76_1262606)) + +# Process ERRATA_A76_1262888 flag +$(eval $(call assert_boolean,ERRATA_A76_1262888)) +$(eval $(call add_define,ERRATA_A76_1262888)) + +# Process ERRATA_A76_1275112 flag +$(eval $(call assert_boolean,ERRATA_A76_1275112)) +$(eval $(call add_define,ERRATA_A76_1275112)) + +# Process ERRATA_A76_1286807 flag +$(eval $(call assert_boolean,ERRATA_A76_1286807)) +$(eval $(call add_define,ERRATA_A76_1286807)) + +# Process ERRATA_A76_1791580 flag +$(eval $(call assert_boolean,ERRATA_A76_1791580)) +$(eval $(call add_define,ERRATA_A76_1791580)) + +# Process ERRATA_A76_1165522 flag +$(eval $(call assert_boolean,ERRATA_A76_1165522)) +$(eval $(call add_define,ERRATA_A76_1165522)) + +# Process ERRATA_A76_1868343 flag +$(eval $(call assert_boolean,ERRATA_A76_1868343)) +$(eval $(call add_define,ERRATA_A76_1868343)) + +# Process ERRATA_A76_1946160 flag +$(eval $(call assert_boolean,ERRATA_A76_1946160)) +$(eval $(call add_define,ERRATA_A76_1946160)) + +# Process ERRATA_A77_1508412 flag +$(eval $(call assert_boolean,ERRATA_A77_1508412)) +$(eval $(call add_define,ERRATA_A77_1508412)) + +# Process ERRATA_A77_1925769 flag +$(eval $(call assert_boolean,ERRATA_A77_1925769)) +$(eval $(call add_define,ERRATA_A77_1925769)) + +# Process ERRATA_A77_1946167 flag +$(eval $(call assert_boolean,ERRATA_A77_1946167)) +$(eval $(call add_define,ERRATA_A77_1946167)) + +# Process ERRATA_A78_1688305 flag +$(eval $(call assert_boolean,ERRATA_A78_1688305)) +$(eval $(call add_define,ERRATA_A78_1688305)) + +# Process ERRATA_A78_1941498 flag +$(eval $(call assert_boolean,ERRATA_A78_1941498)) +$(eval $(call add_define,ERRATA_A78_1941498)) + +# Process ERRATA_A78_1951500 flag +$(eval $(call assert_boolean,ERRATA_A78_1951500)) +$(eval $(call add_define,ERRATA_A78_1951500)) + +# Process ERRATA_N1_1043202 flag +$(eval $(call assert_boolean,ERRATA_N1_1043202)) +$(eval $(call add_define,ERRATA_N1_1043202)) + +# Process ERRATA_N1_1073348 flag +$(eval $(call assert_boolean,ERRATA_N1_1073348)) +$(eval $(call add_define,ERRATA_N1_1073348)) + +# Process ERRATA_N1_1130799 flag +$(eval $(call assert_boolean,ERRATA_N1_1130799)) +$(eval $(call add_define,ERRATA_N1_1130799)) + +# Process ERRATA_N1_1165347 flag +$(eval $(call assert_boolean,ERRATA_N1_1165347)) +$(eval $(call add_define,ERRATA_N1_1165347)) + +# Process ERRATA_N1_1207823 flag +$(eval $(call assert_boolean,ERRATA_N1_1207823)) +$(eval $(call add_define,ERRATA_N1_1207823)) + +# Process ERRATA_N1_1220197 flag +$(eval $(call assert_boolean,ERRATA_N1_1220197)) +$(eval $(call add_define,ERRATA_N1_1220197)) + +# Process ERRATA_N1_1257314 flag +$(eval $(call assert_boolean,ERRATA_N1_1257314)) +$(eval $(call add_define,ERRATA_N1_1257314)) + +# Process ERRATA_N1_1262606 flag +$(eval $(call assert_boolean,ERRATA_N1_1262606)) +$(eval $(call add_define,ERRATA_N1_1262606)) + +# Process ERRATA_N1_1262888 flag +$(eval $(call assert_boolean,ERRATA_N1_1262888)) +$(eval $(call add_define,ERRATA_N1_1262888)) + +# Process ERRATA_N1_1275112 flag +$(eval $(call assert_boolean,ERRATA_N1_1275112)) +$(eval $(call add_define,ERRATA_N1_1275112)) + +# Process ERRATA_N1_1315703 flag +$(eval $(call assert_boolean,ERRATA_N1_1315703)) +$(eval $(call add_define,ERRATA_N1_1315703)) + +# Process ERRATA_N1_1542419 flag +$(eval $(call assert_boolean,ERRATA_N1_1542419)) +$(eval $(call add_define,ERRATA_N1_1542419)) + +# Process ERRATA_N1_1868343 flag +$(eval $(call assert_boolean,ERRATA_N1_1868343)) +$(eval $(call add_define,ERRATA_N1_1868343)) + +# Process ERRATA_N1_1946160 flag +$(eval $(call assert_boolean,ERRATA_N1_1946160)) +$(eval $(call add_define,ERRATA_N1_1946160)) + +# Process ERRATA_DSU_798953 flag +$(eval $(call assert_boolean,ERRATA_DSU_798953)) +$(eval $(call add_define,ERRATA_DSU_798953)) + +# Process ERRATA_DSU_936184 flag +$(eval $(call assert_boolean,ERRATA_DSU_936184)) +$(eval $(call add_define,ERRATA_DSU_936184)) + +# Errata build flags +ifneq (${ERRATA_A53_843419},0) +TF_LDFLAGS_aarch64 += --fix-cortex-a53-843419 +endif + +ifneq (${ERRATA_A53_835769},0) +TF_CFLAGS_aarch64 += -mfix-cortex-a53-835769 +TF_LDFLAGS_aarch64 += --fix-cortex-a53-835769 +endif + +ifneq ($(filter 1,${ERRATA_A53_1530924} ${ERRATA_A55_1530923} \ + ${ERRATA_A57_1319537} ${ERRATA_A72_1319367} ${ERRATA_A76_1165522}),) +ERRATA_SPECULATIVE_AT := 1 +else +ERRATA_SPECULATIVE_AT := 0 +endif diff --git a/drivers/rz/ipl/rza/lib/cpus/errata_report.c b/drivers/rz/ipl/rza/lib/cpus/errata_report.c new file mode 100644 index 00000000..5d1e3c5c --- /dev/null +++ b/drivers/rz/ipl/rza/lib/cpus/errata_report.c @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* Runtime firmware routines to report errata status for the current CPU. */ + +#include +#include + +#include +#include +#include +#include +#include + +#ifdef IMAGE_BL1 +# define BL_STRING "BL1" +#elif defined(__aarch64__) && defined(IMAGE_BL31) +# define BL_STRING "BL31" +#elif !defined(__arch64__) && defined(IMAGE_BL32) +# define BL_STRING "BL32" +#elif defined(IMAGE_BL2) && BL2_AT_EL3 +# define BL_STRING "BL2" +#else +# error This image should not be printing errata status +#endif + +/* Errata format: BL stage, CPU, errata ID, message */ +#define ERRATA_FORMAT "%s: %s: CPU workaround for %s was %s\n" + +/* + * Returns whether errata needs to be reported. Passed arguments are private to + * a CPU type. + */ +int errata_needs_reporting(spinlock_t *lock, uint32_t *reported) +{ + bool report_now; + + /* If already reported, return false. */ + if (*reported != 0U) + return 0; + + /* + * Acquire lock. Determine whether status needs reporting, and then mark + * report status to true. + */ + spin_lock(lock); + report_now = (*reported == 0U); + if (report_now) + *reported = 1; + spin_unlock(lock); + + return report_now; +} + +/* + * Print errata status message. + * + * Unknown: WARN + * Missing: WARN + * Applied: INFO + * Not applied: VERBOSE + */ +void errata_print_msg(unsigned int status, const char *cpu, const char *id) +{ + /* Errata status strings */ + static const char *const errata_status_str[] = { + [ERRATA_NOT_APPLIES] = "not applied", + [ERRATA_APPLIES] = "applied", + [ERRATA_MISSING] = "missing!" + }; + static const char *const __unused bl_str = BL_STRING; + const char *msg __unused; + + + assert(status < ARRAY_SIZE(errata_status_str)); + assert(cpu != NULL); + assert(id != NULL); + + msg = errata_status_str[status]; + + switch (status) { + case ERRATA_NOT_APPLIES: + VERBOSE(ERRATA_FORMAT, bl_str, cpu, id, msg); + break; + + case ERRATA_APPLIES: + INFO(ERRATA_FORMAT, bl_str, cpu, id, msg); + break; + + case ERRATA_MISSING: + WARN(ERRATA_FORMAT, bl_str, cpu, id, msg); + break; + + default: + WARN(ERRATA_FORMAT, bl_str, cpu, id, "unknown"); + break; + } +} diff --git a/drivers/rz/ipl/rza/lib/libc/aarch64/memset.S b/drivers/rz/ipl/rza/lib/libc/aarch64/memset.S new file mode 100644 index 00000000..05437041 --- /dev/null +++ b/drivers/rz/ipl/rza/lib/libc/aarch64/memset.S @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + + .global memset + +/* ----------------------------------------------------------------------- + * void *memset(void *dst, int val, size_t count) + * + * Copy the value of 'val' (converted to an unsigned char) into + * each of the first 'count' characters of the object pointed to by 'dst'. + * + * Returns the value of 'dst'. + * ----------------------------------------------------------------------- + */ +func memset + cbz x2, exit /* exit if 'count' = 0 */ + mov x3, x0 /* keep x0 */ + tst x0, #7 + b.eq aligned /* 8-bytes aligned */ + + /* Unaligned 'dst' */ +unaligned: + strb w1, [x3], #1 + subs x2, x2, #1 + b.eq exit /* exit if 0 */ + tst x3, #7 + b.ne unaligned /* continue while unaligned */ + + /* 8-bytes aligned */ +aligned:cbz x1, x1_zero + bfi w1, w1, #8, #8 /* propagate 'val' */ + bfi w1, w1, #16, #16 + bfi x1, x1, #32, #32 + +x1_zero:ands x4, x2, #~0x3f + b.eq less_64 + +write_64: + .rept 4 + stp x1, x1, [x3], #16 /* write 64 bytes in a loop */ + .endr + subs x4, x4, #64 + b.ne write_64 +less_64:tbz w2, #5, less_32 /* < 32 bytes */ + stp x1, x1, [x3], #16 /* write 32 bytes */ + stp x1, x1, [x3], #16 +less_32:tbz w2, #4, less_16 /* < 16 bytes */ + stp x1, x1, [x3], #16 /* write 16 bytes */ +less_16:tbz w2, #3, less_8 /* < 8 bytes */ + str x1, [x3], #8 /* write 8 bytes */ +less_8: tbz w2, #2, less_4 /* < 4 bytes */ + str w1, [x3], #4 /* write 4 bytes */ +less_4: tbz w2, #1, less_2 /* < 2 bytes */ + strh w1, [x3], #2 /* write 2 bytes */ +less_2: tbz w2, #0, exit + strb w1, [x3] /* write 1 byte */ +exit: ret + +endfunc memset diff --git a/drivers/rz/ipl/rza/lib/libc/aarch64/setjmp.S b/drivers/rz/ipl/rza/lib/libc/aarch64/setjmp.S new file mode 100644 index 00000000..9d9eb49b --- /dev/null +++ b/drivers/rz/ipl/rza/lib/libc/aarch64/setjmp.S @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + + .globl setjmp + .globl longjmp + +/* + * int setjmp(jmp_buf env); + */ +func setjmp + mov x7, sp + + stp x19, x20, [x0, #JMP_CTX_X19] + stp x21, x22, [x0, #JMP_CTX_X21] + stp x23, x24, [x0, #JMP_CTX_X23] + stp x25, x26, [x0, #JMP_CTX_X25] + stp x27, x28, [x0, #JMP_CTX_X27] + stp x29, x30, [x0, #JMP_CTX_X29] + stp x7, xzr, [x0, #JMP_CTX_SP] + + mov x0, #0 + ret +endfunc setjmp + + +/* + * void longjmp(jmp_buf env, int val); + */ +func longjmp + ldp x7, xzr, [x0, #JMP_CTX_SP] + +#if ENABLE_ASSERTIONS + /* + * Since we're unwinding the stack, assert that the stack being reset to + * is shallower. + */ + mov x19, sp + cmp x7, x19 + ASM_ASSERT(ge) +#endif + + ldp x19, x20, [x0, #JMP_CTX_X19] + ldp x21, x22, [x0, #JMP_CTX_X21] + ldp x23, x24, [x0, #JMP_CTX_X23] + ldp x25, x26, [x0, #JMP_CTX_X25] + ldp x27, x28, [x0, #JMP_CTX_X27] + ldp x29, x30, [x0, #JMP_CTX_X29] + + mov sp, x7 + + ands x0, x1, x1 /* Move val to x0 and set flags */ + cinc x0, x0, eq /* If val is 0, return 1 */ + ret +endfunc longjmp diff --git a/drivers/rz/ipl/rza/lib/libc/abort.c b/drivers/rz/ipl/rza/lib/libc/abort.c new file mode 100644 index 00000000..432b1d07 --- /dev/null +++ b/drivers/rz/ipl/rza/lib/libc/abort.c @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +void abort(void) +{ + ERROR("ABORT\n"); + panic(); +} diff --git a/drivers/rz/ipl/rza/lib/libc/assert.c b/drivers/rz/ipl/rza/lib/libc/assert.c new file mode 100644 index 00000000..ff987b3b --- /dev/null +++ b/drivers/rz/ipl/rza/lib/libc/assert.c @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include + +/* + * Only print the output if PLAT_LOG_LEVEL_ASSERT is higher or equal to + * LOG_LEVEL_INFO, which is the default value for builds with DEBUG=1. + */ + +#if PLAT_LOG_LEVEL_ASSERT >= LOG_LEVEL_VERBOSE +void __dead2 __assert(const char *file, unsigned int line, + const char *assertion) +{ + printf("ASSERT: %s:%d:%s\n", file, line, assertion); + backtrace("assert"); + console_flush(); + plat_panic_handler(); +} +#elif PLAT_LOG_LEVEL_ASSERT >= LOG_LEVEL_INFO +void __dead2 __assert(const char *file, unsigned int line) +{ + printf("ASSERT: %s:%d\n", file, line); + backtrace("assert"); + console_flush(); + plat_panic_handler(); +} +#else +void __dead2 __assert(void) +{ + backtrace("assert"); + console_flush(); + plat_panic_handler(); +} +#endif diff --git a/drivers/rz/ipl/rza/lib/libc/exit.c b/drivers/rz/ipl/rza/lib/libc/exit.c new file mode 100644 index 00000000..f4ffe27c --- /dev/null +++ b/drivers/rz/ipl/rza/lib/libc/exit.c @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +static void (*exitfun)(void); + +void exit(int status) +{ + if (exitfun != NULL) + (*exitfun)(); + for (;;) + ; +} + +int atexit(void (*fun)(void)) +{ + if (exitfun != NULL) + return -1; + exitfun = fun; + + return 0; +} diff --git a/drivers/rz/ipl/rza/lib/libc/libc.mk b/drivers/rz/ipl/rza/lib/libc/libc.mk new file mode 100644 index 00000000..b75d09c2 --- /dev/null +++ b/drivers/rz/ipl/rza/lib/libc/libc.mk @@ -0,0 +1,41 @@ +# +# Copyright (c) 2016-2021, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +LIBC_SRCS := $(addprefix lib/libc/, \ + abort.c \ + assert.c \ + exit.c \ + memchr.c \ + memcmp.c \ + memcpy.c \ + memmove.c \ + memrchr.c \ + memset.c \ + printf.c \ + putchar.c \ + puts.c \ + snprintf.c \ + strchr.c \ + strcmp.c \ + strlcat.c \ + strlcpy.c \ + strlen.c \ + strncmp.c \ + strnlen.c \ + strrchr.c \ + strtok.c \ + strtoul.c \ + strtoll.c \ + strtoull.c \ + strtol.c) + +ifeq (${ARCH},aarch64) +LIBC_SRCS += $(addprefix lib/libc/aarch64/, \ + setjmp.S) +endif + +INCLUDES += -Iinclude/lib/libc \ + -Iinclude/lib/libc/$(ARCH) \ diff --git a/drivers/rz/ipl/rza/lib/libc/libc_asm.mk b/drivers/rz/ipl/rza/lib/libc/libc_asm.mk new file mode 100644 index 00000000..2f272651 --- /dev/null +++ b/drivers/rz/ipl/rza/lib/libc/libc_asm.mk @@ -0,0 +1,44 @@ +# +# Copyright (c) 2020-2021, Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +LIBC_SRCS := $(addprefix lib/libc/, \ + abort.c \ + assert.c \ + exit.c \ + memchr.c \ + memcmp.c \ + memcpy.c \ + memmove.c \ + memrchr.c \ + printf.c \ + putchar.c \ + puts.c \ + snprintf.c \ + strchr.c \ + strcmp.c \ + strlcat.c \ + strlcpy.c \ + strlen.c \ + strncmp.c \ + strnlen.c \ + strrchr.c \ + strtok.c \ + strtoul.c \ + strtoll.c \ + strtoull.c \ + strtol.c) + +ifeq (${ARCH},aarch64) +LIBC_SRCS += $(addprefix lib/libc/aarch64/, \ + memset.S \ + setjmp.S) +else +LIBC_SRCS += $(addprefix lib/libc/aarch32/, \ + memset.S) +endif + +INCLUDES += -Iinclude/lib/libc \ + -Iinclude/lib/libc/$(ARCH) \ diff --git a/drivers/rz/ipl/rza/lib/libc/memchr.c b/drivers/rz/ipl/rza/lib/libc/memchr.c new file mode 100644 index 00000000..8cbb7157 --- /dev/null +++ b/drivers/rz/ipl/rza/lib/libc/memchr.c @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +void *memchr(const void *src, int c, size_t len) +{ + const unsigned char *s = src; + + while (len--) { + if (*s == (unsigned char)c) + return (void *) s; + s++; + } + + return NULL; +} diff --git a/drivers/rz/ipl/rza/lib/libc/memcmp.c b/drivers/rz/ipl/rza/lib/libc/memcmp.c new file mode 100644 index 00000000..cd5f0df0 --- /dev/null +++ b/drivers/rz/ipl/rza/lib/libc/memcmp.c @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +int memcmp(const void *s1, const void *s2, size_t len) +{ + const unsigned char *s = s1; + const unsigned char *d = s2; + unsigned char sc; + unsigned char dc; + + while (len--) { + sc = *s++; + dc = *d++; + if (sc - dc) + return (sc - dc); + } + + return 0; +} diff --git a/drivers/rz/ipl/rza/lib/libc/memcpy.c b/drivers/rz/ipl/rza/lib/libc/memcpy.c new file mode 100644 index 00000000..158df9b7 --- /dev/null +++ b/drivers/rz/ipl/rza/lib/libc/memcpy.c @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +void *memcpy(void *dst, const void *src, size_t len) +{ + const char *s = src; + char *d = dst; + + while (len--) + *d++ = *s++; + + return dst; +} diff --git a/drivers/rz/ipl/rza/lib/libc/memmove.c b/drivers/rz/ipl/rza/lib/libc/memmove.c new file mode 100644 index 00000000..63acf267 --- /dev/null +++ b/drivers/rz/ipl/rza/lib/libc/memmove.c @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +void *memmove(void *dst, const void *src, size_t len) +{ + /* + * The following test makes use of unsigned arithmetic overflow to + * more efficiently test the condition !(src <= dst && dst < str+len). + * It also avoids the situation where the more explicit test would give + * incorrect results were the calculation str+len to overflow (though + * that issue is probably moot as such usage is probably undefined + * behaviour and a bug anyway. + */ + if ((size_t)dst - (size_t)src >= len) { + /* destination not in source data, so can safely use memcpy */ + return memcpy(dst, src, len); + } else { + /* copy backwards... */ + const char *end = dst; + const char *s = (const char *)src + len; + char *d = (char *)dst + len; + while (d != end) + *--d = *--s; + } + return dst; +} diff --git a/drivers/rz/ipl/rza/lib/libc/memrchr.c b/drivers/rz/ipl/rza/lib/libc/memrchr.c new file mode 100644 index 00000000..01caef3a --- /dev/null +++ b/drivers/rz/ipl/rza/lib/libc/memrchr.c @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#undef memrchr + +void *memrchr(const void *src, int c, size_t len) +{ + const unsigned char *s = src + (len - 1); + + while (len--) { + if (*s == (unsigned char)c) { + return (void*) s; + } + + s--; + } + + return NULL; +} diff --git a/drivers/rz/ipl/rza/lib/libc/memset.c b/drivers/rz/ipl/rza/lib/libc/memset.c new file mode 100644 index 00000000..17f798cb --- /dev/null +++ b/drivers/rz/ipl/rza/lib/libc/memset.c @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +void *memset(void *dst, int val, size_t count) +{ + uint8_t *ptr = dst; + uint64_t *ptr64; + uint64_t fill = (unsigned char)val; + + /* Simplify code below by making sure we write at least one byte. */ + if (count == 0U) { + return dst; + } + + /* Handle the first part, until the pointer becomes 64-bit aligned. */ + while (((uintptr_t)ptr & 7U) != 0U) { + *ptr = (uint8_t)val; + ptr++; + if (--count == 0U) { + return dst; + } + } + + /* Duplicate the fill byte to the rest of the 64-bit word. */ + fill |= fill << 8; + fill |= fill << 16; + fill |= fill << 32; + + /* Use 64-bit writes for as long as possible. */ + ptr64 = (uint64_t *)ptr; + for (; count >= 8U; count -= 8) { + *ptr64 = fill; + ptr64++; + } + + /* Handle the remaining part byte-per-byte. */ + ptr = (uint8_t *)ptr64; + while (count-- > 0U) { + *ptr = (uint8_t)val; + ptr++; + } + + return dst; +} diff --git a/drivers/rz/ipl/rza/lib/libc/printf.c b/drivers/rz/ipl/rza/lib/libc/printf.c new file mode 100644 index 00000000..45e153ec --- /dev/null +++ b/drivers/rz/ipl/rza/lib/libc/printf.c @@ -0,0 +1,200 @@ +/* + * Copyright (c) 2014-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +#include + +#define get_num_va_args(_args, _lcount) \ + (((_lcount) > 1) ? va_arg(_args, long long int) : \ + (((_lcount) == 1) ? va_arg(_args, long int) : \ + va_arg(_args, int))) + +#define get_unum_va_args(_args, _lcount) \ + (((_lcount) > 1) ? va_arg(_args, unsigned long long int) : \ + (((_lcount) == 1) ? va_arg(_args, unsigned long int) : \ + va_arg(_args, unsigned int))) + +static int string_print(const char *str) +{ + int count = 0; + + assert(str != NULL); + + for ( ; *str != '\0'; str++) { + (void)putchar(*str); + count++; + } + + return count; +} + +static int unsigned_num_print(unsigned long long int unum, unsigned int radix, + char padc, int padn) +{ + /* Just need enough space to store 64 bit decimal integer */ + char num_buf[20]; + int i = 0, count = 0; + unsigned int rem; + + do { + rem = unum % radix; + if (rem < 0xa) + num_buf[i] = '0' + rem; + else + num_buf[i] = 'a' + (rem - 0xa); + i++; + unum /= radix; + } while (unum > 0U); + + if (padn > 0) { + while (i < padn) { + (void)putchar(padc); + count++; + padn--; + } + } + + while (--i >= 0) { + (void)putchar(num_buf[i]); + count++; + } + + return count; +} + +/******************************************************************* + * Reduced format print for Trusted firmware. + * The following type specifiers are supported by this print + * %x - hexadecimal format + * %s - string format + * %d or %i - signed decimal format + * %u - unsigned decimal format + * %p - pointer format + * + * The following length specifiers are supported by this print + * %l - long int (64-bit on AArch64) + * %ll - long long int (64-bit on AArch64) + * %z - size_t sized integer formats (64 bit on AArch64) + * + * The following padding specifiers are supported by this print + * %0NN - Left-pad the number with 0s (NN is a decimal number) + * + * The print exits on all other formats specifiers other than valid + * combinations of the above specifiers. + *******************************************************************/ +int vprintf(const char *fmt, va_list args) +{ + int l_count; + long long int num; + unsigned long long int unum; + char *str; + char padc = '\0'; /* Padding character */ + int padn; /* Number of characters to pad */ + int count = 0; /* Number of printed characters */ + + while (*fmt != '\0') { + l_count = 0; + padn = 0; + + if (*fmt == '%') { + fmt++; + /* Check the format specifier */ +loop: + switch (*fmt) { + case '%': + (void)putchar('%'); + break; + case 'i': /* Fall through to next one */ + case 'd': + num = get_num_va_args(args, l_count); + if (num < 0) { + (void)putchar('-'); + unum = (unsigned long long int)-num; + padn--; + } else + unum = (unsigned long long int)num; + + count += unsigned_num_print(unum, 10, + padc, padn); + break; + case 's': + str = va_arg(args, char *); + count += string_print(str); + break; + case 'p': + unum = (uintptr_t)va_arg(args, void *); + if (unum > 0U) { + count += string_print("0x"); + padn -= 2; + } + + count += unsigned_num_print(unum, 16, + padc, padn); + break; + case 'x': + unum = get_unum_va_args(args, l_count); + count += unsigned_num_print(unum, 16, + padc, padn); + break; + case 'z': + if (sizeof(size_t) == 8U) + l_count = 2; + + fmt++; + goto loop; + case 'l': + l_count++; + fmt++; + goto loop; + case 'u': + unum = get_unum_va_args(args, l_count); + count += unsigned_num_print(unum, 10, + padc, padn); + break; + case '0': + padc = '0'; + padn = 0; + fmt++; + + for (;;) { + char ch = *fmt; + if ((ch < '0') || (ch > '9')) { + goto loop; + } + padn = (padn * 10) + (ch - '0'); + fmt++; + } + assert(0); /* Unreachable */ + default: + /* Exit on any other format specifier */ + return -1; + } + fmt++; + continue; + } + (void)putchar(*fmt); + fmt++; + count++; + } + + return count; +} + +int printf(const char *fmt, ...) +{ + int count; + va_list va; + + va_start(va, fmt); + count = vprintf(fmt, va); + va_end(va); + + return count; +} diff --git a/drivers/rz/ipl/rza/lib/libc/putchar.c b/drivers/rz/ipl/rza/lib/libc/putchar.c new file mode 100644 index 00000000..037e28ac --- /dev/null +++ b/drivers/rz/ipl/rza/lib/libc/putchar.c @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +int putchar(int c) +{ + int res; + if (console_putc((unsigned char)c) >= 0) + res = c; + else + res = EOF; + + return res; +} diff --git a/drivers/rz/ipl/rza/lib/libc/puts.c b/drivers/rz/ipl/rza/lib/libc/puts.c new file mode 100644 index 00000000..2a0ca11c --- /dev/null +++ b/drivers/rz/ipl/rza/lib/libc/puts.c @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +int puts(const char *s) +{ + int count = 0; + + while (*s != '\0') { + if (putchar(*s) == EOF) + return EOF; + s++; + count++; + } + + if (putchar('\n') == EOF) + return EOF; + + return count + 1; +} diff --git a/drivers/rz/ipl/rza/lib/libc/snprintf.c b/drivers/rz/ipl/rza/lib/libc/snprintf.c new file mode 100644 index 00000000..3b175ed6 --- /dev/null +++ b/drivers/rz/ipl/rza/lib/libc/snprintf.c @@ -0,0 +1,259 @@ +/* + * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include + +#define CHECK_AND_PUT_CHAR(buf, size, chars_printed, ch) \ + do { \ + if ((chars_printed) < (size)) { \ + *(buf) = (ch); \ + (buf)++; \ + } \ + (chars_printed)++; \ + } while (false) + +static void string_print(char **s, size_t n, size_t *chars_printed, + const char *str) +{ + while (*str != '\0') { + CHECK_AND_PUT_CHAR(*s, n, *chars_printed, *str); + str++; + } +} + +static void unsigned_num_print(char **s, size_t n, size_t *chars_printed, + unsigned long long int unum, + unsigned int radix, char padc, int padn, + bool capitalise) +{ + /* Just need enough space to store 64 bit decimal integer */ + char num_buf[20]; + int i = 0; + int width; + unsigned int rem; + char ascii_a = capitalise ? 'A' : 'a'; + + do { + rem = unum % radix; + if (rem < 10U) { + num_buf[i] = '0' + rem; + } else { + num_buf[i] = ascii_a + (rem - 10U); + } + i++; + unum /= radix; + } while (unum > 0U); + + width = i; + if (padn > width) { + (*chars_printed) += (size_t)padn; + } else { + (*chars_printed) += (size_t)width; + } + + if (*chars_printed < n) { + + if (padn > 0) { + while (width < padn) { + *(*s)++ = padc; + padn--; + } + } + + while (--i >= 0) { + *(*s)++ = num_buf[i]; + } + + if (padn < 0) { + while (width < -padn) { + *(*s)++ = padc; + padn++; + } + } + } +} + +/******************************************************************* + * Reduced vsnprintf to be used for Trusted firmware. + * The following type specifiers are supported: + * + * %x (or %X) - hexadecimal format + * %d or %i - signed decimal format + * %s - string format + * %u - unsigned decimal format + * %p - pointer format + * + * The following padding specifiers are supported by this print + * %0NN - Left-pad the number with 0s (NN is a decimal number) + * %NN - Left-pad the number or string with spaces (NN is a decimal number) + * %-NN - Right-pad the number or string with spaces (NN is a decimal number) + * + * The function panics on all other formats specifiers. + * + * It returns the number of characters that would be written if the + * buffer was big enough. If it returns a value lower than n, the + * whole string has been written. + *******************************************************************/ +int vsnprintf(char *s, size_t n, const char *fmt, va_list args) +{ + int num; + unsigned long long int unum; + char *str; + char padc; /* Padding character */ + int padn; /* Number of characters to pad */ + bool left; + bool capitalise; + size_t chars_printed = 0U; + + if (n == 0U) { + /* There isn't space for anything. */ + } else if (n == 1U) { + /* Buffer is too small to actually write anything else. */ + *s = '\0'; + n = 0U; + } else { + /* Reserve space for the terminator character. */ + n--; + } + + while (*fmt != '\0') { + left = false; + padc ='\0'; + padn = 0; + capitalise = false; + + if (*fmt == '%') { + fmt++; + /* Check the format specifier. */ +loop: + switch (*fmt) { + case '%': + CHECK_AND_PUT_CHAR(s, n, chars_printed, '%'); + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + padc = (*fmt == '0') ? '0' : ' '; + for (padn = 0; *fmt >= '0' && *fmt <= '9'; fmt++) { + padn = (padn * 10) + (*fmt - '0'); + } + if (left) { + padn = -padn; + } + goto loop; + case '-': + left = true; + fmt++; + goto loop; + + case 'i': + case 'd': + num = va_arg(args, int); + + if (num < 0) { + CHECK_AND_PUT_CHAR(s, n, chars_printed, + '-'); + unum = (unsigned int)-num; + } else { + unum = (unsigned int)num; + } + + unsigned_num_print(&s, n, &chars_printed, + unum, 10, padc, padn, false); + break; + case 's': + str = va_arg(args, char *); + string_print(&s, n, &chars_printed, str); + break; + case 'u': + unum = va_arg(args, unsigned int); + unsigned_num_print(&s, n, &chars_printed, + unum, 10, padc, padn, false); + break; + case 'p': + unum = (uintptr_t)va_arg(args, void *); + if (unum > 0U) { + string_print(&s, n, &chars_printed, "0x"); + padn -= 2; + } + unsigned_num_print(&s, n, &chars_printed, + unum, 16, padc, padn, false); + break; + case 'X': + capitalise = true; + case 'x': + unum = va_arg(args, unsigned int); + unsigned_num_print(&s, n, &chars_printed, + unum, 16, padc, padn, + capitalise); + break; + + default: + /* Panic on any other format specifier. */ + ERROR("snprintf: specifier with ASCII code '%d' not supported.", + *fmt); + plat_panic_handler(); + assert(0); /* Unreachable */ + } + fmt++; + continue; + } + + CHECK_AND_PUT_CHAR(s, n, chars_printed, *fmt); + + fmt++; + } + + if (n > 0U) { + *s = '\0'; + } + + return (int)chars_printed; +} + +/******************************************************************* + * Reduced snprintf to be used for Trusted firmware. + * The following type specifiers are supported: + * + * %x (or %X) - hexadecimal format + * %d or %i - signed decimal format + * %s - string format + * %u - unsigned decimal format + * %p - pointer format + * + * The following padding specifiers are supported by this print + * %0NN - Left-pad the number with 0s (NN is a decimal number) + * %NN - Left-pad the number or string with spaces (NN is a decimal number) + * %-NN - Right-pad the number or string with spaces (NN is a decimal number) + * + * The function panics on all other formats specifiers. + * + * It returns the number of characters that would be written if the + * buffer was big enough. If it returns a value lower than n, the + * whole string has been written. + *******************************************************************/ +int snprintf(char *s, size_t n, const char *fmt, ...) +{ + int count; + va_list all_args; + + va_start(all_args, fmt); + count = vsnprintf(s, n, fmt, all_args); + va_end(all_args); + + return count; +} diff --git a/drivers/rz/ipl/rza/lib/libc/strchr.c b/drivers/rz/ipl/rza/lib/libc/strchr.c new file mode 100644 index 00000000..d94bb9e0 --- /dev/null +++ b/drivers/rz/ipl/rza/lib/libc/strchr.c @@ -0,0 +1,53 @@ +/*- + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright (c) 1990, 1993 + * The Regents of the University of California. 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 of the University 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 REGENTS 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 REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Portions copyright (c) 2018, ARM Limited and Contributors. + * All rights reserved. + */ + +#include +#include + +char * +strchr(const char *p, int ch) +{ + char c; + + c = ch; + for (;; ++p) { + if (*p == c) + return ((char *)p); + if (*p == '\0') + return (NULL); + } + /* NOTREACHED */ +} diff --git a/drivers/rz/ipl/rza/lib/libc/strcmp.c b/drivers/rz/ipl/rza/lib/libc/strcmp.c new file mode 100644 index 00000000..b742f9b9 --- /dev/null +++ b/drivers/rz/ipl/rza/lib/libc/strcmp.c @@ -0,0 +1,52 @@ +/*- + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * 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 of the University 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 REGENTS 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 REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Portions copyright (c) 2018, ARM Limited and Contributors. + * All rights reserved. + */ + +#include + +/* + * Compare strings. + */ +int +strcmp(const char *s1, const char *s2) +{ + while (*s1 == *s2++) + if (*s1++ == '\0') + return (0); + return (*(const unsigned char *)s1 - *(const unsigned char *)(s2 - 1)); +} diff --git a/drivers/rz/ipl/rza/lib/libc/strlcat.c b/drivers/rz/ipl/rza/lib/libc/strlcat.c new file mode 100644 index 00000000..e60c863a --- /dev/null +++ b/drivers/rz/ipl/rza/lib/libc/strlcat.c @@ -0,0 +1,56 @@ +/* $OpenBSD: strlcat.c,v 1.15 2015/03/02 21:41:08 millert Exp $ */ + +/* + * SPDX-License-Identifier: ISC + * + * Copyright (c) 1998, 2015 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +/* + * Appends src to string dst of size dsize (unlike strncat, dsize is the + * full size of dst, not space left). At most dsize-1 characters + * will be copied. Always NUL terminates (unless dsize <= strlen(dst)). + * Returns strlen(src) + MIN(dsize, strlen(initial dst)). + * If retval >= dsize, truncation occurred. + */ +size_t +strlcat(char * dst, const char * src, size_t dsize) +{ + const char *odst = dst; + const char *osrc = src; + size_t n = dsize; + size_t dlen; + + /* Find the end of dst and adjust bytes left but don't go past end. */ + while (n-- != 0 && *dst != '\0') + dst++; + dlen = dst - odst; + n = dsize - dlen; + + if (n-- == 0) + return(dlen + strlen(src)); + while (*src != '\0') { + if (n != 0) { + *dst++ = *src; + n--; + } + src++; + } + *dst = '\0'; + + return(dlen + (src - osrc)); /* count does not include NUL */ +} diff --git a/drivers/rz/ipl/rza/lib/libc/strlcpy.c b/drivers/rz/ipl/rza/lib/libc/strlcpy.c new file mode 100644 index 00000000..c4f39bb9 --- /dev/null +++ b/drivers/rz/ipl/rza/lib/libc/strlcpy.c @@ -0,0 +1,52 @@ +/* $OpenBSD: strlcpy.c,v 1.12 2015/01/15 03:54:12 millert Exp $ */ + +/* + * SPDX-License-Identifier: ISC + * + * Copyright (c) 1998, 2015 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +/* + * Copy string src to buffer dst of size dsize. At most dsize-1 + * chars will be copied. Always NUL terminates (unless dsize == 0). + * Returns strlen(src); if retval >= dsize, truncation occurred. + */ +size_t +strlcpy(char * dst, const char * src, size_t dsize) +{ + const char *osrc = src; + size_t nleft = dsize; + + /* Copy as many bytes as will fit. */ + if (nleft != 0) { + while (--nleft != 0) { + if ((*dst++ = *src++) == '\0') + break; + } + } + + /* Not enough room in dst, add NUL and traverse rest of src. */ + if (nleft == 0) { + if (dsize != 0) + *dst = '\0'; /* NUL-terminate dst */ + while (*src++) + ; + } + + return(src - osrc - 1); /* count does not include NUL */ +} diff --git a/drivers/rz/ipl/rza/lib/libc/strlen.c b/drivers/rz/ipl/rza/lib/libc/strlen.c new file mode 100644 index 00000000..3c276300 --- /dev/null +++ b/drivers/rz/ipl/rza/lib/libc/strlen.c @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +size_t strlen(const char *s) +{ + const char *cursor = s; + + while (*cursor) + cursor++; + + return cursor - s; +} diff --git a/drivers/rz/ipl/rza/lib/libc/strncmp.c b/drivers/rz/ipl/rza/lib/libc/strncmp.c new file mode 100644 index 00000000..ce9e5ed4 --- /dev/null +++ b/drivers/rz/ipl/rza/lib/libc/strncmp.c @@ -0,0 +1,53 @@ +/*- + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright (c) 1989, 1993 + * The Regents of the University of California. 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 of the University 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 REGENTS 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 REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Portions copyright (c) 2018, ARM Limited and Contributors. + * All rights reserved. + */ + +#include + +int +strncmp(const char *s1, const char *s2, size_t n) +{ + + if (n == 0) + return (0); + do { + if (*s1 != *s2++) + return (*(const unsigned char *)s1 - + *(const unsigned char *)(s2 - 1)); + if (*s1++ == '\0') + break; + } while (--n != 0); + return (0); +} diff --git a/drivers/rz/ipl/rza/lib/libc/strnlen.c b/drivers/rz/ipl/rza/lib/libc/strnlen.c new file mode 100644 index 00000000..b944e95b --- /dev/null +++ b/drivers/rz/ipl/rza/lib/libc/strnlen.c @@ -0,0 +1,46 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2009 David Schultz + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Portions copyright (c) 2018, ARM Limited and Contributors. + * All rights reserved. + */ + +#include + +size_t +strnlen(const char *s, size_t maxlen) +{ + size_t len; + + for (len = 0; len < maxlen; len++, s++) { + if (!*s) + break; + } + return (len); +} diff --git a/drivers/rz/ipl/rza/lib/libc/strrchr.c b/drivers/rz/ipl/rza/lib/libc/strrchr.c new file mode 100644 index 00000000..cd435ff3 --- /dev/null +++ b/drivers/rz/ipl/rza/lib/libc/strrchr.c @@ -0,0 +1,49 @@ +/*- + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright (c) 1988, 1993 + * The Regents of the University of California. 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 of the University 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 REGENTS 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 REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include + +char * +strrchr(const char *p, int ch) +{ + char *save; + char c; + + c = ch; + for (save = NULL;; ++p) { + if (*p == c) + save = (char *)p; + if (*p == '\0') + return (save); + } + /* NOTREACHED */ +} diff --git a/drivers/rz/ipl/rza/lib/libc/strtok.c b/drivers/rz/ipl/rza/lib/libc/strtok.c new file mode 100644 index 00000000..7e1a4d2f --- /dev/null +++ b/drivers/rz/ipl/rza/lib/libc/strtok.c @@ -0,0 +1,83 @@ +/*- + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright (c) 1998 Softweyr LLC. All rights reserved. + * + * strtok_r, from Berkeley strtok + * Oct 13, 1998 by Wes Peters + * + * Copyright (c) 1988, 1993 + * The Regents of the University of California. 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 + * notices, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notices, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University 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 SOFTWEYR LLC, THE REGENTS 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 SOFTWEYR LLC, THE + * REGENTS, OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +char * +strtok_r(char *s, const char *delim, char **last) +{ + char *spanp, *tok; + int c, sc; + + if (s == NULL && (s = *last) == NULL) + return (NULL); + + /* + * Skip (span) leading delimiters (s += strspn(s, delim), sort of). + */ +cont: + c = *s++; + for (spanp = (char *)delim; (sc = *spanp++) != 0;) { + if (c == sc) + goto cont; + } + + if (c == 0) { /* no non-delimiter characters */ + *last = NULL; + return (NULL); + } + tok = s - 1; + + /* + * Scan token (scan for delimiters: s += strcspn(s, delim), sort of). + * Note that delim must have one NUL; we stop if we see that, too. + */ + for (;;) { + c = *s++; + spanp = (char *)delim; + do { + if ((sc = *spanp++) == c) { + if (c == 0) + s = NULL; + else + s[-1] = '\0'; + *last = s; + return (tok); + } + } while (sc != 0); + } + /* NOTREACHED */ +} diff --git a/drivers/rz/ipl/rza/lib/libc/strtol.c b/drivers/rz/ipl/rza/lib/libc/strtol.c new file mode 100644 index 00000000..deb862cc --- /dev/null +++ b/drivers/rz/ipl/rza/lib/libc/strtol.c @@ -0,0 +1,133 @@ +/*- + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * + * 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 of the University 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 REGENTS 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 REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include + +/* + * Convert a string to a long integer. + * + * Assumes that the upper and lower case + * alphabets and digits are each contiguous. + */ +long strtol(const char *nptr, char **endptr, int base) +{ + const char *s; + unsigned long acc; + char c; + unsigned long cutoff; + int neg, any, cutlim; + + /* + * Skip white space and pick up leading +/- sign if any. + * If base is 0, allow 0x for hex and 0 for octal, else + * assume decimal; if base is already 16, allow 0x. + */ + s = nptr; + do { + c = *s++; + } while (isspace((unsigned char)c)); + if (c == '-') { + neg = 1; + c = *s++; + } else { + neg = 0; + if (c == '+') + c = *s++; + } + if ((base == 0 || base == 16) && + c == '0' && (*s == 'x' || *s == 'X') && + ((s[1] >= '0' && s[1] <= '9') || + (s[1] >= 'A' && s[1] <= 'F') || + (s[1] >= 'a' && s[1] <= 'f'))) { + c = s[1]; + s += 2; + base = 16; + } + if (base == 0) + base = c == '0' ? 8 : 10; + acc = any = 0; + + /* + * Compute the cutoff value between legal numbers and illegal + * numbers. That is the largest legal value, divided by the + * base. An input number that is greater than this value, if + * followed by a legal input character, is too big. One that + * is equal to this value may be valid or not; the limit + * between valid and invalid numbers is then based on the last + * digit. For instance, if the range for longs is + * [-2147483648..2147483647] and the input base is 10, + * cutoff will be set to 214748364 and cutlim to either + * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated + * a value > 214748364, or equal but the next digit is > 7 (or 8), + * the number is too big, and we will return a range error. + * + * Set 'any' if any `digits' consumed; make it negative to indicate + * overflow. + */ + cutoff = neg ? (unsigned long)-(LONG_MIN + LONG_MAX) + LONG_MAX + : LONG_MAX; + cutlim = cutoff % base; + cutoff /= base; + for ( ; ; c = *s++) { + if (c >= '0' && c <= '9') + c -= '0'; + else if (c >= 'A' && c <= 'Z') + c -= 'A' - 10; + else if (c >= 'a' && c <= 'z') + c -= 'a' - 10; + else + break; + if (c >= base) + break; + if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) + any = -1; + else { + any = 1; + acc *= base; + acc += c; + } + } + if (any < 0) { + acc = neg ? LONG_MIN : LONG_MAX; + } else if (neg) + acc = -acc; + if (endptr != NULL) + *endptr = (char *)(any ? s - 1 : nptr); + return (acc); +} diff --git a/drivers/rz/ipl/rza/lib/libc/strtoll.c b/drivers/rz/ipl/rza/lib/libc/strtoll.c new file mode 100644 index 00000000..4e101e80 --- /dev/null +++ b/drivers/rz/ipl/rza/lib/libc/strtoll.c @@ -0,0 +1,134 @@ +/*- + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * + * 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 of the University 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 REGENTS 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 REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include + +/* + * Convert a string to a long long integer. + * + * Assumes that the upper and lower case + * alphabets and digits are each contiguous. + */ +long long strtoll(const char *nptr, char **endptr, int base) +{ + const char *s; + unsigned long long acc; + char c; + unsigned long long cutoff; + int neg, any, cutlim; + + /* + * Skip white space and pick up leading +/- sign if any. + * If base is 0, allow 0x for hex and 0 for octal, else + * assume decimal; if base is already 16, allow 0x. + */ + s = nptr; + do { + c = *s++; + } while (isspace((unsigned char)c)); + if (c == '-') { + neg = 1; + c = *s++; + } else { + neg = 0; + if (c == '+') + c = *s++; + } + if ((base == 0 || base == 16) && + c == '0' && (*s == 'x' || *s == 'X') && + ((s[1] >= '0' && s[1] <= '9') || + (s[1] >= 'A' && s[1] <= 'F') || + (s[1] >= 'a' && s[1] <= 'f'))) { + c = s[1]; + s += 2; + base = 16; + } + if (base == 0) + base = c == '0' ? 8 : 10; + acc = any = 0; + + /* + * Compute the cutoff value between legal numbers and illegal + * numbers. That is the largest legal value, divided by the + * base. An input number that is greater than this value, if + * followed by a legal input character, is too big. One that + * is equal to this value may be valid or not; the limit + * between valid and invalid numbers is then based on the last + * digit. For instance, if the range for quads is + * [-9223372036854775808..9223372036854775807] and the input base + * is 10, cutoff will be set to 922337203685477580 and cutlim to + * either 7 (neg==0) or 8 (neg==1), meaning that if we have + * accumulated a value > 922337203685477580, or equal but the + * next digit is > 7 (or 8), the number is too big, and we will + * return a range error. + * + * Set 'any' if any `digits' consumed; make it negative to indicate + * overflow. + */ + cutoff = neg ? (unsigned long long)-(LLONG_MIN + LLONG_MAX) + LLONG_MAX + : LLONG_MAX; + cutlim = cutoff % base; + cutoff /= base; + for ( ; ; c = *s++) { + if (c >= '0' && c <= '9') + c -= '0'; + else if (c >= 'A' && c <= 'Z') + c -= 'A' - 10; + else if (c >= 'a' && c <= 'z') + c -= 'a' - 10; + else + break; + if (c >= base) + break; + if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) + any = -1; + else { + any = 1; + acc *= base; + acc += c; + } + } + if (any < 0) { + acc = neg ? LLONG_MIN : LLONG_MAX; + } else if (neg) + acc = -acc; + if (endptr != NULL) + *endptr = (char *)(any ? s - 1 : nptr); + return (acc); +} diff --git a/drivers/rz/ipl/rza/lib/libc/strtoul.c b/drivers/rz/ipl/rza/lib/libc/strtoul.c new file mode 100644 index 00000000..b42fb141 --- /dev/null +++ b/drivers/rz/ipl/rza/lib/libc/strtoul.c @@ -0,0 +1,112 @@ +/*- + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * + * 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 of the University 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 REGENTS 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 REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include + +/* + * Convert a string to an unsigned long integer. + * + * Assumes that the upper and lower case + * alphabets and digits are each contiguous. + */ +unsigned long strtoul(const char *nptr, char **endptr, int base) +{ + const char *s; + unsigned long acc; + char c; + unsigned long cutoff; + int neg, any, cutlim; + + /* + * See strtol for comments as to the logic used. + */ + s = nptr; + do { + c = *s++; + } while (isspace((unsigned char)c)); + if (c == '-') { + neg = 1; + c = *s++; + } else { + neg = 0; + if (c == '+') + c = *s++; + } + if ((base == 0 || base == 16) && + c == '0' && (*s == 'x' || *s == 'X') && + ((s[1] >= '0' && s[1] <= '9') || + (s[1] >= 'A' && s[1] <= 'F') || + (s[1] >= 'a' && s[1] <= 'f'))) { + c = s[1]; + s += 2; + base = 16; + } + if (base == 0) + base = c == '0' ? 8 : 10; + acc = any = 0; + + cutoff = ULONG_MAX / base; + cutlim = ULONG_MAX % base; + for ( ; ; c = *s++) { + if (c >= '0' && c <= '9') + c -= '0'; + else if (c >= 'A' && c <= 'Z') + c -= 'A' - 10; + else if (c >= 'a' && c <= 'z') + c -= 'a' - 10; + else + break; + if (c >= base) + break; + if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) + any = -1; + else { + any = 1; + acc *= base; + acc += c; + } + } + if (any < 0) { + acc = ULONG_MAX; + } else if (neg) + acc = -acc; + if (endptr != NULL) + *endptr = (char *)(any ? s - 1 : nptr); + return (acc); +} diff --git a/drivers/rz/ipl/rza/lib/libc/strtoull.c b/drivers/rz/ipl/rza/lib/libc/strtoull.c new file mode 100644 index 00000000..2e65a433 --- /dev/null +++ b/drivers/rz/ipl/rza/lib/libc/strtoull.c @@ -0,0 +1,112 @@ +/*- + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * + * 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 of the University 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 REGENTS 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 REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include + +/* + * Convert a string to an unsigned long long integer. + * + * Assumes that the upper and lower case + * alphabets and digits are each contiguous. + */ +unsigned long long strtoull(const char *nptr, char **endptr, int base) +{ + const char *s; + unsigned long long acc; + char c; + unsigned long long cutoff; + int neg, any, cutlim; + + /* + * See strtoq for comments as to the logic used. + */ + s = nptr; + do { + c = *s++; + } while (isspace((unsigned char)c)); + if (c == '-') { + neg = 1; + c = *s++; + } else { + neg = 0; + if (c == '+') + c = *s++; + } + if ((base == 0 || base == 16) && + c == '0' && (*s == 'x' || *s == 'X') && + ((s[1] >= '0' && s[1] <= '9') || + (s[1] >= 'A' && s[1] <= 'F') || + (s[1] >= 'a' && s[1] <= 'f'))) { + c = s[1]; + s += 2; + base = 16; + } + if (base == 0) + base = c == '0' ? 8 : 10; + acc = any = 0; + + cutoff = ULLONG_MAX / base; + cutlim = ULLONG_MAX % base; + for ( ; ; c = *s++) { + if (c >= '0' && c <= '9') + c -= '0'; + else if (c >= 'A' && c <= 'Z') + c -= 'A' - 10; + else if (c >= 'a' && c <= 'z') + c -= 'a' - 10; + else + break; + if (c >= base) + break; + if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) + any = -1; + else { + any = 1; + acc *= base; + acc += c; + } + } + if (any < 0) { + acc = ULLONG_MAX; + } else if (neg) + acc = -acc; + if (endptr != NULL) + *endptr = (char *)(any ? s - 1 : nptr); + return (acc); +} diff --git a/drivers/rz/ipl/rza/lib/locks/exclusive/aarch64/spinlock.S b/drivers/rz/ipl/rza/lib/locks/exclusive/aarch64/spinlock.S new file mode 100644 index 00000000..e941b8a3 --- /dev/null +++ b/drivers/rz/ipl/rza/lib/locks/exclusive/aarch64/spinlock.S @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + + .globl spin_lock + .globl spin_unlock + +#if USE_SPINLOCK_CAS +#if !ARM_ARCH_AT_LEAST(8, 1) +#error USE_SPINLOCK_CAS option requires at least an ARMv8.1 platform +#endif + +/* + * When compiled for ARMv8.1 or later, choose spin locks based on Compare and + * Swap instruction. + */ + +/* + * Acquire lock using Compare and Swap instruction. + * + * Compare for 0 with acquire semantics, and swap 1. If failed to acquire, use + * load exclusive semantics to monitor the address and enter WFE. + * + * void spin_lock(spinlock_t *lock); + */ +func spin_lock + mov w2, #1 +1: mov w1, wzr +2: casa w1, w2, [x0] + cbz w1, 3f + ldxr w1, [x0] + cbz w1, 2b + wfe + b 1b +3: + ret +endfunc spin_lock + +#else /* !USE_SPINLOCK_CAS */ + +/* + * Acquire lock using load-/store-exclusive instruction pair. + * + * void spin_lock(spinlock_t *lock); + */ +func spin_lock + mov w2, #1 + sevl +l1: wfe +l2: ldaxr w1, [x0] + cbnz w1, l1 + stxr w1, w2, [x0] + cbnz w1, l2 + ret +endfunc spin_lock + +#endif /* USE_SPINLOCK_CAS */ + +/* + * Release lock previously acquired by spin_lock. + * + * Use store-release to unconditionally clear the spinlock variable. + * Store operation generates an event to all cores waiting in WFE + * when address is monitored by the global monitor. + * + * void spin_unlock(spinlock_t *lock); + */ +func spin_unlock + stlr wzr, [x0] + ret +endfunc spin_unlock diff --git a/drivers/rz/ipl/rza/lib/romlib/Makefile b/drivers/rz/ipl/rza/lib/romlib/Makefile new file mode 100644 index 00000000..2ff480bd --- /dev/null +++ b/drivers/rz/ipl/rza/lib/romlib/Makefile @@ -0,0 +1,98 @@ +# +# Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +AS = $(CROSS_COMPILE)as +AR = $(CROSS_COMPILE)ar +LD = $(CROSS_COMPILE)ld +OC = $(CROSS_COMPILE)objcopy +CPP = $(CROSS_COMPILE)cpp +ROMLIB_GEN = ./romlib_generator.py +BUILD_DIR = $(BUILD_PLAT)/romlib +LIB_DIR = $(BUILD_PLAT)/lib +WRAPPER_DIR = $(BUILD_PLAT)/libwrapper +LIBS = -lmbedtls -lfdt -lc +INC = $(INCLUDES:-I%=-I../../%) +PPFLAGS = $(INC) $(DEFINES) -P -x assembler-with-cpp -D__LINKER__ -MD -MP -MT $(BUILD_DIR)/romlib.ld +OBJS = $(BUILD_DIR)/jmptbl.o $(BUILD_DIR)/init.o +MAPFILE = $(BUILD_PLAT)/romlib/romlib.map + +ifneq ($(PLAT_DIR),) + WRAPPER_SOURCES = $(shell $(ROMLIB_GEN) genwrappers -b $(WRAPPER_DIR) --list ../../$(PLAT_DIR)/jmptbl.i) + WRAPPER_OBJS = $(WRAPPER_SOURCES:.s=.o) +endif + +V ?= 0 +ifeq ($(V),0) + Q := @ +else + Q := +endif + +LDFLAGS := --gc-sections -O1 +ifeq ($(DEBUG),1) + LDFLAGS += -Map=$(MAPFILE) +endif + +ifeq (${ARM_ARCH_MINOR},0) + ASFLAGS = -march=armv8-a +else + ASFLAGS = -march=armv8.${ARM_ARCH_MINOR}-a +endif + +.PHONY: all clean distclean + +all: $(BUILD_DIR)/romlib.bin $(LIB_DIR)/libwrappers.a + +%.o: %.s + @echo " AS $@" + $(Q)$(AS) $(ASFLAGS) -o $@ $< + +$(BUILD_DIR)/%.o: %.s + @echo " AS $@" + $(Q)$(AS) $(ASFLAGS) -o $@ $< + +$(BUILD_DIR)/romlib.ld: romlib.ld.S + @echo " PP $@" + $(Q)$(CPP) $(PPFLAGS) -o $@ romlib.ld.S + +$(BUILD_DIR)/romlib.elf: $(OBJS) $(BUILD_DIR)/romlib.ld + @echo " LD $@" + $(Q)$(LD) -T $(BUILD_DIR)/romlib.ld -L$(LIB_DIR) $(LDFLAGS) -o $@ $(OBJS) $(LIBS) + +$(BUILD_DIR)/romlib.bin: $(BUILD_DIR)/romlib.elf + @echo " BIN $@" + $(Q)$(OC) -O binary $(BUILD_DIR)/romlib.elf $@ + +$(WRAPPER_DIR)/jmpvar.s: $(BUILD_DIR)/romlib.elf + @echo " VAR $@" + $(Q)$(ROMLIB_GEN) genvar --output $@ $< + +$(LIB_DIR)/libwrappers.a: $(WRAPPER_DIR)/jmpvar.o $(WRAPPER_OBJS) + @echo " AR $@" + $(Q)$(AR) -rc $@ $(WRAPPER_DIR)/jmpvar.o $(WRAPPER_OBJS) + +$(BUILD_DIR)/jmptbl.i: ../../$(PLAT_DIR)/jmptbl.i + @echo " PRE $@" + $(Q)$(ROMLIB_GEN) pre --output $@ --deps $(BUILD_DIR)/jmptbl.d $< + +$(BUILD_DIR)/wrappers.stamp: $(BUILD_DIR)/jmptbl.i + @echo " WRP $<" + $(Q)$(ROMLIB_GEN) genwrappers --bti=$(ENABLE_BTI) -b $(WRAPPER_DIR) $< + @touch $@ + +$(WRAPPER_SOURCES): $(BUILD_DIR)/wrappers.stamp + +$(WRAPPER_OBJS): $(WRAPPER_SOURCES) $(BUILD_DIR)/wrappers.stamp + +$(BUILD_DIR)/jmptbl.s: $(BUILD_DIR)/jmptbl.i + @echo " TBL $@" + $(Q)$(ROMLIB_GEN) gentbl --output $@ --bti=$(ENABLE_BTI) $< + +clean: + @rm -f $(BUILD_DIR)/* + +-include $(BUILD_DIR)/romlib.d +-include $(BUILD_DIR)/jmptbl.d diff --git a/drivers/rz/ipl/rza/lib/romlib/gen_combined_bl1_romlib.sh b/drivers/rz/ipl/rza/lib/romlib/gen_combined_bl1_romlib.sh new file mode 100644 index 00000000..1e3f73a0 --- /dev/null +++ b/drivers/rz/ipl/rza/lib/romlib/gen_combined_bl1_romlib.sh @@ -0,0 +1,53 @@ +#!/bin/sh +# Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause + +set -e + +output="bl1_romlib.bin" + +# Set trap for removing temporary file +trap 'r=$?;rm -f $bin_path/$$.tmp;exit $r' EXIT HUP QUIT INT TERM + +# Read input parameters +for i +do + case $i in + -o) + output=$2 + shift 2 + ;; + --) + shift + break + ;; + -*) + echo usage: gen_combined_bl1_romlib.sh [-o output] path_to_build_directory >&2 + ;; + esac +done + + +bin_path=$1 +romlib_path=$1/romlib +bl1_file="$1/bl1/bl1.elf" +romlib_file="$1/romlib/romlib.elf" +bl1_end="" +romlib_begin="" + +# Get address of __BL1_ROM_END__ +bl1_end=`nm -a "$bl1_file" | +awk '$3 == "__BL1_ROM_END__" {print "0x"$1}'` + +# Get start address of romlib "text" section +romlib_begin=`nm -a "$romlib_file" | +awk '$3 == ".text" {print "0x"$1}'` + +# Character "U" will be read as "55" in hex when it is +# concatenated with bl1.bin. Generate combined BL1 and ROMLIB +# binary with filler bytes for juno +(cat $bin_path/bl1.bin + yes U | sed $(($romlib_begin - $bl1_end))q | tr -d '\n' + cat $bin_path/romlib/romlib.bin) > $bin_path/$$.tmp && +mv $bin_path/$$.tmp $bin_path/$output diff --git a/drivers/rz/ipl/rza/lib/romlib/init.s b/drivers/rz/ipl/rza/lib/romlib/init.s new file mode 100644 index 00000000..7d97e4d1 --- /dev/null +++ b/drivers/rz/ipl/rza/lib/romlib/init.s @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + + .globl rom_lib_init + .extern __DATA_RAM_START__, __DATA_ROM_START__, __DATA_RAM_END__ + .extern memset, memcpy + +rom_lib_init: + cmp w0, #1 + mov w0, #0 + b.le 1f + ret + +1: stp x29, x30, [sp, #-16]! + adrp x0, __DATA_RAM_START__ + adrp x1, __DATA_ROM_START__ + add x1, x1, :lo12:__DATA_ROM_START__ + adrp x2, __DATA_RAM_END__ + add x2, x2, :lo12:__DATA_RAM_END__ + sub x2, x2, x0 + bl memcpy + + adrp x0,__BSS_START__ + add x0, x0, :lo12:__BSS_START__ + mov x1, #0 + adrp x2, __BSS_END__ + add x2, x2, :lo12:__BSS_END__ + sub x2, x2, x0 + bl memset + ldp x29, x30, [sp], #16 + + mov w0, #1 + ret diff --git a/drivers/rz/ipl/rza/lib/romlib/jmptbl.i b/drivers/rz/ipl/rza/lib/romlib/jmptbl.i new file mode 100644 index 00000000..33710f58 --- /dev/null +++ b/drivers/rz/ipl/rza/lib/romlib/jmptbl.i @@ -0,0 +1,44 @@ +# +# Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# +# Format: +# lib function [patch] +# Add "patch" at the end of the line to patch a function. For example: +# mbedtls mbedtls_memory_buffer_alloc_init patch +# Holes can be introduced in the table by using a special keyword "reserved". +# Example: +# reserved reserved +# The jump table will contain an invalid instruction instead of branch + +rom rom_lib_init +fdt fdt_getprop_namelen +fdt fdt_setprop_inplace +fdt fdt_check_header +fdt fdt_node_offset_by_compatible +fdt fdt_setprop_inplace_namelen_partial +mbedtls mbedtls_asn1_get_alg +mbedtls mbedtls_asn1_get_alg_null +mbedtls mbedtls_asn1_get_bitstring_null +mbedtls mbedtls_asn1_get_bool +mbedtls mbedtls_asn1_get_int +mbedtls mbedtls_asn1_get_tag +mbedtls mbedtls_free +mbedtls mbedtls_md +mbedtls mbedtls_md_get_size +mbedtls mbedtls_memory_buffer_alloc_init +mbedtls mbedtls_oid_get_md_alg +mbedtls mbedtls_oid_get_numeric_string +mbedtls mbedtls_oid_get_pk_alg +mbedtls mbedtls_oid_get_sig_alg +mbedtls mbedtls_pk_free +mbedtls mbedtls_pk_init +mbedtls mbedtls_pk_parse_subpubkey +mbedtls mbedtls_pk_verify_ext +mbedtls mbedtls_platform_set_snprintf +mbedtls mbedtls_x509_get_rsassa_pss_params +mbedtls mbedtls_x509_get_sig_alg +mbedtls mbedtls_md_info_from_type +c exit +c atexit diff --git a/drivers/rz/ipl/rza/lib/romlib/romlib.ld.S b/drivers/rz/ipl/rza/lib/romlib/romlib.ld.S new file mode 100644 index 00000000..2aac4adf --- /dev/null +++ b/drivers/rz/ipl/rza/lib/romlib/romlib.ld.S @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +MEMORY { + ROM (rx): ORIGIN = ROMLIB_RO_BASE, LENGTH = ROMLIB_RO_LIMIT - ROMLIB_RO_BASE + RAM (rwx): ORIGIN = ROMLIB_RW_BASE, LENGTH = ROMLIB_RW_END - ROMLIB_RW_BASE +} + +OUTPUT_FORMAT(PLATFORM_LINKER_FORMAT) +OUTPUT_ARCH(PLATFORM_LINKER_ARCH) +ENTRY(jmptbl) + +SECTIONS +{ + . = ROMLIB_RO_BASE; + .text : { + *jmptbl.o(.text) + *(.text*) + *(.rodata*) + } >ROM + + __DATA_ROM_START__ = LOADADDR(.data); + + .data : { + __DATA_RAM_START__ = .; + *(.data*) + __DATA_RAM_END__ = .; + } >RAM AT>ROM + + __DATA_SIZE__ = SIZEOF(.data); + + .bss : { + __BSS_START__ = .; + *(.bss*) + __BSS_END__ = .; + } >RAM + __BSS_SIZE__ = SIZEOF(.bss); +} diff --git a/drivers/rz/ipl/rza/lib/romlib/romlib_generator.py b/drivers/rz/ipl/rza/lib/romlib/romlib_generator.py new file mode 100644 index 00000000..0682dd49 --- /dev/null +++ b/drivers/rz/ipl/rza/lib/romlib/romlib_generator.py @@ -0,0 +1,277 @@ +#!/usr/bin/env python3 +# Copyright (c) 2019, Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause + +""" +This module contains a set of classes and a runner that can generate code for the romlib module +based on the templates in the 'templates' directory. +""" + +import argparse +import os +import re +import subprocess +import string +import sys + +class IndexFileParser: + """ + Parses the contents of the index file into the items and dependencies variables. It + also resolves included files in the index files recursively with circular inclusion detection. + """ + + def __init__(self): + self.items = [] + self.dependencies = {} + self.include_chain = [] + + def add_dependency(self, parent, dependency): + """ Adds a dependency into the dependencies variable. """ + if parent in self.dependencies: + self.dependencies[parent].append(dependency) + else: + self.dependencies[parent] = [dependency] + + def get_dependencies(self, parent): + """ Gets all the recursive dependencies of a parent file. """ + parent = os.path.normpath(parent) + if parent in self.dependencies: + direct_deps = self.dependencies[parent] + deps = direct_deps + for direct_dep in direct_deps: + deps += self.get_dependencies(direct_dep) + return deps + + return [] + + def parse(self, file_name): + """ Opens and parses index file. """ + file_name = os.path.normpath(file_name) + + if file_name not in self.include_chain: + self.include_chain.append(file_name) + self.dependencies[file_name] = [] + else: + raise Exception("Circular dependency detected: " + file_name) + + with open(file_name, "r") as index_file: + for line in index_file.readlines(): + line_elements = line.split() + + if line.startswith("#") or not line_elements: + # Comment or empty line + continue + + if line_elements[0] == "reserved": + # Reserved slot in the jump table + self.items.append({"type": "reserved"}) + elif line_elements[0] == "include" and len(line_elements) > 1: + # Include other index file + included_file = os.path.normpath(line_elements[1]) + self.add_dependency(file_name, included_file) + self.parse(included_file) + elif len(line_elements) > 1: + # Library function + library_name = line_elements[0] + function_name = line_elements[1] + patch = bool(len(line_elements) > 2 and line_elements[2] == "patch") + + self.items.append({"type": "function", "library_name": library_name, + "function_name": function_name, "patch": patch}) + else: + raise Exception("Invalid line: '" + line + "'") + + self.include_chain.pop() + +class RomlibApplication: + """ Base class of romlib applications. """ + TEMPLATE_DIR = os.path.dirname(os.path.realpath(__file__)) + "/templates/" + + def __init__(self, prog): + self.args = argparse.ArgumentParser(prog=prog, description=self.__doc__) + self.config = None + + def parse_arguments(self, argv): + """ Parses the arguments that should come from the command line arguments. """ + self.config = self.args.parse_args(argv) + + def build_template(self, name, mapping=None, remove_comment=False): + """ + Loads a template and builds it with the defined mapping. Template paths are always relative + to this script. + """ + + with open(self.TEMPLATE_DIR + name, "r") as template_file: + if remove_comment: + # Removing copyright comment to make the generated code more readable when the + # template is inserted multiple times into the output. + template_lines = template_file.readlines() + end_of_comment_line = 0 + for index, line in enumerate(template_lines): + if line.find("*/") != -1: + end_of_comment_line = index + break + template_data = "".join(template_lines[end_of_comment_line + 1:]) + else: + template_data = template_file.read() + + template = string.Template(template_data) + return template.substitute(mapping) + +class IndexPreprocessor(RomlibApplication): + """ Removes empty and comment lines from the index file and resolves includes. """ + + def __init__(self, prog): + RomlibApplication.__init__(self, prog) + + self.args.add_argument("-o", "--output", help="Output file", metavar="output", + default="jmpvar.s") + self.args.add_argument("--deps", help="Dependency file") + self.args.add_argument("file", help="Input file") + + def main(self): + """ + After parsing the input index file it generates a clean output with all includes resolved. + Using --deps option it also outputs the dependencies in makefile format like gcc's with -M. + """ + + index_file_parser = IndexFileParser() + index_file_parser.parse(self.config.file) + + with open(self.config.output, "w") as output_file: + for item in index_file_parser.items: + if item["type"] == "function": + patch = "\tpatch" if item["patch"] else "" + output_file.write( + item["library_name"] + "\t" + item["function_name"] + patch + "\n") + else: + output_file.write("reserved\n") + + if self.config.deps: + with open(self.config.deps, "w") as deps_file: + deps = [self.config.file] + index_file_parser.get_dependencies(self.config.file) + deps_file.write(self.config.output + ": " + " \\\n".join(deps) + "\n") + +class TableGenerator(RomlibApplication): + """ Generates the jump table by parsing the index file. """ + + def __init__(self, prog): + RomlibApplication.__init__(self, prog) + + self.args.add_argument("-o", "--output", help="Output file", metavar="output", + default="jmpvar.s") + self.args.add_argument("--bti", help="Branch Target Identification", type=int) + self.args.add_argument("file", help="Input file") + + def main(self): + """ + Inserts the jmptbl definition and the jump entries into the output file. Also can insert + BTI related code before entries if --bti option set. It can output a dependency file of the + included index files. This can be directly included in makefiles. + """ + + index_file_parser = IndexFileParser() + index_file_parser.parse(self.config.file) + + with open(self.config.output, "w") as output_file: + output_file.write(self.build_template("jmptbl_header.S")) + bti = "_bti" if self.config.bti == 1 else "" + + for item in index_file_parser.items: + template_name = "jmptbl_entry_" + item["type"] + bti + ".S" + output_file.write(self.build_template(template_name, item, True)) + +class WrapperGenerator(RomlibApplication): + """ + Generates a wrapper function for each entry in the index file except for the ones that contain + the keyword patch. The generated wrapper file is called _.s. + """ + + def __init__(self, prog): + RomlibApplication.__init__(self, prog) + + self.args.add_argument("-b", help="Build directory", default=".", metavar="build") + self.args.add_argument("--bti", help="Branch Target Identification", type=int) + self.args.add_argument("--list", help="Only list assembly files", action="store_true") + self.args.add_argument("file", help="Input file") + + def main(self): + """ + Iterates through the items in the parsed index file and builds the template for each entry. + """ + + index_file_parser = IndexFileParser() + index_file_parser.parse(self.config.file) + + bti = "_bti" if self.config.bti == 1 else "" + function_offset = 0 + files = [] + + for item_index in range(0, len(index_file_parser.items)): + item = index_file_parser.items[item_index] + + if item["type"] == "reserved" or item["patch"]: + continue + + asm = self.config.b + "/" + item["function_name"] + ".s" + if self.config.list: + # Only listing files + files.append(asm) + else: + with open(asm, "w") as asm_file: + # The jump instruction is 4 bytes but BTI requires and extra instruction so + # this makes it 8 bytes per entry. + function_offset = item_index * (8 if self.config.bti else 4) + + item["function_offset"] = function_offset + asm_file.write(self.build_template("wrapper" + bti + ".S", item)) + + if self.config.list: + print(" ".join(files)) + +class VariableGenerator(RomlibApplication): + """ Generates the jump table global variable with the absolute address in ROM. """ + + def __init__(self, prog): + RomlibApplication.__init__(self, prog) + + self.args.add_argument("-o", "--output", help="Output file", metavar="output", + default="jmpvar.s") + self.args.add_argument("file", help="Input file") + + def main(self): + """ + Runs nm -a command on the input file and inserts the address of the .text section into the + template as the ROM address of the jmp_table. + """ + symbols = subprocess.check_output(["nm", "-a", self.config.file]) + + matching_symbol = re.search("([0-9A-Fa-f]+) . \\.text", str(symbols)) + if not matching_symbol: + raise Exception("No '.text' section was found in %s" % self.config.file) + + mapping = {"jmptbl_address": matching_symbol.group(1)} + + with open(self.config.output, "w") as output_file: + output_file.write(self.build_template("jmptbl_glob_var.S", mapping)) + +if __name__ == "__main__": + APPS = {"genvar": VariableGenerator, "pre": IndexPreprocessor, + "gentbl": TableGenerator, "genwrappers": WrapperGenerator} + + if len(sys.argv) < 2 or sys.argv[1] not in APPS: + print("usage: romlib_generator.py [%s] [args]" % "|".join(APPS.keys()), file=sys.stderr) + sys.exit(1) + + APP = APPS[sys.argv[1]]("romlib_generator.py " + sys.argv[1]) + APP.parse_arguments(sys.argv[2:]) + try: + APP.main() + sys.exit(0) + except FileNotFoundError as file_not_found_error: + print(file_not_found_error, file=sys.stderr) + except subprocess.CalledProcessError as called_process_error: + print(called_process_error.output, file=sys.stderr) + + sys.exit(1) diff --git a/drivers/rz/ipl/rza/lib/romlib/templates/jmptbl_entry_function.S b/drivers/rz/ipl/rza/lib/romlib/templates/jmptbl_entry_function.S new file mode 100644 index 00000000..a0f84561 --- /dev/null +++ b/drivers/rz/ipl/rza/lib/romlib/templates/jmptbl_entry_function.S @@ -0,0 +1,6 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + b ${function_name} diff --git a/drivers/rz/ipl/rza/lib/romlib/templates/jmptbl_entry_function_bti.S b/drivers/rz/ipl/rza/lib/romlib/templates/jmptbl_entry_function_bti.S new file mode 100644 index 00000000..d96ee94d --- /dev/null +++ b/drivers/rz/ipl/rza/lib/romlib/templates/jmptbl_entry_function_bti.S @@ -0,0 +1,7 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + bti j + b ${function_name} diff --git a/drivers/rz/ipl/rza/lib/romlib/templates/jmptbl_entry_reserved.S b/drivers/rz/ipl/rza/lib/romlib/templates/jmptbl_entry_reserved.S new file mode 100644 index 00000000..a9b5f181 --- /dev/null +++ b/drivers/rz/ipl/rza/lib/romlib/templates/jmptbl_entry_reserved.S @@ -0,0 +1,6 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + b . diff --git a/drivers/rz/ipl/rza/lib/romlib/templates/jmptbl_entry_reserved_bti.S b/drivers/rz/ipl/rza/lib/romlib/templates/jmptbl_entry_reserved_bti.S new file mode 100644 index 00000000..a9f03759 --- /dev/null +++ b/drivers/rz/ipl/rza/lib/romlib/templates/jmptbl_entry_reserved_bti.S @@ -0,0 +1,7 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + bti j + b . diff --git a/drivers/rz/ipl/rza/lib/romlib/templates/jmptbl_glob_var.S b/drivers/rz/ipl/rza/lib/romlib/templates/jmptbl_glob_var.S new file mode 100644 index 00000000..d3065125 --- /dev/null +++ b/drivers/rz/ipl/rza/lib/romlib/templates/jmptbl_glob_var.S @@ -0,0 +1,9 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + .data + .globl jmptbl + .align 4 +jmptbl: .quad 0x${jmptbl_address} diff --git a/drivers/rz/ipl/rza/lib/romlib/templates/jmptbl_header.S b/drivers/rz/ipl/rza/lib/romlib/templates/jmptbl_header.S new file mode 100644 index 00000000..72b8ce54 --- /dev/null +++ b/drivers/rz/ipl/rza/lib/romlib/templates/jmptbl_header.S @@ -0,0 +1,8 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + .text + .globl jmptbl +jmptbl: diff --git a/drivers/rz/ipl/rza/lib/romlib/templates/wrapper.S b/drivers/rz/ipl/rza/lib/romlib/templates/wrapper.S new file mode 100644 index 00000000..734a68a2 --- /dev/null +++ b/drivers/rz/ipl/rza/lib/romlib/templates/wrapper.S @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + .globl ${function_name} +${function_name}: + ldr x17, =jmptbl + mov x16, #${function_offset} + ldr x17, [x17] + add x16, x16, x17 + br x16 diff --git a/drivers/rz/ipl/rza/lib/romlib/templates/wrapper_bti.S b/drivers/rz/ipl/rza/lib/romlib/templates/wrapper_bti.S new file mode 100644 index 00000000..ba9b11ce --- /dev/null +++ b/drivers/rz/ipl/rza/lib/romlib/templates/wrapper_bti.S @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + .globl ${function_name} +${function_name}: + bti jc + ldr x17, =jmptbl + mov x16, #${function_offset} + ldr x17, [x17] + add x16, x16, x17 + br x16 diff --git a/drivers/rz/ipl/rza/lib/stack_protector/aarch64/asm_stack_protector.S b/drivers/rz/ipl/rza/lib/stack_protector/aarch64/asm_stack_protector.S new file mode 100644 index 00000000..c2245d36 --- /dev/null +++ b/drivers/rz/ipl/rza/lib/stack_protector/aarch64/asm_stack_protector.S @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + + .globl update_stack_protector_canary + +/* ----------------------------------------------------------------------- + * void update_stack_protector_canary(void) + * + * Change the value of the canary used for stack smashing attacks protection. + * Note: This must be called when it is safe to call C code, but this cannot be + * called by C code. Doing this will make the check fail when the calling + * function returns. + * ----------------------------------------------------------------------- + */ + +func update_stack_protector_canary + /* Use x19 as it is callee-saved */ + mov x19, x30 + bl plat_get_stack_protector_canary + + /* Update the canary with the returned value */ + adrp x1, __stack_chk_guard + str x0, [x1, #:lo12:__stack_chk_guard] + ret x19 +endfunc update_stack_protector_canary + + diff --git a/drivers/rz/ipl/rza/lib/stack_protector/stack_protector.c b/drivers/rz/ipl/rza/lib/stack_protector/stack_protector.c new file mode 100644 index 00000000..3ff74fc8 --- /dev/null +++ b/drivers/rz/ipl/rza/lib/stack_protector/stack_protector.c @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +/* + * Canary value used by the compiler runtime checks to detect stack corruption. + * + * Force the canary to be in .data to allow predictable memory layout relatively + * to the stacks. + */ +u_register_t __attribute__((section(".data.stack_protector_canary"))) + __stack_chk_guard = (u_register_t) 3288484550995823360ULL; + +/* + * Function called when the stack's canary check fails, which means the stack + * was corrupted. It must not return. + */ +void __dead2 __stack_chk_fail(void) +{ +#if DEBUG + ERROR("Stack corruption detected\n"); +#endif + panic(); +} + diff --git a/drivers/rz/ipl/rza/lib/stack_protector/stack_protector.mk b/drivers/rz/ipl/rza/lib/stack_protector/stack_protector.mk new file mode 100644 index 00000000..b5aba152 --- /dev/null +++ b/drivers/rz/ipl/rza/lib/stack_protector/stack_protector.mk @@ -0,0 +1,28 @@ +# +# Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# Boolean macro to be used in C code +STACK_PROTECTOR_ENABLED := 0 + +ifeq (${ENABLE_STACK_PROTECTOR},0) + ENABLE_STACK_PROTECTOR := none +endif + +ifeq (${ENABLE_STACK_PROTECTOR},none) + TF_CFLAGS += -fno-stack-protector +else + STACK_PROTECTOR_ENABLED := 1 + BL_COMMON_SOURCES += lib/stack_protector/stack_protector.c \ + lib/stack_protector/${ARCH}/asm_stack_protector.S + + ifeq (${ENABLE_STACK_PROTECTOR},default) + TF_CFLAGS += -fstack-protector + else + TF_CFLAGS += -fstack-protector-${ENABLE_STACK_PROTECTOR} + endif +endif + +$(eval $(call add_define,STACK_PROTECTOR_ENABLED)) diff --git a/drivers/rz/ipl/rza/lib/xlat_tables_v2/aarch64/enable_mmu.S b/drivers/rz/ipl/rza/lib/xlat_tables_v2/aarch64/enable_mmu.S new file mode 100644 index 00000000..9f075e44 --- /dev/null +++ b/drivers/rz/ipl/rza/lib/xlat_tables_v2/aarch64/enable_mmu.S @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + + .global enable_mmu_direct_el1 + .global enable_mmu_direct_el2 + .global enable_mmu_direct_el3 + + /* Macros to read and write to system register for a given EL. */ + .macro _msr reg_name, el, gp_reg + msr \reg_name\()_el\()\el, \gp_reg + .endm + + .macro _mrs gp_reg, reg_name, el + mrs \gp_reg, \reg_name\()_el\()\el + .endm + + .macro tlbi_invalidate_all el + .if \el == 1 + TLB_INVALIDATE(vmalle1) + .elseif \el == 2 + TLB_INVALIDATE(alle2) + .elseif \el == 3 + TLB_INVALIDATE(alle3) + .else + .error "EL must be 1, 2 or 3" + .endif + .endm + + /* void enable_mmu_direct_el(unsigned int flags) */ + .macro define_mmu_enable_func el + func enable_mmu_direct_\()el\el +#if ENABLE_ASSERTIONS + _mrs x1, sctlr, \el + tst x1, #SCTLR_M_BIT + ASM_ASSERT(eq) +#endif + /* Invalidate all TLB entries */ + tlbi_invalidate_all \el + + mov x7, x0 + adrp x0, mmu_cfg_params + add x0, x0, :lo12:mmu_cfg_params + + /* MAIR */ + ldr x1, [x0, #(MMU_CFG_MAIR << 3)] + _msr mair, \el, x1 + + /* TCR */ + ldr x2, [x0, #(MMU_CFG_TCR << 3)] + _msr tcr, \el, x2 + + /* TTBR */ + ldr x3, [x0, #(MMU_CFG_TTBR0 << 3)] + _msr ttbr0, \el, x3 + + /* + * Ensure all translation table writes have drained into memory, the TLB + * invalidation is complete, and translation register writes are + * committed before enabling the MMU + */ + dsb ish + isb + + /* Set and clear required fields of SCTLR */ + _mrs x4, sctlr, \el + mov_imm x5, SCTLR_WXN_BIT | SCTLR_C_BIT | SCTLR_M_BIT + orr x4, x4, x5 + + /* Additionally, amend SCTLR fields based on flags */ + bic x5, x4, #SCTLR_C_BIT + tst x7, #DISABLE_DCACHE + csel x4, x5, x4, ne + + _msr sctlr, \el, x4 + isb + + ret + endfunc enable_mmu_direct_\()el\el + .endm + + /* + * Define MMU-enabling functions for EL1, EL2 and EL3: + * + * enable_mmu_direct_el1 + * enable_mmu_direct_el2 + * enable_mmu_direct_el3 + */ + define_mmu_enable_func 1 + define_mmu_enable_func 2 + define_mmu_enable_func 3 diff --git a/drivers/rz/ipl/rza/lib/xlat_tables_v2/aarch64/xlat_tables_arch.c b/drivers/rz/ipl/rza/lib/xlat_tables_v2/aarch64/xlat_tables_arch.c new file mode 100644 index 00000000..3832b070 --- /dev/null +++ b/drivers/rz/ipl/rza/lib/xlat_tables_v2/aarch64/xlat_tables_arch.c @@ -0,0 +1,297 @@ +/* + * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "../xlat_tables_private.h" + +/* + * Returns true if the provided granule size is supported, false otherwise. + */ +bool xlat_arch_is_granule_size_supported(size_t size) +{ + u_register_t id_aa64mmfr0_el1 = read_id_aa64mmfr0_el1(); + + if (size == PAGE_SIZE_4KB) { + return ((id_aa64mmfr0_el1 >> ID_AA64MMFR0_EL1_TGRAN4_SHIFT) & + ID_AA64MMFR0_EL1_TGRAN4_MASK) == + ID_AA64MMFR0_EL1_TGRAN4_SUPPORTED; + } else if (size == PAGE_SIZE_16KB) { + return ((id_aa64mmfr0_el1 >> ID_AA64MMFR0_EL1_TGRAN16_SHIFT) & + ID_AA64MMFR0_EL1_TGRAN16_MASK) == + ID_AA64MMFR0_EL1_TGRAN16_SUPPORTED; + } else if (size == PAGE_SIZE_64KB) { + return ((id_aa64mmfr0_el1 >> ID_AA64MMFR0_EL1_TGRAN64_SHIFT) & + ID_AA64MMFR0_EL1_TGRAN64_MASK) == + ID_AA64MMFR0_EL1_TGRAN64_SUPPORTED; + } else { + return 0; + } +} + +size_t xlat_arch_get_max_supported_granule_size(void) +{ + if (xlat_arch_is_granule_size_supported(PAGE_SIZE_64KB)) { + return PAGE_SIZE_64KB; + } else if (xlat_arch_is_granule_size_supported(PAGE_SIZE_16KB)) { + return PAGE_SIZE_16KB; + } else { + assert(xlat_arch_is_granule_size_supported(PAGE_SIZE_4KB)); + return PAGE_SIZE_4KB; + } +} + +unsigned long long tcr_physical_addr_size_bits(unsigned long long max_addr) +{ + /* Physical address can't exceed 48 bits */ + assert((max_addr & ADDR_MASK_48_TO_63) == 0U); + + /* 48 bits address */ + if ((max_addr & ADDR_MASK_44_TO_47) != 0U) + return TCR_PS_BITS_256TB; + + /* 44 bits address */ + if ((max_addr & ADDR_MASK_42_TO_43) != 0U) + return TCR_PS_BITS_16TB; + + /* 42 bits address */ + if ((max_addr & ADDR_MASK_40_TO_41) != 0U) + return TCR_PS_BITS_4TB; + + /* 40 bits address */ + if ((max_addr & ADDR_MASK_36_TO_39) != 0U) + return TCR_PS_BITS_1TB; + + /* 36 bits address */ + if ((max_addr & ADDR_MASK_32_TO_35) != 0U) + return TCR_PS_BITS_64GB; + + return TCR_PS_BITS_4GB; +} + +#if ENABLE_ASSERTIONS +/* + * Physical Address ranges supported in the AArch64 Memory Model. Value 0b110 is + * supported in ARMv8.2 onwards. + */ +static const unsigned int pa_range_bits_arr[] = { + PARANGE_0000, PARANGE_0001, PARANGE_0010, PARANGE_0011, PARANGE_0100, + PARANGE_0101, PARANGE_0110 +}; + +unsigned long long xlat_arch_get_max_supported_pa(void) +{ + u_register_t pa_range = read_id_aa64mmfr0_el1() & + ID_AA64MMFR0_EL1_PARANGE_MASK; + + /* All other values are reserved */ + assert(pa_range < ARRAY_SIZE(pa_range_bits_arr)); + + return (1ULL << pa_range_bits_arr[pa_range]) - 1ULL; +} + +/* + * Return minimum virtual address space size supported by the architecture + */ +uintptr_t xlat_get_min_virt_addr_space_size(void) +{ + uintptr_t ret; + + if (is_armv8_4_ttst_present()) + ret = MIN_VIRT_ADDR_SPACE_SIZE_TTST; + else + ret = MIN_VIRT_ADDR_SPACE_SIZE; + + return ret; +} +#endif /* ENABLE_ASSERTIONS*/ + +bool is_mmu_enabled_ctx(const xlat_ctx_t *ctx) +{ + if (ctx->xlat_regime == EL1_EL0_REGIME) { + assert(xlat_arch_current_el() >= 1U); + return (read_sctlr_el1() & SCTLR_M_BIT) != 0U; + } else if (ctx->xlat_regime == EL2_REGIME) { + assert(xlat_arch_current_el() >= 2U); + return (read_sctlr_el2() & SCTLR_M_BIT) != 0U; + } else { + assert(ctx->xlat_regime == EL3_REGIME); + assert(xlat_arch_current_el() >= 3U); + return (read_sctlr_el3() & SCTLR_M_BIT) != 0U; + } +} + +bool is_dcache_enabled(void) +{ + unsigned int el = get_current_el_maybe_constant(); + + if (el == 1U) { + return (read_sctlr_el1() & SCTLR_C_BIT) != 0U; + } else if (el == 2U) { + return (read_sctlr_el2() & SCTLR_C_BIT) != 0U; + } else { + return (read_sctlr_el3() & SCTLR_C_BIT) != 0U; + } +} + +uint64_t xlat_arch_regime_get_xn_desc(int xlat_regime) +{ + if (xlat_regime == EL1_EL0_REGIME) { + return UPPER_ATTRS(UXN) | UPPER_ATTRS(PXN); + } else { + assert((xlat_regime == EL2_REGIME) || + (xlat_regime == EL3_REGIME)); + return UPPER_ATTRS(XN); + } +} + +void xlat_arch_tlbi_va(uintptr_t va, int xlat_regime) +{ + /* + * Ensure the translation table write has drained into memory before + * invalidating the TLB entry. + */ + dsbishst(); + + /* + * This function only supports invalidation of TLB entries for the EL3 + * and EL1&0 translation regimes. + * + * Also, it is architecturally UNDEFINED to invalidate TLBs of a higher + * exception level (see section D4.9.2 of the ARM ARM rev B.a). + */ + if (xlat_regime == EL1_EL0_REGIME) { + assert(xlat_arch_current_el() >= 1U); + tlbivaae1is(TLBI_ADDR(va)); + } else if (xlat_regime == EL2_REGIME) { + assert(xlat_arch_current_el() >= 2U); + tlbivae2is(TLBI_ADDR(va)); + } else { + assert(xlat_regime == EL3_REGIME); + assert(xlat_arch_current_el() >= 3U); + tlbivae3is(TLBI_ADDR(va)); + } +} + +void xlat_arch_tlbi_va_sync(void) +{ + /* + * A TLB maintenance instruction can complete at any time after + * it is issued, but is only guaranteed to be complete after the + * execution of DSB by the PE that executed the TLB maintenance + * instruction. After the TLB invalidate instruction is + * complete, no new memory accesses using the invalidated TLB + * entries will be observed by any observer of the system + * domain. See section D4.8.2 of the ARMv8 (issue k), paragraph + * "Ordering and completion of TLB maintenance instructions". + */ + dsbish(); + + /* + * The effects of a completed TLB maintenance instruction are + * only guaranteed to be visible on the PE that executed the + * instruction after the execution of an ISB instruction by the + * PE that executed the TLB maintenance instruction. + */ + isb(); +} + +unsigned int xlat_arch_current_el(void) +{ + unsigned int el = (unsigned int)GET_EL(read_CurrentEl()); + + assert(el > 0U); + + return el; +} + +void setup_mmu_cfg(uint64_t *params, unsigned int flags, + const uint64_t *base_table, unsigned long long max_pa, + uintptr_t max_va, int xlat_regime) +{ + uint64_t mair, ttbr0, tcr; + uintptr_t virtual_addr_space_size; + + /* Set attributes in the right indices of the MAIR. */ + mair = MAIR_ATTR_SET(ATTR_DEVICE, ATTR_DEVICE_INDEX); + mair |= MAIR_ATTR_SET(ATTR_IWBWA_OWBWA_NTR, ATTR_IWBWA_OWBWA_NTR_INDEX); + mair |= MAIR_ATTR_SET(ATTR_NON_CACHEABLE, ATTR_NON_CACHEABLE_INDEX); + + /* + * Limit the input address ranges and memory region sizes translated + * using TTBR0 to the given virtual address space size. + */ + assert(max_va < ((uint64_t)UINTPTR_MAX)); + + virtual_addr_space_size = (uintptr_t)max_va + 1U; + + assert(virtual_addr_space_size >= + xlat_get_min_virt_addr_space_size()); + assert(virtual_addr_space_size <= MAX_VIRT_ADDR_SPACE_SIZE); + assert(IS_POWER_OF_TWO(virtual_addr_space_size)); + + /* + * __builtin_ctzll(0) is undefined but here we are guaranteed that + * virtual_addr_space_size is in the range [1,UINTPTR_MAX]. + */ + int t0sz = 64 - __builtin_ctzll(virtual_addr_space_size); + + tcr = (uint64_t)t0sz << TCR_T0SZ_SHIFT; + + /* + * Set the cacheability and shareability attributes for memory + * associated with translation table walks. + */ + if ((flags & XLAT_TABLE_NC) != 0U) { + /* Inner & outer non-cacheable non-shareable. */ + tcr |= TCR_SH_NON_SHAREABLE | + TCR_RGN_OUTER_NC | TCR_RGN_INNER_NC; + } else { + /* Inner & outer WBWA & shareable. */ + tcr |= TCR_SH_INNER_SHAREABLE | + TCR_RGN_OUTER_WBA | TCR_RGN_INNER_WBA; + } + + /* + * It is safer to restrict the max physical address accessible by the + * hardware as much as possible. + */ + unsigned long long tcr_ps_bits = tcr_physical_addr_size_bits(max_pa); + + if (xlat_regime == EL1_EL0_REGIME) { + /* + * TCR_EL1.EPD1: Disable translation table walk for addresses + * that are translated using TTBR1_EL1. + */ + tcr |= TCR_EPD1_BIT | (tcr_ps_bits << TCR_EL1_IPS_SHIFT); + } else if (xlat_regime == EL2_REGIME) { + tcr |= TCR_EL2_RES1 | (tcr_ps_bits << TCR_EL2_PS_SHIFT); + } else { + assert(xlat_regime == EL3_REGIME); + tcr |= TCR_EL3_RES1 | (tcr_ps_bits << TCR_EL3_PS_SHIFT); + } + + /* Set TTBR bits as well */ + ttbr0 = (uint64_t) base_table; + + if (is_armv8_2_ttcnp_present()) { + /* Enable CnP bit so as to share page tables with all PEs. */ + ttbr0 |= TTBR_CNP_BIT; + } + + params[MMU_CFG_MAIR] = mair; + params[MMU_CFG_TCR] = tcr; + params[MMU_CFG_TTBR0] = ttbr0; +} diff --git a/drivers/rz/ipl/rza/lib/xlat_tables_v2/ro_xlat_tables.mk b/drivers/rz/ipl/rza/lib/xlat_tables_v2/ro_xlat_tables.mk new file mode 100644 index 00000000..7991e1af --- /dev/null +++ b/drivers/rz/ipl/rza/lib/xlat_tables_v2/ro_xlat_tables.mk @@ -0,0 +1,37 @@ +# +# Copyright (c) 2020, ARM Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +ifeq (${USE_DEBUGFS}, 1) + $(error "Debugfs requires functionality from the dynamic translation \ + library and is incompatible with ALLOW_RO_XLAT_TABLES.") +endif + +ifeq (${ARCH},aarch32) + ifeq (${RESET_TO_SP_MIN},1) + $(error "RESET_TO_SP_MIN requires functionality from the dynamic \ + translation library and is incompatible with \ + ALLOW_RO_XLAT_TABLES.") + endif +else # if AArch64 + ifeq (${PLAT},tegra) + $(error "Tegra requires functionality from the dynamic translation \ + library and is incompatible with ALLOW_RO_XLAT_TABLES.") + endif + ifeq (${RESET_TO_BL31},1) + $(error "RESET_TO_BL31 requires functionality from the dynamic \ + translation library and is incompatible with \ + ALLOW_RO_XLAT_TABLES.") + endif + ifeq (${SPD},trusty) + $(error "Trusty requires functionality from the dynamic translation \ + library and is incompatible with ALLOW_RO_XLAT_TABLES.") + endif + ifeq (${SPM_MM},1) + $(error "SPM_MM requires functionality to change memory region \ + attributes, which is not possible once the translation tables \ + have been made read-only.") + endif +endif diff --git a/drivers/rz/ipl/rza/lib/xlat_tables_v2/xlat_tables.mk b/drivers/rz/ipl/rza/lib/xlat_tables_v2/xlat_tables.mk new file mode 100644 index 00000000..bcc3e68d --- /dev/null +++ b/drivers/rz/ipl/rza/lib/xlat_tables_v2/xlat_tables.mk @@ -0,0 +1,19 @@ +# +# Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +XLAT_TABLES_LIB_SRCS := $(addprefix lib/xlat_tables_v2/, \ + ${ARCH}/enable_mmu.S \ + ${ARCH}/xlat_tables_arch.c \ + xlat_tables_context.c \ + xlat_tables_core.c \ + xlat_tables_utils.c) + +XLAT_TABLES_LIB_V2 := 1 +$(eval $(call add_define,XLAT_TABLES_LIB_V2)) + +ifeq (${ALLOW_RO_XLAT_TABLES}, 1) + include lib/xlat_tables_v2/ro_xlat_tables.mk +endif diff --git a/drivers/rz/ipl/rza/lib/xlat_tables_v2/xlat_tables_context.c b/drivers/rz/ipl/rza/lib/xlat_tables_v2/xlat_tables_context.c new file mode 100644 index 00000000..95dae88e --- /dev/null +++ b/drivers/rz/ipl/rza/lib/xlat_tables_v2/xlat_tables_context.c @@ -0,0 +1,270 @@ +/* + * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include + +#include +#include +#include + +#include "xlat_tables_private.h" + +/* + * MMU configuration register values for the active translation context. Used + * from the MMU assembly helpers. + */ +uint64_t mmu_cfg_params[MMU_CFG_PARAM_MAX]; + +/* + * Allocate and initialise the default translation context for the BL image + * currently executing. + */ +REGISTER_XLAT_CONTEXT(tf, MAX_MMAP_REGIONS, MAX_XLAT_TABLES, + PLAT_VIRT_ADDR_SPACE_SIZE, PLAT_PHY_ADDR_SPACE_SIZE); + +void mmap_add_region(unsigned long long base_pa, uintptr_t base_va, size_t size, + unsigned int attr) +{ + mmap_region_t mm = MAP_REGION(base_pa, base_va, size, attr); + + mmap_add_region_ctx(&tf_xlat_ctx, &mm); +} + +void mmap_add(const mmap_region_t *mm) +{ + mmap_add_ctx(&tf_xlat_ctx, mm); +} + +void mmap_add_region_alloc_va(unsigned long long base_pa, uintptr_t *base_va, + size_t size, unsigned int attr) +{ + mmap_region_t mm = MAP_REGION_ALLOC_VA(base_pa, size, attr); + + mmap_add_region_alloc_va_ctx(&tf_xlat_ctx, &mm); + + *base_va = mm.base_va; +} + +void mmap_add_alloc_va(mmap_region_t *mm) +{ + while (mm->granularity != 0U) { + assert(mm->base_va == 0U); + mmap_add_region_alloc_va_ctx(&tf_xlat_ctx, mm); + mm++; + } +} + +#if PLAT_XLAT_TABLES_DYNAMIC + +int mmap_add_dynamic_region(unsigned long long base_pa, uintptr_t base_va, + size_t size, unsigned int attr) +{ + mmap_region_t mm = MAP_REGION(base_pa, base_va, size, attr); + + return mmap_add_dynamic_region_ctx(&tf_xlat_ctx, &mm); +} + +int mmap_add_dynamic_region_alloc_va(unsigned long long base_pa, + uintptr_t *base_va, size_t size, + unsigned int attr) +{ + mmap_region_t mm = MAP_REGION_ALLOC_VA(base_pa, size, attr); + + int rc = mmap_add_dynamic_region_alloc_va_ctx(&tf_xlat_ctx, &mm); + + *base_va = mm.base_va; + + return rc; +} + + +int mmap_remove_dynamic_region(uintptr_t base_va, size_t size) +{ + return mmap_remove_dynamic_region_ctx(&tf_xlat_ctx, + base_va, size); +} + +#endif /* PLAT_XLAT_TABLES_DYNAMIC */ + +void __init init_xlat_tables(void) +{ + assert(tf_xlat_ctx.xlat_regime == EL_REGIME_INVALID); + + unsigned int current_el = xlat_arch_current_el(); + + if (current_el == 1U) { + tf_xlat_ctx.xlat_regime = EL1_EL0_REGIME; + } else if (current_el == 2U) { + tf_xlat_ctx.xlat_regime = EL2_REGIME; + } else { + assert(current_el == 3U); + tf_xlat_ctx.xlat_regime = EL3_REGIME; + } + + init_xlat_tables_ctx(&tf_xlat_ctx); +} + +int xlat_get_mem_attributes(uintptr_t base_va, uint32_t *attr) +{ + return xlat_get_mem_attributes_ctx(&tf_xlat_ctx, base_va, attr); +} + +int xlat_change_mem_attributes(uintptr_t base_va, size_t size, uint32_t attr) +{ + return xlat_change_mem_attributes_ctx(&tf_xlat_ctx, base_va, size, attr); +} + +#if PLAT_RO_XLAT_TABLES +/* Change the memory attributes of the descriptors which resolve the address + * range that belongs to the translation tables themselves, which are by default + * mapped as part of read-write data in the BL image's memory. + * + * Since the translation tables map themselves via these level 3 (page) + * descriptors, any change applied to them with the MMU on would introduce a + * chicken and egg problem because of the break-before-make sequence. + * Eventually, it would reach the descriptor that resolves the very table it + * belongs to and the invalidation (break step) would cause the subsequent write + * (make step) to it to generate an MMU fault. Therefore, the MMU is disabled + * before making the change. + * + * No assumption is made about what data this function needs, therefore all the + * caches are flushed in order to ensure coherency. A future optimization would + * be to only flush the required data to main memory. + */ +int xlat_make_tables_readonly(void) +{ + assert(tf_xlat_ctx.initialized == true); +#ifdef __aarch64__ + if (tf_xlat_ctx.xlat_regime == EL1_EL0_REGIME) { + disable_mmu_el1(); + } else if (tf_xlat_ctx.xlat_regime == EL3_REGIME) { + disable_mmu_el3(); + } else { + assert(tf_xlat_ctx.xlat_regime == EL2_REGIME); + return -1; + } + + /* Flush all caches. */ + dcsw_op_all(DCCISW); +#else /* !__aarch64__ */ + assert(tf_xlat_ctx.xlat_regime == EL1_EL0_REGIME); + /* On AArch32, we flush the caches before disabling the MMU. The reason + * for this is that the dcsw_op_all AArch32 function pushes some + * registers onto the stack under the assumption that it is writing to + * cache, which is not true with the MMU off. This would result in the + * stack becoming corrupted and a wrong/junk value for the LR being + * restored at the end of the routine. + */ + dcsw_op_all(DC_OP_CISW); + disable_mmu_secure(); +#endif + + int rc = xlat_change_mem_attributes_ctx(&tf_xlat_ctx, + (uintptr_t)tf_xlat_ctx.tables, + tf_xlat_ctx.tables_num * XLAT_TABLE_SIZE, + MT_RO_DATA | MT_SECURE); + +#ifdef __aarch64__ + if (tf_xlat_ctx.xlat_regime == EL1_EL0_REGIME) { + enable_mmu_el1(0U); + } else { + assert(tf_xlat_ctx.xlat_regime == EL3_REGIME); + enable_mmu_el3(0U); + } +#else /* !__aarch64__ */ + enable_mmu_svc_mon(0U); +#endif + + if (rc == 0) { + tf_xlat_ctx.readonly_tables = true; + } + + return rc; +} +#endif /* PLAT_RO_XLAT_TABLES */ + +/* + * If dynamic allocation of new regions is disabled then by the time we call the + * function enabling the MMU, we'll have registered all the memory regions to + * map for the system's lifetime. Therefore, at this point we know the maximum + * physical address that will ever be mapped. + * + * If dynamic allocation is enabled then we can't make any such assumption + * because the maximum physical address could get pushed while adding a new + * region. Therefore, in this case we have to assume that the whole address + * space size might be mapped. + */ +#ifdef PLAT_XLAT_TABLES_DYNAMIC +#define MAX_PHYS_ADDR tf_xlat_ctx.pa_max_address +#else +#define MAX_PHYS_ADDR tf_xlat_ctx.max_pa +#endif + +#ifdef __aarch64__ + +void enable_mmu_el1(unsigned int flags) +{ + setup_mmu_cfg((uint64_t *)&mmu_cfg_params, flags, + tf_xlat_ctx.base_table, MAX_PHYS_ADDR, + tf_xlat_ctx.va_max_address, EL1_EL0_REGIME); + enable_mmu_direct_el1(flags); +} + +void enable_mmu_el2(unsigned int flags) +{ + setup_mmu_cfg((uint64_t *)&mmu_cfg_params, flags, + tf_xlat_ctx.base_table, MAX_PHYS_ADDR, + tf_xlat_ctx.va_max_address, EL2_REGIME); + enable_mmu_direct_el2(flags); +} + +void enable_mmu_el3(unsigned int flags) +{ + setup_mmu_cfg((uint64_t *)&mmu_cfg_params, flags, + tf_xlat_ctx.base_table, MAX_PHYS_ADDR, + tf_xlat_ctx.va_max_address, EL3_REGIME); + enable_mmu_direct_el3(flags); +} + +void enable_mmu(unsigned int flags) +{ + switch (get_current_el_maybe_constant()) { + case 1: + enable_mmu_el1(flags); + break; + case 2: + enable_mmu_el2(flags); + break; + case 3: + enable_mmu_el3(flags); + break; + default: + panic(); + } +} + +#else /* !__aarch64__ */ + +void enable_mmu_svc_mon(unsigned int flags) +{ + setup_mmu_cfg((uint64_t *)&mmu_cfg_params, flags, + tf_xlat_ctx.base_table, MAX_PHYS_ADDR, + tf_xlat_ctx.va_max_address, EL1_EL0_REGIME); + enable_mmu_direct_svc_mon(flags); +} + +void enable_mmu_hyp(unsigned int flags) +{ + setup_mmu_cfg((uint64_t *)&mmu_cfg_params, flags, + tf_xlat_ctx.base_table, MAX_PHYS_ADDR, + tf_xlat_ctx.va_max_address, EL2_REGIME); + enable_mmu_direct_hyp(flags); +} + +#endif /* __aarch64__ */ diff --git a/drivers/rz/ipl/rza/lib/xlat_tables_v2/xlat_tables_core.c b/drivers/rz/ipl/rza/lib/xlat_tables_v2/xlat_tables_core.c new file mode 100644 index 00000000..bb6d1845 --- /dev/null +++ b/drivers/rz/ipl/rza/lib/xlat_tables_v2/xlat_tables_core.c @@ -0,0 +1,1241 @@ +/* + * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include "xlat_tables_private.h" + +/* Helper function that cleans the data cache only if it is enabled. */ +static inline __attribute__((unused)) void xlat_clean_dcache_range(uintptr_t addr, size_t size) +{ + if (is_dcache_enabled()) + clean_dcache_range(addr, size); +} + +#if PLAT_XLAT_TABLES_DYNAMIC + +/* + * The following functions assume that they will be called using subtables only. + * The base table can't be unmapped, so it is not needed to do any special + * handling for it. + */ + +/* + * Returns the index of the array corresponding to the specified translation + * table. + */ +static int xlat_table_get_index(const xlat_ctx_t *ctx, const uint64_t *table) +{ + for (int i = 0; i < ctx->tables_num; i++) + if (ctx->tables[i] == table) + return i; + + /* + * Maybe we were asked to get the index of the base level table, which + * should never happen. + */ + assert(false); + + return -1; +} + +/* Returns a pointer to an empty translation table. */ +static uint64_t *xlat_table_get_empty(const xlat_ctx_t *ctx) +{ + for (int i = 0; i < ctx->tables_num; i++) + if (ctx->tables_mapped_regions[i] == 0) + return ctx->tables[i]; + + return NULL; +} + +/* Increments region count for a given table. */ +static void xlat_table_inc_regions_count(const xlat_ctx_t *ctx, + const uint64_t *table) +{ + int idx = xlat_table_get_index(ctx, table); + + ctx->tables_mapped_regions[idx]++; +} + +/* Decrements region count for a given table. */ +static void xlat_table_dec_regions_count(const xlat_ctx_t *ctx, + const uint64_t *table) +{ + int idx = xlat_table_get_index(ctx, table); + + ctx->tables_mapped_regions[idx]--; +} + +/* Returns 0 if the specified table isn't empty, otherwise 1. */ +static bool xlat_table_is_empty(const xlat_ctx_t *ctx, const uint64_t *table) +{ + return ctx->tables_mapped_regions[xlat_table_get_index(ctx, table)] == 0; +} + +#else /* PLAT_XLAT_TABLES_DYNAMIC */ + +/* Returns a pointer to the first empty translation table. */ +static uint64_t *xlat_table_get_empty(xlat_ctx_t *ctx) +{ + assert(ctx->next_table < ctx->tables_num); + + return ctx->tables[ctx->next_table++]; +} + +#endif /* PLAT_XLAT_TABLES_DYNAMIC */ + +/* + * Returns a block/page table descriptor for the given level and attributes. + */ +uint64_t xlat_desc(const xlat_ctx_t *ctx, uint32_t attr, + unsigned long long addr_pa, unsigned int level) +{ + uint64_t desc; + uint32_t mem_type; + uint32_t shareability_type; + + /* Make sure that the granularity is fine enough to map this address. */ + assert((addr_pa & XLAT_BLOCK_MASK(level)) == 0U); + + desc = addr_pa; + /* + * There are different translation table descriptors for level 3 and the + * rest. + */ + desc |= (level == XLAT_TABLE_LEVEL_MAX) ? PAGE_DESC : BLOCK_DESC; + /* + * Always set the access flag, as this library assumes access flag + * faults aren't managed. + */ + desc |= LOWER_ATTRS(ACCESS_FLAG); + /* + * Deduce other fields of the descriptor based on the MT_NS and MT_RW + * memory region attributes. + */ + desc |= ((attr & MT_NS) != 0U) ? LOWER_ATTRS(NS) : 0U; + desc |= ((attr & MT_RW) != 0U) ? LOWER_ATTRS(AP_RW) : LOWER_ATTRS(AP_RO); + + /* + * Do not allow unprivileged access when the mapping is for a privileged + * EL. For translation regimes that do not have mappings for access for + * lower exception levels, set AP[2] to AP_NO_ACCESS_UNPRIVILEGED. + */ + if (ctx->xlat_regime == EL1_EL0_REGIME) { + if ((attr & MT_USER) != 0U) { + /* EL0 mapping requested, so we give User access */ + desc |= LOWER_ATTRS(AP_ACCESS_UNPRIVILEGED); + } else { + /* EL1 mapping requested, no User access granted */ + desc |= LOWER_ATTRS(AP_NO_ACCESS_UNPRIVILEGED); + } + } else { + assert((ctx->xlat_regime == EL2_REGIME) || + (ctx->xlat_regime == EL3_REGIME)); + desc |= LOWER_ATTRS(AP_ONE_VA_RANGE_RES1); + } + + /* + * Deduce shareability domain and executability of the memory region + * from the memory type of the attributes (MT_TYPE). + * + * Data accesses to device memory and non-cacheable normal memory are + * coherent for all observers in the system, and correspondingly are + * always treated as being Outer Shareable. Therefore, for these 2 types + * of memory, it is not strictly needed to set the shareability field + * in the translation tables. + */ + mem_type = MT_TYPE(attr); + if (mem_type == MT_DEVICE) { + desc |= LOWER_ATTRS(ATTR_DEVICE_INDEX | OSH); + /* + * Always map device memory as execute-never. + * This is to avoid the possibility of a speculative instruction + * fetch, which could be an issue if this memory region + * corresponds to a read-sensitive peripheral. + */ + desc |= xlat_arch_regime_get_xn_desc(ctx->xlat_regime); + + } else { /* Normal memory */ + /* + * Always map read-write normal memory as execute-never. + * This library assumes that it is used by software that does + * not self-modify its code, therefore R/W memory is reserved + * for data storage, which must not be executable. + * + * Note that setting the XN bit here is for consistency only. + * The function that enables the MMU sets the SCTLR_ELx.WXN bit, + * which makes any writable memory region to be treated as + * execute-never, regardless of the value of the XN bit in the + * translation table. + * + * For read-only memory, rely on the MT_EXECUTE/MT_EXECUTE_NEVER + * attribute to figure out the value of the XN bit. The actual + * XN bit(s) to set in the descriptor depends on the context's + * translation regime and the policy applied in + * xlat_arch_regime_get_xn_desc(). + */ + if (((attr & MT_RW) != 0U) || ((attr & MT_EXECUTE_NEVER) != 0U)) { + desc |= xlat_arch_regime_get_xn_desc(ctx->xlat_regime); + } + + shareability_type = MT_SHAREABILITY(attr); + if (mem_type == MT_MEMORY) { + desc |= LOWER_ATTRS(ATTR_IWBWA_OWBWA_NTR_INDEX); + if (shareability_type == MT_SHAREABILITY_NSH) { + desc |= LOWER_ATTRS(NSH); + } else if (shareability_type == MT_SHAREABILITY_OSH) { + desc |= LOWER_ATTRS(OSH); + } else { + desc |= LOWER_ATTRS(ISH); + } + + /* Check if Branch Target Identification is enabled */ +#if ENABLE_BTI + /* Set GP bit for block and page code entries + * if BTI mechanism is implemented. + */ + if (is_armv8_5_bti_present() && + ((attr & (MT_TYPE_MASK | MT_RW | + MT_EXECUTE_NEVER)) == MT_CODE)) { + desc |= GP; + } +#endif + } else { + assert(mem_type == MT_NON_CACHEABLE); + desc |= LOWER_ATTRS(ATTR_NON_CACHEABLE_INDEX | OSH); + } + } + + return desc; +} + +/* + * Enumeration of actions that can be made when mapping table entries depending + * on the previous value in that entry and information about the region being + * mapped. + */ +typedef enum { + + /* Do nothing */ + ACTION_NONE, + + /* Write a block (or page, if in level 3) entry. */ + ACTION_WRITE_BLOCK_ENTRY, + + /* + * Create a new table and write a table entry pointing to it. Recurse + * into it for further processing. + */ + ACTION_CREATE_NEW_TABLE, + + /* + * There is a table descriptor in this entry, read it and recurse into + * that table for further processing. + */ + ACTION_RECURSE_INTO_TABLE, + +} action_t; + +/* + * Function that returns the first VA of the table affected by the specified + * mmap region. + */ +static uintptr_t xlat_tables_find_start_va(mmap_region_t *mm, + const uintptr_t table_base_va, + const unsigned int level) +{ + uintptr_t table_idx_va; + + if (mm->base_va > table_base_va) { + /* Find the first index of the table affected by the region. */ + table_idx_va = mm->base_va & ~XLAT_BLOCK_MASK(level); + } else { + /* Start from the beginning of the table. */ + table_idx_va = table_base_va; + } + + return table_idx_va; +} + +/* + * Function that returns table index for the given VA and level arguments. + */ +static inline unsigned int xlat_tables_va_to_index(const uintptr_t table_base_va, + const uintptr_t va, + const unsigned int level) +{ + return (unsigned int)((va - table_base_va) >> XLAT_ADDR_SHIFT(level)); +} + +#if PLAT_XLAT_TABLES_DYNAMIC + +/* + * From the given arguments, it decides which action to take when unmapping the + * specified region. + */ +static action_t xlat_tables_unmap_region_action(const mmap_region_t *mm, + const uintptr_t table_idx_va, const uintptr_t table_idx_end_va, + const unsigned int level, const uint64_t desc_type) +{ + action_t action; + uintptr_t region_end_va = mm->base_va + mm->size - 1U; + + if ((mm->base_va <= table_idx_va) && + (region_end_va >= table_idx_end_va)) { + /* Region covers all block */ + + if (level == 3U) { + /* + * Last level, only page descriptors allowed, + * erase it. + */ + assert(desc_type == PAGE_DESC); + + action = ACTION_WRITE_BLOCK_ENTRY; + } else { + /* + * Other levels can have table descriptors. If + * so, recurse into it and erase descriptors + * inside it as needed. If there is a block + * descriptor, just erase it. If an invalid + * descriptor is found, this table isn't + * actually mapped, which shouldn't happen. + */ + if (desc_type == TABLE_DESC) { + action = ACTION_RECURSE_INTO_TABLE; + } else { + assert(desc_type == BLOCK_DESC); + action = ACTION_WRITE_BLOCK_ENTRY; + } + } + + } else if ((mm->base_va <= table_idx_end_va) || + (region_end_va >= table_idx_va)) { + /* + * Region partially covers block. + * + * It can't happen in level 3. + * + * There must be a table descriptor here, if not there + * was a problem when mapping the region. + */ + assert(level < 3U); + assert(desc_type == TABLE_DESC); + + action = ACTION_RECURSE_INTO_TABLE; + } else { + /* The region doesn't cover the block at all */ + action = ACTION_NONE; + } + + return action; +} +/* + * Recursive function that writes to the translation tables and unmaps the + * specified region. + */ +static void xlat_tables_unmap_region(xlat_ctx_t *ctx, mmap_region_t *mm, + const uintptr_t table_base_va, + uint64_t *const table_base, + const unsigned int table_entries, + const unsigned int level) +{ + assert((level >= ctx->base_level) && (level <= XLAT_TABLE_LEVEL_MAX)); + + uint64_t *subtable; + uint64_t desc; + + uintptr_t table_idx_va; + uintptr_t table_idx_end_va; /* End VA of this entry */ + + uintptr_t region_end_va = mm->base_va + mm->size - 1U; + + unsigned int table_idx; + + table_idx_va = xlat_tables_find_start_va(mm, table_base_va, level); + table_idx = xlat_tables_va_to_index(table_base_va, table_idx_va, level); + + while (table_idx < table_entries) { + + table_idx_end_va = table_idx_va + XLAT_BLOCK_SIZE(level) - 1U; + + desc = table_base[table_idx]; + uint64_t desc_type = desc & DESC_MASK; + + action_t action = xlat_tables_unmap_region_action(mm, + table_idx_va, table_idx_end_va, level, + desc_type); + + if (action == ACTION_WRITE_BLOCK_ENTRY) { + + table_base[table_idx] = INVALID_DESC; + xlat_arch_tlbi_va(table_idx_va, ctx->xlat_regime); + + } else if (action == ACTION_RECURSE_INTO_TABLE) { + + subtable = (uint64_t *)(uintptr_t)(desc & TABLE_ADDR_MASK); + + /* Recurse to write into subtable */ + xlat_tables_unmap_region(ctx, mm, table_idx_va, + subtable, XLAT_TABLE_ENTRIES, + level + 1U); +#if !(HW_ASSISTED_COHERENCY || WARMBOOT_ENABLE_DCACHE_EARLY) + xlat_clean_dcache_range((uintptr_t)subtable, + XLAT_TABLE_ENTRIES * sizeof(uint64_t)); +#endif + /* + * If the subtable is now empty, remove its reference. + */ + if (xlat_table_is_empty(ctx, subtable)) { + table_base[table_idx] = INVALID_DESC; + xlat_arch_tlbi_va(table_idx_va, + ctx->xlat_regime); + } + + } else { + assert(action == ACTION_NONE); + } + + table_idx++; + table_idx_va += XLAT_BLOCK_SIZE(level); + + /* If reached the end of the region, exit */ + if (region_end_va <= table_idx_va) + break; + } + + if (level > ctx->base_level) + xlat_table_dec_regions_count(ctx, table_base); +} + +#endif /* PLAT_XLAT_TABLES_DYNAMIC */ + +/* + * From the given arguments, it decides which action to take when mapping the + * specified region. + */ +static action_t xlat_tables_map_region_action(const mmap_region_t *mm, + unsigned int desc_type, unsigned long long dest_pa, + uintptr_t table_entry_base_va, unsigned int level) +{ + uintptr_t mm_end_va = mm->base_va + mm->size - 1U; + uintptr_t table_entry_end_va = + table_entry_base_va + XLAT_BLOCK_SIZE(level) - 1U; + + /* + * The descriptor types allowed depend on the current table level. + */ + + if ((mm->base_va <= table_entry_base_va) && + (mm_end_va >= table_entry_end_va)) { + + /* + * Table entry is covered by region + * -------------------------------- + * + * This means that this table entry can describe the whole + * translation with this granularity in principle. + */ + + if (level == 3U) { + /* + * Last level, only page descriptors are allowed. + */ + if (desc_type == PAGE_DESC) { + /* + * There's another region mapped here, don't + * overwrite. + */ + return ACTION_NONE; + } else { + assert(desc_type == INVALID_DESC); + return ACTION_WRITE_BLOCK_ENTRY; + } + + } else { + + /* + * Other levels. Table descriptors are allowed. Block + * descriptors too, but they have some limitations. + */ + + if (desc_type == TABLE_DESC) { + /* There's already a table, recurse into it. */ + return ACTION_RECURSE_INTO_TABLE; + + } else if (desc_type == INVALID_DESC) { + /* + * There's nothing mapped here, create a new + * entry. + * + * Check if the destination granularity allows + * us to use a block descriptor or we need a + * finer table for it. + * + * Also, check if the current level allows block + * descriptors. If not, create a table instead. + */ + if (((dest_pa & XLAT_BLOCK_MASK(level)) != 0U) + || (level < MIN_LVL_BLOCK_DESC) || + (mm->granularity < XLAT_BLOCK_SIZE(level))) + return ACTION_CREATE_NEW_TABLE; + else + return ACTION_WRITE_BLOCK_ENTRY; + + } else { + /* + * There's another region mapped here, don't + * overwrite. + */ + assert(desc_type == BLOCK_DESC); + + return ACTION_NONE; + } + } + + } else if ((mm->base_va <= table_entry_end_va) || + (mm_end_va >= table_entry_base_va)) { + + /* + * Region partially covers table entry + * ----------------------------------- + * + * This means that this table entry can't describe the whole + * translation, a finer table is needed. + + * There cannot be partial block overlaps in level 3. If that + * happens, some of the preliminary checks when adding the + * mmap region failed to detect that PA and VA must at least be + * aligned to PAGE_SIZE. + */ + assert(level < 3U); + + if (desc_type == INVALID_DESC) { + /* + * The block is not fully covered by the region. Create + * a new table, recurse into it and try to map the + * region with finer granularity. + */ + return ACTION_CREATE_NEW_TABLE; + + } else { + assert(desc_type == TABLE_DESC); + /* + * The block is not fully covered by the region, but + * there is already a table here. Recurse into it and + * try to map with finer granularity. + * + * PAGE_DESC for level 3 has the same value as + * TABLE_DESC, but this code can't run on a level 3 + * table because there can't be overlaps in level 3. + */ + return ACTION_RECURSE_INTO_TABLE; + } + } else { + + /* + * This table entry is outside of the region specified in the + * arguments, don't write anything to it. + */ + return ACTION_NONE; + } +} + +/* + * Recursive function that writes to the translation tables and maps the + * specified region. On success, it returns the VA of the last byte that was + * successfully mapped. On error, it returns the VA of the next entry that + * should have been mapped. + */ +static uintptr_t xlat_tables_map_region(xlat_ctx_t *ctx, mmap_region_t *mm, + uintptr_t table_base_va, + uint64_t *const table_base, + unsigned int table_entries, + unsigned int level) +{ + assert((level >= ctx->base_level) && (level <= XLAT_TABLE_LEVEL_MAX)); + + uintptr_t mm_end_va = mm->base_va + mm->size - 1U; + + uintptr_t table_idx_va; + unsigned long long table_idx_pa; + + uint64_t *subtable; + uint64_t desc; + + unsigned int table_idx; + + table_idx_va = xlat_tables_find_start_va(mm, table_base_va, level); + table_idx = xlat_tables_va_to_index(table_base_va, table_idx_va, level); + +#if PLAT_XLAT_TABLES_DYNAMIC + if (level > ctx->base_level) + xlat_table_inc_regions_count(ctx, table_base); +#endif + + while (table_idx < table_entries) { + + desc = table_base[table_idx]; + + table_idx_pa = mm->base_pa + table_idx_va - mm->base_va; + + action_t action = xlat_tables_map_region_action(mm, + (uint32_t)(desc & DESC_MASK), table_idx_pa, + table_idx_va, level); + + if (action == ACTION_WRITE_BLOCK_ENTRY) { + + table_base[table_idx] = + xlat_desc(ctx, (uint32_t)mm->attr, table_idx_pa, + level); + + } else if (action == ACTION_CREATE_NEW_TABLE) { + uintptr_t end_va; + + subtable = xlat_table_get_empty(ctx); + if (subtable == NULL) { + /* Not enough free tables to map this region */ + return table_idx_va; + } + + /* Point to new subtable from this one. */ + table_base[table_idx] = + TABLE_DESC | (uintptr_t)subtable; + + /* Recurse to write into subtable */ + end_va = xlat_tables_map_region(ctx, mm, table_idx_va, + subtable, XLAT_TABLE_ENTRIES, + level + 1U); +#if !(HW_ASSISTED_COHERENCY || WARMBOOT_ENABLE_DCACHE_EARLY) + xlat_clean_dcache_range((uintptr_t)subtable, + XLAT_TABLE_ENTRIES * sizeof(uint64_t)); +#endif + if (end_va != + (table_idx_va + XLAT_BLOCK_SIZE(level) - 1U)) + return end_va; + + } else if (action == ACTION_RECURSE_INTO_TABLE) { + uintptr_t end_va; + + subtable = (uint64_t *)(uintptr_t)(desc & TABLE_ADDR_MASK); + /* Recurse to write into subtable */ + end_va = xlat_tables_map_region(ctx, mm, table_idx_va, + subtable, XLAT_TABLE_ENTRIES, + level + 1U); +#if !(HW_ASSISTED_COHERENCY || WARMBOOT_ENABLE_DCACHE_EARLY) + xlat_clean_dcache_range((uintptr_t)subtable, + XLAT_TABLE_ENTRIES * sizeof(uint64_t)); +#endif + if (end_va != + (table_idx_va + XLAT_BLOCK_SIZE(level) - 1U)) + return end_va; + + } else { + + assert(action == ACTION_NONE); + + } + + table_idx++; + table_idx_va += XLAT_BLOCK_SIZE(level); + + /* If reached the end of the region, exit */ + if (mm_end_va <= table_idx_va) + break; + } + + return table_idx_va - 1U; +} + +/* + * Function that verifies that a region can be mapped. + * Returns: + * 0: Success, the mapping is allowed. + * EINVAL: Invalid values were used as arguments. + * ERANGE: The memory limits were surpassed. + * ENOMEM: There is not enough memory in the mmap array. + * EPERM: Region overlaps another one in an invalid way. + */ +static int mmap_add_region_check(const xlat_ctx_t *ctx, const mmap_region_t *mm) +{ + unsigned long long base_pa = mm->base_pa; + uintptr_t base_va = mm->base_va; + size_t size = mm->size; + size_t granularity = mm->granularity; + + unsigned long long end_pa = base_pa + size - 1U; + uintptr_t end_va = base_va + size - 1U; + + if (!IS_PAGE_ALIGNED(base_pa) || !IS_PAGE_ALIGNED(base_va) || + !IS_PAGE_ALIGNED(size)) + return -EINVAL; + + if ((granularity != XLAT_BLOCK_SIZE(1U)) && + (granularity != XLAT_BLOCK_SIZE(2U)) && + (granularity != XLAT_BLOCK_SIZE(3U))) { + return -EINVAL; + } + + /* Check for overflows */ + if ((base_pa > end_pa) || (base_va > end_va)) + return -ERANGE; + + if (end_va > ctx->va_max_address) + return -ERANGE; + + if (end_pa > ctx->pa_max_address) + return -ERANGE; + + /* Check that there is space in the ctx->mmap array */ + if (ctx->mmap[ctx->mmap_num - 1].size != 0U) + return -ENOMEM; + + /* Check for PAs and VAs overlaps with all other regions */ + for (const mmap_region_t *mm_cursor = ctx->mmap; + mm_cursor->size != 0U; ++mm_cursor) { + + uintptr_t mm_cursor_end_va = mm_cursor->base_va + + mm_cursor->size - 1U; + + /* + * Check if one of the regions is completely inside the other + * one. + */ + bool fully_overlapped_va = + ((base_va >= mm_cursor->base_va) && + (end_va <= mm_cursor_end_va)) || + ((mm_cursor->base_va >= base_va) && + (mm_cursor_end_va <= end_va)); + + /* + * Full VA overlaps are only allowed if both regions are + * identity mapped (zero offset) or have the same VA to PA + * offset. Also, make sure that it's not the exact same area. + * This can only be done with static regions. + */ + if (fully_overlapped_va) { + +#if PLAT_XLAT_TABLES_DYNAMIC + if (((mm->attr & MT_DYNAMIC) != 0U) || + ((mm_cursor->attr & MT_DYNAMIC) != 0U)) + return -EPERM; +#endif /* PLAT_XLAT_TABLES_DYNAMIC */ + if ((mm_cursor->base_va - mm_cursor->base_pa) != + (base_va - base_pa)) + return -EPERM; + + if ((base_va == mm_cursor->base_va) && + (size == mm_cursor->size)) + return -EPERM; + + } else { + /* + * If the regions do not have fully overlapping VAs, + * then they must have fully separated VAs and PAs. + * Partial overlaps are not allowed + */ + + unsigned long long mm_cursor_end_pa = + mm_cursor->base_pa + mm_cursor->size - 1U; + + bool separated_pa = (end_pa < mm_cursor->base_pa) || + (base_pa > mm_cursor_end_pa); + bool separated_va = (end_va < mm_cursor->base_va) || + (base_va > mm_cursor_end_va); + + if (!separated_va || !separated_pa) + return -EPERM; + } + } + + return 0; +} + +void mmap_add_region_ctx(xlat_ctx_t *ctx, const mmap_region_t *mm) +{ + mmap_region_t *mm_cursor = ctx->mmap, *mm_destination; + const mmap_region_t *mm_end = ctx->mmap + ctx->mmap_num; + const mmap_region_t *mm_last; + unsigned long long end_pa = mm->base_pa + mm->size - 1U; + uintptr_t end_va = mm->base_va + mm->size - 1U; + int ret; + + /* Ignore empty regions */ + if (mm->size == 0U) + return; + + /* Static regions must be added before initializing the xlat tables. */ + assert(!ctx->initialized); + + ret = mmap_add_region_check(ctx, mm); + if (ret != 0) { + ERROR("mmap_add_region_check() failed. error %d\n", ret); + assert(false); + return; + } + + /* + * Find correct place in mmap to insert new region. + * + * 1 - Lower region VA end first. + * 2 - Smaller region size first. + * + * VA 0 0xFF + * + * 1st |------| + * 2nd |------------| + * 3rd |------| + * 4th |---| + * 5th |---| + * 6th |----------| + * 7th |-------------------------------------| + * + * This is required for overlapping regions only. It simplifies adding + * regions with the loop in xlat_tables_init_internal because the outer + * ones won't overwrite block or page descriptors of regions added + * previously. + * + * Overlapping is only allowed for static regions. + */ + + while (((mm_cursor->base_va + mm_cursor->size - 1U) < end_va) + && (mm_cursor->size != 0U)) { + ++mm_cursor; + } + + while (((mm_cursor->base_va + mm_cursor->size - 1U) == end_va) && + (mm_cursor->size != 0U) && (mm_cursor->size < mm->size)) { + ++mm_cursor; + } + + /* + * Find the last entry marker in the mmap + */ + mm_last = ctx->mmap; + while ((mm_last->size != 0U) && (mm_last < mm_end)) { + ++mm_last; + } + + /* + * Check if we have enough space in the memory mapping table. + * This shouldn't happen as we have checked in mmap_add_region_check + * that there is free space. + */ + assert(mm_last->size == 0U); + + /* Make room for new region by moving other regions up by one place */ + mm_destination = mm_cursor + 1; + (void)memmove(mm_destination, mm_cursor, + (uintptr_t)mm_last - (uintptr_t)mm_cursor); + + /* + * Check we haven't lost the empty sentinel from the end of the array. + * This shouldn't happen as we have checked in mmap_add_region_check + * that there is free space. + */ + assert(mm_end->size == 0U); + + *mm_cursor = *mm; + + if (end_pa > ctx->max_pa) + ctx->max_pa = end_pa; + if (end_va > ctx->max_va) + ctx->max_va = end_va; +} + +/* + * Determine the table level closest to the initial lookup level that + * can describe this translation. Then, align base VA to the next block + * at the determined level. + */ +static void mmap_alloc_va_align_ctx(xlat_ctx_t *ctx, mmap_region_t *mm) +{ + /* + * By or'ing the size and base PA the alignment will be the one + * corresponding to the smallest boundary of the two of them. + * + * There are three different cases. For example (for 4 KiB page size): + * + * +--------------+------------------++--------------+ + * | PA alignment | Size multiple of || VA alignment | + * +--------------+------------------++--------------+ + * | 2 MiB | 2 MiB || 2 MiB | (1) + * | 2 MiB | 4 KiB || 4 KiB | (2) + * | 4 KiB | 2 MiB || 4 KiB | (3) + * +--------------+------------------++--------------+ + * + * - In (1), it is possible to take advantage of the alignment of the PA + * and the size of the region to use a level 2 translation table + * instead of a level 3 one. + * + * - In (2), the size is smaller than a block entry of level 2, so it is + * needed to use a level 3 table to describe the region or the library + * will map more memory than the desired one. + * + * - In (3), even though the region has the size of one level 2 block + * entry, it isn't possible to describe the translation with a level 2 + * block entry because of the alignment of the base PA. + * + * Only bits 47:21 of a level 2 block descriptor are used by the MMU, + * bits 20:0 of the resulting address are 0 in this case. Because of + * this, the PA generated as result of this translation is aligned to + * 2 MiB. The PA that was requested to be mapped is aligned to 4 KiB, + * though, which means that the resulting translation is incorrect. + * The only way to prevent this is by using a finer granularity. + */ + unsigned long long align_check; + + align_check = mm->base_pa | (unsigned long long)mm->size; + + /* + * Assume it is always aligned to level 3. There's no need to check that + * level because its block size is PAGE_SIZE. The checks to verify that + * the addresses and size are aligned to PAGE_SIZE are inside + * mmap_add_region. + */ + for (unsigned int level = ctx->base_level; level <= 2U; ++level) { + + if ((align_check & XLAT_BLOCK_MASK(level)) != 0U) + continue; + + mm->base_va = round_up(mm->base_va, XLAT_BLOCK_SIZE(level)); + return; + } +} + +void mmap_add_region_alloc_va_ctx(xlat_ctx_t *ctx, mmap_region_t *mm) +{ + mm->base_va = ctx->max_va + 1UL; + + assert(mm->size > 0U); + + mmap_alloc_va_align_ctx(ctx, mm); + + /* Detect overflows. More checks are done in mmap_add_region_check(). */ + assert(mm->base_va > ctx->max_va); + + mmap_add_region_ctx(ctx, mm); +} + +void mmap_add_ctx(xlat_ctx_t *ctx, const mmap_region_t *mm) +{ + const mmap_region_t *mm_cursor = mm; + + while (mm_cursor->granularity != 0U) { + mmap_add_region_ctx(ctx, mm_cursor); + mm_cursor++; + } +} + +#if PLAT_XLAT_TABLES_DYNAMIC + +int mmap_add_dynamic_region_ctx(xlat_ctx_t *ctx, mmap_region_t *mm) +{ + mmap_region_t *mm_cursor = ctx->mmap; + const mmap_region_t *mm_last = mm_cursor + ctx->mmap_num; + unsigned long long end_pa = mm->base_pa + mm->size - 1U; + uintptr_t end_va = mm->base_va + mm->size - 1U; + int ret; + + /* Nothing to do */ + if (mm->size == 0U) + return 0; + + /* Now this region is a dynamic one */ + mm->attr |= MT_DYNAMIC; + + ret = mmap_add_region_check(ctx, mm); + if (ret != 0) + return ret; + + /* + * Find the adequate entry in the mmap array in the same way done for + * static regions in mmap_add_region_ctx(). + */ + + while (((mm_cursor->base_va + mm_cursor->size - 1U) < end_va) + && (mm_cursor->size != 0U)) { + ++mm_cursor; + } + + while (((mm_cursor->base_va + mm_cursor->size - 1U) == end_va) && + (mm_cursor->size != 0U) && (mm_cursor->size < mm->size)) { + ++mm_cursor; + } + + /* Make room for new region by moving other regions up by one place */ + (void)memmove(mm_cursor + 1U, mm_cursor, + (uintptr_t)mm_last - (uintptr_t)mm_cursor); + + /* + * Check we haven't lost the empty sentinal from the end of the array. + * This shouldn't happen as we have checked in mmap_add_region_check + * that there is free space. + */ + assert(mm_last->size == 0U); + + *mm_cursor = *mm; + + /* + * Update the translation tables if the xlat tables are initialized. If + * not, this region will be mapped when they are initialized. + */ + if (ctx->initialized) { + end_va = xlat_tables_map_region(ctx, mm_cursor, + 0U, ctx->base_table, ctx->base_table_entries, + ctx->base_level); +#if !(HW_ASSISTED_COHERENCY || WARMBOOT_ENABLE_DCACHE_EARLY) + xlat_clean_dcache_range((uintptr_t)ctx->base_table, + ctx->base_table_entries * sizeof(uint64_t)); +#endif + /* Failed to map, remove mmap entry, unmap and return error. */ + if (end_va != (mm_cursor->base_va + mm_cursor->size - 1U)) { + (void)memmove(mm_cursor, mm_cursor + 1U, + (uintptr_t)mm_last - (uintptr_t)mm_cursor); + + /* + * Check if the mapping function actually managed to map + * anything. If not, just return now. + */ + if (mm->base_va >= end_va) + return -ENOMEM; + + /* + * Something went wrong after mapping some table + * entries, undo every change done up to this point. + */ + mmap_region_t unmap_mm = { + .base_pa = 0U, + .base_va = mm->base_va, + .size = end_va - mm->base_va, + .attr = 0U + }; + xlat_tables_unmap_region(ctx, &unmap_mm, 0U, + ctx->base_table, ctx->base_table_entries, + ctx->base_level); +#if !(HW_ASSISTED_COHERENCY || WARMBOOT_ENABLE_DCACHE_EARLY) + xlat_clean_dcache_range((uintptr_t)ctx->base_table, + ctx->base_table_entries * sizeof(uint64_t)); +#endif + return -ENOMEM; + } + + /* + * Make sure that all entries are written to the memory. There + * is no need to invalidate entries when mapping dynamic regions + * because new table/block/page descriptors only replace old + * invalid descriptors, that aren't TLB cached. + */ + dsbishst(); + } + + if (end_pa > ctx->max_pa) + ctx->max_pa = end_pa; + if (end_va > ctx->max_va) + ctx->max_va = end_va; + + return 0; +} + +int mmap_add_dynamic_region_alloc_va_ctx(xlat_ctx_t *ctx, mmap_region_t *mm) +{ + mm->base_va = ctx->max_va + 1UL; + + if (mm->size == 0U) + return 0; + + mmap_alloc_va_align_ctx(ctx, mm); + + /* Detect overflows. More checks are done in mmap_add_region_check(). */ + if (mm->base_va < ctx->max_va) { + return -ENOMEM; + } + + return mmap_add_dynamic_region_ctx(ctx, mm); +} + +/* + * Removes the region with given base Virtual Address and size from the given + * context. + * + * Returns: + * 0: Success. + * EINVAL: Invalid values were used as arguments (region not found). + * EPERM: Tried to remove a static region. + */ +int mmap_remove_dynamic_region_ctx(xlat_ctx_t *ctx, uintptr_t base_va, + size_t size) +{ + mmap_region_t *mm = ctx->mmap; + const mmap_region_t *mm_last = mm + ctx->mmap_num; + int update_max_va_needed = 0; + int update_max_pa_needed = 0; + + /* Check sanity of mmap array. */ + assert(mm[ctx->mmap_num].size == 0U); + + while (mm->size != 0U) { + if ((mm->base_va == base_va) && (mm->size == size)) + break; + ++mm; + } + + /* Check that the region was found */ + if (mm->size == 0U) + return -EINVAL; + + /* If the region is static it can't be removed */ + if ((mm->attr & MT_DYNAMIC) == 0U) + return -EPERM; + + /* Check if this region is using the top VAs or PAs. */ + if ((mm->base_va + mm->size - 1U) == ctx->max_va) + update_max_va_needed = 1; + if ((mm->base_pa + mm->size - 1U) == ctx->max_pa) + update_max_pa_needed = 1; + + /* Update the translation tables if needed */ + if (ctx->initialized) { + xlat_tables_unmap_region(ctx, mm, 0U, ctx->base_table, + ctx->base_table_entries, + ctx->base_level); +#if !(HW_ASSISTED_COHERENCY || WARMBOOT_ENABLE_DCACHE_EARLY) + xlat_clean_dcache_range((uintptr_t)ctx->base_table, + ctx->base_table_entries * sizeof(uint64_t)); +#endif + xlat_arch_tlbi_va_sync(); + } + + /* Remove this region by moving the rest down by one place. */ + (void)memmove(mm, mm + 1U, (uintptr_t)mm_last - (uintptr_t)mm); + + /* Check if we need to update the max VAs and PAs */ + if (update_max_va_needed == 1) { + ctx->max_va = 0U; + mm = ctx->mmap; + while (mm->size != 0U) { + if ((mm->base_va + mm->size - 1U) > ctx->max_va) + ctx->max_va = mm->base_va + mm->size - 1U; + ++mm; + } + } + + if (update_max_pa_needed == 1) { + ctx->max_pa = 0U; + mm = ctx->mmap; + while (mm->size != 0U) { + if ((mm->base_pa + mm->size - 1U) > ctx->max_pa) + ctx->max_pa = mm->base_pa + mm->size - 1U; + ++mm; + } + } + + return 0; +} + +void xlat_setup_dynamic_ctx(xlat_ctx_t *ctx, unsigned long long pa_max, + uintptr_t va_max, struct mmap_region *mmap, + unsigned int mmap_num, uint64_t **tables, + unsigned int tables_num, uint64_t *base_table, + int xlat_regime, int *mapped_regions) +{ + ctx->xlat_regime = xlat_regime; + + ctx->pa_max_address = pa_max; + ctx->va_max_address = va_max; + + ctx->mmap = mmap; + ctx->mmap_num = mmap_num; + memset(ctx->mmap, 0, sizeof(struct mmap_region) * mmap_num); + + ctx->tables = (void *) tables; + ctx->tables_num = tables_num; + + uintptr_t va_space_size = va_max + 1; + ctx->base_level = GET_XLAT_TABLE_LEVEL_BASE(va_space_size); + ctx->base_table = base_table; + ctx->base_table_entries = GET_NUM_BASE_LEVEL_ENTRIES(va_space_size); + + ctx->tables_mapped_regions = mapped_regions; + + ctx->max_pa = 0; + ctx->max_va = 0; + ctx->initialized = 0; +} + +#endif /* PLAT_XLAT_TABLES_DYNAMIC */ + +void __init init_xlat_tables_ctx(xlat_ctx_t *ctx) +{ + assert(ctx != NULL); + assert(!ctx->initialized); + assert((ctx->xlat_regime == EL3_REGIME) || + (ctx->xlat_regime == EL2_REGIME) || + (ctx->xlat_regime == EL1_EL0_REGIME)); + assert(!is_mmu_enabled_ctx(ctx)); + + mmap_region_t *mm = ctx->mmap; + + assert(ctx->va_max_address >= + (xlat_get_min_virt_addr_space_size() - 1U)); + assert(ctx->va_max_address <= (MAX_VIRT_ADDR_SPACE_SIZE - 1U)); + assert(IS_POWER_OF_TWO(ctx->va_max_address + 1U)); + + xlat_mmap_print(mm); + + /* All tables must be zeroed before mapping any region. */ + + for (unsigned int i = 0U; i < ctx->base_table_entries; i++) + ctx->base_table[i] = INVALID_DESC; + + for (int j = 0; j < ctx->tables_num; j++) { +#if PLAT_XLAT_TABLES_DYNAMIC + ctx->tables_mapped_regions[j] = 0; +#endif + for (unsigned int i = 0U; i < XLAT_TABLE_ENTRIES; i++) + ctx->tables[j][i] = INVALID_DESC; + } + + while (mm->size != 0U) { + uintptr_t end_va = xlat_tables_map_region(ctx, mm, 0U, + ctx->base_table, ctx->base_table_entries, + ctx->base_level); +#if !(HW_ASSISTED_COHERENCY || WARMBOOT_ENABLE_DCACHE_EARLY) + xlat_clean_dcache_range((uintptr_t)ctx->base_table, + ctx->base_table_entries * sizeof(uint64_t)); +#endif + if (end_va != (mm->base_va + mm->size - 1U)) { + ERROR("Not enough memory to map region:\n" + " VA:0x%lx PA:0x%llx size:0x%zx attr:0x%x\n", + mm->base_va, mm->base_pa, mm->size, mm->attr); + panic(); + } + + mm++; + } + + assert(ctx->pa_max_address <= xlat_arch_get_max_supported_pa()); + assert(ctx->max_va <= ctx->va_max_address); + assert(ctx->max_pa <= ctx->pa_max_address); + + ctx->initialized = true; + + xlat_tables_print(ctx); +} diff --git a/drivers/rz/ipl/rza/lib/xlat_tables_v2/xlat_tables_private.h b/drivers/rz/ipl/rza/lib/xlat_tables_v2/xlat_tables_private.h new file mode 100644 index 00000000..863470cf --- /dev/null +++ b/drivers/rz/ipl/rza/lib/xlat_tables_v2/xlat_tables_private.h @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef XLAT_TABLES_PRIVATE_H +#define XLAT_TABLES_PRIVATE_H + +#include + +#include + +#include + +#if PLAT_XLAT_TABLES_DYNAMIC +/* + * Private shifts and masks to access fields of an mmap attribute + */ +/* Dynamic or static */ +#define MT_DYN_SHIFT U(31) + +/* + * Memory mapping private attributes + * + * Private attributes not exposed in the public header. + */ + +/* + * Regions mapped before the MMU can't be unmapped dynamically (they are + * static) and regions mapped with MMU enabled can be unmapped. This + * behaviour can't be overridden. + * + * Static regions can overlap each other, dynamic regions can't. + */ +#define MT_STATIC (U(0) << MT_DYN_SHIFT) +#define MT_DYNAMIC (U(1) << MT_DYN_SHIFT) + +#endif /* PLAT_XLAT_TABLES_DYNAMIC */ + +extern uint64_t mmu_cfg_params[MMU_CFG_PARAM_MAX]; + +/* + * Return the execute-never mask that will prevent instruction fetch at the + * given translation regime. + */ +uint64_t xlat_arch_regime_get_xn_desc(int xlat_regime); + +/* + * Invalidate all TLB entries that match the given virtual address. This + * operation applies to all PEs in the same Inner Shareable domain as the PE + * that executes this function. This functions must be called for every + * translation table entry that is modified. It only affects the specified + * translation regime. + * + * Note, however, that it is architecturally UNDEFINED to invalidate TLB entries + * pertaining to a higher exception level, e.g. invalidating EL3 entries from + * S-EL1. + */ +void xlat_arch_tlbi_va(uintptr_t va, int xlat_regime); + +/* + * This function has to be called at the end of any code that uses the function + * xlat_arch_tlbi_va(). + */ +void xlat_arch_tlbi_va_sync(void); + +/* Print VA, PA, size and attributes of all regions in the mmap array. */ +void xlat_mmap_print(const mmap_region_t *mmap); + +/* + * Print the current state of the translation tables by reading them from + * memory. + */ +void xlat_tables_print(xlat_ctx_t *ctx); + +/* + * Returns a block/page table descriptor for the given level and attributes. + */ +uint64_t xlat_desc(const xlat_ctx_t *ctx, uint32_t attr, + unsigned long long addr_pa, unsigned int level); + +/* + * Architecture-specific initialization code. + */ + +/* Returns the current Exception Level. The returned EL must be 1 or higher. */ +unsigned int xlat_arch_current_el(void); + +/* + * Return the maximum physical address supported by the hardware. + * This value depends on the execution state (AArch32/AArch64). + */ +unsigned long long xlat_arch_get_max_supported_pa(void); + +/* + * Returns true if the MMU of the translation regime managed by the given + * xlat_ctx_t is enabled, false otherwise. + */ +bool is_mmu_enabled_ctx(const xlat_ctx_t *ctx); + +/* + * Returns minimum virtual address space size supported by the architecture + */ +uintptr_t xlat_get_min_virt_addr_space_size(void); + +#endif /* XLAT_TABLES_PRIVATE_H */ diff --git a/drivers/rz/ipl/rza/lib/xlat_tables_v2/xlat_tables_utils.c b/drivers/rz/ipl/rza/lib/xlat_tables_v2/xlat_tables_utils.c new file mode 100644 index 00000000..9fae7e91 --- /dev/null +++ b/drivers/rz/ipl/rza/lib/xlat_tables_v2/xlat_tables_utils.c @@ -0,0 +1,575 @@ +/* + * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +#include "xlat_tables_private.h" + +#if LOG_LEVEL < LOG_LEVEL_VERBOSE + +void xlat_mmap_print(__unused const mmap_region_t *mmap) +{ + /* Empty */ +} + +void xlat_tables_print(__unused xlat_ctx_t *ctx) +{ + /* Empty */ +} + +#else /* if LOG_LEVEL >= LOG_LEVEL_VERBOSE */ + +void xlat_mmap_print(const mmap_region_t *mmap) +{ + printf("mmap:\n"); + const mmap_region_t *mm = mmap; + + while (mm->size != 0U) { + printf(" VA:0x%lx PA:0x%llx size:0x%zx attr:0x%x granularity:0x%zx\n", + mm->base_va, mm->base_pa, mm->size, mm->attr, + mm->granularity); + ++mm; + }; + printf("\n"); +} + +/* Print the attributes of the specified block descriptor. */ +static void xlat_desc_print(const xlat_ctx_t *ctx, uint64_t desc) +{ + uint64_t mem_type_index = ATTR_INDEX_GET(desc); + int xlat_regime = ctx->xlat_regime; + + if (mem_type_index == ATTR_IWBWA_OWBWA_NTR_INDEX) { + printf("MEM"); + } else if (mem_type_index == ATTR_NON_CACHEABLE_INDEX) { + printf("NC"); + } else { + assert(mem_type_index == ATTR_DEVICE_INDEX); + printf("DEV"); + } + + if ((xlat_regime == EL3_REGIME) || (xlat_regime == EL2_REGIME)) { + /* For EL3 and EL2 only check the AP[2] and XN bits. */ + printf(((desc & LOWER_ATTRS(AP_RO)) != 0ULL) ? "-RO" : "-RW"); + printf(((desc & UPPER_ATTRS(XN)) != 0ULL) ? "-XN" : "-EXEC"); + } else { + assert(xlat_regime == EL1_EL0_REGIME); + /* + * For EL0 and EL1: + * - In AArch64 PXN and UXN can be set independently but in + * AArch32 there is no UXN (XN affects both privilege levels). + * For consistency, we set them simultaneously in both cases. + * - RO and RW permissions must be the same in EL1 and EL0. If + * EL0 can access that memory region, so can EL1, with the + * same permissions. + */ +#if ENABLE_ASSERTIONS + uint64_t xn_mask = xlat_arch_regime_get_xn_desc(EL1_EL0_REGIME); + uint64_t xn_perm = desc & xn_mask; + + assert((xn_perm == xn_mask) || (xn_perm == 0ULL)); +#endif + printf(((desc & LOWER_ATTRS(AP_RO)) != 0ULL) ? "-RO" : "-RW"); + /* Only check one of PXN and UXN, the other one is the same. */ + printf(((desc & UPPER_ATTRS(PXN)) != 0ULL) ? "-XN" : "-EXEC"); + /* + * Privileged regions can only be accessed from EL1, user + * regions can be accessed from EL1 and EL0. + */ + printf(((desc & LOWER_ATTRS(AP_ACCESS_UNPRIVILEGED)) != 0ULL) + ? "-USER" : "-PRIV"); + } + + printf(((LOWER_ATTRS(NS) & desc) != 0ULL) ? "-NS" : "-S"); + +#ifdef __aarch64__ + /* Check Guarded Page bit */ + if ((desc & GP) != 0ULL) { + printf("-GP"); + } +#endif +} + +static const char * const level_spacers[] = { + "[LV0] ", + " [LV1] ", + " [LV2] ", + " [LV3] " +}; + +static const char *invalid_descriptors_ommited = + "%s(%d invalid descriptors omitted)\n"; + +/* + * Recursive function that reads the translation tables passed as an argument + * and prints their status. + */ +static void xlat_tables_print_internal(xlat_ctx_t *ctx, uintptr_t table_base_va, + const uint64_t *table_base, unsigned int table_entries, + unsigned int level) +{ + assert(level <= XLAT_TABLE_LEVEL_MAX); + + uint64_t desc; + uintptr_t table_idx_va = table_base_va; + unsigned int table_idx = 0U; + size_t level_size = XLAT_BLOCK_SIZE(level); + + /* + * Keep track of how many invalid descriptors are counted in a row. + * Whenever multiple invalid descriptors are found, only the first one + * is printed, and a line is added to inform about how many descriptors + * have been omitted. + */ + int invalid_row_count = 0; + + while (table_idx < table_entries) { + + desc = table_base[table_idx]; + + if ((desc & DESC_MASK) == INVALID_DESC) { + + if (invalid_row_count == 0) { + printf("%sVA:0x%lx size:0x%zx\n", + level_spacers[level], + table_idx_va, level_size); + } + invalid_row_count++; + + } else { + + if (invalid_row_count > 1) { + printf(invalid_descriptors_ommited, + level_spacers[level], + invalid_row_count - 1); + } + invalid_row_count = 0; + + /* + * Check if this is a table or a block. Tables are only + * allowed in levels other than 3, but DESC_PAGE has the + * same value as DESC_TABLE, so we need to check. + */ + if (((desc & DESC_MASK) == TABLE_DESC) && + (level < XLAT_TABLE_LEVEL_MAX)) { + /* + * Do not print any PA for a table descriptor, + * as it doesn't directly map physical memory + * but instead points to the next translation + * table in the translation table walk. + */ + printf("%sVA:0x%lx size:0x%zx\n", + level_spacers[level], + table_idx_va, level_size); + + uintptr_t addr_inner = desc & TABLE_ADDR_MASK; + + xlat_tables_print_internal(ctx, table_idx_va, + (uint64_t *)addr_inner, + XLAT_TABLE_ENTRIES, level + 1U); + } else { + printf("%sVA:0x%lx PA:0x%llx size:0x%zx ", + level_spacers[level], table_idx_va, + (uint64_t)(desc & TABLE_ADDR_MASK), + level_size); + xlat_desc_print(ctx, desc); + printf("\n"); + } + } + + table_idx++; + table_idx_va += level_size; + } + + if (invalid_row_count > 1) { + printf(invalid_descriptors_ommited, + level_spacers[level], invalid_row_count - 1); + } +} + +void xlat_tables_print(xlat_ctx_t *ctx) +{ + const char *xlat_regime_str; + int used_page_tables; + + if (ctx->xlat_regime == EL1_EL0_REGIME) { + xlat_regime_str = "1&0"; + } else if (ctx->xlat_regime == EL2_REGIME) { + xlat_regime_str = "2"; + } else { + assert(ctx->xlat_regime == EL3_REGIME); + xlat_regime_str = "3"; + } + VERBOSE("Translation tables state:\n"); + VERBOSE(" Xlat regime: EL%s\n", xlat_regime_str); + VERBOSE(" Max allowed PA: 0x%llx\n", ctx->pa_max_address); + VERBOSE(" Max allowed VA: 0x%lx\n", ctx->va_max_address); + VERBOSE(" Max mapped PA: 0x%llx\n", ctx->max_pa); + VERBOSE(" Max mapped VA: 0x%lx\n", ctx->max_va); + + VERBOSE(" Initial lookup level: %u\n", ctx->base_level); + VERBOSE(" Entries @initial lookup level: %u\n", + ctx->base_table_entries); + +#if PLAT_XLAT_TABLES_DYNAMIC + used_page_tables = 0; + for (int i = 0; i < ctx->tables_num; ++i) { + if (ctx->tables_mapped_regions[i] != 0) + ++used_page_tables; + } +#else + used_page_tables = ctx->next_table; +#endif + VERBOSE(" Used %d sub-tables out of %d (spare: %d)\n", + used_page_tables, ctx->tables_num, + ctx->tables_num - used_page_tables); + + xlat_tables_print_internal(ctx, 0U, ctx->base_table, + ctx->base_table_entries, ctx->base_level); +} + +#endif /* LOG_LEVEL >= LOG_LEVEL_VERBOSE */ + +/* + * Do a translation table walk to find the block or page descriptor that maps + * virtual_addr. + * + * On success, return the address of the descriptor within the translation + * table. Its lookup level is stored in '*out_level'. + * On error, return NULL. + * + * xlat_table_base + * Base address for the initial lookup level. + * xlat_table_base_entries + * Number of entries in the translation table for the initial lookup level. + * virt_addr_space_size + * Size in bytes of the virtual address space. + */ +static uint64_t *find_xlat_table_entry(uintptr_t virtual_addr, + void *xlat_table_base, + unsigned int xlat_table_base_entries, + unsigned long long virt_addr_space_size, + unsigned int *out_level) +{ + unsigned int start_level; + uint64_t *table; + unsigned int entries; + + start_level = GET_XLAT_TABLE_LEVEL_BASE(virt_addr_space_size); + + table = xlat_table_base; + entries = xlat_table_base_entries; + + for (unsigned int level = start_level; + level <= XLAT_TABLE_LEVEL_MAX; + ++level) { + uint64_t idx, desc, desc_type; + + idx = XLAT_TABLE_IDX(virtual_addr, level); + if (idx >= entries) { + WARN("Missing xlat table entry at address 0x%lx\n", + virtual_addr); + return NULL; + } + + desc = table[idx]; + desc_type = desc & DESC_MASK; + + if (desc_type == INVALID_DESC) { + VERBOSE("Invalid entry (memory not mapped)\n"); + return NULL; + } + + if (level == XLAT_TABLE_LEVEL_MAX) { + /* + * Only page descriptors allowed at the final lookup + * level. + */ + assert(desc_type == PAGE_DESC); + *out_level = level; + return &table[idx]; + } + + if (desc_type == BLOCK_DESC) { + *out_level = level; + return &table[idx]; + } + + assert(desc_type == TABLE_DESC); + table = (uint64_t *)(uintptr_t)(desc & TABLE_ADDR_MASK); + entries = XLAT_TABLE_ENTRIES; + } + + /* + * This shouldn't be reached, the translation table walk should end at + * most at level XLAT_TABLE_LEVEL_MAX and return from inside the loop. + */ + assert(false); + + return NULL; +} + + +static int xlat_get_mem_attributes_internal(const xlat_ctx_t *ctx, + uintptr_t base_va, uint32_t *attributes, uint64_t **table_entry, + unsigned long long *addr_pa, unsigned int *table_level) +{ + uint64_t *entry; + uint64_t desc; + unsigned int level; + unsigned long long virt_addr_space_size; + + /* + * Sanity-check arguments. + */ + assert(ctx != NULL); + assert(ctx->initialized); + assert((ctx->xlat_regime == EL1_EL0_REGIME) || + (ctx->xlat_regime == EL2_REGIME) || + (ctx->xlat_regime == EL3_REGIME)); + + virt_addr_space_size = (unsigned long long)ctx->va_max_address + 1ULL; + assert(virt_addr_space_size > 0U); + + entry = find_xlat_table_entry(base_va, + ctx->base_table, + ctx->base_table_entries, + virt_addr_space_size, + &level); + if (entry == NULL) { + WARN("Address 0x%lx is not mapped.\n", base_va); + return -EINVAL; + } + + if (addr_pa != NULL) { + *addr_pa = *entry & TABLE_ADDR_MASK; + } + + if (table_entry != NULL) { + *table_entry = entry; + } + + if (table_level != NULL) { + *table_level = level; + } + + desc = *entry; + +#if LOG_LEVEL >= LOG_LEVEL_VERBOSE + VERBOSE("Attributes: "); + xlat_desc_print(ctx, desc); + printf("\n"); +#endif /* LOG_LEVEL >= LOG_LEVEL_VERBOSE */ + + assert(attributes != NULL); + *attributes = 0U; + + uint64_t attr_index = (desc >> ATTR_INDEX_SHIFT) & ATTR_INDEX_MASK; + + if (attr_index == ATTR_IWBWA_OWBWA_NTR_INDEX) { + *attributes |= MT_MEMORY; + } else if (attr_index == ATTR_NON_CACHEABLE_INDEX) { + *attributes |= MT_NON_CACHEABLE; + } else { + assert(attr_index == ATTR_DEVICE_INDEX); + *attributes |= MT_DEVICE; + } + + uint64_t ap2_bit = (desc >> AP2_SHIFT) & 1U; + + if (ap2_bit == AP2_RW) + *attributes |= MT_RW; + + if (ctx->xlat_regime == EL1_EL0_REGIME) { + uint64_t ap1_bit = (desc >> AP1_SHIFT) & 1U; + + if (ap1_bit == AP1_ACCESS_UNPRIVILEGED) + *attributes |= MT_USER; + } + + uint64_t ns_bit = (desc >> NS_SHIFT) & 1U; + + if (ns_bit == 1U) + *attributes |= MT_NS; + + uint64_t xn_mask = xlat_arch_regime_get_xn_desc(ctx->xlat_regime); + + if ((desc & xn_mask) == xn_mask) { + *attributes |= MT_EXECUTE_NEVER; + } else { + assert((desc & xn_mask) == 0U); + } + + return 0; +} + + +int xlat_get_mem_attributes_ctx(const xlat_ctx_t *ctx, uintptr_t base_va, + uint32_t *attr) +{ + return xlat_get_mem_attributes_internal(ctx, base_va, attr, + NULL, NULL, NULL); +} + + +int xlat_change_mem_attributes_ctx(const xlat_ctx_t *ctx, uintptr_t base_va, + size_t size, uint32_t attr) +{ + /* Note: This implementation isn't optimized. */ + + assert(ctx != NULL); + assert(ctx->initialized); + + unsigned long long virt_addr_space_size = + (unsigned long long)ctx->va_max_address + 1U; + assert(virt_addr_space_size > 0U); + + if (!IS_PAGE_ALIGNED(base_va)) { + WARN("%s: Address 0x%lx is not aligned on a page boundary.\n", + __func__, base_va); + return -EINVAL; + } + + if (size == 0U) { + WARN("%s: Size is 0.\n", __func__); + return -EINVAL; + } + + if ((size % PAGE_SIZE) != 0U) { + WARN("%s: Size 0x%zx is not a multiple of a page size.\n", + __func__, size); + return -EINVAL; + } + + if (((attr & MT_EXECUTE_NEVER) == 0U) && ((attr & MT_RW) != 0U)) { + WARN("%s: Mapping memory as read-write and executable not allowed.\n", + __func__); + return -EINVAL; + } + + size_t pages_count = size / PAGE_SIZE; + + VERBOSE("Changing memory attributes of %zu pages starting from address 0x%lx...\n", + pages_count, base_va); + + uintptr_t base_va_original = base_va; + + /* + * Sanity checks. + */ + for (unsigned int i = 0U; i < pages_count; ++i) { + const uint64_t *entry; + uint64_t desc, attr_index; + unsigned int level; + + entry = find_xlat_table_entry(base_va, + ctx->base_table, + ctx->base_table_entries, + virt_addr_space_size, + &level); + if (entry == NULL) { + WARN("Address 0x%lx is not mapped.\n", base_va); + return -EINVAL; + } + + desc = *entry; + + /* + * Check that all the required pages are mapped at page + * granularity. + */ + if (((desc & DESC_MASK) != PAGE_DESC) || + (level != XLAT_TABLE_LEVEL_MAX)) { + WARN("Address 0x%lx is not mapped at the right granularity.\n", + base_va); + WARN("Granularity is 0x%lx, should be 0x%lx.\n", + XLAT_BLOCK_SIZE(level), PAGE_SIZE); + return -EINVAL; + } + + /* + * If the region type is device, it shouldn't be executable. + */ + attr_index = (desc >> ATTR_INDEX_SHIFT) & ATTR_INDEX_MASK; + if (attr_index == ATTR_DEVICE_INDEX) { + if ((attr & MT_EXECUTE_NEVER) == 0U) { + WARN("Setting device memory as executable at address 0x%lx.", + base_va); + return -EINVAL; + } + } + + base_va += PAGE_SIZE; + } + + /* Restore original value. */ + base_va = base_va_original; + + for (unsigned int i = 0U; i < pages_count; ++i) { + + uint32_t old_attr = 0U, new_attr; + uint64_t *entry = NULL; + unsigned int level = 0U; + unsigned long long addr_pa = 0ULL; + + (void) xlat_get_mem_attributes_internal(ctx, base_va, &old_attr, + &entry, &addr_pa, &level); + + /* + * From attr, only MT_RO/MT_RW, MT_EXECUTE/MT_EXECUTE_NEVER and + * MT_USER/MT_PRIVILEGED are taken into account. Any other + * information is ignored. + */ + + /* Clean the old attributes so that they can be rebuilt. */ + new_attr = old_attr & ~(MT_RW | MT_EXECUTE_NEVER | MT_USER); + + /* + * Update attributes, but filter out the ones this function + * isn't allowed to change. + */ + new_attr |= attr & (MT_RW | MT_EXECUTE_NEVER | MT_USER); + + /* + * The break-before-make sequence requires writing an invalid + * descriptor and making sure that the system sees the change + * before writing the new descriptor. + */ + *entry = INVALID_DESC; +#if !HW_ASSISTED_COHERENCY + dccvac((uintptr_t)entry); +#endif + /* Invalidate any cached copy of this mapping in the TLBs. */ + xlat_arch_tlbi_va(base_va, ctx->xlat_regime); + + /* Ensure completion of the invalidation. */ + xlat_arch_tlbi_va_sync(); + + /* Write new descriptor */ + *entry = xlat_desc(ctx, new_attr, addr_pa, level); +#if !HW_ASSISTED_COHERENCY + dccvac((uintptr_t)entry); +#endif + base_va += PAGE_SIZE; + } + + /* Ensure that the last descriptor writen is seen by the system. */ + dsbish(); + + return 0; +} diff --git a/drivers/rz/ipl/rza/license.rst b/drivers/rz/ipl/rza/license.rst new file mode 100644 index 00000000..f0caa39b --- /dev/null +++ b/drivers/rz/ipl/rza/license.rst @@ -0,0 +1,89 @@ +License +======= + +The software is provided under a BSD-3-Clause license (below). Contributions to +this project are accepted under the same license with developer sign-off as +described in the :ref:`Contributor's Guide`. + +:: + + Copyright (c) [XXXX-]YYYY, . All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + - Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + - 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. + + - Neither the name of Arm 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. + +SPDX Identifiers +---------------- + +Individual files contain the following tag instead of the full license text. + +:: + + SPDX-License-Identifier: BSD-3-Clause + +This enables machine processing of license information based on the SPDX +License Identifiers that are here available: http://spdx.org/licenses/ + + +Other Projects +-------------- + +This project contains code from other projects as listed below. The original +license text is included in those source files. + +- The libc source code is derived from `FreeBSD`_ and `SCC`_. FreeBSD uses + various BSD licenses, including BSD-3-Clause and BSD-2-Clause. The SCC code + is used under the BSD-3-Clause license with the author's permission. + +- The libfdt source code is disjunctively dual licensed + (GPL-2.0+ OR BSD-2-Clause). It is used by this project under the terms of + the BSD-2-Clause license. Any contributions to this code must be made under + the terms of both licenses. + +- The LLVM compiler-rt source code is disjunctively dual licensed + (NCSA OR MIT). It is used by this project under the terms of the NCSA + license (also known as the University of Illinois/NCSA Open Source License), + which is a permissive license compatible with BSD-3-Clause. Any + contributions to this code must be made under the terms of both licenses. + +- The zlib source code is licensed under the Zlib license, which is a + permissive license compatible with BSD-3-Clause. + +- Some STMicroelectronics platform source code is disjunctively dual licensed + (GPL-2.0+ OR BSD-3-Clause). It is used by this project under the terms of the + BSD-3-Clause license. Any contributions to this code must be made under the + terms of both licenses. + +- Some source files originating from the Linux source tree, which are + disjunctively dual licensed (GPL-2.0 OR MIT), are redistributed under the + terms of the MIT license. These files are: + + - ``include/dt-bindings/interrupt-controller/arm-gic.h`` + + See the original `Linux MIT license`_. + +.. _FreeBSD: http://www.freebsd.org +.. _Linux MIT license: https://raw.githubusercontent.com/torvalds/linux/master/LICENSES/preferred/MIT +.. _SCC: http://www.simple-cc.org/ diff --git a/drivers/rz/ipl/rza/licenses/LICENSE.MIT b/drivers/rz/ipl/rza/licenses/LICENSE.MIT new file mode 100644 index 00000000..8aa26455 --- /dev/null +++ b/drivers/rz/ipl/rza/licenses/LICENSE.MIT @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) [year] [fullname] + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/drivers/rz/ipl/rza/make_helpers/armv7-a-cpus.mk b/drivers/rz/ipl/rza/make_helpers/armv7-a-cpus.mk new file mode 100644 index 00000000..eec85cc1 --- /dev/null +++ b/drivers/rz/ipl/rza/make_helpers/armv7-a-cpus.mk @@ -0,0 +1,58 @@ +# +# Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +ifneq (${ARCH},aarch32) +$(error ARM_ARCH_MAJOR=7 mandates ARCH=aarch32) +endif + +# For ARMv7, set march32 from platform directive ARMV7_CORTEX_Ax=yes +# and ARM_WITH_NEON=yes/no. +# +# GCC and Clang require -march=armv7-a for C-A9 and -march=armv7ve for C-A15. +# armClang requires -march=armv7-a for all ARMv7 Cortex-A. To comply with +# all, just drop -march and supply only -mcpu. + +# Platform can override march32-directive through MARCH32_DIRECTIVE +ifdef MARCH32_DIRECTIVE +march32-directive := $(MARCH32_DIRECTIVE) +else +march32-set-${ARM_CORTEX_A5} := -mcpu=cortex-a5 +march32-set-${ARM_CORTEX_A7} := -mcpu=cortex-a7 +march32-set-${ARM_CORTEX_A9} := -mcpu=cortex-a9 +march32-set-${ARM_CORTEX_A12} := -mcpu=cortex-a12 +march32-set-${ARM_CORTEX_A15} := -mcpu=cortex-a15 +march32-set-${ARM_CORTEX_A17} := -mcpu=cortex-a17 +march32-neon-$(ARM_WITH_NEON) := -mfpu=neon + +# default to -march=armv7-a as target directive +march32-set-yes ?= -march=armv7-a +march32-directive := ${march32-set-yes} ${march32-neon-yes} +endif + +# Platform may override these extension support directives: +# +# ARMV7_SUPPORTS_LARGE_PAGE_ADDRESSING +# Defined if core supports the Large Page Addressing extension. +# +# ARMV7_SUPPORTS_VIRTUALIZATION +# Defined if ARMv7 core supports the Virtualization extension. +# +# ARMV7_SUPPORTS_GENERIC_TIMER +# Defined if ARMv7 core supports the Generic Timer extension. + +ifeq ($(filter yes,$(ARM_CORTEX_A7) $(ARM_CORTEX_A12) $(ARM_CORTEX_A15) $(ARM_CORTEX_A17)),yes) +$(eval $(call add_defines,\ + $(sort \ + ARMV7_SUPPORTS_LARGE_PAGE_ADDRESSING \ + ARMV7_SUPPORTS_VIRTUALIZATION \ + ARMV7_SUPPORTS_GENERIC_TIMER \ + ARMV7_SUPPORTS_VFP \ +))) +endif + +ifeq ($(ARM_CORTEX_A5),yes) +$(eval $(call add_define,ARM_CORTEX_A5)) +endif diff --git a/drivers/rz/ipl/rza/make_helpers/build_env.mk b/drivers/rz/ipl/rza/make_helpers/build_env.mk new file mode 100644 index 00000000..83093bd6 --- /dev/null +++ b/drivers/rz/ipl/rza/make_helpers/build_env.mk @@ -0,0 +1,72 @@ +# +# Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# This file contains the logic to identify and include any relevant +# build environment specific make include files. + +ifndef BUILD_ENV_MK + BUILD_ENV_MK := $(lastword $(MAKEFILE_LIST)) + + # Block possible built-in command definitions that are not fully portable. + # This traps occurences that need replacing with our OS portable macros + COPY := $$(error "Replace COPY with call to SHELL_COPY or SHELL_COPY_TREE.") + CP := $$(error "Replace CP with call to SHELL_COPY or SHELL_COPY_TREE.") + DEL := $$(error "Replace DEL with call to SHELL_DELETE.") + MD := $$(error "Replace MD with call to MAKE_PREREQ_DIR.") + MKDIR := $$(error "Replace MKDIR with call to MAKE_PREREQ_DIR.") + RD := $$(error "Replace RD with call to SHELL_REMOVE_DIR.") + RM := $$(error "Replace RM with call to SHELL_DELETE.") + RMDIR := $$(error "Replace RMDIR with call to SHELL_REMOVE_DIR.") + + ENV_FILE_TO_INCLUDE := unix.mk + ifdef OSTYPE + ifneq ($(findstring ${OSTYPE}, cygwin),) + ENV_FILE_TO_INCLUDE := cygwin.mk + else + ifneq ($(findstring ${OSTYPE}, MINGW32 mingw msys),) + ENV_FILE_TO_INCLUDE := msys.mk + endif + endif + else + ifdef MSYSTEM + # Although the MINGW MSYS shell sets OSTYPE as msys in its environment, + # it does not appear in the GNU make view of environment variables. + # We use MSYSTEM as an alternative, as that is seen by make + ifneq ($(findstring ${MSYSTEM}, MINGW32 mingw msys),) + OSTYPE ?= msys + ENV_FILE_TO_INCLUDE := msys.mk + endif + else + ifdef OS + ifneq ($(findstring ${OS}, Windows_NT),) + ENV_FILE_TO_INCLUDE := windows.mk + endif + endif + endif + endif + include ${MAKE_HELPERS_DIRECTORY}${ENV_FILE_TO_INCLUDE} + ENV_FILE_TO_INCLUDE := + + ifndef SHELL_COPY + $(error "SHELL_COPY not defined for build environment.") + endif + ifndef SHELL_COPY_TREE + $(error "SHELL_COPY_TREE not defined for build environment.") + endif + ifndef SHELL_DELETE_ALL + $(error "SHELL_DELETE_ALL not defined for build environment.") + endif + ifndef SHELL_DELETE + $(error "SHELL_DELETE not defined for build environment.") + endif + ifndef MAKE_PREREQ_DIR + $(error "MAKE_PREREQ_DIR not defined for build environment.") + endif + ifndef SHELL_REMOVE_DIR + $(error "SHELL_REMOVE_DIR not defined for build environment.") + endif + +endif diff --git a/drivers/rz/ipl/rza/make_helpers/build_macros.mk b/drivers/rz/ipl/rza/make_helpers/build_macros.mk new file mode 100644 index 00000000..86550288 --- /dev/null +++ b/drivers/rz/ipl/rza/make_helpers/build_macros.mk @@ -0,0 +1,614 @@ +# +# Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# Report an error if the eval make function is not available. +$(eval eval_available := T) +ifneq (${eval_available},T) + $(error This makefile only works with a Make program that supports $$(eval)) +endif + +# Some utility macros for manipulating awkward (whitespace) characters. +blank := +space :=${blank} ${blank} + +# A user defined function to recursively search for a filename below a directory +# $1 is the directory root of the recursive search (blank for current directory). +# $2 is the file name to search for. +define rwildcard +$(strip $(foreach d,$(wildcard ${1}*),$(call rwildcard,${d}/,${2}) $(filter $(subst *,%,%${2}),${d}))) +endef + +# This table is used in converting lower case to upper case. +uppercase_table:=a,A b,B c,C d,D e,E f,F g,G h,H i,I j,J k,K l,L m,M n,N o,O p,P q,Q r,R s,S t,T u,U v,V w,W x,X y,Y z,Z + +# Internal macro used for converting lower case to upper case. +# $(1) = upper case table +# $(2) = String to convert +define uppercase_internal +$(if $(1),$$(subst $(firstword $(1)),$(call uppercase_internal,$(wordlist 2,$(words $(1)),$(1)),$(2))),$(2)) +endef + +# A macro for converting a string to upper case +# $(1) = String to convert +define uppercase +$(eval uppercase_result:=$(call uppercase_internal,$(uppercase_table),$(1)))$(uppercase_result) +endef + +# Convenience function for adding build definitions +# $(eval $(call add_define,FOO)) will have: +# -DFOO if $(FOO) is empty; -DFOO=$(FOO) otherwise +define add_define + DEFINES += -D$(1)$(if $(value $(1)),=$(value $(1)),) +endef + + +# Convenience function for addding multiple build definitions +# $(eval $(call add_defines,FOO BOO)) +define add_defines + $(foreach def,$1,$(eval $(call add_define,$(def)))) +endef + +# Convenience function for adding build definitions +# $(eval $(call add_define_val,FOO,BAR)) will have: +# -DFOO=BAR +define add_define_val + DEFINES += -D$(1)=$(2) +endef + +# Convenience function for verifying option has a boolean value +# $(eval $(call assert_boolean,FOO)) will assert FOO is 0 or 1 +define assert_boolean + $(if $(filter-out 0 1,$($1)),$(error $1 must be boolean)) +endef + +# Convenience function for verifying options have boolean values +# $(eval $(call assert_booleans,FOO BOO)) will assert FOO and BOO for 0 or 1 values +define assert_booleans + $(foreach bool,$1,$(eval $(call assert_boolean,$(bool)))) +endef + +0-9 := 0 1 2 3 4 5 6 7 8 9 + +# Function to verify that a given option $(1) contains a numeric value +define assert_numeric +$(if $($(1)),,$(error $(1) must not be empty)) +$(eval __numeric := $($(1))) +$(foreach d,$(0-9),$(eval __numeric := $(subst $(d),,$(__numeric)))) +$(if $(__numeric),$(error $(1) must be numeric)) +endef + +# Convenience function for verifying options have numeric values +# $(eval $(call assert_numerics,FOO BOO)) will assert FOO and BOO contain numeric values +define assert_numerics + $(foreach num,$1,$(eval $(call assert_numeric,$(num)))) +endef + +# CREATE_SEQ is a recursive function to create sequence of numbers from 1 to +# $(2) and assign the sequence to $(1) +define CREATE_SEQ +$(if $(word $(2), $($(1))),\ + $(eval $(1) += $(words $($(1))))\ + $(eval $(1) := $(filter-out 0,$($(1)))),\ + $(eval $(1) += $(words $($(1))))\ + $(call CREATE_SEQ,$(1),$(2))\ +) +endef + +# IMG_LINKERFILE defines the linker script corresponding to a BL stage +# $(1) = BL stage (1, 2, 2u, 31, 32) +define IMG_LINKERFILE + ${BUILD_DIR}/bl$(1).ld +endef + +# IMG_MAPFILE defines the output file describing the memory map corresponding +# to a BL stage +# $(1) = BL stage (1, 2, 2u, 31, 32) +define IMG_MAPFILE + ${BUILD_DIR}/bl$(1).map +endef + +# IMG_ELF defines the elf file corresponding to a BL stage +# $(1) = BL stage (1, 2, 2u, 31, 32) +define IMG_ELF + ${BUILD_DIR}/bl$(1).elf +endef + +# IMG_DUMP defines the symbols dump file corresponding to a BL stage +# $(1) = BL stage (1, 2, 2u, 31, 32) +define IMG_DUMP + ${BUILD_DIR}/bl$(1).dump +endef + +# IMG_BIN defines the default image file corresponding to a BL stage +# $(1) = BL stage (1, 2, 2u, 31, 32) +define IMG_BIN + ${BUILD_PLAT}/bl$(1).bin +endef + +# IMG_ENC_BIN defines the default encrypted image file corresponding to a +# BL stage +# $(1) = BL stage (2, 30, 31, 32, 33) +define IMG_ENC_BIN + ${BUILD_PLAT}/bl$(1)_enc.bin +endef + +# ENCRYPT_FW invokes enctool to encrypt firmware binary +# $(1) = input firmware binary +# $(2) = output encrypted firmware binary +define ENCRYPT_FW +$(2): $(1) enctool + $$(ECHO) " ENC $$<" + $$(Q)$$(ENCTOOL) $$(ENC_ARGS) -i $$< -o $$@ +endef + +# TOOL_ADD_PAYLOAD appends the command line arguments required by fiptool to +# package a new payload and/or by cert_create to generate certificate. +# Optionally, it adds the dependency on this payload +# $(1) = payload filename (i.e. bl31.bin) +# $(2) = command line option for the specified payload (i.e. --soc-fw) +# $(3) = tool target dependency (optional) (ex. build/fvp/release/bl31.bin) +# $(4) = FIP prefix (optional) (if FWU_, target is fwu_fip instead of fip) +# $(5) = encrypted payload (optional) (ex. build/fvp/release/bl31_enc.bin) +define TOOL_ADD_PAYLOAD +ifneq ($(5),) + $(4)FIP_ARGS += $(2) $(5) + $(if $(3),$(4)CRT_DEPS += $(1)) +else + $(4)FIP_ARGS += $(2) $(1) + $(if $(3),$(4)CRT_DEPS += $(3)) +endif + $(if $(3),$(4)FIP_DEPS += $(3)) + $(4)CRT_ARGS += $(2) $(1) +endef + +# TOOL_ADD_IMG_PAYLOAD works like TOOL_ADD_PAYLOAD, but applies image filters +# before passing them to host tools if BL*_PRE_TOOL_FILTER is defined. +# $(1) = image_type (scp_bl2, bl33, etc.) +# $(2) = payload filepath (ex. build/fvp/release/bl31.bin) +# $(3) = command line option for the specified payload (ex. --soc-fw) +# $(4) = tool target dependency (optional) (ex. build/fvp/release/bl31.bin) +# $(5) = FIP prefix (optional) (if FWU_, target is fwu_fip instead of fip) +# $(6) = encrypted payload (optional) (ex. build/fvp/release/bl31_enc.bin) + +define TOOL_ADD_IMG_PAYLOAD + +$(eval PRE_TOOL_FILTER := $($(call uppercase,$(1))_PRE_TOOL_FILTER)) + +ifneq ($(PRE_TOOL_FILTER),) + +$(eval PROCESSED_PATH := $(BUILD_PLAT)/$(1).bin$($(PRE_TOOL_FILTER)_SUFFIX)) + +$(call $(PRE_TOOL_FILTER)_RULE,$(PROCESSED_PATH),$(2)) + +$(PROCESSED_PATH): $(4) + +$(call TOOL_ADD_PAYLOAD,$(PROCESSED_PATH),$(3),$(PROCESSED_PATH),$(5),$(6)) + +else +$(call TOOL_ADD_PAYLOAD,$(2),$(3),$(4),$(5),$(6)) +endif +endef + +# CERT_ADD_CMD_OPT adds a new command line option to the cert_create invocation +# $(1) = parameter filename +# $(2) = cert_create command line option for the specified parameter +# $(3) = FIP prefix (optional) (if FWU_, target is fwu_fip instead of fip) +define CERT_ADD_CMD_OPT + $(3)CRT_ARGS += $(2) $(1) +endef + +# TOOL_ADD_IMG allows the platform to specify an external image to be packed +# in the FIP and/or for which certificate is generated. It also adds a +# dependency on the image file, aborting the build if the file does not exist. +# $(1) = image_type (scp_bl2, bl33, etc.) +# $(2) = command line option for fiptool (--scp-fw, --nt-fw, etc) +# $(3) = FIP prefix (optional) (if FWU_, target is fwu_fip instead of fip) +# $(4) = Image encryption flag (optional) (0, 1) +# Example: +# $(eval $(call TOOL_ADD_IMG,bl33,--nt-fw)) +define TOOL_ADD_IMG + # Build option to specify the image filename (SCP_BL2, BL33, etc) + # This is the uppercase form of the first parameter + $(eval _V := $(call uppercase,$(1))) + + # $(check_$(1)_cmd) variable is executed in the check_$(1) target and also + # is put into the ${CHECK_$(3)FIP_CMD} variable which is executed by the + # target ${BUILD_PLAT}/${$(3)FIP_NAME}. + $(eval check_$(1)_cmd := \ + $(if $(value $(_V)),,$$$$(error "Platform '${PLAT}' requires $(_V). Please set $(_V) to point to the right file")) \ + $(if $(wildcard $(value $(_V))),,$$$$(error '$(_V)=$(value $(_V))' was specified, but '$(value $(_V))' does not exist)) \ + ) + + $(3)CRT_DEPS += check_$(1) + CHECK_$(3)FIP_CMD += $$(check_$(1)_cmd) +ifeq ($(4),1) + $(eval ENC_BIN := ${BUILD_PLAT}/$(1)_enc.bin) + $(call ENCRYPT_FW,$(value $(_V)),$(ENC_BIN)) + $(call TOOL_ADD_IMG_PAYLOAD,$(1),$(value $(_V)),$(2),$(ENC_BIN),$(3), \ + $(ENC_BIN)) +else + $(call TOOL_ADD_IMG_PAYLOAD,$(1),$(value $(_V)),$(2),$(if $(wildcard $(value $(_V))),$(value $(_V)),FORCE),$(3)) +endif + +.PHONY: check_$(1) +check_$(1): + $(check_$(1)_cmd) +endef + +################################################################################ +# Generic image processing filters +################################################################################ + +# GZIP +define GZIP_RULE +$(1): $(2) + $(ECHO) " GZIP $$@" + $(Q)gzip -n -f -9 $$< --stdout > $$@ +endef + +GZIP_SUFFIX := .gz + +################################################################################ +# Auxiliary macros to build TF images from sources +################################################################################ + +MAKE_DEP = -Wp,-MD,$(DEP) -MT $$@ -MP + + +# MAKE_C_LIB builds a C source file and generates the dependency file +# $(1) = output directory +# $(2) = source file (%.c) +# $(3) = library name +define MAKE_C_LIB +$(eval OBJ := $(1)/$(patsubst %.c,%.o,$(notdir $(2)))) +$(eval DEP := $(patsubst %.o,%.d,$(OBJ))) + +$(OBJ): $(2) $(filter-out %.d,$(MAKEFILE_LIST)) | lib$(3)_dirs + $$(ECHO) " CC $$<" + $$(Q)$$(CC) $$(TF_CFLAGS) $$(CFLAGS) $(MAKE_DEP) -c $$< -o $$@ + +-include $(DEP) + +endef + +# MAKE_S_LIB builds an assembly source file and generates the dependency file +# $(1) = output directory +# $(2) = source file (%.S) +# $(3) = library name +define MAKE_S_LIB +$(eval OBJ := $(1)/$(patsubst %.S,%.o,$(notdir $(2)))) +$(eval DEP := $(patsubst %.o,%.d,$(OBJ))) + +$(OBJ): $(2) $(filter-out %.d,$(MAKEFILE_LIST)) | lib$(3)_dirs + $$(ECHO) " AS $$<" + $$(Q)$$(AS) $$(ASFLAGS) $(MAKE_DEP) -c $$< -o $$@ + +-include $(DEP) + +endef + + +# MAKE_C builds a C source file and generates the dependency file +# $(1) = output directory +# $(2) = source file (%.c) +# $(3) = BL stage (1, 2, 2u, 31, 32) +define MAKE_C + +$(eval OBJ := $(1)/$(patsubst %.c,%.o,$(notdir $(2)))) +$(eval DEP := $(patsubst %.o,%.d,$(OBJ))) +$(eval BL_CPPFLAGS := $(BL$(call uppercase,$(3))_CPPFLAGS) -DIMAGE_BL$(call uppercase,$(3))) +$(eval BL_CFLAGS := $(BL$(call uppercase,$(3))_CFLAGS)) + +$(OBJ): $(2) $(filter-out %.d,$(MAKEFILE_LIST)) | bl$(3)_dirs + $$(ECHO) " CC $$<" + $$(Q)$$(CC) $$(LTO_CFLAGS) $$(TF_CFLAGS) $$(CFLAGS) $(BL_CPPFLAGS) $(BL_CFLAGS) $(MAKE_DEP) -c $$< -o $$@ + +-include $(DEP) + +endef + + +# MAKE_S builds an assembly source file and generates the dependency file +# $(1) = output directory +# $(2) = assembly file (%.S) +# $(3) = BL stage (1, 2, 2u, 31, 32) +define MAKE_S + +$(eval OBJ := $(1)/$(patsubst %.S,%.o,$(notdir $(2)))) +$(eval DEP := $(patsubst %.o,%.d,$(OBJ))) +$(eval BL_CPPFLAGS := $(BL$(call uppercase,$(3))_CPPFLAGS) -DIMAGE_BL$(call uppercase,$(3))) +$(eval BL_ASFLAGS := $(BL$(call uppercase,$(3))_ASFLAGS)) + +$(OBJ): $(2) $(filter-out %.d,$(MAKEFILE_LIST)) | bl$(3)_dirs + $$(ECHO) " AS $$<" + $$(Q)$$(AS) $$(ASFLAGS) $(BL_CPPFLAGS) $(BL_ASFLAGS) $(MAKE_DEP) -c $$< -o $$@ + +-include $(DEP) + +endef + + +# MAKE_LD generate the linker script using the C preprocessor +# $(1) = output linker script +# $(2) = input template +# $(3) = BL stage (1, 2, 2u, 31, 32) +define MAKE_LD + +$(eval DEP := $(1).d) +$(eval BL_CPPFLAGS := $(BL$(call uppercase,$(3))_CPPFLAGS) -DIMAGE_BL$(call uppercase,$(3))) + +$(1): $(2) $(filter-out %.d,$(MAKEFILE_LIST)) | bl$(3)_dirs + $$(ECHO) " PP $$<" + $$(Q)$$(CPP) $$(CPPFLAGS) $(BL_CPPFLAGS) $(TF_CFLAGS_$(ARCH)) -P -x assembler-with-cpp -D__LINKER__ $(MAKE_DEP) -o $$@ $$< + +-include $(DEP) + +endef + +# MAKE_LIB_OBJS builds both C and assembly source files +# $(1) = output directory +# $(2) = list of source files +# $(3) = name of the library +define MAKE_LIB_OBJS + $(eval C_OBJS := $(filter %.c,$(2))) + $(eval REMAIN := $(filter-out %.c,$(2))) + $(eval $(foreach obj,$(C_OBJS),$(call MAKE_C_LIB,$(1),$(obj),$(3)))) + + $(eval S_OBJS := $(filter %.S,$(REMAIN))) + $(eval REMAIN := $(filter-out %.S,$(REMAIN))) + $(eval $(foreach obj,$(S_OBJS),$(call MAKE_S_LIB,$(1),$(obj),$(3)))) + + $(and $(REMAIN),$(error Unexpected source files present: $(REMAIN))) +endef + + +# MAKE_OBJS builds both C and assembly source files +# $(1) = output directory +# $(2) = list of source files (both C and assembly) +# $(3) = BL stage (1, 2, 2u, 31, 32) +define MAKE_OBJS + $(eval C_OBJS := $(filter %.c,$(2))) + $(eval REMAIN := $(filter-out %.c,$(2))) + $(eval $(foreach obj,$(C_OBJS),$(call MAKE_C,$(1),$(obj),$(3)))) + + $(eval S_OBJS := $(filter %.S,$(REMAIN))) + $(eval REMAIN := $(filter-out %.S,$(REMAIN))) + $(eval $(foreach obj,$(S_OBJS),$(call MAKE_S,$(1),$(obj),$(3)))) + + $(and $(REMAIN),$(error Unexpected source files present: $(REMAIN))) +endef + + +# NOTE: The line continuation '\' is required in the next define otherwise we +# end up with a line-feed characer at the end of the last c filename. +# Also bear this issue in mind if extending the list of supported filetypes. +define SOURCES_TO_OBJS + $(notdir $(patsubst %.c,%.o,$(filter %.c,$(1)))) \ + $(notdir $(patsubst %.S,%.o,$(filter %.S,$(1)))) +endef + +# Allow overriding the timestamp, for example for reproducible builds, or to +# synchronize timestamps across multiple projects. +# This must be set to a C string (including quotes where applicable). +BUILD_MESSAGE_TIMESTAMP ?= __TIME__", "__DATE__ + +.PHONY: libraries + +# MAKE_LIB_DIRS macro defines the target for the directory where +# libraries are created +define MAKE_LIB_DIRS + $(eval LIB_DIR := ${BUILD_PLAT}/lib) + $(eval ROMLIB_DIR := ${BUILD_PLAT}/romlib) + $(eval LIBWRAPPER_DIR := ${BUILD_PLAT}/libwrapper) + $(eval $(call MAKE_PREREQ_DIR,${LIB_DIR},${BUILD_PLAT})) + $(eval $(call MAKE_PREREQ_DIR,${ROMLIB_DIR},${BUILD_PLAT})) + $(eval $(call MAKE_PREREQ_DIR,${LIBWRAPPER_DIR},${BUILD_PLAT})) +endef + +# MAKE_LIB macro defines the targets and options to build each BL image. +# Arguments: +# $(1) = Library name +define MAKE_LIB + $(eval BUILD_DIR := ${BUILD_PLAT}/lib$(1)) + $(eval LIB_DIR := ${BUILD_PLAT}/lib) + $(eval ROMLIB_DIR := ${BUILD_PLAT}/romlib) + $(eval SOURCES := $(LIB$(call uppercase,$(1))_SRCS)) + $(eval OBJS := $(addprefix $(BUILD_DIR)/,$(call SOURCES_TO_OBJS,$(SOURCES)))) + +$(eval $(call MAKE_PREREQ_DIR,${BUILD_DIR},${BUILD_PLAT})) +$(eval $(call MAKE_LIB_OBJS,$(BUILD_DIR),$(SOURCES),$(1))) + +.PHONY : lib${1}_dirs +lib${1}_dirs: | ${BUILD_DIR} ${LIB_DIR} ${ROMLIB_DIR} ${LIBWRAPPER_DIR} +libraries: ${LIB_DIR}/lib$(1).a +ifneq ($(findstring armlink,$(notdir $(LD))),) +LDPATHS = --userlibpath=${LIB_DIR} +LDLIBS += --library=$(1) +else +LDPATHS = -L${LIB_DIR} +LDLIBS += -l$(1) +endif + +ifeq ($(USE_ROMLIB),1) +LIBWRAPPER = -lwrappers +endif + +all: ${LIB_DIR}/lib$(1).a + +${LIB_DIR}/lib$(1).a: $(OBJS) + $$(ECHO) " AR $$@" + $$(Q)$$(AR) cr $$@ $$? +endef + +# MAKE_BL macro defines the targets and options to build each BL image. +# Arguments: +# $(1) = BL stage (1, 2, 2u, 31, 32) +# $(2) = FIP command line option (if empty, image will not be included in the FIP) +# $(3) = FIP prefix (optional) (if FWU_, target is fwu_fip instead of fip) +# $(4) = BL encryption flag (optional) (0, 1) +define MAKE_BL + $(eval BUILD_DIR := ${BUILD_PLAT}/bl$(1)) + $(eval BL_SOURCES := $(BL$(call uppercase,$(1))_SOURCES)) + $(eval SOURCES := $(BL_SOURCES) $(BL_COMMON_SOURCES) $(PLAT_BL_COMMON_SOURCES)) + $(eval OBJS := $(addprefix $(BUILD_DIR)/,$(call SOURCES_TO_OBJS,$(SOURCES)))) + $(eval LINKERFILE := $(call IMG_LINKERFILE,$(1))) + $(eval MAPFILE := $(call IMG_MAPFILE,$(1))) + $(eval ELF := $(call IMG_ELF,$(1))) + $(eval DUMP := $(call IMG_DUMP,$(1))) + $(eval BIN := $(call IMG_BIN,$(1))) + $(eval ENC_BIN := $(call IMG_ENC_BIN,$(1))) + $(eval BL_LINKERFILE := $(BL$(call uppercase,$(1))_LINKERFILE)) + $(eval BL_LIBS := $(BL$(call uppercase,$(1))_LIBS)) + # We use sort only to get a list of unique object directory names. + # ordering is not relevant but sort removes duplicates. + $(eval TEMP_OBJ_DIRS := $(sort $(dir ${OBJS} ${LINKERFILE}))) + # The $(dir ) function leaves a trailing / on the directory names + # Rip off the / to match directory names with make rule targets. + $(eval OBJ_DIRS := $(patsubst %/,%,$(TEMP_OBJ_DIRS))) + +# Create generators for object directory structure + +$(eval $(call MAKE_PREREQ_DIR,${BUILD_DIR},${BUILD_PLAT})) + +$(eval $(foreach objd,${OBJ_DIRS},$(call MAKE_PREREQ_DIR,${objd},${BUILD_DIR}))) + +.PHONY : bl${1}_dirs + +# We use order-only prerequisites to ensure that directories are created, +# but do not cause re-builds every time a file is written. +bl${1}_dirs: | ${OBJ_DIRS} + +$(eval $(call MAKE_OBJS,$(BUILD_DIR),$(SOURCES),$(1))) +$(eval $(call MAKE_LD,$(LINKERFILE),$(BL_LINKERFILE),$(1))) +$(eval BL_LDFLAGS := $(BL$(call uppercase,$(1))_LDFLAGS)) + +ifeq ($(USE_ROMLIB),1) +$(ELF): romlib.bin +endif + +$(ELF): $(OBJS) $(LINKERFILE) | bl$(1)_dirs libraries $(BL_LIBS) + $$(ECHO) " LD $$@" +ifdef MAKE_BUILD_STRINGS + $(call MAKE_BUILD_STRINGS, $(BUILD_DIR)/build_message.o) +else + @echo 'const char build_message[] = "Built : "$(BUILD_MESSAGE_TIMESTAMP); \ + const char version_string[] = "${VERSION_STRING}";' | \ + $$(CC) $$(TF_CFLAGS) $$(CFLAGS) -xc -c - -o $(BUILD_DIR)/build_message.o +endif +ifneq ($(findstring armlink,$(notdir $(LD))),) + $$(Q)$$(LD) -o $$@ $$(TF_LDFLAGS) $$(LDFLAGS) $(BL_LDFLAGS) --entry=bl${1}_entrypoint \ + --predefine="-D__LINKER__=$(__LINKER__)" \ + --predefine="-DTF_CFLAGS=$(TF_CFLAGS)" \ + --map --list="$(MAPFILE)" --scatter=${PLAT_DIR}/scat/bl${1}.scat \ + $(LDPATHS) $(LIBWRAPPER) $(LDLIBS) $(BL_LIBS) \ + $(BUILD_DIR)/build_message.o $(OBJS) +else ifneq ($(findstring gcc,$(notdir $(LD))),) + $$(Q)$$(LD) -o $$@ $$(TF_LDFLAGS) $$(LDFLAGS) -Wl,-Map=$(MAPFILE) \ + -Wl,-T$(LINKERFILE) $(BUILD_DIR)/build_message.o \ + $(OBJS) $(LDPATHS) $(LIBWRAPPER) $(LDLIBS) $(BL_LIBS) +else + $$(Q)$$(LD) -o $$@ $$(TF_LDFLAGS) $$(LDFLAGS) $(BL_LDFLAGS) -Map=$(MAPFILE) \ + --script $(LINKERFILE) $(BUILD_DIR)/build_message.o \ + $(OBJS) $(LDPATHS) $(LIBWRAPPER) $(LDLIBS) $(BL_LIBS) +endif +ifeq ($(DISABLE_BIN_GENERATION),1) + @${ECHO_BLANK_LINE} + @echo "Built $$@ successfully" + @${ECHO_BLANK_LINE} +endif + +$(DUMP): $(ELF) + $${ECHO} " OD $$@" + $${Q}$${OD} -dx $$< > $$@ + +$(BIN): $(ELF) + $${ECHO} " BIN $$@" + $$(Q)$$(OC) -O binary $$< $$@ + @${ECHO_BLANK_LINE} + @echo "Built $$@ successfully" + @${ECHO_BLANK_LINE} + +.PHONY: bl$(1) +ifeq ($(DISABLE_BIN_GENERATION),1) +bl$(1): $(ELF) $(DUMP) +else +bl$(1): $(BIN) $(DUMP) +endif + +all: bl$(1) + +ifeq ($(4),1) +$(call ENCRYPT_FW,$(BIN),$(ENC_BIN)) +$(if $(2),$(call TOOL_ADD_IMG_PAYLOAD,bl$(1),$(BIN),--$(2),$(ENC_BIN),$(3), \ + $(ENC_BIN))) +else +$(if $(2),$(call TOOL_ADD_IMG_PAYLOAD,bl$(1),$(BIN),--$(2),$(BIN),$(3))) +endif + +endef + +# Convert device tree source file names to matching blobs +# $(1) = input dts +define SOURCES_TO_DTBS + $(notdir $(patsubst %.dts,%.dtb,$(filter %.dts,$(1)))) +endef + +# MAKE_FDT_DIRS macro creates the prerequisite directories that host the +# FDT binaries +# $(1) = output directory +# $(2) = input dts +define MAKE_FDT_DIRS + $(eval DTBS := $(addprefix $(1)/,$(call SOURCES_TO_DTBS,$(2)))) + $(eval TEMP_DTB_DIRS := $(sort $(dir ${DTBS}))) + # The $(dir ) function leaves a trailing / on the directory names + # Rip off the / to match directory names with make rule targets. + $(eval DTB_DIRS := $(patsubst %/,%,$(TEMP_DTB_DIRS))) + +$(eval $(foreach objd,${DTB_DIRS},$(call MAKE_PREREQ_DIR,${objd},${BUILD_DIR}))) + +fdt_dirs: ${DTB_DIRS} +endef + +# MAKE_DTB generate the Flattened device tree binary +# $(1) = output directory +# $(2) = input dts +define MAKE_DTB + +# List of DTB file(s) to generate, based on DTS file basename list +$(eval DOBJ := $(addprefix $(1)/,$(call SOURCES_TO_DTBS,$(2)))) +# List of the pre-compiled DTS file(s) +$(eval DPRE := $(addprefix $(1)/,$(patsubst %.dts,%.pre.dts,$(notdir $(2))))) +# Dependencies of the pre-compiled DTS file(s) on its source and included files +$(eval DTSDEP := $(patsubst %.dtb,%.o.d,$(DOBJ))) +# Dependencies of the DT compilation on its pre-compiled DTS +$(eval DTBDEP := $(patsubst %.dtb,%.d,$(DOBJ))) + +$(DOBJ): $(2) $(filter-out %.d,$(MAKEFILE_LIST)) | fdt_dirs + $${ECHO} " CPP $$<" + $(eval DTBS := $(addprefix $(1)/,$(call SOURCES_TO_DTBS,$(2)))) + $$(Q)$$(PP) $$(DTC_CPPFLAGS) -MT $(DTBS) -MMD -MF $(DTSDEP) -o $(DPRE) $$< + $${ECHO} " DTC $$<" + $$(Q)$$(DTC) $$(DTC_FLAGS) -d $(DTBDEP) -o $$@ $(DPRE) + +-include $(DTBDEP) +-include $(DTSDEP) + +endef + +# MAKE_DTBS builds flattened device tree sources +# $(1) = output directory +# $(2) = list of flattened device tree source files +define MAKE_DTBS + $(eval DOBJS := $(filter %.dts,$(2))) + $(eval REMAIN := $(filter-out %.dts,$(2))) + $(and $(REMAIN),$(error FDT_SOURCES contain non-DTS files: $(REMAIN))) + $(eval $(foreach obj,$(DOBJS),$(call MAKE_DTB,$(1),$(obj)))) + + $(eval $(call MAKE_FDT_DIRS,$(1),$(2))) + +dtbs: $(DTBS) +all: dtbs +endef diff --git a/drivers/rz/ipl/rza/make_helpers/cygwin.mk b/drivers/rz/ipl/rza/make_helpers/cygwin.mk new file mode 100644 index 00000000..04a963ff --- /dev/null +++ b/drivers/rz/ipl/rza/make_helpers/cygwin.mk @@ -0,0 +1,19 @@ +# +# Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# +# + +# OS specific definitions for builds in a Cygwin environment. +# Cygwin allows us to use unix style commands on a windows platform. + +ifndef CYGWIN_MK + CYGWIN_MK := $(lastword $(MAKEFILE_LIST)) + + include ${MAKE_HELPERS_DIRECTORY}unix.mk + + # In cygwin executable files have the Windows .exe extension type. + BIN_EXT := .exe + +endif diff --git a/drivers/rz/ipl/rza/make_helpers/defaults.mk b/drivers/rz/ipl/rza/make_helpers/defaults.mk new file mode 100644 index 00000000..8d0cd047 --- /dev/null +++ b/drivers/rz/ipl/rza/make_helpers/defaults.mk @@ -0,0 +1,341 @@ +# +# Copyright (c) 2016-2021, ARM Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# Default, static values for build variables, listed in alphabetic order. +# Dependencies between build options, if any, are handled in the top-level +# Makefile, after this file is included. This ensures that the former is better +# poised to handle dependencies, as all build variables would have a default +# value by then. + +# Use T32 by default +AARCH32_INSTRUCTION_SET := T32 + +# The AArch32 Secure Payload to be built as BL32 image +AARCH32_SP := none + +# The Target build architecture. Supported values are: aarch64, aarch32. +ARCH := aarch64 + +# ARM Architecture feature modifiers: none by default +ARM_ARCH_FEATURE := none + +# ARM Architecture major and minor versions: 8.0 by default. +ARM_ARCH_MAJOR := 8 +ARM_ARCH_MINOR := 0 + +# Base commit to perform code check on +BASE_COMMIT := origin/master + +# Execute BL2 at EL3 +BL2_AT_EL3 := 0 + +# BL2 image is stored in XIP memory, for now, this option is only supported +# when BL2_AT_EL3 is 1. +BL2_IN_XIP_MEM := 0 + +# Do dcache invalidate upon BL2 entry at EL3 +BL2_INV_DCACHE := 1 + +# Select the branch protection features to use. +BRANCH_PROTECTION := 0 + +# By default, consider that the platform may release several CPUs out of reset. +# The platform Makefile is free to override this value. +COLD_BOOT_SINGLE_CPU := 0 + +# Flag to compile in coreboot support code. Exclude by default. The coreboot +# Makefile system will set this when compiling TF as part of a coreboot image. +COREBOOT := 0 + +# For Chain of Trust +CREATE_KEYS := 1 + +# Build flag to include AArch32 registers in cpu context save and restore during +# world switch. This flag must be set to 0 for AArch64-only platforms. +CTX_INCLUDE_AARCH32_REGS := 1 + +# Include FP registers in cpu context +CTX_INCLUDE_FPREGS := 0 + +# Include pointer authentication (ARMv8.3-PAuth) registers in cpu context. This +# must be set to 1 if the platform wants to use this feature in the Secure +# world. It is not needed to use it in the Non-secure world. +CTX_INCLUDE_PAUTH_REGS := 0 + +# Include Nested virtualization control (Armv8.4-NV) registers in cpu context. +# This must be set to 1 if architecture implements Nested Virtualization +# Extension and platform wants to use this feature in the Secure world +CTX_INCLUDE_NEVE_REGS := 0 + +# Debug build +DEBUG := 0 + +# By default disable authenticated decryption support. +DECRYPTION_SUPPORT := none + +# Build platform +DEFAULT_PLAT := fvp + +# Disable the generation of the binary image (ELF only). +DISABLE_BIN_GENERATION := 0 + +# Disable MTPMU if FEAT_MTPMU is supported. Default is 0 to keep backwards +# compatibility. +DISABLE_MTPMU := 0 + +# Enable capability to disable authentication dynamically. Only meant for +# development platforms. +DYN_DISABLE_AUTH := 0 + +# Build option to enable MPAM for lower ELs +ENABLE_MPAM_FOR_LOWER_ELS := 0 + +# Flag to Enable Position Independant support (PIE) +ENABLE_PIE := 0 + +# Flag to enable Performance Measurement Framework +ENABLE_PMF := 0 + +# Flag to enable PSCI STATs functionality +ENABLE_PSCI_STAT := 0 + +# Flag to enable runtime instrumentation using PMF +ENABLE_RUNTIME_INSTRUMENTATION := 0 + +# Flag to enable stack corruption protection +ENABLE_STACK_PROTECTOR := 0 + +# Flag to enable exception handling in EL3 +EL3_EXCEPTION_HANDLING := 0 + +# Flag to enable Branch Target Identification. +# Internal flag not meant for direct setting. +# Use BRANCH_PROTECTION to enable BTI. +ENABLE_BTI := 0 + +# Flag to enable Pointer Authentication. +# Internal flag not meant for direct setting. +# Use BRANCH_PROTECTION to enable PAUTH. +ENABLE_PAUTH := 0 + +# By default BL31 encryption disabled +ENCRYPT_BL31 := 0 + +# By default BL32 encryption disabled +ENCRYPT_BL32 := 0 + +# Default dummy firmware encryption key +ENC_KEY := 1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef + +# Default dummy nonce for firmware encryption +ENC_NONCE := 1234567890abcdef12345678 + +# Build flag to treat usage of deprecated platform and framework APIs as error. +ERROR_DEPRECATED := 0 + +# Fault injection support +FAULT_INJECTION_SUPPORT := 0 + +# Byte alignment that each component in FIP is aligned to +FIP_ALIGN := 0 + +# Default FIP file name +FIP_NAME := fip.bin + +# Default FWU_FIP file name +FWU_FIP_NAME := fwu_fip.bin + +# By default firmware encryption with SSK +FW_ENC_STATUS := 0 + +# For Chain of Trust +GENERATE_COT := 0 + +# Hint platform interrupt control layer that Group 0 interrupts are for EL3. By +# default, they are for Secure EL1. +GICV2_G0_FOR_EL3 := 0 + +# Route External Aborts to EL3. Disabled by default; External Aborts are handled +# by lower ELs. +HANDLE_EA_EL3_FIRST := 0 + +# Secure hash algorithm flag, accepts 3 values: sha256, sha384 and sha512. +# The default value is sha256. +HASH_ALG := sha256 + +# Whether system coherency is managed in hardware, without explicit software +# operations. +HW_ASSISTED_COHERENCY := 0 + +# Set the default algorithm for the generation of Trusted Board Boot keys +KEY_ALG := rsa + +# Set the default key size in case KEY_ALG is rsa +ifeq ($(KEY_ALG),rsa) +KEY_SIZE := 2048 +endif + +# Option to build TF with Measured Boot support +MEASURED_BOOT := 0 + +# NS timer register save and restore +NS_TIMER_SWITCH := 0 + +# Include lib/libc in the final image +OVERRIDE_LIBC := 0 + +# Build PL011 UART driver in minimal generic UART mode +PL011_GENERIC_UART := 0 + +# By default, consider that the platform's reset address is not programmable. +# The platform Makefile is free to override this value. +PROGRAMMABLE_RESET_ADDRESS := 0 + +# Flag used to choose the power state format: Extended State-ID or Original +PSCI_EXTENDED_STATE_ID := 0 + +# Enable RAS support +RAS_EXTENSION := 0 + +# By default, BL1 acts as the reset handler, not BL31 +RESET_TO_BL31 := 0 + +# For Chain of Trust +SAVE_KEYS := 0 + +# Software Delegated Exception support +SDEI_SUPPORT := 0 + +# True Random Number firmware Interface +TRNG_SUPPORT := 0 + +# Whether code and read-only data should be put on separate memory pages. The +# platform Makefile is free to override this value. +SEPARATE_CODE_AND_RODATA := 0 + +# Put NOBITS sections (.bss, stacks, page tables, and coherent memory) in a +# separate memory region, which may be discontiguous from the rest of BL31. +SEPARATE_NOBITS_REGION := 0 + +# If the BL31 image initialisation code is recalimed after use for the secondary +# cores stack +RECLAIM_INIT_CODE := 0 + +# SPD choice +SPD := none + +# Enable the Management Mode (MM)-based Secure Partition Manager implementation +SPM_MM := 0 + +# Use SPM at S-EL2 as a default config for SPMD +SPMD_SPM_AT_SEL2 := 1 + +# Flag to introduce an infinite loop in BL1 just before it exits into the next +# image. This is meant to help debugging the post-BL2 phase. +SPIN_ON_BL1_EXIT := 0 + +# Flags to build TF with Trusted Boot support +TRUSTED_BOARD_BOOT := 0 + +# Build option to choose whether Trusted Firmware uses Coherent memory or not. +USE_COHERENT_MEM := 1 + +# Build option to add debugfs support +USE_DEBUGFS := 0 + +# Build option to fconf based io +ARM_IO_IN_DTB := 0 + +# Build option to support SDEI through fconf +SDEI_IN_FCONF := 0 + +# Build option to support Secure Interrupt descriptors through fconf +SEC_INT_DESC_IN_FCONF := 0 + +# Build option to choose whether Trusted Firmware uses library at ROM +USE_ROMLIB := 0 + +# Build option to choose whether the xlat tables of BL images can be read-only. +# Note that this only serves as a higher level option to PLAT_RO_XLAT_TABLES, +# which is the per BL-image option that actually enables the read-only tables +# API. The reason for having this additional option is to have a common high +# level makefile where we can check for incompatible features/build options. +ALLOW_RO_XLAT_TABLES := 0 + +# Chain of trust. +COT := tbbr + +# Use tbbr_oid.h instead of platform_oid.h +USE_TBBR_DEFS := 1 + +# Build verbosity +V := 0 + +# Whether to enable D-Cache early during warm boot. This is usually +# applicable for platforms wherein interconnect programming is not +# required to enable cache coherency after warm reset (eg: single cluster +# platforms). +WARMBOOT_ENABLE_DCACHE_EARLY := 0 + +# Build option to enable/disable the Statistical Profiling Extensions +ENABLE_SPE_FOR_LOWER_ELS := 1 + +# SPE is only supported on AArch64 so disable it on AArch32. +ifeq (${ARCH},aarch32) + override ENABLE_SPE_FOR_LOWER_ELS := 0 +endif + +# Include Memory Tagging Extension registers in cpu context. This must be set +# to 1 if the platform wants to use this feature in the Secure world and MTE is +# enabled at ELX. +CTX_INCLUDE_MTE_REGS := 0 + +ENABLE_AMU := 0 +AMU_RESTRICT_COUNTERS := 0 + +# By default, enable Scalable Vector Extension if implemented for Non-secure +# lower ELs +# Note SVE is only supported on AArch64 - therefore do not enable in AArch32 +ifneq (${ARCH},aarch32) + ENABLE_SVE_FOR_NS := 1 +else + override ENABLE_SVE_FOR_NS := 0 +endif + +SANITIZE_UB := off + +# For ARMv8.1 (AArch64) platforms, enabling this option selects the spinlock +# implementation variant using the ARMv8.1-LSE compare-and-swap instruction. +# Default: disabled +USE_SPINLOCK_CAS := 0 + +# Enable Link Time Optimization +ENABLE_LTO := 0 + +# Build flag to include EL2 registers in cpu context save and restore during +# S-EL2 firmware entry/exit. This flag is to be used with SPD=spmd option. +# Default is 0. +CTX_INCLUDE_EL2_REGS := 0 + +# Enable Memory tag extension which is supported for architecture greater +# than Armv8.5-A +# By default it is set to "no" +SUPPORT_STACK_MEMTAG := no + +# Select workaround for AT speculative behaviour. +ERRATA_SPECULATIVE_AT := 0 + +# Trap RAS error record access from lower EL +RAS_TRAP_LOWER_EL_ERR_ACCESS := 0 + +# Build option to create cot descriptors using fconf +COT_DESC_IN_DTB := 0 + +# Build option to provide openssl directory path +OPENSSL_DIR := /usr + +# Build option to use the SP804 timer instead of the generic one +USE_SP804_TIMER := 0 diff --git a/drivers/rz/ipl/rza/make_helpers/msys.mk b/drivers/rz/ipl/rza/make_helpers/msys.mk new file mode 100644 index 00000000..7e60d57f --- /dev/null +++ b/drivers/rz/ipl/rza/make_helpers/msys.mk @@ -0,0 +1,20 @@ +# +# Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# +# + +# OS specific definitions for builds in a Mingw32 MSYS environment. +# Mingw32 allows us to use some unix style commands on a windows platform. + +ifndef MSYS_MK + MSYS_MK := $(lastword $(MAKEFILE_LIST)) + + include ${MAKE_HELPERS_DIRECTORY}unix.mk + + # In MSYS executable files have the Windows .exe extension type. + BIN_EXT := .exe + +endif + diff --git a/drivers/rz/ipl/rza/make_helpers/plat_helpers.mk b/drivers/rz/ipl/rza/make_helpers/plat_helpers.mk new file mode 100644 index 00000000..a7ae9a27 --- /dev/null +++ b/drivers/rz/ipl/rza/make_helpers/plat_helpers.mk @@ -0,0 +1,38 @@ +# +# Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +################################################################################ +# Helpers for finding and referencing platform directories +################################################################################ + +ifndef PLAT_HELPERS_MK + PLAT_HELPERS_MK := $(lastword $(MAKEFILE_LIST)) + + ifeq (${PLAT},) + $(error "Error: Unknown platform. Please use PLAT= to specify the platform") + endif + + # TF_PLATFORM_ROOT can be overridden for when building tools directly + TF_PLATFORM_ROOT ?= plat/ + PLAT_MAKEFILE := platform.mk + + # Generate the platforms list by recursively searching for all directories + # under /plat containing a PLAT_MAKEFILE. Append each platform with a `|` + # char and strip out the final '|'. + ALL_PLATFORM_MK_FILES := $(call rwildcard,${TF_PLATFORM_ROOT},${PLAT_MAKEFILE}) + ALL_PLATFORM_DIRS := $(patsubst %/,%,$(dir ${ALL_PLATFORM_MK_FILES})) + ALL_PLATFORMS := $(sort $(notdir ${ALL_PLATFORM_DIRS})) + + PLAT_MAKEFILE_FULL := $(filter %/${PLAT}/${PLAT_MAKEFILE},${ALL_PLATFORM_MK_FILES}) + PLATFORM_LIST := $(subst ${space},|,${ALL_PLATFORMS}) + ifeq ($(PLAT_MAKEFILE_FULL),) + $(error "Error: Invalid platform. The following platforms are available: ${PLATFORM_LIST}") + endif + + # Record the directory where the platform make file was found. + PLAT_DIR := $(dir ${PLAT_MAKEFILE_FULL}) + +endif diff --git a/drivers/rz/ipl/rza/make_helpers/tbbr/tbbr_tools.mk b/drivers/rz/ipl/rza/make_helpers/tbbr/tbbr_tools.mk new file mode 100644 index 00000000..f7cced48 --- /dev/null +++ b/drivers/rz/ipl/rza/make_helpers/tbbr/tbbr_tools.mk @@ -0,0 +1,112 @@ +# +# Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# This file defines the keys and certificates that must be created to establish +# a Chain of Trust following the TBBR document. These definitions include the +# command line options passed to the cert_create and fiptool commands. +# +# Expected environment: +# +# BUILD_PLAT: output directory +# NEED_BL32: indicates whether BL32 is needed by the platform +# BL2: image filename (optional). Default is IMG_BIN(2) (see macro IMG_BIN) +# SCP_BL2: image filename (optional). Default is IMG_BIN(30) +# BL31: image filename (optional). Default is IMG_BIN(31) +# BL32: image filename (optional). Default is IMG_BIN(32) +# BL33: image filename (optional). Default is IMG_BIN(33) +# +# Build options added by this file: +# +# KEY_ALG +# KEY_SIZE +# ROT_KEY +# PROT_KEY +# TRUSTED_WORLD_KEY +# NON_TRUSTED_WORLD_KEY +# SCP_BL2_KEY +# BL31_KEY +# BL32_KEY +# BL33_KEY +# + +# Certificate generation tool default parameters +TRUSTED_KEY_CERT ?= ${BUILD_PLAT}/trusted_key.crt +FWU_CERT := ${BUILD_PLAT}/fwu_cert.crt + +# Default non-volatile counter values (overridable by the platform) +TFW_NVCTR_VAL ?= 0 +NTFW_NVCTR_VAL ?= 0 + +# Pass the non-volatile counters to the cert_create tool +$(eval $(call CERT_ADD_CMD_OPT,${TFW_NVCTR_VAL},--tfw-nvctr)) +$(eval $(call CERT_ADD_CMD_OPT,${NTFW_NVCTR_VAL},--ntfw-nvctr)) + +# Add Trusted Key certificate to the fiptool and cert_create command line options +$(eval $(call TOOL_ADD_PAYLOAD,${TRUSTED_KEY_CERT},--trusted-key-cert)) + +# Add fwu certificate to the fiptool and cert_create command line options +$(eval $(call TOOL_ADD_PAYLOAD,${FWU_CERT},--fwu-cert,,FWU_)) + +# Add the keys to the cert_create command line options (private keys are NOT +# packed in the FIP). Developers can use their own keys by specifying the proper +# build option in the command line when building the Trusted Firmware +$(if ${KEY_ALG},$(eval $(call CERT_ADD_CMD_OPT,${KEY_ALG},--key-alg))) +$(if ${KEY_ALG},$(eval $(call CERT_ADD_CMD_OPT,${KEY_ALG},--key-alg,FWU_))) +$(if ${KEY_SIZE},$(eval $(call CERT_ADD_CMD_OPT,${KEY_SIZE},--key-size))) +$(if ${KEY_SIZE},$(eval $(call CERT_ADD_CMD_OPT,${KEY_SIZE},--key-size,FWU_))) +$(if ${HASH_ALG},$(eval $(call CERT_ADD_CMD_OPT,${HASH_ALG},--hash-alg))) +$(if ${HASH_ALG},$(eval $(call CERT_ADD_CMD_OPT,${HASH_ALG},--hash-alg,FWU_))) +$(if ${ROT_KEY},$(eval $(call CERT_ADD_CMD_OPT,${ROT_KEY},--rot-key))) +$(if ${ROT_KEY},$(eval $(call CERT_ADD_CMD_OPT,${ROT_KEY},--rot-key,FWU_))) +$(if ${PROT_KEY},$(eval $(call CERT_ADD_CMD_OPT,${PROT_KEY},--prot-key))) +$(if ${TRUSTED_WORLD_KEY},$(eval $(call CERT_ADD_CMD_OPT,${TRUSTED_WORLD_KEY},--trusted-world-key))) +$(if ${NON_TRUSTED_WORLD_KEY},$(eval $(call CERT_ADD_CMD_OPT,${NON_TRUSTED_WORLD_KEY},--non-trusted-world-key))) + + +# Add the BL2 CoT (image cert) +ifeq (${BL2_AT_EL3}, 0) +$(eval $(call TOOL_ADD_PAYLOAD,${BUILD_PLAT}/tb_fw.crt,--tb-fw-cert)) +endif + +# Add the SCP_BL2 CoT (key cert + img cert) +ifneq (${SCP_BL2},) + $(if ${SCP_BL2_KEY},$(eval $(call CERT_ADD_CMD_OPT,${SCP_BL2_KEY},--scp-fw-key))) + $(eval $(call TOOL_ADD_PAYLOAD,${BUILD_PLAT}/scp_fw_content.crt,--scp-fw-cert)) + $(eval $(call TOOL_ADD_PAYLOAD,${BUILD_PLAT}/scp_fw_key.crt,--scp-fw-key-cert)) +endif + +ifeq (${ARCH},aarch64) +ifeq (${NEED_BL31},yes) +# Add the BL31 CoT (key cert + img cert) +$(if ${BL31_KEY},$(eval $(call CERT_ADD_CMD_OPT,${BL31_KEY},--soc-fw-key))) +$(eval $(call TOOL_ADD_PAYLOAD,${BUILD_PLAT}/soc_fw_content.crt,--soc-fw-cert)) +$(eval $(call TOOL_ADD_PAYLOAD,${BUILD_PLAT}/soc_fw_key.crt,--soc-fw-key-cert)) +endif +endif + +# Add the BL32 CoT (key cert + img cert) +ifeq (${NEED_BL32},yes) + $(if ${BL32_KEY},$(eval $(call CERT_ADD_CMD_OPT,${BL32_KEY},--tos-fw-key))) + $(eval $(call TOOL_ADD_PAYLOAD,${BUILD_PLAT}/tos_fw_content.crt,--tos-fw-cert)) + $(eval $(call TOOL_ADD_PAYLOAD,${BUILD_PLAT}/tos_fw_key.crt,--tos-fw-key-cert)) +endif + +# Add the BL33 CoT (key cert + img cert) +ifneq (${BL33},) + $(if ${BL33_KEY},$(eval $(call CERT_ADD_CMD_OPT,${BL33_KEY},--nt-fw-key))) + $(eval $(call TOOL_ADD_PAYLOAD,${BUILD_PLAT}/nt_fw_content.crt,--nt-fw-cert)) +ifneq (${COT},dualroot) + $(eval $(call TOOL_ADD_PAYLOAD,${BUILD_PLAT}/nt_fw_key.crt,--nt-fw-key-cert)) +endif +endif + +# Add SiP owned Secure Partitions CoT (image cert) +ifneq (${SP_LAYOUT_FILE},) + $(eval $(call TOOL_ADD_PAYLOAD,${BUILD_PLAT}/sip_sp_content.crt,--sip-sp-cert)) +ifeq (${COT},dualroot) + $(eval $(call TOOL_ADD_PAYLOAD,${BUILD_PLAT}/plat_sp_content.crt,--plat-sp-cert)) +endif +endif diff --git a/drivers/rz/ipl/rza/make_helpers/unix.mk b/drivers/rz/ipl/rza/make_helpers/unix.mk new file mode 100644 index 00000000..545ddfde --- /dev/null +++ b/drivers/rz/ipl/rza/make_helpers/unix.mk @@ -0,0 +1,60 @@ +# +# Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# Trusted Firmware shell command definitions for a Unix style environment. + +ifndef UNIX_MK + UNIX_MK := $(lastword $(MAKEFILE_LIST)) + + ECHO_BLANK_LINE := echo + ECHO_QUIET := @\# + + DIR_DELIM := / + PATH_SEP := : + + # These defines provide Unix style equivalents of the shell commands + # required by the Trusted Firmware build environment. + + # ${1} is the file to be copied. + # ${2} is the destination file name. + define SHELL_COPY + ${Q}cp -f "${1}" "${2}" + endef + + # ${1} is the directory to be copied. + # ${2} is the destination directory path. + define SHELL_COPY_TREE + ${Q}cp -rf "${1}" "${2}" + endef + + # ${1} is the file to be deleted. + define SHELL_DELETE + -${Q}rm -f "${1}" + endef + + # ${1} is a space delimited list of files to be deleted. + # Note that we do not quote ${1}, as multiple parameters may be passed. + define SHELL_DELETE_ALL + -${Q}rm -rf ${1} + endef + + # ${1} is the directory to be generated. + # ${2} is optional, and allows a prerequisite to be specified. + # Do nothing if $1 == $2, to ignore self dependencies. + define MAKE_PREREQ_DIR + ifneq (${1},${2}) + +${1} : ${2} + ${Q}mkdir -p "${1}" + + endif + endef + + define SHELL_REMOVE_DIR + -${Q}rm -rf "${1}" + endef + +endif diff --git a/drivers/rz/ipl/rza/make_helpers/windows.mk b/drivers/rz/ipl/rza/make_helpers/windows.mk new file mode 100644 index 00000000..26ea88ef --- /dev/null +++ b/drivers/rz/ipl/rza/make_helpers/windows.mk @@ -0,0 +1,90 @@ +# +# Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# OS specific parts for builds in a Windows_NT environment. The +# environment variable OS is set to Windows_NT on all modern Windows platforms + +# Include generic windows command definitions. + +ifndef WINDOWS_MK + WINDOWS_MK := $(lastword $(MAKEFILE_LIST)) + + ECHO_BLANK_LINE := @cmd /c echo. + ECHO_QUIET := @rem + DIR_DELIM := $(strip \) + BIN_EXT := .exe + PATH_SEP := ; + + # For some Windows native commands there is a problem with the directory delimiter. + # Make uses / (slash) and the commands expect \ (backslash) + # We have to provide a means of translating these, so we define local functions. + + # ${1} is the file to be copied. + # ${2} is the destination file name. + define SHELL_COPY + $(eval tmp_from_file:=$(subst /,\,${1})) + $(eval tmp_to_file:=$(subst /,\,${2})) + copy "${tmp_from_file}" "${tmp_to_file}" + endef + + # ${1} is the directory to be copied. + # ${2} is the destination directory path. + define SHELL_COPY_TREE + $(eval tmp_from_dir:=$(subst /,\,${1})) + $(eval tmp_to_dir:=$(subst /,\,${2})) + xcopy /HIVE "${tmp_from_dir}" "${tmp_to_dir}" + endef + + # ${1} is the file to be deleted. + define SHELL_DELETE + $(eval tmp_del_file:=$(subst /,\,${*})) + -@if exist $(tmp_del_file) del /Q $(tmp_del_file) + endef + + # ${1} is a space delimited list of files to be deleted. + define SHELL_DELETE_ALL + $(eval $(foreach filename,$(wildcard ${1}),$(call DELETE_IF_THERE,${filename}))) + endef + + # ${1} is the directory to be generated. + # ${2} is optional, and allows prerequisites to be specified. + # Do nothing if $1 == $2, to ignore self dependencies. + define MAKE_PREREQ_DIR + ifneq (${1},${2}) + +${1} : ${2} + $(eval tmp_dir:=$(subst /,\,${1})) + -@if not exist "$(tmp_dir)" mkdir "${tmp_dir}" + + endif + endef + + # ${1} is the directory to be removed. + define SHELL_REMOVE_DIR + $(eval tmp_dir:=$(subst /,\,${1})) + -@if exist "$(tmp_dir)" rd /Q /S "$(tmp_dir)" + endef + +endif + +# Because git is not available from CMD.EXE, we need to avoid +# the BUILD_STRING generation which uses git. +# For now we use "development build". +# This can be overridden from the command line or environment. +BUILD_STRING ?= development build + +# The DOS echo shell command does not strip ' characters from the command +# parameters before printing. We therefore use an alternative method invoked +# by defining the MAKE_BUILD_STRINGS macro. +BUILT_TIME_DATE_STRING = const char build_message[] = "Built : "${BUILD_MESSAGE_TIMESTAMP}; +VERSION_STRING_MESSAGE = const char version_string[] = "${VERSION_STRING}"; +define MAKE_BUILD_STRINGS + @echo $$(BUILT_TIME_DATE_STRING) $$(VERSION_STRING_MESSAGE) | \ + $$(CC) $$(TF_CFLAGS) $$(CFLAGS) -x c -c - -o $1 +endef + +MSVC_NMAKE := nmake.exe + diff --git a/drivers/rz/ipl/rza/plat/common/aarch64/crash_console_helpers.S b/drivers/rz/ipl/rza/plat/common/aarch64/crash_console_helpers.S new file mode 100644 index 00000000..e2950f5f --- /dev/null +++ b/drivers/rz/ipl/rza/plat/common/aarch64/crash_console_helpers.S @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * If a platform wishes to use the functions in this file it has to be added to + * the Makefile of the platform. It is not included in the common Makefile. + */ + +#include +#include + + .globl plat_crash_console_init + .globl plat_crash_console_putc + .globl plat_crash_console_flush + + /* + * Spinlock to syncronize access to crash_console_triggered. We cannot + * acquire spinlocks when the cache is disabled, so in some cases (like + * late during CPU suspend) some risk remains. + */ +.section .data.crash_console_spinlock + define_asm_spinlock crash_console_spinlock + + /* + * Flag to make sure that only one CPU can write a crash dump even if + * multiple crash at the same time. Interleaving crash dumps on the same + * console would just make the output unreadable, so it's better to only + * get a single but uncorrupted dump. This also means that we don't have + * to duplicate the reg_stash below for each CPU. + */ +.section .data.crash_console_triggered + crash_console_triggered: .byte 0 + + /* + * Space to stash away some register values while we're calling into + * console drivers and don't have a real stack available. We need x14, + * x15 and x30 for bookkeeping within the plat_crash_console functions + * themselves, and some console drivers use x16 and x17 as additional + * scratch space that is not preserved by the main crash reporting + * framework. (Note that x16 and x17 should really never be expected to + * retain their values across any function call, even between carefully + * designed assembly functions, since the linker is always free to + * insert a function call veneer that uses these registers as scratch + * space at any time. The current crash reporting framework doesn't + * really respect that, but since TF is usually linked as a single + * contiguous binary of less than 128MB, it seems to work in practice.) + */ +.section .data.crash_console_reg_stash + .align 3 + crash_console_reg_stash: .quad 0, 0, 0, 0, 0 + + /* -------------------------------------------------------------------- + * int plat_crash_console_init(void) + * Takes the crash console spinlock (if possible) and checks the trigger + * flag to make sure we're the first CPU to dump. If not, return an + * error (so crash dumping will fail but the CPU will still call + * plat_panic_handler() which may do important platform-specific tasks + * that may be needed on all crashing CPUs). In either case, the lock + * will be released so other CPUs can make forward progress on this. + * Clobbers: x0 - x4, x30 + * -------------------------------------------------------------------- + */ +func plat_crash_console_init +#if defined(IMAGE_BL31) + mov x4, x30 /* x3 and x4 are not clobbered by spin_lock() */ + mov x3, #0 /* return value */ + + mrs x1, sctlr_el3 + tst x1, #SCTLR_C_BIT + beq skip_spinlock /* can't synchronize when cache disabled */ + + adrp x0, crash_console_spinlock + add x0, x0, :lo12:crash_console_spinlock + bl spin_lock + +skip_spinlock: + adrp x1, crash_console_triggered + add x1, x1, :lo12:crash_console_triggered + ldarb w2, [x1] + cmp w2, #0 + bne init_error + + mov x3, #1 /* set return value to success */ + stlrb w3, [x1] + +init_error: + bl spin_unlock /* harmless if we didn't acquire the lock */ + mov x0, x3 + ret x4 +#else /* Only one CPU in BL1/BL2, no need to synchronize anything */ + mov x0, #1 + ret +#endif +endfunc plat_crash_console_init + + /* -------------------------------------------------------------------- + * int plat_crash_console_putc(char c) + * Prints the character on all consoles registered with the console + * framework that have CONSOLE_FLAG_CRASH set. Note that this is only + * helpful for crashes that occur after the platform intialization code + * has registered a console. Platforms using this implementation need to + * ensure that all console drivers they use that have the CRASH flag set + * support this (i.e. are written in assembly and comply to the register + * clobber requirements of plat_crash_console_putc(). + * -------------------------------------------------------------------- + */ +func plat_crash_console_putc + adrp x1, crash_console_reg_stash + add x1, x1, :lo12:crash_console_reg_stash + stp x14, x15, [x1] + stp x16, x17, [x1, #16] + str x30, [x1, #32] + + mov w14, w0 /* W14 = character to print */ + adrp x15, console_list + ldr x15, [x15, :lo12:console_list] /* X15 = first console struct */ + +putc_loop: + cbz x15, putc_done + ldr w1, [x15, #CONSOLE_T_FLAGS] + tst w1, #CONSOLE_FLAG_CRASH + b.eq putc_continue + ldr x2, [x15, #CONSOLE_T_PUTC] + cbz x2, putc_continue + cmp w14, #'\n' + b.ne putc + tst w1, #CONSOLE_FLAG_TRANSLATE_CRLF + b.eq putc + mov x1, x15 + mov w0, #'\r' + blr x2 + ldr x2, [x15, #CONSOLE_T_PUTC] +putc: + mov x1, x15 + mov w0, w14 + blr x2 +putc_continue: + ldr x15, [x15] /* X15 = next struct */ + b putc_loop + +putc_done: + adrp x1, crash_console_reg_stash + add x1, x1, :lo12:crash_console_reg_stash + ldp x14, x15, [x1] + ldp x16, x17, [x1, #16] + ldr x30, [x1, #32] + ret +endfunc plat_crash_console_putc + + /* -------------------------------------------------------------------- + * int plat_crash_console_flush(char c) + * Flushes all consoles registered with the console framework that have + * CONSOLE_FLAG_CRASH set. Same requirements as putc(). + * -------------------------------------------------------------------- + */ +func plat_crash_console_flush + adrp x1, crash_console_reg_stash + add x1, x1, :lo12:crash_console_reg_stash + stp x30, x15, [x1] + stp x16, x17, [x1, #16] + + adrp x15, console_list + ldr x15, [x15, :lo12:console_list] /* X15 = first console struct */ + +flush_loop: + cbz x15, flush_done + ldr w1, [x15, #CONSOLE_T_FLAGS] + tst w1, #CONSOLE_FLAG_CRASH + b.eq flush_continue + ldr x2, [x15, #CONSOLE_T_FLUSH] + cbz x2, flush_continue + mov x0, x15 + blr x2 +flush_continue: + ldr x15, [x15] /* X15 = next struct */ + b flush_loop + +flush_done: + adrp x1, crash_console_reg_stash + add x1, x1, :lo12:crash_console_reg_stash + ldp x30, x15, [x1] + ldp x16, x17, [x1, #16] + ret +endfunc plat_crash_console_flush diff --git a/drivers/rz/ipl/rza/plat/common/aarch64/plat_common.c b/drivers/rz/ipl/rza/plat/common/aarch64/plat_common.c new file mode 100644 index 00000000..ba4c366a --- /dev/null +++ b/drivers/rz/ipl/rza/plat/common/aarch64/plat_common.c @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#if RAS_EXTENSION +#include +#endif +#include +#include +#include + +/* + * The following platform setup functions are weakly defined. They + * provide typical implementations that may be re-used by multiple + * platforms but may also be overridden by a platform if required. + */ +#pragma weak bl31_plat_runtime_setup +#pragma weak plat_arm_set_twedel_scr_el3 + +#if SDEI_SUPPORT +#pragma weak plat_sdei_handle_masked_trigger +#pragma weak plat_sdei_validate_entry_point +#endif + +#pragma weak plat_ea_handler + +void bl31_plat_runtime_setup(void) +{ + console_switch_state(CONSOLE_FLAG_RUNTIME); +} + +/* + * Helper function for platform_get_pos() when platform compatibility is + * disabled. This is to enable SPDs using the older platform API to continue + * to work. + */ +unsigned int platform_core_pos_helper(unsigned long mpidr) +{ + int idx = plat_core_pos_by_mpidr(mpidr); + assert(idx >= 0); + return idx; +} + +#if SDEI_SUPPORT +/* + * Function that handles spurious SDEI interrupts while events are masked. + */ +void plat_sdei_handle_masked_trigger(uint64_t mpidr, unsigned int intr) +{ + WARN("Spurious SDEI interrupt %u on masked PE %llx\n", intr, mpidr); +} + +/* + * Default Function to validate SDEI entry point, which returns success. + * Platforms may override this with their own validation mechanism. + */ +int plat_sdei_validate_entry_point(uintptr_t ep, unsigned int client_mode) +{ + return 0; +} +#endif + +#if !ENABLE_BACKTRACE +static const char *get_el_str(unsigned int el) +{ + if (el == MODE_EL3) { + return "EL3"; + } else if (el == MODE_EL2) { + return "EL2"; + } + return "S-EL1"; +} +#endif /* !ENABLE_BACKTRACE */ + +/* RAS functions common to AArch64 ARM platforms */ +void plat_ea_handler(unsigned int ea_reason, uint64_t syndrome, void *cookie, + void *handle, uint64_t flags) +{ +#if RAS_EXTENSION + /* Call RAS EA handler */ + int handled = ras_ea_handler(ea_reason, syndrome, cookie, handle, flags); + if (handled != 0) + return; +#endif + unsigned int level = (unsigned int)GET_EL(read_spsr_el3()); + + ERROR("Unhandled External Abort received on 0x%lx from %s\n", + read_mpidr_el1(), get_el_str(level)); + ERROR("exception reason=%u syndrome=0x%llx\n", ea_reason, syndrome); +#if HANDLE_EA_EL3_FIRST + /* Skip backtrace for lower EL */ + if (level != MODE_EL3) { + console_flush(); + do_panic(); + } +#endif + panic(); +} + +/******************************************************************************* + * In v8.6+ platforms with delayed trapping of WFE this hook sets the delay. It + * is a weak function definition so can be overridden depending on the + * requirements of a platform. The only hook provided is for the TWED fields + * in SCR_EL3, the TWED fields in HCR_EL2, SCTLR_EL2, and SCTLR_EL1 should be + * configured as needed in lower exception levels. + ******************************************************************************/ + +uint32_t plat_arm_set_twedel_scr_el3(void) +{ + return TWED_DISABLED; +} diff --git a/drivers/rz/ipl/rza/plat/common/aarch64/plat_ehf.c b/drivers/rz/ipl/rza/plat/common/aarch64/plat_ehf.c new file mode 100644 index 00000000..da768843 --- /dev/null +++ b/drivers/rz/ipl/rza/plat/common/aarch64/plat_ehf.c @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2020, Broadcom + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +/* + * Enumeration of priority levels on ARM platforms. + */ +ehf_pri_desc_t plat_exceptions[] = { +#if RAS_EXTENSION + /* RAS Priority */ + EHF_PRI_DESC(PLAT_PRI_BITS, PLAT_RAS_PRI), +#endif + +#if SDEI_SUPPORT + /* Critical priority SDEI */ + EHF_PRI_DESC(PLAT_PRI_BITS, PLAT_SDEI_CRITICAL_PRI), + + /* Normal priority SDEI */ + EHF_PRI_DESC(PLAT_PRI_BITS, PLAT_SDEI_NORMAL_PRI), +#endif +#if SPM_MM + EHF_PRI_DESC(PLAT_PRI_BITS, PLAT_SP_PRI), +#endif + /* Plaform specific exceptions description */ +#ifdef PLAT_EHF_DESC + PLAT_EHF_DESC, +#endif +}; + +/* Plug in ARM exceptions to Exception Handling Framework. */ +EHF_REGISTER_PRIORITIES(plat_exceptions, ARRAY_SIZE(plat_exceptions), PLAT_PRI_BITS); diff --git a/drivers/rz/ipl/rza/plat/common/aarch64/platform_helpers.S b/drivers/rz/ipl/rza/plat/common/aarch64/platform_helpers.S new file mode 100644 index 00000000..bc650c96 --- /dev/null +++ b/drivers/rz/ipl/rza/plat/common/aarch64/platform_helpers.S @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + + .weak plat_report_exception + .weak plat_reset_handler + .weak plat_disable_acp + .weak bl1_plat_prepare_exit + .weak plat_panic_handler + .weak bl31_plat_enable_mmu + .weak bl32_plat_enable_mmu + + .weak plat_handle_uncontainable_ea + .weak plat_handle_double_fault + .weak plat_handle_el3_ea + +#define MPIDR_RES_BIT_MASK 0xff000000 + + /* ----------------------------------------------------- + * Placeholder function which should be redefined by + * each platform. + * ----------------------------------------------------- + */ +func plat_report_exception + ret +endfunc plat_report_exception + + /* ----------------------------------------------------- + * Placeholder function which should be redefined by + * each platform. This function should preserve x19 - x29. + * ----------------------------------------------------- + */ +func plat_reset_handler + ret +endfunc plat_reset_handler + + /* ----------------------------------------------------- + * Placeholder function which should be redefined by + * each platform. This function is allowed to use + * registers x0 - x17. + * ----------------------------------------------------- + */ +func plat_disable_acp + ret +endfunc plat_disable_acp + + /* ----------------------------------------------------- + * void bl1_plat_prepare_exit(entry_point_info_t *ep_info); + * Called before exiting BL1. Default: do nothing + * ----------------------------------------------------- + */ +func bl1_plat_prepare_exit + ret +endfunc bl1_plat_prepare_exit + + /* ----------------------------------------------------- + * void plat_panic_handler(void) __dead2; + * Endless loop by default. + * ----------------------------------------------------- + */ +func plat_panic_handler + wfi + b plat_panic_handler +endfunc plat_panic_handler + + /* ----------------------------------------------------- + * void bl31_plat_enable_mmu(uint32_t flags); + * + * Enable MMU in BL31. + * ----------------------------------------------------- + */ +func bl31_plat_enable_mmu + b enable_mmu_direct_el3 +endfunc bl31_plat_enable_mmu + + /* ----------------------------------------------------- + * void bl32_plat_enable_mmu(uint32_t flags); + * + * Enable MMU in BL32. + * ----------------------------------------------------- + */ +func bl32_plat_enable_mmu + b enable_mmu_direct_el1 +endfunc bl32_plat_enable_mmu + + + /* ----------------------------------------------------- + * Platform handler for Uncontainable External Abort. + * + * x0: EA reason + * x1: EA syndrome + * ----------------------------------------------------- + */ +func plat_handle_uncontainable_ea + b report_unhandled_exception +endfunc plat_handle_uncontainable_ea + + /* ----------------------------------------------------- + * Platform handler for Double Fault. + * + * x0: EA reason + * x1: EA syndrome + * ----------------------------------------------------- + */ +func plat_handle_double_fault + b report_unhandled_exception +endfunc plat_handle_double_fault + + /* ----------------------------------------------------- + * Platform handler for EL3 External Abort. + * ----------------------------------------------------- + */ +func plat_handle_el3_ea + b report_unhandled_exception +endfunc plat_handle_el3_ea diff --git a/drivers/rz/ipl/rza/plat/common/aarch64/platform_mp_stack.S b/drivers/rz/ipl/rza/plat/common/aarch64/platform_mp_stack.S new file mode 100644 index 00000000..c0668ea7 --- /dev/null +++ b/drivers/rz/ipl/rza/plat/common/aarch64/platform_mp_stack.S @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + + .local platform_normal_stacks + .weak plat_get_my_stack + .weak plat_set_my_stack + + /* --------------------------------------------------------------------- + * When the compatibility layer is disabled, the platform APIs + * plat_get_my_stack() and plat_set_my_stack() are supported by the + * platform and the previous APIs platform_get_stack() and + * platform_set_stack() are defined in terms of new APIs making use of + * the fact that they are only ever invoked for the current CPU. This + * is to enable components of Trusted Firmware like SPDs using the old + * platform APIs to continue to work. + * -------------------------------------------------------------------- + */ + + /* ----------------------------------------------------- + * uintptr_t plat_get_my_stack () + * + * For the current CPU, this function returns the stack + * pointer for a stack allocated in device memory. + * ----------------------------------------------------- + */ +func plat_get_my_stack + mov x10, x30 + get_my_mp_stack platform_normal_stacks, PLATFORM_STACK_SIZE + ret x10 +endfunc plat_get_my_stack + + /* ----------------------------------------------------- + * void plat_set_my_stack () + * + * For the current CPU, this function sets the stack + * pointer to a stack allocated in normal memory. + * ----------------------------------------------------- + */ +func plat_set_my_stack + mov x9, x30 + bl plat_get_my_stack + mov sp, x0 + ret x9 +endfunc plat_set_my_stack + + /* ----------------------------------------------------- + * Per-CPU stacks in normal memory. Each CPU gets a + * stack of PLATFORM_STACK_SIZE bytes. + * ----------------------------------------------------- + */ +declare_stack platform_normal_stacks, tzfw_normal_stacks, \ + PLATFORM_STACK_SIZE, PLATFORM_CORE_COUNT, \ + CACHE_WRITEBACK_GRANULE diff --git a/drivers/rz/ipl/rza/plat/common/aarch64/platform_up_stack.S b/drivers/rz/ipl/rza/plat/common/aarch64/platform_up_stack.S new file mode 100644 index 00000000..c6e5e2d7 --- /dev/null +++ b/drivers/rz/ipl/rza/plat/common/aarch64/platform_up_stack.S @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2014-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + + + .local platform_normal_stacks + .weak plat_set_my_stack + .weak plat_get_my_stack + + /* ----------------------------------------------------- + * uintptr_t plat_get_my_stack () + * + * For cold-boot BL images, only the primary CPU needs a + * stack. This function returns the stack pointer for a + * stack allocated in device memory. + * ----------------------------------------------------- + */ +func plat_get_my_stack + get_up_stack platform_normal_stacks, PLATFORM_STACK_SIZE + ret +endfunc plat_get_my_stack + + /* ----------------------------------------------------- + * void plat_set_my_stack () + * + * For cold-boot BL images, only the primary CPU needs a + * stack. This function sets the stack pointer to a stack + * allocated in normal memory. + * ----------------------------------------------------- + */ +func plat_set_my_stack + get_up_stack platform_normal_stacks, PLATFORM_STACK_SIZE + mov sp, x0 + ret +endfunc plat_set_my_stack + + /* ----------------------------------------------------- + * Single cpu stack in normal memory. + * Used for C code during boot, PLATFORM_STACK_SIZE bytes + * are allocated + * ----------------------------------------------------- + */ +declare_stack platform_normal_stacks, tzfw_normal_stacks, \ + PLATFORM_STACK_SIZE, 1, CACHE_WRITEBACK_GRANULE diff --git a/drivers/rz/ipl/rza/plat/common/plat_bl_common.c b/drivers/rz/ipl/rza/plat/common/plat_bl_common.c new file mode 100644 index 00000000..89b77ba6 --- /dev/null +++ b/drivers/rz/ipl/rza/plat/common/plat_bl_common.c @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * The following platform functions are weakly defined. The Platforms + * may redefine with strong definition. + */ +#pragma weak bl2_el3_plat_prepare_exit +#pragma weak plat_error_handler +#pragma weak bl2_plat_preload_setup +#pragma weak bl2_plat_handle_pre_image_load +#pragma weak bl2_plat_handle_post_image_load +#pragma weak plat_try_next_boot_source +#pragma weak plat_get_enc_key_info +#pragma weak plat_is_smccc_feature_available +#pragma weak plat_get_soc_version +#pragma weak plat_get_soc_revision + +int32_t plat_get_soc_version(void) +{ + return SMC_ARCH_CALL_NOT_SUPPORTED; +} + +int32_t plat_get_soc_revision(void) +{ + return SMC_ARCH_CALL_NOT_SUPPORTED; +} + +int32_t plat_is_smccc_feature_available(u_register_t fid __unused) +{ + return SMC_ARCH_CALL_NOT_SUPPORTED; +} + +void bl2_el3_plat_prepare_exit(void) +{ +} + +void __dead2 plat_error_handler(int err) +{ + while (1) + wfi(); +} + +void bl2_plat_preload_setup(void) +{ +} + +int bl2_plat_handle_pre_image_load(unsigned int image_id) +{ + return 0; +} + +int bl2_plat_handle_post_image_load(unsigned int image_id) +{ + return 0; +} + +int plat_try_next_boot_source(void) +{ + return 0; +} + +/* + * Weak implementation to provide dummy decryption key only for test purposes, + * platforms must override this API for any real world firmware encryption + * use-case. + */ +int plat_get_enc_key_info(enum fw_enc_status_t fw_enc_status, uint8_t *key, + size_t *key_len, unsigned int *flags, + const uint8_t *img_id, size_t img_id_len) +{ +#define DUMMY_FIP_ENC_KEY { 0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef, \ + 0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef, \ + 0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef, \ + 0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef } + + const uint8_t dummy_key[] = DUMMY_FIP_ENC_KEY; + + assert(*key_len >= sizeof(dummy_key)); + + *key_len = sizeof(dummy_key); + memcpy(key, dummy_key, *key_len); + *flags = 0; + + return 0; +} + +/* + * Set up the page tables for the generic and platform-specific memory regions. + * The size of the Trusted SRAM seen by the BL image must be specified as well + * as an array specifying the generic memory regions which can be; + * - Code section; + * - Read-only data section; + * - Init code section, if applicable + * - Coherent memory region, if applicable. + */ + +void __init setup_page_tables(const mmap_region_t *bl_regions, + const mmap_region_t *plat_regions) +{ +#if LOG_LEVEL >= LOG_LEVEL_VERBOSE + const mmap_region_t *regions = bl_regions; + + while (regions->size != 0U) { + VERBOSE("Region: 0x%lx - 0x%lx has attributes 0x%x\n", + regions->base_va, + regions->base_va + regions->size, + regions->attr); + regions++; + } +#endif + /* + * Map the Trusted SRAM with appropriate memory attributes. + * Subsequent mappings will adjust the attributes for specific regions. + */ + mmap_add(bl_regions); + + /* Now (re-)map the platform-specific memory regions */ + mmap_add(plat_regions); + + /* Create the page tables to reflect the above mappings */ + init_xlat_tables(); +} diff --git a/drivers/rz/ipl/rza/plat/common/plat_log_common.c b/drivers/rz/ipl/rza/plat/common/plat_log_common.c new file mode 100644 index 00000000..66b9758b --- /dev/null +++ b/drivers/rz/ipl/rza/plat/common/plat_log_common.c @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +/* Allow platforms to override the log prefix string */ +#pragma weak plat_log_get_prefix + +static const char *plat_prefix_str[] = { + "ERROR: ", "NOTICE: ", "WARNING: ", "INFO: ", "VERBOSE: "}; + +const char *plat_log_get_prefix(unsigned int log_level) +{ + unsigned int level; + + if (log_level < LOG_LEVEL_ERROR) { + level = LOG_LEVEL_ERROR; + } else if (log_level > LOG_LEVEL_VERBOSE) { + level = LOG_LEVEL_VERBOSE; + } else { + level = log_level; + } + + return plat_prefix_str[(level / 10U) - 1U]; +} diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/board/a3m_ek_nor/rz_board.mk b/drivers/rz/ipl/rza/plat/renesas/rz/board/a3m_ek_nor/rz_board.mk new file mode 100644 index 00000000..14c409fb --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/board/a3m_ek_nor/rz_board.mk @@ -0,0 +1,27 @@ +# +# Copyright (c) 2024, Renesas Electronics Corporation. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +XSPI0_DEVICE?=qspiflash_mx25l25645g +XSPI_DEVICE_TYPE:=QSPI + +NAND:=0 +RZ_FLASH_SIZE ?= 33554432 # 32MB +$(eval $(call add_define,RZ_FLASH_SIZE)) + +ifneq (${USE_SDRAM},0) + +ifeq (${DDR_PLL4},1333) +DDR_SOURCES += plat/renesas/rz/soc/${PLAT}/drivers/ddr/param_mc_C-011_D3-02-1.c \ + plat/renesas/rz/common/drivers/ddr/param_swizzle_T1.c +else +DDR_PLL4 := 1600 +DDR_SOURCES += plat/renesas/rz/soc/${PLAT}/drivers/ddr/param_mc_C-011_D3-01-1.c \ + plat/renesas/rz/common/drivers/ddr/param_swizzle_T1.c +endif + +$(eval $(call add_define,DDR_PLL4)) +endif +$(eval $(call add_define_val,XSPI_DEVICE_TYPE,\"${XSPI_DEVICE_TYPE}\")) diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/board/a3ul_smarc_octal/rz_board.mk b/drivers/rz/ipl/rza/plat/renesas/rz/board/a3ul_smarc_octal/rz_board.mk new file mode 100644 index 00000000..6091417a --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/board/a3ul_smarc_octal/rz_board.mk @@ -0,0 +1,24 @@ +# +# Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +XSPI1_DEVICE?=octaflash_mx66uw +XSPI1_IF_OPTION?=.device_size=128*1024*1024 +XSPI2_DEVICE?=octaram_apsxx +XSPI2_IF_OPTION?=.device_size=64*1024*1024 +XSPI_DEVICE_TYPE:=OCTA + +NAND:=0 +RZ_FLASH_SIZE ?= 134217728 # 128MB +$(eval $(call add_define,RZ_FLASH_SIZE)) + +ifneq (${USE_SDRAM},0) +DDR_SOURCES += plat/renesas/rz/soc/${PLAT}/drivers/ddr/param_mc_C-011_D4-01-2.c \ + plat/renesas/rz/common/drivers/ddr/param_swizzle_T3bcud2.c + +DDR_PLL4 := 1600 +$(eval $(call add_define,DDR_PLL4)) +endif +$(eval $(call add_define_val,XSPI_DEVICE_TYPE,\"${XSPI_DEVICE_TYPE}\")) diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/board/a3ul_smarc_qspi/rz_board.mk b/drivers/rz/ipl/rza/plat/renesas/rz/board/a3ul_smarc_qspi/rz_board.mk new file mode 100644 index 00000000..ae951cea --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/board/a3ul_smarc_qspi/rz_board.mk @@ -0,0 +1,21 @@ +# +# Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +XSPI0_DEVICE?=qspiflash_at25 +XSPI_DEVICE_TYPE:=QSPI + +NAND:=0 +RZ_FLASH_SIZE ?= 16777216 # 16MB +$(eval $(call add_define,RZ_FLASH_SIZE)) + +ifneq (${USE_SDRAM},0) +DDR_SOURCES += plat/renesas/rz/soc/${PLAT}/drivers/ddr/param_mc_C-011_D4-01-2.c \ + plat/renesas/rz/common/drivers/ddr/param_swizzle_T3bcud2.c + +DDR_PLL4 := 1600 +$(eval $(call add_define,DDR_PLL4)) +endif +$(eval $(call add_define_val,XSPI_DEVICE_TYPE,\"${XSPI_DEVICE_TYPE}\")) diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/aarch64/plat_helpers.S b/drivers/rz/ipl/rza/plat/renesas/rz/common/aarch64/plat_helpers.S new file mode 100644 index 00000000..5acfc9c9 --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/aarch64/plat_helpers.S @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + + .globl platform_mem_init + .globl plat_my_core_pos + .globl plat_crash_console_init + .globl plat_crash_console_putc + .globl plat_crash_console_flush + +func platform_mem_init + ret +endfunc platform_mem_init + +func plat_my_core_pos + mrs x0, mpidr_el1 + lsr x0, x0, #MPIDR_AFF1_SHIFT + and x0, x0, #MPIDR_CPU_MASK + ret +endfunc plat_my_core_pos + +func plat_crash_console_init + mov x0, #1 + ret +endfunc plat_crash_console_init + +func plat_crash_console_putc + ret +endfunc plat_crash_console_putc + +func plat_crash_console_flush + mov x0, #0 + ret +endfunc plat_crash_console_flush diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/bl2_plat_mem_params_desc.c b/drivers/rz/ipl/rza/plat/renesas/rz/common/bl2_plat_mem_params_desc.c new file mode 100644 index 00000000..64a434aa --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/bl2_plat_mem_params_desc.c @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#if (RZG2L_BL33_EXECUTION_EL == 0) +#define BL33_MODE MODE_EL1 +#else +#define BL33_MODE MODE_EL2 +#endif + +static bl_mem_params_node_t bl2_mem_params_descs[] = { +#if (APPLOAD == RZ_NOFIP) + { + .image_id = MAX_IMAGE_IDS, + + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, VERSION_2, + entry_point_info_t, SECURE | EXECUTABLE | EP_FIRST_EXE), + .ep_info.spsr = SPSR_64(MODE_EL3, + MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS), + .ep_info.pc = BSP_BASE, + .ep_info.args.arg0 = (uintptr_t)PARAMS_BASE, + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, VERSION_2, + image_info_t, IMAGE_ATTRIB_PLAT_SETUP | IMAGE_ATTRIB_SKIP_LOADING), + + .next_handoff_image_id = INVALID_IMAGE_ID, + } +#else + { +#if RZA3 + .image_id = BL31_IMAGE_ID, + + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, VERSION_2, + entry_point_info_t, SECURE | EXECUTABLE | EP_FIRST_EXE), + .ep_info.spsr = SPSR_64(MODE_EL3, + MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS), + .ep_info.pc = BSP_BASE, + .ep_info.args.arg0 = (uintptr_t)PARAMS_BASE, + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, VERSION_2, + image_info_t, IMAGE_ATTRIB_PLAT_SETUP | IMAGE_ATTRIB_SKIP_LOADING), + .image_info.image_max_size = BSP_LIMIT - BSP_BASE, + .image_info.image_base = BSP_BASE, + + .next_handoff_image_id = INVALID_IMAGE_ID, +#else + .image_id = BL31_IMAGE_ID, + + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, VERSION_2, + entry_point_info_t, SECURE | EXECUTABLE | EP_FIRST_EXE), + .ep_info.spsr = SPSR_64(MODE_EL3, + MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS), + .ep_info.pc = BL31_BASE, + .ep_info.args.arg0 = (uintptr_t)PARAMS_BASE, + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, VERSION_2, + image_info_t, IMAGE_ATTRIB_PLAT_SETUP), + .image_info.image_max_size = BL31_LIMIT - BL31_BASE, + .image_info.image_base = BL31_BASE, + + +# ifdef BL32_BASE + .next_handoff_image_id = BL32_IMAGE_ID, +# else + .next_handoff_image_id = BL33_IMAGE_ID, +# endif /* BL32_BASE */ + }, +# ifdef BL32_BASE + { + .image_id = BL32_IMAGE_ID, + + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, VERSION_2, + entry_point_info_t, SECURE | EXECUTABLE), + .ep_info.pc = BL32_BASE, + .ep_info.spsr = 0, + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, VERSION_2, + image_info_t, 0), + .image_info.image_max_size = BL32_LIMIT - BL32_BASE, + .image_info.image_base = BL32_BASE, + + .next_handoff_image_id = BL33_IMAGE_ID, + }, +# endif /* BL32_BASE */ + { + .image_id = BL33_IMAGE_ID, + + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, VERSION_2, + entry_point_info_t, NON_SECURE | EXECUTABLE), + .ep_info.spsr = SPSR_64(BL33_MODE, MODE_SP_ELX, + DISABLE_ALL_EXCEPTIONS), + .ep_info.pc = BL33_BASE, + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, VERSION_2, + image_info_t, 0), + .image_info.image_max_size = + (uint32_t) (BL33_LIMIT - BL33_BASE), + .image_info.image_base = BL33_BASE, + + .next_handoff_image_id = INVALID_IMAGE_ID, +#endif /* RZA3 */ + } +#endif /* (APPLOAD == RZ_NOFIP) */ +}; + +REGISTER_BL_IMAGE_DESCS(bl2_mem_params_descs) diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/bl2_plat_setup.c b/drivers/rz/ipl/rza/plat/renesas/rz/common/bl2_plat_setup.c new file mode 100644 index 00000000..76c80df4 --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/bl2_plat_setup.c @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef RZA3 +static const mmap_region_t rzg2l_mmap[] = { + /* MMU table for non-RZ/A3UL */ +#if TRUSTED_BOARD_BOOT + MAP_REGION_FLAT(RZG2L_BOOT_ROM_BASE, RZG2L_BOOT_ROM_SIZE, + MT_MEMORY | MT_RO | MT_SECURE), +#endif /*TRUSTED_BOARD_BOOT */ + MAP_REGION_FLAT(RZG2L_SRAM_BASE, RZG2L_SRAM_SIZE, + MT_MEMORY | MT_RW | MT_SECURE), + MAP_REGION_FLAT(PARAMS_BASE, PARAMS_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(RZG2L_DEVICE_BASE, RZG2L_DEVICE_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(RZG2L_SPIROM_BASE, RZG2L_SPIROM_SIZE, + MT_MEMORY | MT_RO | MT_SECURE), + MAP_REGION_FLAT(RZG2L_DDR1_BASE, RZG2L_DDR1_SIZE, + MT_MEMORY | MT_RW | MT_SECURE), + {0} +}; +#endif /* RZA3 */ + +static console_t rzg2l_bl31_console; + +int bl2_plat_handle_pre_image_load(unsigned int image_id) +{ + return 0; +} + +int bl2_plat_handle_post_image_load(unsigned int image_id) +{ + static bl2_to_bl31_params_mem_t *params; + bl_mem_params_node_t *bl_mem_params; + + if (!params) { + params = (bl2_to_bl31_params_mem_t *) PARAMS_BASE; + memset((void *)PARAMS_BASE, 0, sizeof(*params)); + } + + bl_mem_params = get_bl_mem_params_node(image_id); + + switch (image_id) { + case BL32_IMAGE_ID: + memcpy(¶ms->bl32_ep_info, &bl_mem_params->ep_info, + sizeof(entry_point_info_t)); + break; + case BL33_IMAGE_ID: + memcpy(¶ms->bl33_ep_info, &bl_mem_params->ep_info, + sizeof(entry_point_info_t)); + break; + default: + /* Do nothing in default case */ + break; + } + + return 0; +} + + +void bl2_el3_early_platform_setup(u_register_t arg1, u_register_t arg2, + u_register_t arg3, u_register_t arg4) +{ + int ret; + + /* early setup Clock and Reset */ + cpg_early_setup(); + + /* initialize SYC */ + syc_init(RZG2L_SYC_INCK_HZ); + + /* initialize Timer */ + generic_delay_timer_init(); + + /* setup PFC */ + pfc_setup(); + + /* setup Clock and Reset */ + cpg_setup(); + + /* initialize console driver */ + ret = console_rzg2l_register( + RZG2L_SCIF0_BASE, + RZG2L_UART_INCK_HZ, + RZG2L_UART_BARDRATE, + &rzg2l_bl31_console); + if (!ret) + panic(); + + console_set_scope(&rzg2l_bl31_console, + CONSOLE_FLAG_BOOT | CONSOLE_FLAG_CRASH); + + RZA_PRINTF("Initial Program Loader %s\n", RZA_IPL_VERSION_STRING); + RZA_PRINTF("%s\n", build_message); +} + +void bl2_el3_plat_arch_setup(void) +{ +#if RZA3 + rza_mmu_pgtbl_cfg_t g_mmu_pagetable_array[] = { + /* vaddress, paddress, size, attribute */ + {0x00000000, 0x00000000, 0x00200000, RZA_MMU_ATTRIBUTE_NORMAL_CACHEABLE}, + {0x00200000, 0x00200000, 0x0FE00000, RZA_MMU_ATTRIBUTE_ACCESS_FAULT }, + {0x10000000, 0x10000000, 0x10000000, RZA_MMU_ATTRIBUTE_DEVICE }, + {0x20000000, 0x20000000, 0x10000000, RZA_MMU_ATTRIBUTE_NORMAL_CACHEABLE}, + {0x30000000, 0x30000000, 0x10000000, RZA_MMU_ATTRIBUTE_ACCESS_FAULT }, + {0x40000000, 0x40000000, 0x40000000, RZA_MMU_ATTRIBUTE_NORMAL_CACHEABLE}, + {0x80000000, 0x80000000, 0x40000000, RZA_MMU_ATTRIBUTE_ACCESS_FAULT }, + {0xC0000000, 0xC0000000, 0x40000000, RZA_MMU_ATTRIBUTE_ACCESS_FAULT }, + {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, RZA_MMU_ATTRIBUTE_CONFIG_END } + }; +#else + const mmap_region_t bl2_regions[] = { + /* MMU table for non-RZ/A3UL */ + MAP_REGION_FLAT(BL2_BASE, BL2_END - BL2_BASE, + MT_MEMORY | MT_RW | MT_SECURE), + MAP_REGION_FLAT(BL_CODE_BASE, BL_CODE_END - BL_CODE_BASE, + MT_CODE | MT_SECURE), + MAP_REGION_FLAT(BL_RO_DATA_BASE, BL_RO_DATA_END - BL_RO_DATA_BASE, + MT_RO_DATA | MT_SECURE), + {0} + }; +#endif /* RZA3 */ + +#if RZA3 + if (0 != plat_mmu_init(g_mmu_pagetable_array)) { + panic(); + } + plat_mmu_enable(); + +#else + setup_page_tables(bl2_regions, rzg2l_mmap); + enable_mmu_el3(0); +#endif +} + +void bl2_platform_setup(void) +{ + /* Setup TZC-400, Access Control */ + plat_security_setup(); + +#if USE_SDRAM + /* initialize DDR */ + ddr_setup(); +#endif /* DEBUG_FPGA */ + + rz_io_setup(); + + RZ_RUN_TESTS(); + +#if (APPLOAD == RZ_NOFIP) + rza_load_fsp(); +#endif + rza_print_descs(); +} diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/bl31_plat_setup.c b/drivers/rz/ipl/rza/plat/renesas/rz/common/bl31_plat_setup.c new file mode 100644 index 00000000..84ee7917 --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/bl31_plat_setup.c @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +static const mmap_region_t rzg2l_mmap[] = { + MAP_REGION_FLAT(RZG2L_SRAM_BASE, RZG2L_SRAM_SIZE, + MT_MEMORY | MT_RW | MT_SECURE), + MAP_REGION_FLAT(RZG2L_DEVICE_BASE, RZG2L_DEVICE_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(RZG2L_DDR1_BASE, RZG2L_DDR1_SIZE, + MT_MEMORY | MT_RW | MT_SECURE), + {0} +}; + +static console_t rzg2l_bl31_console; +static bl2_to_bl31_params_mem_t from_bl2; + +void bl31_early_platform_setup2(u_register_t arg0, + u_register_t arg1, + u_register_t arg2, + u_register_t arg3) +{ + int ret; + + /* initialize console driver */ + ret = console_rzg2l_register( + RZG2L_SCIF0_BASE, + RZG2L_UART_INCK_HZ, + RZG2L_UART_BARDRATE, + &rzg2l_bl31_console); + if (!ret) + panic(); + + console_set_scope(&rzg2l_bl31_console, + CONSOLE_FLAG_BOOT | CONSOLE_FLAG_RUNTIME | CONSOLE_FLAG_CRASH); + + /* copy bl2_to_bl31_params_mem_t*/ + memcpy(&from_bl2, (void *)arg0, sizeof(from_bl2)); +} + +void bl31_plat_arch_setup(void) +{ + const mmap_region_t bl31_regions[] = { + MAP_REGION_FLAT(BL31_START, BL31_END - BL31_START, + MT_MEMORY | MT_RW | MT_SECURE), + MAP_REGION_FLAT(BL_CODE_BASE, BL_CODE_END - BL_CODE_BASE, + MT_CODE | MT_SECURE), + MAP_REGION_FLAT(BL_RO_DATA_BASE, BL_RO_DATA_END - BL_RO_DATA_BASE, + MT_RO_DATA | MT_SECURE), + {0} + }; + + setup_page_tables(bl31_regions, rzg2l_mmap); + enable_mmu_el3(0); +} + +void bl31_platform_setup(void) +{ + /* Setup TZC-400 */ + plat_security_setup(); + +#if !DEBUG_RZG2L_FPGA + /* initialize GIC-600 */ + plat_gic_driver_init(); + plat_gic_init(); +#endif +} + +entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type) +{ + entry_point_info_t *next_image_info = NULL; + + next_image_info = (type == NON_SECURE) + ? &from_bl2.bl33_ep_info : &from_bl2.bl32_ep_info; + + if (next_image_info->pc) + return next_image_info; + else + return NULL; +} diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/auth/auth_mod.c b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/auth/auth_mod.c new file mode 100644 index 00000000..ec902cb6 --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/auth/auth_mod.c @@ -0,0 +1,249 @@ +/* + * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include +#include "../../include/drivers/auth/auth_common.h" +#include +#include "../../include/drivers/auth/sblib/crypto_sblib.h" +#include +#include + +#define return_if_error(rc) \ + do { \ + if (rc != 0) { \ + return rc; \ + } \ + } while (0) + +#define TBBR_COT_GETTER(id) __extension__ ({ \ + assert((id) < cot_desc_size); \ + cot_desc_ptr[id]; \ +}) + +static int cmp_auth_param_type_desc(const auth_param_type_desc_t *a, + const auth_param_type_desc_t *b) +{ + if ((a->type == b->type) && (a->cookie == b->cookie)) { + return 0; + } + return 1; +} + +/* + * This function obtains the requested authentication parameter data from the + * information extracted from the parent image after its authentication. + */ +static int auth_get_param(const auth_param_type_desc_t *param_type_desc, + const auth_img_desc_t *img_desc, + void **param, unsigned int *len) +{ + int i; + + if (img_desc->authenticated_data == NULL) + return 1; + + for (i = 0 ; i < COT_MAX_VERIFIED_PARAMS ; i++) { + if (0 == cmp_auth_param_type_desc(param_type_desc, + img_desc->authenticated_data[i].type_desc)) { + *param = img_desc->authenticated_data[i].data.ptr; + *len = img_desc->authenticated_data[i].data.len; + return 0; + } + } + + return 1; +} + +/* + * Authenticate an image using Renesas SB-Lib + * + * This function implements 'AUTH_METHOD_SBLIB'. To authenticate an image using + * this method, the image must contain: + * + * - Data to calculate the hash from + * or + * - Data to be signed + * + * The parent image must contain: + * + * - Key Certificate + * - Content Certificate + * + * Key certificate contains the signature and public key to verify itself, + * and the hash value of the public key in the content certificate. + * Content certificate contains the signature and public key to verify itself, + * and an algorithm to authenticate an image. If the image is authenticated + * by matching the hash, content certificate contains the hash of the image. + * If the image is authenticated by digital signature, content certificate + * signature is used to authenticate the certificate and image together. + * + * Renesas SB-Lib authenticates the key certificate, content certificate and + * image together. + * + * Crypto Module is not used because it does not fit the SB-Lib interface. + * + * Return: + * 0 = success, Otherwise = error + */ +static int auth_sblib(const auth_method_param_sblib_t *param, + const auth_img_desc_t *img_desc, + void *img, unsigned int img_len) +{ + const auth_img_desc_t *key_cert_desc, *content_cert_desc; + void *data_ptr, *key_cert_ptr, *content_cert_ptr; + unsigned int data_len, key_cert_len, content_cert_len; + int rc = 0; + + /* Get the content certificate that is the parent of the image */ + content_cert_desc = img_desc->parent; + rc = auth_get_param(param->key_cert, content_cert_desc, + &content_cert_ptr, &content_cert_len); + return_if_error(rc); + + /* Get the key certificate that is the parent of the content certificate */ + key_cert_desc = content_cert_desc->parent; + rc = auth_get_param(param->content_cert, key_cert_desc, + &key_cert_ptr, &key_cert_len); + return_if_error(rc); + + /* Get the data to authenticate from the current image */ + rc = img_parser_get_auth_param(img_desc->img_type, param->data, + img, img_len, &data_ptr, &data_len); + return_if_error(rc); + + /* Ask Renesas SB-Lib to authenticate this image */ + rc = crypto_sblib_auth(data_ptr, data_len, key_cert_ptr, key_cert_len, + content_cert_ptr, content_cert_len); + + return rc; +} + +/* + * Return the parent id in the output parameter '*parent_id' + * + * Return value: + * 0 = Image has parent, 1 = Image has no parent or parent is authenticated + */ +int auth_mod_get_parent_id(unsigned int img_id, unsigned int *parent_id) +{ + const auth_img_desc_t *img_desc = NULL; + + assert(parent_id != NULL); + /* Get the image descriptor */ + img_desc = TBBR_COT_GETTER(img_id); + + /* Check if the image has no parent (ROT) */ + if (img_desc->parent == NULL) { + *parent_id = 0; + return 1; + } + + /* Check if the parent has already been authenticated */ + if (auth_img_flags[img_desc->parent->img_id] & IMG_FLAG_AUTHENTICATED) { + *parent_id = 0; + return 1; + } + + *parent_id = img_desc->parent->img_id; + return 0; +} + +/* + * Initialize the different modules in the authentication framework + */ +void auth_mod_init(void) +{ + /* Check we have a valid CoT registered */ + assert(cot_desc_ptr != NULL); + + /* Renesas SB-Lib */ + crypto_sblib_init(); + + /* Image parser module */ + img_parser_init(); +} + +/* + * Authenticate a certificate/image + * + * Return: 0 = success, Otherwise = error + */ +int auth_mod_verify_img(unsigned int img_id, + void *img_ptr, + unsigned int img_len) +{ + const auth_img_desc_t *img_desc = NULL; + const auth_method_desc_t *auth_method = NULL; + void *param_ptr; + unsigned int param_len; + int rc, i; + + /* Get the image descriptor from the chain of trust */ + img_desc = TBBR_COT_GETTER(img_id); + + /* Ask the parser to check the image integrity */ + rc = img_parser_check_integrity(img_desc->img_type, img_ptr, img_len); + return_if_error(rc); + + /* Authenticate the image using the methods indicated in the image + * descriptor. */ + if (img_desc->img_auth_methods == NULL) + return 1; + for (i = 0 ; i < AUTH_METHOD_NUM ; i++) { + auth_method = &img_desc->img_auth_methods[i]; + switch (auth_method->type) { + case AUTH_METHOD_NONE: + rc = 0; + break; + case AUTH_METHOD_SBLIB: + rc = auth_sblib(&auth_method->param.sblib, + img_desc, img_ptr, img_len); + break; + default: + /* Unknown authentication method */ + rc = 1; + break; + } + return_if_error(rc); + } + + /* Extract the parameters indicated in the image descriptor to + * authenticate the children images. */ + if (img_desc->authenticated_data != NULL) { + for (i = 0 ; i < COT_MAX_VERIFIED_PARAMS ; i++) { + if (img_desc->authenticated_data[i].type_desc == NULL) { + continue; + } + + /* Get the parameter from the image parser module */ + rc = img_parser_get_auth_param(img_desc->img_type, + img_desc->authenticated_data[i].type_desc, + img_ptr, img_len, ¶m_ptr, ¶m_len); + return_if_error(rc); + + /* Check parameter size */ + if (param_len > img_desc->authenticated_data[i].data.len) { + return 1; + } + + /* Copy the parameter for later use */ + memcpy((void *)img_desc->authenticated_data[i].data.ptr, + (void *)param_ptr, param_len); + } + } + + /* Mark image as authenticated */ + auth_img_flags[img_desc->img_id] |= IMG_FLAG_AUTHENTICATED; + + return 0; +} diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/auth/sblib/crypto_sblib.c b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/auth/sblib/crypto_sblib.c new file mode 100644 index 00000000..6367a2e0 --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/auth/sblib/crypto_sblib.c @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include +#include +#include + +#include +#include +#include "../../../include/drivers/auth/sblib/crypto_sblib.h" + +#include "sblib_api_private.h" + +#define SECURE_BOOT_API_ADDR (0x000007F00) + +static sb_secure_boot_api_t secure_boot_api; + +int crypto_sblib_auth(void *data_ptr, size_t len, + const void *key_cert, unsigned int key_cert_len, + const void *content_cert, unsigned int content_cert_len) +{ + sb_ret_t rc; + + assert(secure_boot_api != NULL); + + rc = secure_boot_api(key_cert, key_cert_len, content_cert, + content_cert_len, NULL); + if(SB_RET_SUCCESS != rc) + return CRYPTO_ERR_UNKNOWN; + + return CRYPTO_SUCCESS; +} + +void crypto_sblib_init(void) +{ + secure_boot_api = (sb_secure_boot_api_t)SECURE_BOOT_API_ADDR; +} + diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/auth/sblib/sblib_api_private.h b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/auth/sblib/sblib_api_private.h new file mode 100644 index 00000000..a6d56eca --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/auth/sblib/sblib_api_private.h @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/*!***************************************************************************** +* \file : sblib_api_private.h +* \par version : 1.00 +* \par Product Name : Renesas-SB-Lib +* \par Device(s) : Does not depend on specific hardware +* \par Description : This file defines the public macros, types and +* : declarations in used the SB-Lib. +*******************************************************************************/ + +#ifndef SBLIB_API_PRIVATE_H +#define SBLIB_API_PRIVATE_H + +/** SB-Lib return value definition */ +/**\addtogroup group_return_code Return code */ +/*! \{*/ + +/** API succeeded */ +#define SB_RET_SUCCESS ((sb_ret_t)0x55555555UL) + +/** An image of the same version as the current version is input + (verification completed successfully) */ +#define SB_RET_SAME_IMAGE_VERSION ((sb_ret_t)0x55005501UL) + +/** A internal failure */ +#define SB_RET_ERR_INTERNAL_FAIL ((sb_ret_t)0xAAAA0000UL) + +/** An invalid argument was entered */ +#define SB_RET_ERR_INVALID_ARG ((sb_ret_t)0xAAAA0001UL) + +/** Unsupported function executed */ +#define SB_RET_ERR_UNSUPPORTED_FUNCTION ((sb_ret_t)0xAAAA0002UL) + +/** Data entered with incorrect alignment */ +#define SB_RET_ERR_INVALID_ALIGNMENT ((sb_ret_t)0xAAAA0003UL) + +/** An invalid magic number is set */ +#define SB_RET_ERR_MANI_INVALID_MAGIC ((sb_ret_t)0xAAAA0100UL) + +/** Unsupported version is set */ +#define SB_RET_ERR_MANI_UNSUPPORTED_VERSION ((sb_ret_t)0xAAAA0101UL) + +/** Out of range TLV Length is set */ +#define SB_RET_ERR_MANI_OUT_OF_RANGE_LEN ((sb_ret_t)0xAAAA0102UL) + +/** Missing required TLV field */ +#define SB_RET_ERR_MANI_TLV_FIELD_ERR ((sb_ret_t)0xAAAA0103UL) + +/** The length exceeding the end of the manifest is specified in Length + of the TLV field */ +#define SB_RET_ERR_MANI_TLV_INVALID_LEN ((sb_ret_t)0xAAAA0104UL) + +/** An invalid image length is set */ +#define SB_RET_ERR_MANI_INVALID_IMAGE_LEN ((sb_ret_t)0xAAAA0105UL) + +/** There is a wrong combination of signature algorithms */ +#define SB_RET_ERR_MANI_MISMATCH_SIGN_ALGORITHM ((sb_ret_t)0xAAAA0106UL) + +/** An algorithm was specified that the manifest does not support */ +#define SB_RET_ERR_MANI_UNSUPPORTED_ALGORITHM ((sb_ret_t)0xAAAA0107UL) + +/** Cryptographic processing failure */ +#define SB_RET_ERR_CRYPTO_FAIL ((sb_ret_t)0xAAAA0200UL) + +/** Verification failed */ +#define SB_RET_ERR_CRYPTO_AUTH_FAIL ((sb_ret_t)0xAAAA0201UL) + +/** Unsupported algorithm */ +#define SB_RET_ERR_CRYPTO_UNSUPPORTED_ALGORITHM ((sb_ret_t)0xAAAA0202UL) + +/** Other resorece is using CryptoIP. */ +#define SB_RET_ERR_CRYPTO_RESOURCE_CONFLICT ((sb_ret_t)0xAAAA0203UL) + +/** Parameter error */ +#define SB_RET_ERR_CRYPTO_PARAM_ERR ((sb_ret_t)0xAAAA0204UL) + +/** CRC mismatch */ +#define SB_RET_ERR_CRC_MISMATCH ((sb_ret_t)0xAAAA0300UL) + +/** Unsupported polynominal */ +#define SB_RET_ERR_CRC_UNSUPPORTED_POLYNOMIAL ((sb_ret_t)0xAAAA0301UL) + +/** Image version lower than the current image version is installed */ +#define SB_RET_ERR_LOWER_IMAGE_VERSION ((sb_ret_t)0xAAAA0400UL) + +/*! \}*/ + +/** Manifest size definition */ +/**\addtogroup group_manifest_size Manifest size */ +/*! \{*/ +#define SB_MANIFEST_LEN_MIN (36UL) /**< Minimum manifest length */ +#define SB_MANIFEST_LEN_MAX (10240UL) /**< Maximum manifest length */ +/*! \}*/ + +/** Reserved WORD size definition */ +/**\addtogroup group_unused_area Reserved WORD size */ +/*! \{*/ + +/** Key Certificate header reserved WORD size */ +#define SB_KEY_CERT_RESERVED_WORD_SIZE (5U) + +/*! \}*/ + +/** SB-Lib return type */ +typedef uint32_t sb_ret_t; + +/** SB-Lib Secure Boot API pointer type */ +typedef sb_ret_t (* sb_secure_boot_api_t)( + const uint8_t* const p_key_cert, + const uint32_t key_cert_len_max, + const uint8_t* const p_code_cert, + const uint32_t code_cert_len_max, + const uint8_t* const p_mac_tlv); + +/*!********************************************************* + * \addtogroup SBLIBManifestTypes + * \{*******************************************************/ +/** Key Certificate header structure */ +typedef struct +{ + /** Magic number unique to KeyCertificate */ + uint32_t magic; + + /** Manifest version */ + uint32_t manifest_version; + + /** KeyCertificate flag (Unused in V.1.00) */ + uint32_t flags; + + /** Unused area */ + uint32_t reserved[SB_KEY_CERT_RESERVED_WORD_SIZE]; +} st_sb_key_cert_header_t; + +/** Code Certificate header structure */ +typedef struct +{ + /** Magic number unique to CodeCertificate */ + uint32_t magic; + + /** Manifest version */ + uint32_t manifest_version; + + /** CodeCertificate flag */ + uint32_t flags; + + /** Image storage address */ + uint32_t load_addr; + + /** Image expansion destination address */ + uint32_t dest_addr; + + /** Image byte size */ + uint32_t img_len; + + /** Image version */ + uint32_t img_version; + + /** Image build number */ + uint32_t build_num; +} st_sb_code_cert_header_t; +/*! \}*/ + +#endif /* SBLIB_API_PRIVATE_H */ diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/auth/sblib/sblib_parser.c b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/auth/sblib/sblib_parser.c new file mode 100644 index 00000000..3d01f7d9 --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/auth/sblib/sblib_parser.c @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +#include +#include "../../../include/drivers/auth/auth_common.h" +#include +#include + +#include "sblib_api_private.h" + +#define LIB_NAME "Renesas SB-Lib" + +#define KEY_CERT_HEADER_MAGIC_NUMBER (0x6b657963) +#define CONTENT_CERT_HEADER_MAGIC_NUMBER (0x636f6463) + +/* + * Clear all static temporary variables. + */ +static void clear_temp_vars(void) +{ +#define ZERO_AND_CLEAN(x) \ + do { \ + zeromem(&x, sizeof(x)); \ + clean_dcache_range((uintptr_t)&x, sizeof(x)); \ + } while (0); + +#undef ZERO_AND_CLEAN +} + +static int key_cert_parse(void *img, unsigned int img_len) +{ + return IMG_PARSER_OK; +} + +static int content_cert_parse(void *img, unsigned int img_len) +{ + return IMG_PARSER_OK; +} + +/* Exported functions */ + +static void init(void) +{ + /* Do Nothing */ +} + +/* + * Wrapper for cert_parse() that clears the static variables used by it in case + * of an error. + */ +static int check_integrity(void *img, unsigned int img_len) +{ + int rc; + uint32_t magic; + + if(SB_MANIFEST_LEN_MIN > img_len) + return IMG_PARSER_ERR_FORMAT; + + magic = *(uint32_t *)img; + + switch(magic) + { + case KEY_CERT_HEADER_MAGIC_NUMBER: + rc = key_cert_parse(img, img_len); + break; + case CONTENT_CERT_HEADER_MAGIC_NUMBER: + rc = content_cert_parse(img, img_len); + break; + default: + rc = IMG_PARSER_ERR_FORMAT; + break; + } + + if (rc != IMG_PARSER_OK) + clear_temp_vars(); + + return rc; +} + +/* + * Extract an authentication parameter from an SBLib Manifest + */ +static int get_auth_param(const auth_param_type_desc_t *type_desc, + void *img, unsigned int img_len, + void **param, unsigned int *param_len) +{ + int rc = IMG_PARSER_OK; + + switch (type_desc->type) { + case AUTH_PARAM_RAW_DATA: + *param = (void *)img; + *param_len = (unsigned int)img_len; + break; + default: + rc = IMG_PARSER_ERR_NOT_FOUND; + break; + } + + return rc; +} + +REGISTER_IMG_PARSER_LIB(IMG_PLAT, LIB_NAME, init, \ + check_integrity, get_auth_param); diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/auth/tbbr/tbbr_cot.c b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/auth/tbbr/tbbr_cot.c new file mode 100644 index 00000000..90c4045d --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/auth/tbbr/tbbr_cot.c @@ -0,0 +1,241 @@ +/* + * Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include "../../../include/drivers/auth/auth_common.h" +#include +#if USE_TBBR_DEFS +#include +#else +#include +#endif + +#define KEY_CERT_LEN (256) +#define CONTENT_CERT_LEN (512) + +#ifdef IMAGE_BL2 + +static unsigned char soc_fw_key_cert_buf[KEY_CERT_LEN]; +static unsigned char soc_fw_content_cert_buf[CONTENT_CERT_LEN]; + +static unsigned char tos_fw_key_cert_buf[KEY_CERT_LEN]; +static unsigned char tos_fw_content_cert_buf[CONTENT_CERT_LEN]; + +static unsigned char nt_fw_key_cert_buf[KEY_CERT_LEN]; +static unsigned char nt_fw_content_cert_buf[CONTENT_CERT_LEN]; + + +static auth_param_type_desc_t key_cert = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_RAW_DATA, 0); +static auth_param_type_desc_t content_cert = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_RAW_DATA, 0); +static auth_param_type_desc_t raw_data = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_RAW_DATA, 0); + +/* + * SoC Firmware + */ +static const auth_img_desc_t soc_fw_key_cert = { + .img_id = SOC_FW_KEY_CERT_ID, + .img_type = IMG_PLAT, + .parent = NULL, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_NONE + }, + }, + .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { + [0] = { + .type_desc = &key_cert, + .data = { + .ptr = (void *)soc_fw_key_cert_buf, + .len = (unsigned int)KEY_CERT_LEN + } + } + } +}; + +static const auth_img_desc_t soc_fw_content_cert = { + .img_id = SOC_FW_CONTENT_CERT_ID, + .img_type = IMG_PLAT, + .parent = &soc_fw_key_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_NONE + }, + }, + .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { + [0] = { + .type_desc = &content_cert, + .data = { + .ptr = (void *)soc_fw_content_cert_buf, + .len = (unsigned int)CONTENT_CERT_LEN + } + } + } +}; + +/* + * BL31 + */ +static const auth_img_desc_t bl31_image = { + .img_id = BL31_IMAGE_ID, + .img_type = IMG_RAW, + .parent = &soc_fw_content_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SBLIB, + .param.sblib = { + .data = &raw_data, + .key_cert = &key_cert, + .content_cert = &content_cert + } + } + } +}; + +/* + * Trusted OS Firmware + */ +static const auth_img_desc_t trusted_os_fw_key_cert = { + .img_id = TRUSTED_OS_FW_KEY_CERT_ID, + .img_type = IMG_PLAT, + .parent = NULL, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_NONE + }, + }, + .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { + [0] = { + .type_desc = &key_cert, + .data = { + .ptr = (void *)tos_fw_key_cert_buf, + .len = (unsigned int)KEY_CERT_LEN + } + } + } +}; + +static const auth_img_desc_t trusted_os_fw_content_cert = { + .img_id = TRUSTED_OS_FW_CONTENT_CERT_ID, + .img_type = IMG_PLAT, + .parent = &trusted_os_fw_key_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_NONE + }, + }, + .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { + [0] = { + .type_desc = &content_cert, + .data = { + .ptr = (void *)tos_fw_content_cert_buf, + .len = (unsigned int)CONTENT_CERT_LEN + } + } + } +}; + +/* + * BL32 + */ +static const auth_img_desc_t bl32_image = { + .img_id = BL32_IMAGE_ID, + .img_type = IMG_RAW, + .parent = &trusted_os_fw_content_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SBLIB, + .param.sblib = { + .data = &raw_data, + .key_cert = &key_cert, + .content_cert = &content_cert + } + } + } +}; + +/* + * Non-Trusted Firmware + */ +static const auth_img_desc_t non_trusted_fw_key_cert = { + .img_id = NON_TRUSTED_FW_KEY_CERT_ID, + .img_type = IMG_PLAT, + .parent = NULL, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_NONE + }, + }, + .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { + [0] = { + .type_desc = &key_cert, + .data = { + .ptr = (void *)nt_fw_key_cert_buf, + .len = (unsigned int)KEY_CERT_LEN + } + } + } +}; + +static const auth_img_desc_t non_trusted_fw_content_cert = { + .img_id = NON_TRUSTED_FW_CONTENT_CERT_ID, + .img_type = IMG_PLAT, + .parent = &non_trusted_fw_key_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_NONE + }, + }, + .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { + [0] = { + .type_desc = &content_cert, + .data = { + .ptr = (void *)nt_fw_content_cert_buf, + .len = (unsigned int)CONTENT_CERT_LEN + } + } + } +}; + +/* + * BL33 + */ +static const auth_img_desc_t bl33_image = { + .img_id = BL33_IMAGE_ID, + .img_type = IMG_RAW, + .parent = &non_trusted_fw_content_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SBLIB, + .param.sblib = { + .data = &raw_data, + .key_cert = &key_cert, + .content_cert = &content_cert + } + } + } +}; + +static const auth_img_desc_t * const cot_desc[] = { + [SOC_FW_KEY_CERT_ID] = &soc_fw_key_cert, + [SOC_FW_CONTENT_CERT_ID] = &soc_fw_content_cert, + [BL31_IMAGE_ID] = &bl31_image, + [TRUSTED_OS_FW_KEY_CERT_ID] = &trusted_os_fw_key_cert, + [TRUSTED_OS_FW_CONTENT_CERT_ID] = &trusted_os_fw_content_cert, + [BL32_IMAGE_ID] = &bl32_image, + [NON_TRUSTED_FW_KEY_CERT_ID] = &non_trusted_fw_key_cert, + [NON_TRUSTED_FW_CONTENT_CERT_ID] = &non_trusted_fw_content_cert, + [BL33_IMAGE_ID] = &bl33_image, +}; + +/* Register the CoT in the authentication module */ +REGISTER_COT(cot_desc); + +#endif /* IMAGE_BL2 */ diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/cpg.c b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/cpg.c new file mode 100644 index 00000000..92205d2f --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/cpg.c @@ -0,0 +1,1154 @@ +/* + * Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include + +#define CPG_OFF (0) +#define CPG_ON (1) + +#define CPG_T_CLK (0) +#define CPG_T_RST (1) + +typedef struct { + uintptr_t reg; + uintptr_t mon; + uint32_t val; + uint32_t type; +} CPG_SETUP_DATA; + +typedef struct { + uintptr_t reg; + uint32_t val; +} CPG_REG_SETTING; + +typedef struct { + CPG_REG_SETTING clk1_dat; + CPG_REG_SETTING clk2_dat; + CPG_REG_SETTING stby_dat; +} CPG_PLL_SETDATA_146; + +typedef struct { + CPG_REG_SETTING clk1_dat; + CPG_REG_SETTING clk2_dat; + CPG_REG_SETTING clk3_dat; + CPG_REG_SETTING clk4_dat; + CPG_REG_SETTING clk5_dat; + CPG_REG_SETTING stby_dat; +} CPG_PLL_SETDATA_235; + +typedef struct st_cpg_spi_clk_table { + int frequency; + uint8_t selector; + uint8_t divider; +} cpg_spi_clk_table; + +static cpg_spi_clk_table cpg_xspi_table[] = { + {533000000, 0, 0}, /* 533.0MHz */ + {400000000, 1, 0}, /* 400.0MHz */ + {266500000, 0, 1}, /* 266.5MHz */ + {200000000, 1, 1}, /* 200.0MHz */ + {133250000, 0, 2}, /* 133.3MHz */ + {100000000, 1, 2}, /* 100.0MHz */ + { 66625000, 0, 3}, /* 66.6MHz */ + { 50000000, 1, 3}, /* 50.0MHz */ + { 16656250, 0, 4}, /* 16.7MHz */ + { 12500000, 1, 4}, /* 12.5MHz */ +}; + +#if USE_SDRAM +static CPG_PLL_SETDATA_146 cpg_pll4_setdata = { +#if (DDR_PLL4 ==1600) + { CPG_PLL4_CLK1, 0xFAE13203 }, + { CPG_PLL4_CLK2, 0x00081000 }, +#elif (DDR_PLL4 == 1333) + { CPG_PLL4_CLK1, 0xA66629C3 }, + { CPG_PLL4_CLK2, 0x00080D00 }, +#else +#error "Unknown Board Type." +#endif + { CPG_PLL4_STBY, 0x00010001 } +}; +#endif + +static CPG_PLL_SETDATA_146 cpg_pll6_setdata = { + { CPG_PLL6_CLK1, 0x00003e83 }, + { CPG_PLL6_CLK2, 0x00082D02 }, + { CPG_PLL6_STBY, 0x00010001 }, /* SSC OFF */ +}; + +#define CPG_PLL2_INDEX (0) +#define CPG_PLL3_INDEX (1) +#define CPG_PLL5_INDEX (2) + +static const CPG_SETUP_DATA early_setup_tbl[] = { + { + (uintptr_t)CPG_CLKON_SYC, + (uintptr_t)CPG_CLKMON_SYC, + 0x00010001, + CPG_T_CLK + }, + { + (uintptr_t)CPG_RST_SYC, + (uintptr_t)CPG_RSTMON_SYC, + 0x00010001, + CPG_T_RST + } +}; + +static CPG_SETUP_DATA cpg_clk_on_tbl[] = { + { /* CM33 */ + (uintptr_t)CPG_CLKON_CM33, + (uintptr_t)CPG_CLKMON_CM33, + 0x00030000, + CPG_T_CLK + }, + { /* MHU */ + (uintptr_t)CPG_CLKON_MHU, + (uintptr_t)CPG_CLKMON_MHU, + 0x00010000, + CPG_T_CLK + }, + { /* DMAC */ + (uintptr_t)CPG_CLKON_DAMC_REG, + (uintptr_t)CPG_CLKMON_DAMC_REG, + 0x00030003, + CPG_T_CLK + }, + { /* OSTM */ + (uintptr_t)CPG_CLKON_OSTM, + (uintptr_t)CPG_CLKMON_OSTM, + 0x00060000, + CPG_T_CLK + }, + { /* MTU */ + (uintptr_t)CPG_CLKON_MTU, + (uintptr_t)CPG_CLKMON_MTU, + 0x00010000, + CPG_T_CLK + }, + { /* POE3 */ + (uintptr_t)CPG_CLKON_POE3, + (uintptr_t)CPG_CLKMON_POE3, + 0x00010000, + CPG_T_CLK + }, +#if !(RZG2UL||RZA3) + { /* GPT */ + (uintptr_t)CPG_CLKON_GPT, + (uintptr_t)CPG_CLKMON_GPT, + 0x00010000, + CPG_T_CLK + }, + { /* POEG */ + (uintptr_t)CPG_CLKON_POEG, + (uintptr_t)CPG_CLKMON_POEG, + 0x000F0000, + CPG_T_CLK + }, +#endif + { /* WDT */ + (uintptr_t)CPG_CLKON_WDT, + (uintptr_t)CPG_CLKMON_WDT, +#if (RZG2UL||RZA3) + 0x00300000, +#else + 0x003C0000, +#endif + CPG_T_CLK + }, +#if USE_SDRAM + { /* DDR */ + (uintptr_t)CPG_CLKON_DDR, + (uintptr_t)CPG_CLKMON_DDR, + 0x00030000, + CPG_T_CLK + }, +#else + { /* DDR */ + (uintptr_t)CPG_CLKON_DDR, + (uintptr_t)CPG_CLKMON_DDR, + 0x00030003, + CPG_T_CLK + }, +#endif + { /* SDHI */ + (uintptr_t)CPG_CLKON_SDHI, + (uintptr_t)CPG_CLKMON_SDHI, +#if RZA3M + 0x000f0000, +#else + 0x00ff0000, +#endif + CPG_T_CLK + }, +#if !(RZG2UL||RZA3) + { /* GPU */ + (uintptr_t)CPG_CLKON_GPU, + (uintptr_t)CPG_CLKMON_GPU, + 0x00070000, + CPG_T_CLK + }, +#endif + { /* Image Scaling Unit */ + (uintptr_t)CPG_CLKON_ISU, + (uintptr_t)CPG_CLKMON_ISU, + 0x00030000, + CPG_T_CLK + }, +#if !(RZG2UL||RZA3) + { /* H.264 codec */ + (uintptr_t)CPG_CLKON_H264, + (uintptr_t)CPG_CLKMON_H264, + 0x00010001, + CPG_T_CLK + }, +#endif + { /* Camera Data Receive Unit */ + (uintptr_t)CPG_CLKON_CRU, + (uintptr_t)CPG_CLKMON_CRU, + 0x001f0000, + CPG_T_CLK + }, +#if !(RZG2UL||RZA3) + { /* MIPI-DSI */ + (uintptr_t)CPG_CLKON_MIPI_DSI, + (uintptr_t)CPG_CLKMON_MIPI_DSI, + 0x003f0000, + CPG_T_CLK + }, +#endif + { /* LCDC */ + (uintptr_t)CPG_CLKON_LCDC, + (uintptr_t)CPG_CLKMON_LCDC, + 0x00030000, + CPG_T_CLK + }, + { /* Serial Sound Interface */ + (uintptr_t)CPG_CLKON_SSI, + (uintptr_t)CPG_CLKMON_SSI, + 0x00ff0000, + CPG_T_CLK + }, + { /* Sampling Rate Converter */ + (uintptr_t)CPG_CLKON_SRC, + (uintptr_t)CPG_CLKMON_SRC, + 0x00010000, + CPG_T_CLK + }, + { /* USB2.0 */ + (uintptr_t)CPG_CLKON_USB, + (uintptr_t)CPG_CLKMON_USB, + 0x000f0000, + CPG_T_CLK + }, + { /* ETHER */ + (uintptr_t)CPG_CLKON_ETH, + (uintptr_t)CPG_CLKMON_ETH, + 0x00030000, + CPG_T_CLK + }, + { /* I2C */ + (uintptr_t)CPG_CLKON_I2C, + (uintptr_t)CPG_CLKMON_I2C, + 0x000f0000, + CPG_T_CLK + }, + { /* SCIF */ + (uintptr_t)CPG_CLKON_SCIF, + (uintptr_t)CPG_CLKMON_SCIF, + 0x001f0001, + CPG_T_CLK + }, + { /* SCI */ + (uintptr_t)CPG_CLKON_SCI, + (uintptr_t)CPG_CLKMON_SCI, + 0x00030000, + CPG_T_CLK + }, + { /* IrDA */ + (uintptr_t)CPG_CLKON_IRDA, + (uintptr_t)CPG_CLKMON_IRDA, + 0x00010000, + CPG_T_CLK + }, + { /* SPI */ + (uintptr_t)CPG_CLKON_RSPI, + (uintptr_t)CPG_CLKMON_RSPI, + 0x00070000, + CPG_T_CLK + }, + { /* CAN */ + (uintptr_t)CPG_CLKON_CANFD, + (uintptr_t)CPG_CLKMON_CANFD, + 0x00010000, + CPG_T_CLK + }, + { /* GPIO */ + (uintptr_t)CPG_CLKON_GPIO, + (uintptr_t)CPG_CLKMON_GPIO, + 0x00010001, + CPG_T_CLK + }, + { /* ADC */ + (uintptr_t)CPG_CLKON_ADC, + (uintptr_t)CPG_CLKMON_ADC, + 0x00030000, + CPG_T_CLK + }, + { /* Thermal Sensor Unit */ + (uintptr_t)CPG_CLKON_TSU, + (uintptr_t)CPG_CLKMON_TSU, + 0x00010000, + CPG_T_CLK + } +}; + +static CPG_SETUP_DATA cpg_reset_tbl[] = { + { /* CM33 */ + (uintptr_t)CPG_RST_CM33, + (uintptr_t)CPG_RSTMON_CM33, + 0x00070000, + CPG_T_RST + }, + { /* MHU */ + (uintptr_t)CPG_RST_MHU, + (uintptr_t)CPG_RSTMON_MHU, + 0x00010000, + CPG_T_RST + }, + { /* DMAC */ + (uintptr_t)CPG_RST_DMAC, + (uintptr_t)CPG_RSTMON_DMAC, + 0x00030003, + CPG_T_RST + }, + { /* OSTM */ + (uintptr_t)CPG_RST_OSTM, + (uintptr_t)CPG_RSTMON_OSTM, + 0x00060000, + CPG_T_RST + }, + { /* MTU */ + (uintptr_t)CPG_RST_MTU, + (uintptr_t)CPG_RSTMON_MTU, + 0x00010000, + CPG_T_RST + }, + { /* POE3 */ + (uintptr_t)CPG_RST_POE3, + (uintptr_t)CPG_RSTMON_POE3, + 0x00010000, + CPG_T_RST + }, +#if !(RZG2UL||RZA3) + { /* GPT */ + (uintptr_t)CPG_RST_GPT, + (uintptr_t)CPG_RSTMON_GPT, + 0x00010000, + CPG_T_RST + }, + { /* POEG */ + (uintptr_t)CPG_RST_POEG, + (uintptr_t)CPG_RSTMON_POEG, + 0x000f0000, + CPG_T_RST + }, +#endif + { /* WDT */ + (uintptr_t)CPG_RST_WDT, + (uintptr_t)CPG_RSTMON_WDT, +#if (RZG2UL||RZA3) + 0x00040000, +#else + 0x00060000, +#endif + CPG_T_RST + }, +#if USE_SDRAM + { /* DDR */ + (uintptr_t)CPG_RST_DDR, + (uintptr_t)CPG_RSTMON_DDR, + 0x007F0000, + CPG_T_RST + }, +#else + { /* DDR */ + (uintptr_t)CPG_RST_DDR, + (uintptr_t)CPG_RSTMON_DDR, + 0x007F007F, + CPG_T_RST + }, +#endif + { /* SDHI */ + (uintptr_t)CPG_RST_SDHI, + (uintptr_t)CPG_RSTMON_SDHI, +#if RZA3M + 0x00010000, +#else + 0x00030000, +#endif + CPG_T_RST + }, +#if !(RZG2UL||RZA3) + { /* GPU */ + (uintptr_t)CPG_RST_GPU, + (uintptr_t)CPG_RSTMON_GPU, + 0x00070000, + CPG_T_RST + }, +#endif + { /* Image Scaling Unit */ + (uintptr_t)CPG_RST_ISU, + (uintptr_t)CPG_RSTMON_ISU, + 0x00030000, + CPG_T_RST + }, +#if !(RZG2UL||RZA3) + { /* H.264 codec */ + (uintptr_t)CPG_RST_H264, + (uintptr_t)CPG_RSTMON_H264, + 0x00030003, + CPG_T_RST + }, +#endif + { /* Camera Data Receive Unit */ + (uintptr_t)CPG_RST_CRU, + (uintptr_t)CPG_RSTMON_CRU, + 0x00070000, + CPG_T_RST + }, +#if !(RZG2UL||RZA3) + { /* MIPI-DSI */ + (uintptr_t)CPG_RST_MIPI_DSI, + (uintptr_t)CPG_RSTMON_MIPI_DSI, + 0x00070000, + CPG_T_RST + }, +#endif + { /* LCDC */ + (uintptr_t)CPG_RST_LCDC, + (uintptr_t)CPG_RSTMON_LCDC, + 0x00010000, + CPG_T_RST + }, + { /* Serial Sound Interface */ + (uintptr_t)CPG_RST_SSIF, + (uintptr_t)CPG_RSTMON_SSIF, + 0x000f0000, + CPG_T_RST + }, + { /* Sampling Rate Converter */ + (uintptr_t)CPG_RST_SRC, + (uintptr_t)CPG_RSTMON_SRC, + 0x00010000, + CPG_T_RST + }, + { /* USB2.0 */ + (uintptr_t)CPG_RST_USB, + (uintptr_t)CPG_RSTMON_USB, + 0x000f0000, + CPG_T_RST + }, + { /* ETHER */ + (uintptr_t)CPG_RST_ETH, + (uintptr_t)CPG_RSTMON_ETH, + 0x00030000, + CPG_T_RST + }, + { /* I2C */ + (uintptr_t)CPG_RST_I2C, + (uintptr_t)CPG_RSTMON_I2C, + 0x000f0000, + CPG_T_RST + }, + { /* SCIF */ + (uintptr_t)CPG_RST_SCIF, + (uintptr_t)CPG_RSTMON_SCIF, + 0x001f0001, + CPG_T_RST + }, + { /* SCI */ + (uintptr_t)CPG_RST_SCI, + (uintptr_t)CPG_RSTMON_SCI, + 0x00030000, + CPG_T_RST + }, + { /* IrDA */ + (uintptr_t)CPG_RST_IRDA, + (uintptr_t)CPG_RSTMON_IRDA, + 0x00010000, + CPG_T_RST + }, + { /* SPI */ + (uintptr_t)CPG_RST_RSPI, + (uintptr_t)CPG_RSTMON_RSPI, + 0x00070000, + CPG_T_RST + }, + { /* CAN */ + (uintptr_t)CPG_RST_CANFD, + (uintptr_t)CPG_RSTMON_CANFD, + 0x00030000, + CPG_T_RST + }, + { /* GPIO */ + (uintptr_t)CPG_RST_GPIO, + (uintptr_t)CPG_RSTMON_GPIO, + 0x00070007, + CPG_T_RST + }, + { /* ADC */ + (uintptr_t)CPG_RST_ADC, + (uintptr_t)CPG_RSTMON_ADC, + 0x00030000, + CPG_T_RST + }, + { /* Thermal Sensor Unit */ + (uintptr_t)CPG_RST_TSU, + (uintptr_t)CPG_RSTMON_TSU, + 0x00010000, + CPG_T_RST + }, +}; + +static CPG_REG_SETTING cpg_static_select_tbl[] = { + { (uintptr_t)CPG_PL3A_DDIV, 0x01000100 }, + { (uintptr_t)CPG_PL3_SSEL, 0x01000000 }, +}; + +static CPG_REG_SETTING cpg_dynamic_select_tbl[] = { + { (uintptr_t)CPG_PL4_DSEL, 0x00010001 }, +#if RZA3M + { (uintptr_t)CPG_PL2SDHI_DSEL, 0x00010003 }, + { (uintptr_t)CPG_PL2SDHI_DSEL, 0x00010002 }, +#else + { (uintptr_t)CPG_PL2SDHI_DSEL, 0x00110033 }, + { (uintptr_t)CPG_PL2SDHI_DSEL, 0x00110022 }, +#endif +}; + +#define CPG_SEL_PLL1_ON_OFF (0) +#define CPG_SEL_PLL2_1_ON_OFF (1) +#define CPG_SEL_PLL2_2_ON_OFF (2) +#define CPG_SEL_PLL3_1_ON_OFF (3) +#define CPG_SEL_PLL3_2_ON_OFF (4) +#define CPG_SEL_PLL3_3_ON_OFF (5) +#define CPG_SEL_PLL5_1_ON_OFF (6) +#define CPG_SEL_PLL5_3_ON_OFF (7) +#define CPG_SEL_PLL5_4_ON_OFF (8) +#define CPG_SEL_PLL6_1_ON_OFF (9) +#define CPG_SEL_GPU1_1_ON_OFF (10) +#define CPG_SEL_GPU1_2_ON_OFF (11) +#define CPG_SEL_GPU2_ON_OFF (12) + +static CPG_REG_SETTING cpg_sel_pll1_on_off[] = { + {(uintptr_t)CPG_CLKON_CA55, 0x00010001 } +}; + +static CPG_REG_SETTING cpg_sel_pll2_1_on_off[] = { + {(uintptr_t)CPG_CLKON_ADC, 0x00010001 }, + {(uintptr_t)CPG_CLKON_TSU, 0x00010001 }, +#if RZA3M + {(uintptr_t)CPG_CLKON_SDHI, 0x000f0000 }, +#else + {(uintptr_t)CPG_CLKON_SDHI, 0x00ff0000 }, +#endif +}; + +static CPG_REG_SETTING cpg_sel_pll2_2_on_off[] = { +#if RZA3M + {(uintptr_t)CPG_CLKON_SDHI, 0x000f0000 }, +#else + {(uintptr_t)CPG_CLKON_SDHI, 0x00ff0000 }, +#endif +#if !(RZG2UL||RZA3) + {(uintptr_t)CPG_CLKON_MIPI_DSI, 0x00200020 }, +#endif +}; + +static CPG_REG_SETTING cpg_sel_pll3_1_on_off[] = { + {(uintptr_t)CPG_CLKON_AXI_ACPU_BUS, 0x000F000F }, + {(uintptr_t)CPG_CLKON_AXI_COM_BUS, 0x00030003 }, + {(uintptr_t)CPG_CLKON_AXI_DEFAULT_SLV, 0x00010001 }, + {(uintptr_t)CPG_CLKON_AXI_MCPU_BUS, 0x01930193 }, + {(uintptr_t)CPG_CLKON_AXI_TZCDDR, 0x001F001F }, + {(uintptr_t)CPG_CLKON_AXI_VIDEO_BUS, 0x00030003 }, + {(uintptr_t)CPG_CLKON_CA55, 0x001E001E }, + {(uintptr_t)CPG_CLKON_CM33, 0x00010001 }, + {(uintptr_t)CPG_CLKON_CRU, 0x000C000C }, + {(uintptr_t)CPG_CLKON_CST, 0x07FD07FD }, + {(uintptr_t)CPG_CLKON_DAMC_REG, 0x00030003 }, + {(uintptr_t)CPG_CLKON_DDR, 0x00030003 }, + {(uintptr_t)CPG_CLKON_ETH, 0x00030003 }, + {(uintptr_t)CPG_CLKON_GIC600, 0x00010001 }, +#if !(RZG2UL||RZA3) + {(uintptr_t)CPG_CLKON_GPU, 0x00070007 }, + {(uintptr_t)CPG_CLKON_H264, 0x00010001 }, +#endif + {(uintptr_t)CPG_CLKON_IA55, 0x00030003 }, + {(uintptr_t)CPG_CLKON_IM33, 0x00030003 }, + {(uintptr_t)CPG_CLKON_ISU, 0x00030003 }, + {(uintptr_t)CPG_CLKON_JAUTH, 0x00010001 }, + {(uintptr_t)CPG_CLKON_LCDC, 0x00010001 }, +#if !(RZG2UL||RZA3) + {(uintptr_t)CPG_CLKON_MIPI_DSI, 0x000C000C }, +#endif + {(uintptr_t)CPG_CLKON_OTP, 0x00020002 }, + {(uintptr_t)CPG_CLKON_PERI_COM, 0x00030003 }, + {(uintptr_t)CPG_CLKON_PERI_CPU, 0x000D000D }, + {(uintptr_t)CPG_CLKON_PERI_DDR, 0x00010001 }, + {(uintptr_t)CPG_CLKON_PERI_VIDEO, 0x00070007 }, + {(uintptr_t)CPG_CLKON_REG0_BUS, 0x00010001 }, + {(uintptr_t)CPG_CLKON_REG1_BUS, 0x00030003 }, + {(uintptr_t)CPG_CLKON_ROM, 0x00010001 }, +#if RZA3M + {(uintptr_t)CPG_CLKON_SDHI, 0x000f0000 }, +#else + {(uintptr_t)CPG_CLKON_SDHI, 0x00ff0000 }, +#endif + {(uintptr_t)CPG_CLKON_SRAM_ACPU, 0x00010001 }, + {(uintptr_t)CPG_CLKON_SRAM_MCPU, 0x00010001 }, + {(uintptr_t)CPG_CLKON_SYSC, 0x00020002 }, + {(uintptr_t)CPG_CLKON_TSIPG, 0x00030003 }, + {(uintptr_t)CPG_CLKON_USB, 0x000F000F } +}; + +static CPG_REG_SETTING cpg_sel_pll3_2_on_off[] = { + {(uintptr_t)CPG_CLKON_CRU, 0x00030003 }, +#if !(RZG2UL||RZA3) + {(uintptr_t)CPG_CLKON_MIPI_DSI, 0x00020002 }, + {(uintptr_t)CPG_CLKON_GPU, 0x00010001 }, +#endif + {(uintptr_t)CPG_CLKON_SPI_MULTI, 0x00030003 }, + {(uintptr_t)CPG_CLKON_AXI_MCPU_BUS, 0x02080208 }, +}; + +static CPG_REG_SETTING cpg_sel_pll3_3_on_off[] = { + {(uintptr_t)CPG_CLKON_SPI_MULTI, 0x00030003 }, + {(uintptr_t)CPG_CLKON_AXI_MCPU_BUS, 0x02080208 }, +}; + +static CPG_REG_SETTING cpg_sel_pll5_1_on_off[] = { +#if !(RZG2UL||RZA3) + {(uintptr_t)CPG_CLKON_MIPI_DSI, 0x00010001 }, +#endif + {(uintptr_t)CPG_CLKON_CRU, 0x00100010 }, +#if !(RZG2UL||RZA3) + {(uintptr_t)CPG_CLKON_MIPI_DSI, 0x00100010 }, +#endif + {(uintptr_t)CPG_CLKON_LCDC, 0x00020002 } +}; + +static CPG_REG_SETTING cpg_sel_pll5_3_on_off[] = { +#if !(RZG2UL||RZA3) + {(uintptr_t)CPG_CLKON_MIPI_DSI, 0x00100010 }, +#endif + {(uintptr_t)CPG_CLKON_LCDC, 0x00020002 } +}; + +static CPG_REG_SETTING cpg_sel_pll5_4_on_off[] = { +#if !(RZG2UL||RZA3) + {(uintptr_t)CPG_CLKON_MIPI_DSI, 0x00100010 }, +#endif + {(uintptr_t)CPG_CLKON_LCDC, 0x00020002 } +}; + +static CPG_REG_SETTING cpg_sel_pll6_1_on_off[] = { +#if !(RZG2UL||RZA3) + {(uintptr_t)CPG_CLKON_GPU, 0x00010001 } +#endif +}; + +static CPG_REG_SETTING cpg_sel_gpu1_1_on_off[] = { +#if !(RZG2UL||RZA3) + {(uintptr_t)CPG_CLKON_GPU, 0x00010001 } +#endif +}; + +static CPG_REG_SETTING cpg_sel_gpu1_2_on_off[] = { +#if !(RZG2UL||RZA3) + {(uintptr_t)CPG_CLKON_GPU, 0x00010001 } +#endif +}; + +static CPG_REG_SETTING cpg_sel_gpu2_on_off[] = { +#if !(RZG2UL||RZA3) + {(uintptr_t)CPG_CLKON_GPU, 0x00010001 } +#endif +}; + + +static void cpg_ctrl_clkrst(CPG_SETUP_DATA const *array, uint32_t num) +{ + int i; + uint32_t mask; + uint32_t cmp; + + for (i = 0; i < num; i++, array++) { + mmio_write_32(array->reg, array->val); + + mask = (array->val >> 16) & 0xFFFF; + cmp = array->val & 0xFFFF; + if (array->type == CPG_T_RST) { + cmp = ~(cmp); + } + while ((mmio_read_32(array->mon) & mask) != (cmp & mask)) + ; + } +} + +static void cpg_selector_on_off(uint32_t sel, uint8_t flag) +{ + uint32_t cnt; + uint32_t tbl_num; + CPG_REG_SETTING *ptr; + + switch (sel) { + case CPG_SEL_PLL1_ON_OFF: + tbl_num = ARRAY_SIZE(cpg_sel_pll1_on_off); + ptr = &cpg_sel_pll1_on_off[0]; + break; + case CPG_SEL_PLL2_1_ON_OFF: + tbl_num = ARRAY_SIZE(cpg_sel_pll2_1_on_off); + ptr = &cpg_sel_pll2_1_on_off[0]; + break; + case CPG_SEL_PLL2_2_ON_OFF: + tbl_num = ARRAY_SIZE(cpg_sel_pll2_2_on_off); + ptr = &cpg_sel_pll2_2_on_off[0]; + break; + case CPG_SEL_PLL3_1_ON_OFF: + tbl_num = ARRAY_SIZE(cpg_sel_pll3_1_on_off); + ptr = &cpg_sel_pll3_1_on_off[0]; + break; + case CPG_SEL_PLL3_2_ON_OFF: + tbl_num = ARRAY_SIZE(cpg_sel_pll3_2_on_off); + ptr = &cpg_sel_pll3_2_on_off[0]; + break; + case CPG_SEL_PLL3_3_ON_OFF: + tbl_num = ARRAY_SIZE(cpg_sel_pll3_3_on_off); + ptr = &cpg_sel_pll3_3_on_off[0]; + break; + case CPG_SEL_PLL5_1_ON_OFF: + tbl_num = ARRAY_SIZE(cpg_sel_pll5_1_on_off); + ptr = &cpg_sel_pll5_1_on_off[0]; + break; + case CPG_SEL_PLL5_3_ON_OFF: + tbl_num = ARRAY_SIZE(cpg_sel_pll5_3_on_off); + ptr = &cpg_sel_pll5_3_on_off[0]; + break; + case CPG_SEL_PLL5_4_ON_OFF: + tbl_num = ARRAY_SIZE(cpg_sel_pll5_4_on_off); + ptr = &cpg_sel_pll5_4_on_off[0]; + break; + case CPG_SEL_PLL6_1_ON_OFF: + tbl_num = ARRAY_SIZE(cpg_sel_pll6_1_on_off); + ptr = &cpg_sel_pll6_1_on_off[0]; + break; + case CPG_SEL_GPU1_1_ON_OFF: + tbl_num = ARRAY_SIZE(cpg_sel_gpu1_1_on_off); + ptr = &cpg_sel_gpu1_1_on_off[0]; + break; + case CPG_SEL_GPU1_2_ON_OFF: + tbl_num = ARRAY_SIZE(cpg_sel_gpu1_2_on_off); + ptr = &cpg_sel_gpu1_2_on_off[0]; + break; + case CPG_SEL_GPU2_ON_OFF: + tbl_num = ARRAY_SIZE(cpg_sel_gpu2_on_off); + ptr = &cpg_sel_gpu2_on_off[0]; + break; + default: + break; + } + + for (cnt = 0; cnt < tbl_num; cnt++) { + if (flag == CPG_ON) { + mmio_write_32(ptr[cnt].reg, (mmio_read_32(ptr[cnt].reg) | ptr[cnt].val)); + } else { + mmio_write_32(ptr[cnt].reg, (ptr[cnt].val & 0xFFFF0000)); + } + } + +} + +static void cpg_pll_start_146(CPG_PLL_SETDATA_146 *pdata) +{ + mmio_write_32(pdata->clk1_dat.reg, pdata->clk1_dat.val); + mmio_write_32(pdata->clk2_dat.reg, pdata->clk2_dat.val); + mmio_write_32(pdata->stby_dat.reg, pdata->stby_dat.val); +} + +/* It is assumed that the PLL has stopped by the time this function is executed. */ +static void cpg_pll_setup(void) +{ + uint32_t val = 0; +#if USE_SDRAM + /* PLL4 reset (RESET=0) */ + mmio_write_32(CPG_PLL4_STBY, PLL4_STBY_RESETB_WEN); + + /* PLL4 startup */ + /* PLL4 standby mode transition confirmation */ + do { + val = mmio_read_32(CPG_PLL4_MON); + } while ((val & (PLL4_MON_PLL4_RESETB | PLL4_MON_PLL4_LOCK)) != 0); +#endif + /* PLL6 reset (RESET=0) */ + mmio_write_32(CPG_PLL6_STBY, PLL6_STBY_RESETB_WEN); + + /* PLL6 startup */ + /* PLL6 standby mode transition confirmation */ + do { + val = mmio_read_32(CPG_PLL6_MON); + } while ((val & (PLL6_MON_PLL6_RESETB | PLL6_MON_PLL6_LOCK)) != 0); + +#if USE_SDRAM + /* Set PLL4 to normal mode */ + cpg_pll_start_146(&cpg_pll4_setdata); +#endif + /* Set PLL6 to normal mode */ + cpg_pll_start_146(&cpg_pll6_setdata); + +#if USE_SDRAM + /* PLL4 normal mode transition confirmation */ + do { + val = mmio_read_32(CPG_PLL4_MON); + } while ((val & (PLL4_MON_PLL4_RESETB | PLL4_MON_PLL4_LOCK)) == 0); +#endif +#if !(RZA3M) + /* PLL6 normal mode transition confirmation */ + do { + val = mmio_read_32(CPG_PLL6_MON); + } while ((val & (PLL6_MON_PLL6_RESETB | PLL6_MON_PLL6_LOCK)) == 0); +#endif +} + +static void cpg_div_sel_setup(CPG_REG_SETTING *tbl, uint32_t size) +{ + int cnt; + + for (cnt = 0; cnt < size; cnt++, tbl++) { + mmio_write_32(tbl->reg, tbl->val); + } + +#if USE_SDRAM + /* Wait for completion of settings */ + while (mmio_read_32(CPG_CLKSTATUS) != 0) + ; +#endif +} + +static void cpg_div_sel_static_setup(void) +{ + cpg_div_sel_setup(cpg_static_select_tbl, ARRAY_SIZE(cpg_static_select_tbl)); +} + +static void cpg_div_sel_dynamic_setup(void) +{ + cpg_div_sel_setup(cpg_dynamic_select_tbl, ARRAY_SIZE(cpg_dynamic_select_tbl)); +} + +static void cpg_clk_on_setup(void) +{ + cpg_ctrl_clkrst(&cpg_clk_on_tbl[0], ARRAY_SIZE(cpg_clk_on_tbl)); +} + +static void cpg_reset_setup(void) +{ + cpg_ctrl_clkrst(&cpg_reset_tbl[0], ARRAY_SIZE(cpg_reset_tbl)); +} + +void cpg_active_ddr(void (*disable_phy)(void)) +{ +#if RZA3M + /* Assert AXI_PERIDDR.RESTn */ //Added according to APP006 + mmio_write_32(CPG_RST_PERI_DDR, 0x00010000); + while ((mmio_read_32(CPG_RSTMON_PERI_DDR) & 0x00000001) != 0x00000001) + ; +#endif + /* Assert the reset of DDRTOP */ + mmio_write_32(CPG_RST_DDR, 0x005F0000 | (CPG_RST_DDR_OPT_VALUE << 16)); + mmio_write_32(CPG_OTHERFUNC2_REG, 0x00010000); + while ((mmio_read_32(CPG_RSTMON_DDR) & 0x0000005F) != 0x0000005F) + ; + + /* Start the clocks of DDRTOP */ + mmio_write_32(CPG_CLKON_DDR, 0x00030003); + while ((mmio_read_32(CPG_CLKMON_DDR) & 0x00000003) != 0x00000003) + ; + + udelay(1); + +#if RZA3M + /*AXI_PERIDDR.RESTn */ //Added according to APP006 + mmio_write_32(CPG_RST_PERI_DDR, 0x00010001); + while ((mmio_read_32(CPG_RSTMON_PERI_DDR) & 0x00000001) != 0x00000000) + ; +#endif + /* De-assert rst_n */ + mmio_write_32(CPG_OTHERFUNC2_REG, 0x00010001); + + udelay(1); + + /* De-assert PRESETN */ + mmio_write_32(CPG_RST_DDR, 0x00020002); + while ((mmio_read_32(CPG_RSTMON_DDR) & 0x00000002) != 0x00000000) + ; + + udelay(1); + + disable_phy(); + + /* De-assert axiY_ARESETn, regARESETn, reset_n */ + mmio_write_32(CPG_RST_DDR, 0x005D005D | (CPG_RST_DDR_OPT_VALUE << 16) | CPG_RST_DDR_OPT_VALUE); + while ((mmio_read_32(CPG_RSTMON_DDR) & 0x0000005D) != 0x00000000) + ; + + udelay(1); +} + +void cpg_reset_ddr_mc(void) +{ +#if RZA3M + /* Assert AXI_PERIDDR.RESTn */ //Added according to APP006 + mmio_write_32(CPG_RST_PERI_DDR, 0x00010000); + while ((mmio_read_32(CPG_RSTMON_PERI_DDR) & 0x00000001) != 0x00000001) + ; +#endif + /* Assert rst_n, axiY_ARESETn, regARESETn */ + mmio_write_32(CPG_RST_DDR, 0x005C0000 | (CPG_RST_DDR_OPT_VALUE << 16)); + mmio_write_32(CPG_OTHERFUNC2_REG, 0x00010000); + while ((mmio_read_32(CPG_RSTMON_DDR) & 0x0000005C) != 0x0000005C) + ; + + udelay(1); + +#if RZA3M + /*AXI_PERIDDR.RESTn */ //Added according to APP006 + mmio_write_32(CPG_RST_PERI_DDR, 0x00010001); + while ((mmio_read_32(CPG_RSTMON_PERI_DDR) & 0x00000001) != 0x00000000) + ; +#endif + /* De-assert rst_n */ + mmio_write_32(CPG_OTHERFUNC2_REG, 0x00010001); + + udelay(1); + + /* De-assert axiY_ARESETn, regARESETn */ + mmio_write_32(CPG_RST_DDR, 0x005C005C | (CPG_RST_DDR_OPT_VALUE << 16) | CPG_RST_DDR_OPT_VALUE); + while ((mmio_read_32(CPG_RSTMON_DDR) & 0x0000005C) != 0x00000000) + ; + + udelay(1); +} + +void cpg_early_setup(void) +{ + cpg_ctrl_clkrst(&early_setup_tbl[0], ARRAY_SIZE(early_setup_tbl)); +} + +void cpg_wdtrst_sel_setup(void) +{ + uint32_t reg; + reg = mmio_read_32(CPG_WDTRST_SEL); + reg |= +#if RZA3 + /* setting for RZ/A3UL */ + WDTRST_SEL_WDTRSTSEL0 | WDTRST_SEL_WDTRSTSEL0_WEN ; +#elif RZG2UL + /* setting for RZ/G2UL */ + WDTRST_SEL_WDTRSTSEL0 | WDTRST_SEL_WDTRSTSEL0_WEN | + WDTRST_SEL_WDTRSTSEL2 | WDTRST_SEL_WDTRSTSEL2_WEN ; +#else + /* setting for RZ/G2L, RZ/V2L */ + WDTRST_SEL_WDTRSTSEL0 | WDTRST_SEL_WDTRSTSEL0_WEN | + WDTRST_SEL_WDTRSTSEL1 | WDTRST_SEL_WDTRSTSEL1_WEN | + WDTRST_SEL_WDTRSTSEL2 | WDTRST_SEL_WDTRSTSEL2_WEN ; +#endif + + mmio_write_32(CPG_WDTRST_SEL, reg); +} + +void cpu_cpg_setup(void) +{ + while ((mmio_read_32(CPG_CLKSTATUS) & CLKSTATUS_DIVPL1_STS) != 0x00000000) + ; + mmio_write_32(CPG_PL1_DDIV, PL1_DDIV_DIVPL1_SET_WEN | PL1_DDIV_DIVPL1_SET_1_1); + while ((mmio_read_32(CPG_CLKSTATUS) & CLKSTATUS_DIVPL1_STS) != 0x00000000) + ; +} + +void cpg_setup(void) +{ + cpu_cpg_setup(); + cpg_selector_on_off(CPG_SEL_PLL3_3_ON_OFF, CPG_OFF); + cpg_div_sel_static_setup(); + cpg_selector_on_off(CPG_SEL_PLL3_3_ON_OFF, CPG_ON); + cpg_pll_setup(); + cpg_clk_on_setup(); + cpg_reset_setup(); + cpg_div_sel_dynamic_setup(); + cpg_wdtrst_sel_setup(); +} + +static int cpg_search_spi_clk_table(int frequency) +{ + int tables = sizeof(cpg_xspi_table) / sizeof(cpg_xspi_table[0]); + for (int i = 0; i < tables; i++) { + if (frequency >= cpg_xspi_table[i].frequency) { + return i; + } + } + return -1; +} + +static int cpg_rsearch_spi_clk_table(uint8_t selector, uint8_t divider) +{ + int tables = sizeof(cpg_xspi_table) / sizeof(cpg_xspi_table[0]); + for (int i = 0; i < tables; i++) { + if ( selector == cpg_xspi_table[i].selector && + divider == cpg_xspi_table[i].divider) { + return cpg_xspi_table[i].frequency; + } + } + return -1; +} + +static void wait_until_32(uintptr_t addr, uint32_t mask, uint32_t test) +{ + while((mmio_read_32(addr) & mask) != test) {}; +} + +static void cpg_stop_xspi_clock(xspi_clock spi) +{ + int onoff_pos; + uintptr_t clkon_ctrl; + uintptr_t clkmon_ctrl; + switch(spi) { + case XSPI_CLOCK_SPIM: + onoff_pos = 9; + clkon_ctrl = CPG_CLKON_SPI_MULTI; + clkmon_ctrl = CPG_CLKMON_SPI_MULTI; + break; + case XSPI_CLOCK_OCTA: + onoff_pos = 11; + clkon_ctrl = CPG_CLKON_OCTA; + clkmon_ctrl = CPG_CLKMON_OCTA; + break; + default: + ERROR("Not expected value %d passed to %s.", (int)spi, __func__); + return; + } + + mmio_write_32(clkon_ctrl, 0x00030000); + mmio_write_32(CPG_CLKON_AXI_MCPU_BUS, 0x10000<> seldiv_pos) & 1; + int prev_div = (mmio_read_32(CPG_PL3A_DDIV) >> seldiv_pos) & 7; + + if (prev_sel != cpg_xspi_table[index].selector) { + /* Changing static selector */ + cpg_stop_xspi_clock(spi); + uint32_t sel = cpg_xspi_table[index].selector << seldiv_pos; + sel |= 0x10000 << seldiv_pos; + mmio_write_32(CPG_PL3_SSEL, sel); + cpg_start_xspi_clock(spi); + } + + if (prev_div != cpg_xspi_table[index].divider) { + /* Changing dynamic divider */ + wait_until_32(CPG_CLKSTATUS, 1u<> seldiv_pos) & 1); + div = (uint8_t)((mmio_read_32(CPG_PL3A_DDIV) >> seldiv_pos) & 7); + + int frequency = cpg_rsearch_spi_clk_table(sel,div); + if (frequency == -1) ERROR("CPG register value error (sel=%d, div=%d) in %s", sel, div, __func__); + + return frequency; +} diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/ddr/ddr.c b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/ddr/ddr.c new file mode 100644 index 00000000..cce873b1 --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/ddr/ddr.c @@ -0,0 +1,1025 @@ +/* + * Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +// include +#include +#include + +#include +#include +#include + +#define CEIL(a, div) (((a) + ((div) - 1)) / (div)) +#define _MIN(a, b) ((a) < (b) ? (a) : (b)) +#define _MAX(a, b) ((a) > (b) ? (a) : (b)) + +#define MAX_BYTE_LANES (2U) +#define MAX_BEST_VREF_SAVED (30U) +#define VREF_SETP (1U) + +extern const uint32_t mc_init_tbl[MC_INIT_NUM][2]; +extern const uint32_t mc_odt_pins_tbl[4]; +extern const uint32_t mc_mr1_tbl[2]; +extern const uint32_t mc_mr2_tbl[2]; +extern const uint32_t mc_mr5_tbl[2]; +extern const uint32_t mc_mr6_tbl[2]; +extern const uint32_t mc_phy_settings_tbl[MC_PHYSET_NUM][2]; +extern const uint32_t swizzle_mc_tbl[SWIZZLE_MC_NUM][2]; +extern const uint32_t swizzle_phy_tbl[SIZZLE_PHY_NUM][2]; +extern const char ddr_an_version[]; + +// prototypes +void ddr_setup(void); +static void disable_phy_clk(void); +static void program_mc1(uint8_t *lp_auto_entry_en); +static void program_phy1(uint32_t sl_lanes, uint32_t byte_lanes); +static void exec_trainingWRLVL(uint32_t sl_lanes); +static void exec_trainingVREF(uint32_t sl_lanes, uint32_t byte_lanes); +static void setup_vref_training_registers(uint8_t vref_value, uint8_t cs, uint8_t turn_on_off_vref_training); +static void write_mr(uint8_t cs, uint8_t mrw_sel, uint16_t mrw_data); +static void exec_trainingBITLVL(uint32_t sl_lanes); +static void opt_delay(uint32_t sl_lanes, uint32_t byte_lanes); +static void exec_trainingSL(uint32_t sl_lanes); +static void program_phy2(void); +static void program_mc2(void); + +// main +void ddr_setup(void) +{ + uint32_t sl_lanes, byte_lanes; + uint8_t runBITLVL, runSL, runVREF; + uint8_t lp_auto_entry_en = 0; + uint32_t tmp; + int i; + + RZA_PRINTF("setup DDR (Rev. %s)\n", ddr_an_version); + // Step2 - Step11 + cpg_active_ddr(disable_phy_clk); + + // Step12 + program_mc1(&lp_auto_entry_en); + + // Step13 + tmp = read_mc_reg(DDRMC_R019); + sl_lanes = ((tmp & 0x1) == 0) ? 3 : 1; + byte_lanes = ((tmp & 0x1) == 0) ? 2 : 1; + tmp = read_mc_reg(DDRMC_R039); + runBITLVL = (tmp >> 20) & 0x1; + runSL = (tmp >> 21) & 0x1; + runVREF = (tmp >> 25) & 0x1; + + // Step14 + program_phy1(sl_lanes, byte_lanes); + + // Step15 + while ((read_phy_reg(DDRPHY_R42) & 0x00000003) != sl_lanes) + ; + + // Step16 + ddr_ctrl_reten_en_n(0); + rmw_mc_reg(DDRMC_R007, 0xFFFFFEFF, 0x00000000); + rmw_mc_reg(DDRMC_R001, 0xFEFFFFFF, 0x01000000); + rmw_mc_reg(DDRMC_R000, 0xFFFFFFFE, 0x00000001); + while ((read_mc_reg(DDRMC_R021) & 0x02000000) != 0x02000000) + ; + rmw_phy_reg(DDRPHY_R74, 0xFFF7FFFF, 0x00080000); + rmw_mc_reg(DDRMC_R029, 0xFF0000FF, 64 << 8); + rmw_mc_reg(DDRMC_R027, 0xE00000FF, 111 << 8); + rmw_mc_reg(DDRMC_R020, 0xFFFFFEFF, 0x00000100); + udelay(1); + rmw_phy_reg(DDRPHY_R74, 0xFFF7FFFF, 0x00000000); + + // Step17 + cpg_reset_ddr_mc(); + ddr_ctrl_reten_en_n(1); + + // Step18-19 + program_mc1(&lp_auto_entry_en); + + // Step20 + for (i = 0; i < ARRAY_SIZE(swizzle_mc_tbl); i++) { + write_mc_reg(swizzle_mc_tbl[i][0], swizzle_mc_tbl[i][1]); + } + for (i = 0; i < ARRAY_SIZE(swizzle_phy_tbl); i++) { + write_phy_reg(swizzle_phy_tbl[i][0], swizzle_phy_tbl[i][1]); + } + + // Step21 + rmw_mc_reg(DDRMC_R000, 0xFFFFFFFE, 0x00000001); + + // Step22 + while ((read_mc_reg(DDRMC_R021) & 0x02000000) != 0x02000000) + ; + + // Step23 + rmw_mc_reg(DDRMC_R023, 0xFDFFFFFF, 0x02000000); + + // Step24 + exec_trainingWRLVL(sl_lanes); + + // Step25 + if (runVREF == 1) + exec_trainingVREF(sl_lanes, byte_lanes); + + // Step26 + if (runBITLVL == 1) + exec_trainingBITLVL(sl_lanes); + + // Step27 + opt_delay(sl_lanes, byte_lanes); + + // Step28 + if (runSL == 1) + exec_trainingSL(sl_lanes); + + // Step29 + program_phy2(); + + // Step30 + program_mc2(); + + // Step31 is skipped because ECC is unused. + + // Step32 + rmw_mc_reg(DDRMC_R006, 0xFFFFFFF0, lp_auto_entry_en & 0xF); +} + +static void disable_phy_clk(void) +{ + // Initialization Step9 + write_phy_reg(DDRPHY_R77, 0x00000200); + write_phy_reg(DDRPHY_R78, 0x00010001); +} + +static void program_mc1(uint8_t *lp_auto_entry_en) +{ + int i; + + // Step1 + for (i = 0; i < ARRAY_SIZE(mc_init_tbl); i++) { + if (mc_init_tbl[i][0] == DDRMC_R006) { + *lp_auto_entry_en = mc_init_tbl[i][1] & 0xF; + write_mc_reg(DDRMC_R006, mc_init_tbl[i][1] & 0xFFFFFFF0); + } else { + write_mc_reg(mc_init_tbl[i][0], mc_init_tbl[i][1]); + } + } + + // Step2 + rmw_mc_reg(DDRMC_R025, 0xFCFFFFFF, mc_odt_pins_tbl[0] << 24); + rmw_mc_reg(DDRMC_R026, 0xFFFFFCFF, mc_odt_pins_tbl[1] << 8); + rmw_mc_reg(DDRMC_R025, 0xFFFCFFFF, mc_odt_pins_tbl[2] << 16); + rmw_mc_reg(DDRMC_R026, 0xFFFFFFFC, mc_odt_pins_tbl[3] << 0); + + // Step3 + rmw_mc_reg(DDRMC_R009, ~(mc_mr1_tbl[0]), mc_mr1_tbl[1]); + rmw_mc_reg(DDRMC_R011, ~(mc_mr1_tbl[0]), mc_mr1_tbl[1]); + + // Step4 + rmw_mc_reg(DDRMC_R010, ~(mc_mr2_tbl[0]), mc_mr2_tbl[1]); + rmw_mc_reg(DDRMC_R012, ~(mc_mr2_tbl[0]), mc_mr2_tbl[1]); + + // Step5 + rmw_mc_reg(DDRMC_R015, ~(mc_mr5_tbl[0]), mc_mr5_tbl[1]); + rmw_mc_reg(DDRMC_R016, ~(mc_mr5_tbl[0]), mc_mr5_tbl[1]); + + // Step6 + rmw_mc_reg(DDRMC_R017, ~(mc_mr6_tbl[0]), mc_mr6_tbl[1]); + rmw_mc_reg(DDRMC_R018, ~(mc_mr6_tbl[0]), mc_mr6_tbl[1]); + + // Step7 + for (i = 0; i < ARRAY_SIZE(mc_phy_settings_tbl); i++) { + write_mc_reg(mc_phy_settings_tbl[i][0], mc_phy_settings_tbl[i][1]); + } + + // Step8 is skipped because ECC is unused. +} + +static void program_phy1(uint32_t sl_lanes, uint32_t byte_lanes) +{ + uint16_t dram_clk_period; + uint8_t dram; + uint8_t odt_wr_map_cs0, odt_rd_map_cs0; + uint8_t CL, CWL, AL, PL, RL, WL; + uint32_t mr1, mr1_wl, mr1_wl_mask; + uint32_t mr2, mr2_wl, mr2_wl_mask; + uint8_t clk_drive, dq_dqs_drive, dq_dqs_term, vref_value, vref_ca_value; +#if RZA3M + uint8_t adrctrl_drive; +#endif + uint8_t read_lat, trim_lat; + uint32_t tmp; + int i; + + // Step1 + tmp = read_mc_reg(DDRMC_R039); + dram_clk_period = tmp & 0xFFFF; + dram = (tmp >> 16) & 0xF; + + tmp = read_mc_reg(DDRMC_R025); + odt_wr_map_cs0 = (tmp >> 24) & 0x3; + odt_rd_map_cs0 = (tmp >> 16) & 0x3; + + // Step2 + tmp = read_mc_reg(DDRMC_R002); + CL = (tmp >> 17) & 0x1F; + CWL = (tmp >> 24) & 0x1F; + + tmp = read_mc_reg(DDRMC_R003); + AL = tmp & 0x1F; + PL = (tmp >> 8) & 0xF; + + RL = CL + AL + PL; + WL = CWL + AL + PL; + + // Step3 + mr1 = read_mc_reg(DDRMC_R009) & 0xFFFF; + mr2 = read_mc_reg(DDRMC_R010) & 0xFFFF; + if (dram == 2) { + // DDR4 + mr1_wl_mask = (0x7 << 8) | (0x1 << 7); // 0x78 + mr2_wl_mask = 0x7 << 9; // 0xe0 + switch ((mr2 & mr2_wl_mask) >> 9) { + case 0: + mr1_wl = 0x0; + mr1_wl_mask = 0x0000; + break; + case 1: + mr1_wl = 0x2 << 8; + break; + case 2: + mr1_wl = 0x4 << 8; + break; + case 4: + mr1_wl = 0x6 << 8; + break; + default: + panic(); + } + } else { + // DDR3L, DDR3 + mr1_wl_mask = (0x1 << 9) | (0x1 << 7) | (0x1 << 6) | (0x1 << 2); + mr2_wl_mask = 0x3 << 9; + switch ((mr2 & mr2_wl_mask) >> 9) { + case 0: + mr1_wl = 0x0; + mr1_wl_mask = 0x0000; + break; + case 1: + mr1_wl = (0x0 << 9) | (0x0 << 6) | (0x1 << 2); + break; + case 2: + mr1_wl = (0x0 << 9) | (0x1 << 6) | (0x0 << 2); + break; + default: + panic(); + } + } + mr1_wl |= (mr1 & (0xFFFF ^ mr1_wl_mask)) | (0x1 << 7); + mr2_wl = (mr2 & (0xFFFF ^ mr2_wl_mask)) | (0x0 << 9); + + // Step4 + tmp = read_mc_reg(DDRMC_R040); + clk_drive = tmp & 0xF; + dq_dqs_drive = (tmp >> 4) & 0xF; + dq_dqs_term = (tmp >> 8) & 0xF; +#if RZA3M + adrctrl_drive = (tmp >> 12) & 0xF; +#endif + vref_value = (tmp >> 16) & 0xFF; + vref_ca_value = (tmp >> 24) & 0xFF; + read_lat = (dram == 2 ? 12 : 10) + (CEIL(RL, 2) * 2) - CEIL(WL, 2) + 28; + trim_lat = (dram == 2 ? 11 : 9) + CEIL(RL, 2) - CEIL(WL, 2) + 29; + + // Step5 + tmp = ((WL == 5 ? 0x1 : 0x0) << 16) | 0x00100000; + write_phy_reg(DDRPHY_R77, tmp); + + // Step6 + write_phy_reg(DDRPHY_R05, 0x00000006); + + // Step7 + if (dram == 2) { + // DDR4 + write_phy_reg(DDRPHY_R65, 0x00000009); + } + + // Step8 + write_phy_reg(DDRPHY_R67, (dram == 2 ? 1 : 0) << 27); + write_phy_reg(DDRPHY_R47, (dram == 2 ? 1 : 0) << 24); + + // Step9 + tmp = ((dram == 0 ? 0 : 1) << 15) | ((dram_clk_period < 1000 ? 1 : 0) << 8) | 0x10004000; + write_phy_reg(DDRPHY_R26, tmp); + + // Step10 +#if RZA3M + write_phy_reg(DDRPHY_R13, + clk_drive | (clk_drive << 4) | (adrctrl_drive << 8) | (adrctrl_drive<<12) | + (dq_dqs_drive << 16) | (dq_dqs_drive << 20)); +#else + write_phy_reg(DDRPHY_R13, + clk_drive | (clk_drive << 4) | (clk_drive << 8) | (clk_drive<<12) | + (dq_dqs_drive << 16) | (dq_dqs_drive << 20)); +#endif + + // Step11 + tmp = dq_dqs_term | ((dram == 2) ? 0 : (dq_dqs_term << 4)); + write_phy_reg(DDRPHY_R14, tmp); + + // Step12 + write_phy_reg(DDRPHY_R10, 0x00000000); + + // Step13 + for (i = 0; i < byte_lanes; i++) { + write_phy_reg(DDRPHY_R29, 7 * i); + write_phy_reg(DDRPHY_R66, (vref_value << 4) | 0x00000004); + } + + // Step14 + write_phy_reg(DDRPHY_R12, vref_ca_value); + + // Step15 + write_phy_reg(DDRPHY_R61, 0x1A09002D); + + // Step16 + write_phy_reg(DDRPHY_R41, 0x00000000); + + // Step17 + write_phy_reg(DDRPHY_R74, 0x0000001A); + + // Step18 + tmp = ((dram == 2 ? 0 : 1) << 2) | (CEIL(CL, 2) << 4) | (CEIL(AL, 2) << 8) | + (odt_rd_map_cs0 << 16) | (odt_wr_map_cs0 << 24) | 0x00000001; + write_phy_reg(DDRPHY_R24, tmp); + + // Step19 + tmp = (CEIL(CWL, 2) << 8) | ((((WL % 2) == 0) ? 0 : 1) << 24) | 0x80000001; + write_phy_reg(DDRPHY_R25, tmp); + + // Step20 + write_phy_reg(DDRPHY_R45, sl_lanes ^ 0x3); + + // Step21 + write_phy_reg(DDRPHY_R64, (trim_lat << 4) | (read_lat << 12)); + + // Step22 + tmp = ((WL % 2) == 0) & 0x1; + write_phy_reg(DDRPHY_R63, tmp); + + // Step23 + write_phy_reg(DDRPHY_R72, 0x00000170); + + // Step24 + write_phy_reg(DDRPHY_R38, mr2_wl | (mr2 << 16)); + + // Step25 + write_phy_reg(DDRPHY_R39, mr1 | (mr1_wl << 16)); + + // Step26 + write_phy_reg(DDRPHY_R27, 0xAC001000); + + // Step27 + udelay(10); + + // Step28 is skipped because dll_mas_dly is unused. + + // Step29 + write_phy_reg(DDRPHY_R44, 0x00000000); + + // Step30 + write_phy_reg(DDRPHY_R43, 0x00000000); + + // Step31 + for (i = 0; i < byte_lanes; i++) { + write_phy_reg(DDRPHY_R29, 6 * i); + write_phy_reg(DDRPHY_R30, 9); +#if RZA3M + write_phy_reg(DDRPHY_R32, 14); //Changed from 10 to 14 according to APP_005 +#else + write_phy_reg(DDRPHY_R32, 10); +#endif + } + + // Step32 + write_phy_reg(DDRPHY_R28, 26 | 0x00000200); + + // Step33 + write_phy_reg(DDRPHY_R29, 0); +#if RZA3M + write_phy_reg(DDRPHY_R57, 29 | 0x00000080); +#else + write_phy_reg(DDRPHY_R57, 26 | 0x00000080); +#endif + + // Step34 + write_phy_reg(DDRPHY_R27, 26 | (0x10 << 8) | 0xAC000000); + + // Step35 + write_phy_reg(DDRPHY_R21, 0x00035076); + + // Step36 + write_phy_reg(DDRPHY_R07, 0x00000032); + + // lpddr4_combo_io_cal + { + // Step37-2 + rmw_phy_reg(DDRPHY_R47, 0xFF800000, 0x00000000); + + // Step37-3 + switch (dram) { + case 0: + tmp = 0x00003200; + break; + case 1: + tmp = 0x00005200; + break; + case 2: + tmp = 0x08009200; + break; + default: + tmp = 0x00000000; + break; + } + write_phy_reg(DDRPHY_R67, tmp); + write_phy_reg(DDRPHY_R46, 0x00000002); + while ((read_phy_reg(DDRPHY_R46) & 0x00000008) != 0x00000008) + ; + + write_phy_reg(DDRPHY_R46, 0x00000000); + udelay(100); + + // Step37-4 + switch (dram) { + case 0: + case 1: + tmp = 0x00041200; + break; + case 2: + tmp = 0x08101300; + break; + default: + tmp = 0x00000000; + break; + } + write_phy_reg(DDRPHY_R67, tmp); + write_phy_reg(DDRPHY_R46, 0x00000001); + while ((read_phy_reg(DDRPHY_R46) & 0x00000004) != 0x00000004) + ; + + rmw_phy_reg(DDRPHY_R46, 0xFFFFFFEF, 0x00000010); + rmw_phy_reg(DDRPHY_R46, 0xFFFFFFEF, 0x00000000); + udelay(1); + } + + // Step38 + rmw_phy_reg(DDRPHY_R27, 0xFBFFFFFF, 0x00000000); + + // Step39 + rmw_phy_reg(DDRPHY_R78, 0xFFFFF0FE, (sl_lanes << 8)); +} + +static void exec_trainingWRLVL(uint32_t sl_lanes) +{ + uint32_t tmp; + + // Step2 + tmp = read_phy_reg(DDRPHY_R24); + write_phy_reg(DDRPHY_R24, tmp | 0x01000000); + + // Step3 + write_phy_reg(DDRPHY_R37, sl_lanes); + + // Step4 + write_phy_reg(DDRPHY_R31, 0x00010000); + + // Step5 + write_phy_reg(DDRPHY_R18, 0x50200000); + + // Step6 + while ((read_phy_reg(DDRPHY_R18) & 0x10000000) != 0x00000000) + ; + + // Step7 - Step8 + if (((read_phy_reg(DDRPHY_R36) & sl_lanes) != sl_lanes) || + ((read_phy_reg(DDRPHY_R37) & sl_lanes) != 0)) { + panic(); + } + + // Step9 + write_phy_reg(DDRPHY_R24, tmp); +} + +static void exec_trainingVREF(uint32_t sl_lanes, uint32_t byte_lanes) +{ + uint32_t vref_mid_level_code; + uint32_t vref_training_value; + uint32_t sweep_range; + uint16_t current_vref = 0; + uint32_t best_window_diff_so_far[MAX_BYTE_LANES]; + uint32_t num_best_vref_matches[MAX_BYTE_LANES]; + uint32_t all_best_vref_matches[MAX_BYTE_LANES][MAX_BEST_VREF_SAVED]; + uint8_t window_0, window_1, window_diff; + uint32_t highest_best_vref_val, lowest_best_vref_val; + uint8_t orig_cs_config; + uint32_t tmp; + int i, j; + + // Step2 + for (i = 0; i < byte_lanes; i++) { + write_phy_reg(DDRPHY_R29, i); + rmw_phy_reg(DDRPHY_R07, 0xFFFFFFCF, 0x00000010); + } + // Step3 + vref_mid_level_code = (read_mc_reg(DDRMC_R040) >> 16) & 0xFF; + sweep_range = read_mc_reg(DDRMC_R043) & 0xFF; + + // Step4 + for (i = 0; i < byte_lanes; i++) { + best_window_diff_so_far[i] = 255; + num_best_vref_matches[i] = 0; + } + + // Step5 + for (vref_training_value = 0; + vref_training_value < (sweep_range * 2) + 1; + vref_training_value += VREF_SETP) { + // Step5.1 + if (vref_training_value < sweep_range + 1) { + if (vref_mid_level_code < vref_training_value + 2) { + vref_training_value = sweep_range; + continue; + } else { + current_vref = vref_mid_level_code - vref_training_value; + } + } else { + if ((vref_mid_level_code + vref_training_value - sweep_range) > 126) { + break; + } else { + current_vref = vref_mid_level_code + vref_training_value - sweep_range; + } + } + for (i = 0; i < byte_lanes; i++) { + write_phy_reg(DDRPHY_R29, 7 * i); + write_phy_reg(DDRPHY_R66, (current_vref << 4) | 0x00000001); + } + + // Step5.2 + write_phy_reg(DDRPHY_R18, 0x30800000); + while ((read_phy_reg(DDRPHY_R18) & 0x10000000) != 0x00000000) + ; + + // Step5.3 + for (i = 0; i < byte_lanes; i++) { + if (((read_phy_reg(DDRPHY_R59) >> (14 + i)) & 0x1) == 0x0) { + RZA_PRINTF_INFO("PHY side VREF training passed on lane %0d, current_vref = %0d\n", i, current_vref); + write_phy_reg(DDRPHY_R29, i * 6); + window_0 = read_phy_reg(DDRPHY_R69) & 0x3F; + window_1 = (read_phy_reg(DDRPHY_R69) >> 8) & 0x3F; + window_diff = (window_0 > window_1) ? + window_0 - window_1 : window_1 - window_0; + RZA_PRINTF_INFO("window_0 = %0d, window_1 = %0d, window_diff = %0d\n", window_0, window_1, window_diff); + if (window_diff < best_window_diff_so_far[i]) { + best_window_diff_so_far[i] = window_diff; + all_best_vref_matches[i][0] = current_vref; + num_best_vref_matches[i] = 1; + RZA_PRINTF_INFO("CURRENT BEST VREF PHY side :%d\n", current_vref); + } else if ((window_diff == best_window_diff_so_far[i]) && + (num_best_vref_matches[i] < MAX_BEST_VREF_SAVED)) { + all_best_vref_matches[i][num_best_vref_matches[i]] = current_vref; + num_best_vref_matches[i] += 1; + } + } else { + RZA_PRINTF_INFO("PHY side VREF training failed lane %d, current_vref = %d\n", + i, current_vref); + } + } + // Step5.4 + } + + // Step6 + for (i = 0; i < byte_lanes; i++) { + highest_best_vref_val = 0x0; + lowest_best_vref_val = 0x7F; + for (j = 0; j < num_best_vref_matches[i]; j++) { + highest_best_vref_val = + _MAX(all_best_vref_matches[i][j], highest_best_vref_val); + lowest_best_vref_val = + _MIN(all_best_vref_matches[i][j], lowest_best_vref_val); + } + current_vref = (highest_best_vref_val + lowest_best_vref_val) >> 1; + write_phy_reg(DDRPHY_R29, 7 * i); + write_phy_reg(DDRPHY_R66, current_vref << 4); + } + + // Step7 + write_phy_reg(DDRPHY_R19, 0xFF00FF00); + write_phy_reg(DDRPHY_R20, 0xFF00FF00); + + // Step8 + write_phy_reg(DDRPHY_R18, 0x30800000); + while ((read_phy_reg(DDRPHY_R18) & 0x10000000) != 0x00000000) + ; + + // Step9 + tmp = (read_phy_reg(DDRPHY_R59) >> 14) & sl_lanes; + if ((tmp ^ sl_lanes) != sl_lanes) { + panic(); + } + + // Step10 + rmw_phy_reg(DDRPHY_R54, 0xFFFFFF7F, 0x00000080); + + // Step11 + vref_mid_level_code = (read_mc_reg(DDRMC_R043) >> 8) & 0xFF; + sweep_range = (read_mc_reg(DDRMC_R043) >> 16) & 0xFF; + + // Step12 + orig_cs_config = read_phy_reg(DDRPHY_R25) & 0x3; + + // Step13 + setup_vref_training_registers(vref_mid_level_code, sl_lanes, 1); + + // Step14 + rmw_phy_reg(DDRPHY_R66, 0xFFFFFFFE, 0x00000001); + + // Step15 + for (i = 0; i < byte_lanes; i++) { + best_window_diff_so_far[i] = 255; + num_best_vref_matches[i] = 0; + } + + // Step16 + for (vref_training_value = 0; + vref_training_value < (sweep_range * 2) + 1; + vref_training_value += VREF_SETP) { + // Step16.1 + if (vref_training_value < (sweep_range + 1)) { + if (vref_training_value > vref_mid_level_code) { + vref_training_value = sweep_range; + continue; + } else { + current_vref = vref_mid_level_code - vref_training_value; + } + } else { + if ((vref_mid_level_code + vref_training_value - sweep_range) <= 73) { + current_vref = + vref_mid_level_code + vref_training_value - sweep_range; + } else { + break; + } + } + setup_vref_training_registers(current_vref, orig_cs_config, 0); + + // Step16.2 + write_phy_reg(DDRPHY_R18, 0x30500000); + while ((read_phy_reg(DDRPHY_R18) & 0x10000000) != 0x00000000) + ; + + // Step16.3 + tmp = (read_phy_reg(DDRPHY_R64) >> 20) & sl_lanes; + for (i = 0; i < byte_lanes; i++) { + if ((tmp ^ sl_lanes) == sl_lanes) { + RZA_PRINTF_INFO("VREF training passed during VrefDQ training DRAM side, current_vref = %d\n", current_vref); + write_phy_reg(DDRPHY_R29, i * 6); + window_0 = read_phy_reg(DDRPHY_R69) & 0x3F; + window_1 = (read_phy_reg(DDRPHY_R69) >> 8) & 0x3F; + window_diff = (window_0 > window_1) ? + window_0 - window_1 : window_1 - window_0; + RZA_PRINTF_INFO("window_0 = %0d, window_1 = %0d, window_diff = %0d\n", window_0, window_1, window_diff); + if (window_diff < best_window_diff_so_far[i]) { + best_window_diff_so_far[i] = window_diff; + all_best_vref_matches[i][0] = current_vref; + num_best_vref_matches[i] = 1; + RZA_PRINTF_INFO("CURRENT BEST VREF DRAM side :%d\n", current_vref); + } else if ((window_diff == best_window_diff_so_far[i]) && + (num_best_vref_matches[i] < MAX_BEST_VREF_SAVED)) { + all_best_vref_matches[i][num_best_vref_matches[i]] = current_vref; + num_best_vref_matches[i] += 1; + } + } else { + RZA_PRINTF_INFO("VREF training failed during VrefDQ training DRAM side, current_vref = %d\n", current_vref); + } + } + // Step16.4 + } + + // Step17 + highest_best_vref_val = 0x0; + lowest_best_vref_val = 0x7F; + for (i = 0; i < byte_lanes; i++) { + for (j = 0; j < num_best_vref_matches[i]; j++) { + highest_best_vref_val = + _MAX(all_best_vref_matches[i][j], highest_best_vref_val); + lowest_best_vref_val = + _MIN(all_best_vref_matches[i][j], lowest_best_vref_val); + } + } + current_vref = (highest_best_vref_val + lowest_best_vref_val) >> 1; + + // Step18 + setup_vref_training_registers(current_vref, sl_lanes, 0); + + // Step19 + rmw_mc_reg(DDRMC_R044, 0xFFFFFF00, current_vref); + + // Step20 + rmw_phy_reg(DDRPHY_R66, 0xFFFFFFFE, 0x00000000); + + // Step21 + setup_vref_training_registers(current_vref, sl_lanes, 2); + + // Step22 + rmw_phy_reg(DDRPHY_R54, 0xFFFFFF7F, 0x00000000); + + // Step23 + for (i = 0; i < byte_lanes; i++) { + write_phy_reg(DDRPHY_R29, i); + rmw_phy_reg(DDRPHY_R07, 0xFFFFFFCF, 0x00000030); + } +} + +static void setup_vref_training_registers(uint8_t vref_value, uint8_t cs, uint8_t turn_on_off_vref_training) +{ + uint8_t vref_op_code; + uint16_t mr; + + // Step1 + if (vref_value > 50) { + vref_op_code = vref_value - 23; + } else { + vref_op_code = vref_value | (1 << 6); + } + + // Step2 + mr = read_mc_reg(DDRMC_R017) & 0xFF00; + write_mr(cs, 6, + mr | (((turn_on_off_vref_training == 2) ? 0 : 1) << 7) | vref_op_code); + + // Step3 + udelay(1); +} + +static void write_mr(uint8_t cs, uint8_t mrw_sel, uint16_t mrw_data) +{ + uint8_t mrw_cs; + uint8_t mrw_allcs; + + // Step1 + mrw_cs = 0; + if (cs & 0x1) { + rmw_mc_reg(DDRMC_R013, 0xFFFF0000, mrw_data); + mrw_cs = 0; + } + if (cs & 0x2) { + rmw_mc_reg(DDRMC_R014, 0xFFFF0000, mrw_data); + mrw_cs = 1; + } + mrw_allcs = ((cs & 0x3) == 0x3) ? 1 : 0; + + // Step2 + rmw_mc_reg(DDRMC_R008, 0xFC000000, + 0x02800000 | (mrw_allcs << 24) | (mrw_cs << 8) | mrw_sel); + + // Step3 + while ((read_mc_reg(DDRMC_R022) & (1 << 3)) != (1 << 3)) + ; + + // Step4 + rmw_mc_reg(DDRMC_R024, 0xFFFFFFF7, 0x00000008); +} + +static void exec_trainingBITLVL(uint32_t sl_lanes) +{ + uint32_t tmp; + + // Step2 + write_phy_reg(DDRPHY_R62, 0x00000000); + + // Step3 + write_phy_reg(DDRPHY_R19, 0xFF00FF00); + write_phy_reg(DDRPHY_R20, 0xFF00FF00); + + // Step4 + write_phy_reg(DDRPHY_R18, 0x30A00000); + + // Step5 + while ((read_phy_reg(DDRPHY_R18) & 0x10000000) != 0x00000000) + ; + + // Step6 + tmp = (read_phy_reg(DDRPHY_R59) >> 14) & sl_lanes; + if ((tmp ^ sl_lanes) != sl_lanes) { + panic(); + } + + // Step7 + rmw_phy_reg(DDRPHY_R54, 0xFFFFFF7F, 0x00000080); + + // Step8 + write_phy_reg(DDRPHY_R18, 0x30700000); + + // Step9 + while ((read_phy_reg(DDRPHY_R18) & 0x10000000) != 0x00000000) + ; + + // Step10 + tmp = (read_phy_reg(DDRPHY_R64) >> 20) & sl_lanes; + if ((tmp ^ sl_lanes) != sl_lanes) { + panic(); + } + + // Step11 + rmw_phy_reg(DDRPHY_R54, 0xFFFFFF7F, 0x00000000); + + // Step12 + write_phy_reg(DDRPHY_R51, 0x00080000); + + // Step13 + write_phy_reg(DDRPHY_R18, 0x11200000); + + // Step14 + while ((read_phy_reg(DDRPHY_R18) & 0x10000000) != 0x00000000) + ; + + // Step15 + write_phy_reg(DDRPHY_R51, 0x00000000); + + // Step16 + write_phy_reg(DDRPHY_R18, 0x30A00000); + + // Step17 + while ((read_phy_reg(DDRPHY_R18) & 0x10000000) != 0x00000000) + ; +} + +static void opt_delay(uint32_t sl_lanes, uint32_t byte_lanes) +{ + uint32_t tmp; + uint16_t dlls_trim_ca; +#if RZA3M + uint16_t dlls_trim_clk; +#endif + uint16_t dlls_trim_2[MAX_BYTE_LANES]; + uint16_t op_dqs_trim[MAX_BYTE_LANES]; + uint16_t min_WL; + uint16_t min_WD = 128; + int i, j; + + // Step2 + rmw_phy_reg(DDRPHY_R27, 0xFBFFFFFF, 0x04000000); + + // Step3 + rmw_mc_reg(DDRMC_R004, ~(0x7F << LP_CMD_OFFSET), (0x00000011 << LP_CMD_OFFSET)); + while (((read_mc_reg(DDRMC_R005) >> 24) & 0x7F) != 0x48) + ; + + // Step4 + write_phy_reg(DDRPHY_R29, 0); +#if RZA3M + dlls_trim_clk = read_phy_reg(DDRPHY_R57) & 0x7F; + dlls_trim_ca = read_phy_reg(DDRPHY_R28) & 0x7F; + if (dlls_trim_clk <= dlls_trim_ca) { + panic(); + } +#else + dlls_trim_ca = read_phy_reg(DDRPHY_R57) & 0x7F; +#endif + min_WL = dlls_trim_ca; + + for (i = 0; i < byte_lanes; i++) { + write_phy_reg(DDRPHY_R29, 6 * i); + dlls_trim_2[i] = read_phy_reg(DDRPHY_R31) & 0x3F; + min_WL = _MIN(min_WL, dlls_trim_2[i]); + + write_phy_reg(DDRPHY_R29, (7 * i) | 0x00000900); + op_dqs_trim[i] = read_phy_reg(DDRPHY_R56) & 0x3F; + min_WD = _MIN(min_WD, op_dqs_trim[i]); + for (j = 0; j < 9; j++) { + write_phy_reg(DDRPHY_R29, (i * 7) | (j << 8)); + tmp = read_phy_reg(DDRPHY_R56) & 0x7F; + tmp = (tmp & 0x40) ? + (op_dqs_trim[i] + (tmp & 0x3F)) : (op_dqs_trim[i] - (tmp & 0x3F)); + min_WD = _MIN(min_WD, tmp); + } + } + + // Step5 +#if RZA3M + tmp = (dlls_trim_clk - min_WL) & 0x7F; +#else + tmp = (dlls_trim_ca - min_WL) & 0x7F; +#endif + write_phy_reg(DDRPHY_R29, 0); + write_phy_reg(DDRPHY_R57, tmp | 0x00000080); +#if RZA3M + tmp = (dlls_trim_ca - min_WL) & 0x7F; +#endif + write_phy_reg(DDRPHY_R28, tmp | 0x00000200); + rmw_phy_reg(DDRPHY_R27, 0xFFFFFF80, tmp); + + for (i = 0; i < byte_lanes; i++) { + tmp = (dlls_trim_2[i] - min_WL) & 0x3F; + write_phy_reg(DDRPHY_R29, 6 * i); + rmw_phy_reg(DDRPHY_R31, 0xFFFFFFC0, tmp); + + write_phy_reg(DDRPHY_R29, (7 * i) | 0x00000900); + tmp = (op_dqs_trim[i] - min_WD) & 0x3F; + rmw_phy_reg(DDRPHY_R56, 0xFFFFFF80, tmp); + } + + // Step6 + rmw_mc_reg(DDRMC_R004, ~(0x7F << LP_CMD_OFFSET), (0x00000002 << LP_CMD_OFFSET)); + while (((read_mc_reg(DDRMC_R005) >> 24) & 0x7F) != 0x40) + ; + + // Step6 + rmw_phy_reg(DDRPHY_R27, 0xFBFFFFFF, 0x00000000); + while ((read_phy_reg(DDRPHY_R42) & 0x3) != sl_lanes) + ; +} + +static void exec_trainingSL(uint32_t sl_lanes) +{ + // Step2 + write_phy_reg(DDRPHY_R62, 0x00000001); + + // Step3 + write_phy_reg(DDRPHY_R34, 0x00000010); + + // Step4 + write_phy_reg(DDRPHY_R19, 0x789B3DE0); + write_phy_reg(DDRPHY_R20, 0xF10E4A56); + + // Step5 + write_phy_reg(DDRPHY_R18, 0x11200000); + + // Step6 + while ((read_phy_reg(DDRPHY_R18) & 0x10000000) != 0x00000000) + ; + + // Step7 + write_phy_reg(DDRPHY_R18, 0x11200000); + + // Step8 + while ((read_phy_reg(DDRPHY_R18) & 0x10000000) != 0x00000000) + ; + + // Step9 + write_phy_reg(DDRPHY_R18, 0x34200000); + + // Step10 + while ((read_phy_reg(DDRPHY_R18) & 0x10000000) != 0x00000000) + ; + + // Step11 + if ((read_phy_reg(DDRPHY_R18) & sl_lanes) != sl_lanes) { + panic(); + } + + // Step12 + write_phy_reg(DDRPHY_R62, 0x00000003); +} + +static void program_phy2(void) +{ + uint16_t dram_clk_period; + uint32_t tmp, b21, b22, b23; + + // Step1 + tmp = read_mc_reg(DDRMC_R039); + dram_clk_period = tmp & 0xFFFF; + b21 = (tmp >> 21) & 0x1; + b22 = (tmp >> 22) & 0x1; + b23 = (tmp >> 23) & 0x1; + + // Step2 + rmw_phy_reg(DDRPHY_R64, 0xFFFFFFFE, b23); + rmw_phy_reg(DDRPHY_R59, 0xFFFFFFFE, (b23 == 1 ? 0 : b22)); + write_phy_reg(DDRPHY_R55, (b21 << 24) | + _MIN(1000000000000 / (2 * dram_clk_period * 256), 0xFFFFFF)); + + // Step3 + rmw_phy_reg(DDRPHY_R27, 0xFBFFFFFF, 0x04000000); + rmw_phy_reg(DDRPHY_R27, 0xFC0000FF, + _MIN(1000000000000 / (dram_clk_period * 256), 0x3FFFF) << 8); + rmw_phy_reg(DDRPHY_R27, 0xFBFFFFFF, 0x00000000); +} + +static void program_mc2(void) +{ + uint8_t main_clk_dly; + uint8_t tphy_rdlat; + uint32_t tmp; + + // Step1 + main_clk_dly = (read_phy_reg(DDRPHY_R21) >> 4) & 0xF; + tmp = (read_mc_reg(DDRMC_R028) >> 24) & 0x7F; + tphy_rdlat = ((main_clk_dly + 1 + 1) * 2) + 2 + ((tmp == 1) ? 2 : 0); + + // Step2 + rmw_mc_reg(DDRMC_R027, 0xFFFFFF80, tphy_rdlat & 0x7F); +} diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/ddr/param_swizzle_T1.c b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/ddr/param_swizzle_T1.c new file mode 100644 index 00000000..98ee1363 --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/ddr/param_swizzle_T1.c @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +const uint32_t mc_odt_pins_tbl[4] = { + 0x00000001 , + 0x00000000 , + 0x00000000 , + 0x00000000 +}; + +const uint32_t mc_mr1_tbl[2] = { + 0x00000266 , + 0x00000004 +}; + +const uint32_t mc_mr2_tbl[2] = { + 0x00000600 , + 0x00000000 +}; + +const uint32_t mc_mr5_tbl[2] = { + 0x00000000 , + 0x00000000 +}; + +const uint32_t mc_mr6_tbl[2] = { + 0x00000000 , + 0x00000000 +}; + +const uint32_t mc_phy_settings_tbl[][2] = { + {DDRMC_R040, 0x4F7F64A8 }, + {DDRMC_R041, 0x00003C30 }, + {DDRMC_R042, 0x00003C28 }, + {DDRMC_R043, 0x00000000 } +}; + +const uint32_t swizzle_mc_tbl[][2] = { + {DDRMC_R030, 0x00000C0B }, + {DDRMC_R031, 0x00001C00 }, + {DDRMC_R032, 0x17121500 }, + {DDRMC_R033, 0x00140116 }, + {DDRMC_R034, 0x180E1300 }, + {DDRMC_R035, 0x0D190F1B }, + {DDRMC_R036, 0x0A021E1A }, + {DDRMC_R037, 0x21201F06 }, + {DDRMC_R038, 0x0000001D } +}; + +const uint32_t swizzle_phy_tbl[][2] = { + {DDRPHY_R29, 0x00000000 }, + {DDRPHY_R11, 0x19160018 }, + {DDRPHY_R29, 0x00000001 }, + {DDRPHY_R11, 0x05021714 }, + {DDRPHY_R29, 0x00000002 }, + {DDRPHY_R11, 0x0F1D0307 }, + {DDRPHY_R29, 0x00000003 }, + {DDRPHY_R11, 0x0E0D0C08 }, + {DDRPHY_R29, 0x00000004 }, + {DDRPHY_R11, 0x13121110 }, + {DDRPHY_R29, 0x00000005 }, + {DDRPHY_R11, 0x1B040106 }, + {DDRPHY_R29, 0x00000006 }, + {DDRPHY_R11, 0x09150A1A }, + {DDRPHY_R29, 0x00000007 }, + {DDRPHY_R11, 0x001E0B1C } +}; diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/ddr/param_swizzle_T1b.c b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/ddr/param_swizzle_T1b.c new file mode 100644 index 00000000..b35c4c27 --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/ddr/param_swizzle_T1b.c @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2020-2022, Renesas Electronics Corporation. All rights reserved. + * SPDX-License-Identifier: BSD-3-Clause + * This code was generated with RZ/G2L, G2UL, Five, A3UL DDR config generation tool v3.0.0 + */ + +#include +#include + +const uint32_t mc_odt_pins_tbl[4] = { + 0x00000001 , + 0x00000000 , + 0x00000000 , + 0x00000000 +}; + +const uint32_t mc_mr1_tbl[2] = { + 0x00000706 , + 0x00000100 +}; + +const uint32_t mc_mr2_tbl[2] = { + 0x00000E00 , + 0x00000000 +}; + +const uint32_t mc_mr5_tbl[2] = { + 0x000001C0 , + 0x000001C0 +}; + +const uint32_t mc_mr6_tbl[2] = { + 0x0000007F , + 0x0000000F +}; + +const uint32_t mc_phy_settings_tbl[MC_PHYSET_NUM][2] = { + {DDRMC_R040, 0x57630BB8 }, + {DDRMC_R041, 0x00002828 }, + {DDRMC_R042, 0x00003C22 }, + {DDRMC_R043, 0x00102611 } +}; + +const uint32_t swizzle_mc_tbl[SWIZZLE_MC_NUM][2] = { + {DDRMC_R030, 0x00000B02 }, + {DDRMC_R031, 0x00000106 }, + {DDRMC_R032, 0x11131C0D }, + {DDRMC_R033, 0x12001F15 }, + {DDRMC_R034, 0x1D19140E }, + {DDRMC_R035, 0x17091B1A }, + {DDRMC_R036, 0x0A10160C }, + {DDRMC_R037, 0x0018051E }, + {DDRMC_R038, 0x00000000 } +}; + +const uint32_t swizzle_phy_tbl[SIZZLE_PHY_NUM][2] = { + {DDRPHY_R29, 0x00000000 }, + {DDRPHY_R11, 0x14001816 }, + {DDRPHY_R29, 0x00000001 }, + {DDRPHY_R11, 0x010D0608 }, + {DDRPHY_R29, 0x00000002 }, + {DDRPHY_R11, 0x02190403 }, + {DDRPHY_R29, 0x00000003 }, + {DDRPHY_R11, 0x1705150B }, + {DDRPHY_R29, 0x00000004 }, + {DDRPHY_R11, 0x13121110 }, + {DDRPHY_R29, 0x00000005 }, + {DDRPHY_R11, 0x07090F0E }, + {DDRPHY_R29, 0x00000006 }, + {DDRPHY_R11, 0x1A1D0A1B }, + {DDRPHY_R29, 0x00000007 }, + {DDRPHY_R11, 0x001E1C0C } +}; diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/ddr/param_swizzle_T1bc.c b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/ddr/param_swizzle_T1bc.c new file mode 100644 index 00000000..b35c4c27 --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/ddr/param_swizzle_T1bc.c @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2020-2022, Renesas Electronics Corporation. All rights reserved. + * SPDX-License-Identifier: BSD-3-Clause + * This code was generated with RZ/G2L, G2UL, Five, A3UL DDR config generation tool v3.0.0 + */ + +#include +#include + +const uint32_t mc_odt_pins_tbl[4] = { + 0x00000001 , + 0x00000000 , + 0x00000000 , + 0x00000000 +}; + +const uint32_t mc_mr1_tbl[2] = { + 0x00000706 , + 0x00000100 +}; + +const uint32_t mc_mr2_tbl[2] = { + 0x00000E00 , + 0x00000000 +}; + +const uint32_t mc_mr5_tbl[2] = { + 0x000001C0 , + 0x000001C0 +}; + +const uint32_t mc_mr6_tbl[2] = { + 0x0000007F , + 0x0000000F +}; + +const uint32_t mc_phy_settings_tbl[MC_PHYSET_NUM][2] = { + {DDRMC_R040, 0x57630BB8 }, + {DDRMC_R041, 0x00002828 }, + {DDRMC_R042, 0x00003C22 }, + {DDRMC_R043, 0x00102611 } +}; + +const uint32_t swizzle_mc_tbl[SWIZZLE_MC_NUM][2] = { + {DDRMC_R030, 0x00000B02 }, + {DDRMC_R031, 0x00000106 }, + {DDRMC_R032, 0x11131C0D }, + {DDRMC_R033, 0x12001F15 }, + {DDRMC_R034, 0x1D19140E }, + {DDRMC_R035, 0x17091B1A }, + {DDRMC_R036, 0x0A10160C }, + {DDRMC_R037, 0x0018051E }, + {DDRMC_R038, 0x00000000 } +}; + +const uint32_t swizzle_phy_tbl[SIZZLE_PHY_NUM][2] = { + {DDRPHY_R29, 0x00000000 }, + {DDRPHY_R11, 0x14001816 }, + {DDRPHY_R29, 0x00000001 }, + {DDRPHY_R11, 0x010D0608 }, + {DDRPHY_R29, 0x00000002 }, + {DDRPHY_R11, 0x02190403 }, + {DDRPHY_R29, 0x00000003 }, + {DDRPHY_R11, 0x1705150B }, + {DDRPHY_R29, 0x00000004 }, + {DDRPHY_R11, 0x13121110 }, + {DDRPHY_R29, 0x00000005 }, + {DDRPHY_R11, 0x07090F0E }, + {DDRPHY_R29, 0x00000006 }, + {DDRPHY_R11, 0x1A1D0A1B }, + {DDRPHY_R29, 0x00000007 }, + {DDRPHY_R11, 0x001E1C0C } +}; diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/ddr/param_swizzle_T1c.c b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/ddr/param_swizzle_T1c.c new file mode 100644 index 00000000..a9d7e778 --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/ddr/param_swizzle_T1c.c @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2020-2022, Renesas Electronics Corporation. All rights reserved. + * SPDX-License-Identifier: BSD-3-Clause + * This code was generated with RZ/G2L, G2UL, Five, A3UL DDR config generation tool v3.0.0 + */ + +#include +#include + +const uint32_t mc_odt_pins_tbl[4] = { + 0x00000001 , + 0x00000002 , + 0x00000000 , + 0x00000000 +}; + +const uint32_t mc_mr1_tbl[2] = { + 0x00000706 , + 0x00000200 +}; + +const uint32_t mc_mr2_tbl[2] = { + 0x00000E00 , + 0x00000000 +}; + +const uint32_t mc_mr5_tbl[2] = { + 0x000001C0 , + 0x000001C0 +}; + +const uint32_t mc_mr6_tbl[2] = { + 0x0000007F , + 0x0000001C +}; + +const uint32_t mc_phy_settings_tbl[MC_PHYSET_NUM][2] = { + {DDRMC_R040, 0x576E08E8 }, + {DDRMC_R041, 0x00003C22 }, + {DDRMC_R042, 0x22227822 }, + {DDRMC_R043, 0x00123312 } +}; + +const uint32_t swizzle_mc_tbl[SWIZZLE_MC_NUM][2] = { + {DDRMC_R030, 0x00001502 }, + {DDRMC_R031, 0x00000A06 }, + {DDRMC_R032, 0x170D1112 }, + {DDRMC_R033, 0x1900130B }, + {DDRMC_R034, 0x1F09180C }, + {DDRMC_R035, 0x161C0E14 }, + {DDRMC_R036, 0x01101B1A }, + {DDRMC_R037, 0x001D051E }, + {DDRMC_R038, 0x00000000 } +}; + +const uint32_t swizzle_phy_tbl[SIZZLE_PHY_NUM][2] = { + {DDRPHY_R29, 0x00000000 }, + {DDRPHY_R11, 0x1B03150E }, + {DDRPHY_R29, 0x00000001 }, + {DDRPHY_R11, 0x16001706 }, + {DDRPHY_R29, 0x00000002 }, + {DDRPHY_R11, 0x0D050807 }, + {DDRPHY_R29, 0x00000003 }, + {DDRPHY_R11, 0x1901020B }, + {DDRPHY_R29, 0x00000004 }, + {DDRPHY_R11, 0x13121110 }, + {DDRPHY_R29, 0x00000005 }, + {DDRPHY_R11, 0x0F090418 }, + {DDRPHY_R29, 0x00000006 }, + {DDRPHY_R11, 0x1A0A1D14 }, + {DDRPHY_R29, 0x00000007 }, + {DDRPHY_R11, 0x001E1C0C } +}; diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/ddr/param_swizzle_T1vbc.c b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/ddr/param_swizzle_T1vbc.c new file mode 100644 index 00000000..022ad122 --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/ddr/param_swizzle_T1vbc.c @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2020-2022, Renesas Electronics Corporation. All rights reserved. + * SPDX-License-Identifier: BSD-3-Clause + * This code was generated with RZ/V2L DDR config generation tool v1.13.0 + */ + +#include +#include + +const uint32_t mc_odt_pins_tbl[4] = { + 0x00000001 , + 0x00000000 , + 0x00000000 , + 0x00000000 +}; + +const uint32_t mc_mr1_tbl[2] = { + 0x00000706 , + 0x00000100 +}; + +const uint32_t mc_mr2_tbl[2] = { + 0x00000E00 , + 0x00000000 +}; + +const uint32_t mc_mr5_tbl[2] = { + 0x000001C0 , + 0x000001C0 +}; + +const uint32_t mc_mr6_tbl[2] = { + 0x0000007F , + 0x0000000F +}; + +const uint32_t mc_phy_settings_tbl[MC_PHYSET_NUM][2] = { + {DDRMC_R040, 0x57630BB8 }, + {DDRMC_R041, 0x00002828 }, + {DDRMC_R042, 0x00003C22 }, + {DDRMC_R043, 0x00102611 } +}; + +const uint32_t swizzle_mc_tbl[SWIZZLE_MC_NUM][2] = { + {DDRMC_R030, 0x00000B02 }, + {DDRMC_R031, 0x00000106 }, + {DDRMC_R032, 0x11131C0D }, + {DDRMC_R033, 0x12001F15 }, + {DDRMC_R034, 0x1D19140E }, + {DDRMC_R035, 0x17091B1A }, + {DDRMC_R036, 0x0A10160C }, + {DDRMC_R037, 0x0018051E }, + {DDRMC_R038, 0x00000000 } +}; + +const uint32_t swizzle_phy_tbl[SIZZLE_PHY_NUM][2] = { + {DDRPHY_R29, 0x00000000 }, + {DDRPHY_R11, 0x14001816 }, + {DDRPHY_R29, 0x00000001 }, + {DDRPHY_R11, 0x010D0608 }, + {DDRPHY_R29, 0x00000002 }, + {DDRPHY_R11, 0x02190403 }, + {DDRPHY_R29, 0x00000003 }, + {DDRPHY_R11, 0x1705150B }, + {DDRPHY_R29, 0x00000004 }, + {DDRPHY_R11, 0x13121110 }, + {DDRPHY_R29, 0x00000005 }, + {DDRPHY_R11, 0x07090F0E }, + {DDRPHY_R29, 0x00000006 }, + {DDRPHY_R11, 0x1A1D0A1B }, + {DDRPHY_R29, 0x00000007 }, + {DDRPHY_R11, 0x001E1C0C } +}; diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/ddr/param_swizzle_T1vc.c b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/ddr/param_swizzle_T1vc.c new file mode 100644 index 00000000..4f19ecd6 --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/ddr/param_swizzle_T1vc.c @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2020-2022, Renesas Electronics Corporation. All rights reserved. + * SPDX-License-Identifier: BSD-3-Clause + * This code was generated with RZ/V2L DDR config generation tool v1.13.0 + */ + +#include +#include + +const uint32_t mc_odt_pins_tbl[4] = { + 0x00000001 , + 0x00000002 , + 0x00000000 , + 0x00000000 +}; + +const uint32_t mc_mr1_tbl[2] = { + 0x00000706 , + 0x00000200 +}; + +const uint32_t mc_mr2_tbl[2] = { + 0x00000E00 , + 0x00000000 +}; + +const uint32_t mc_mr5_tbl[2] = { + 0x000001C0 , + 0x000001C0 +}; + +const uint32_t mc_mr6_tbl[2] = { + 0x0000007F , + 0x0000001C +}; + +const uint32_t mc_phy_settings_tbl[MC_PHYSET_NUM][2] = { + {DDRMC_R040, 0x576E08E8 }, + {DDRMC_R041, 0x00003C22 }, + {DDRMC_R042, 0x22227822 }, + {DDRMC_R043, 0x00123312 } +}; + +const uint32_t swizzle_mc_tbl[SWIZZLE_MC_NUM][2] = { + {DDRMC_R030, 0x00001502 }, + {DDRMC_R031, 0x00000A06 }, + {DDRMC_R032, 0x170D1112 }, + {DDRMC_R033, 0x1900130B }, + {DDRMC_R034, 0x1F09180C }, + {DDRMC_R035, 0x161C0E14 }, + {DDRMC_R036, 0x01101B1A }, + {DDRMC_R037, 0x001D051E }, + {DDRMC_R038, 0x00000000 } +}; + +const uint32_t swizzle_phy_tbl[SIZZLE_PHY_NUM][2] = { + {DDRPHY_R29, 0x00000000 }, + {DDRPHY_R11, 0x1B03150E }, + {DDRPHY_R29, 0x00000001 }, + {DDRPHY_R11, 0x16001706 }, + {DDRPHY_R29, 0x00000002 }, + {DDRPHY_R11, 0x0D050807 }, + {DDRPHY_R29, 0x00000003 }, + {DDRPHY_R11, 0x1901020B }, + {DDRPHY_R29, 0x00000004 }, + {DDRPHY_R11, 0x13121110 }, + {DDRPHY_R29, 0x00000005 }, + {DDRPHY_R11, 0x0F090418 }, + {DDRPHY_R29, 0x00000006 }, + {DDRPHY_R11, 0x1A0A1D14 }, + {DDRPHY_R29, 0x00000007 }, + {DDRPHY_R11, 0x001E1C0C } +}; diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/ddr/param_swizzle_T2c.c b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/ddr/param_swizzle_T2c.c new file mode 100644 index 00000000..f6797f29 --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/ddr/param_swizzle_T2c.c @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2020-2022, Renesas Electronics Corporation. All rights reserved. + * SPDX-License-Identifier: BSD-3-Clause + * This code was generated with RZ/G2L, G2UL, Five, A3UL DDR config generation tool v3.0.0 + */ + +#include +#include + +const uint32_t mc_odt_pins_tbl[4] = { + 0x00000001 , + 0x00000002 , + 0x00000000 , + 0x00000000 +}; + +const uint32_t mc_mr1_tbl[2] = { + 0x00000706 , + 0x00000200 +}; + +const uint32_t mc_mr2_tbl[2] = { + 0x00000E00 , + 0x00000000 +}; + +const uint32_t mc_mr5_tbl[2] = { + 0x000001C0 , + 0x000001C0 +}; + +const uint32_t mc_mr6_tbl[2] = { + 0x0000007F , + 0x0000001C +}; + +const uint32_t mc_phy_settings_tbl[MC_PHYSET_NUM][2] = { + {DDRMC_R040, 0x576E08E8 }, + {DDRMC_R041, 0x00003C22 }, + {DDRMC_R042, 0x22227822 }, + {DDRMC_R043, 0x00123312 } +}; + +const uint32_t swizzle_mc_tbl[SWIZZLE_MC_NUM][2] = { + {DDRMC_R030, 0x00000A02 }, + {DDRMC_R031, 0x00000106 }, + {DDRMC_R032, 0x171E120B }, + {DDRMC_R033, 0x1800000C }, + {DDRMC_R034, 0x00161C00 }, + {DDRMC_R035, 0x0D1F1319 }, + {DDRMC_R036, 0x15101B1A }, + {DDRMC_R037, 0x001D0509 }, + {DDRMC_R038, 0x00000000 } +}; + +const uint32_t swizzle_phy_tbl[SIZZLE_PHY_NUM][2] = { + {DDRPHY_R29, 0x00000000 }, + {DDRPHY_R11, 0x0A020419 }, + {DDRPHY_R29, 0x00000001 }, + {DDRPHY_R11, 0x03161701 }, + {DDRPHY_R29, 0x00000002 }, + {DDRPHY_R11, 0x0D000807 }, + {DDRPHY_R29, 0x00000003 }, + {DDRPHY_R11, 0x0F0B0518 }, + {DDRPHY_R29, 0x00000004 }, + {DDRPHY_R11, 0x13121110 }, + {DDRPHY_R29, 0x00000005 }, + {DDRPHY_R11, 0x14091506 }, + {DDRPHY_R29, 0x00000006 }, + {DDRPHY_R11, 0x1A1D1B0E }, + {DDRPHY_R29, 0x00000007 }, + {DDRPHY_R11, 0x001E1C0C } +}; diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/ddr/param_swizzle_T2vc.c b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/ddr/param_swizzle_T2vc.c new file mode 100644 index 00000000..4b3e1942 --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/ddr/param_swizzle_T2vc.c @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2020-2022, Renesas Electronics Corporation. All rights reserved. + * SPDX-License-Identifier: BSD-3-Clause + * This code was generated with RZ/V2L DDR config generation tool v1.13.0 + */ + +#include +#include + +const uint32_t mc_odt_pins_tbl[4] = { + 0x00000001 , + 0x00000002 , + 0x00000000 , + 0x00000000 +}; + +const uint32_t mc_mr1_tbl[2] = { + 0x00000706 , + 0x00000200 +}; + +const uint32_t mc_mr2_tbl[2] = { + 0x00000E00 , + 0x00000000 +}; + +const uint32_t mc_mr5_tbl[2] = { + 0x000001C0 , + 0x000001C0 +}; + +const uint32_t mc_mr6_tbl[2] = { + 0x0000007F , + 0x0000001C +}; + +const uint32_t mc_phy_settings_tbl[MC_PHYSET_NUM][2] = { + {DDRMC_R040, 0x576E08E8 }, + {DDRMC_R041, 0x00003C22 }, + {DDRMC_R042, 0x22227822 }, + {DDRMC_R043, 0x00123312 } +}; + +const uint32_t swizzle_mc_tbl[SWIZZLE_MC_NUM][2] = { + {DDRMC_R030, 0x00000A02 }, + {DDRMC_R031, 0x00000106 }, + {DDRMC_R032, 0x171E120B }, + {DDRMC_R033, 0x1800000C }, + {DDRMC_R034, 0x00161C00 }, + {DDRMC_R035, 0x0D1F1319 }, + {DDRMC_R036, 0x15101B1A }, + {DDRMC_R037, 0x001D0509 }, + {DDRMC_R038, 0x00000000 } +}; + +const uint32_t swizzle_phy_tbl[SIZZLE_PHY_NUM][2] = { + {DDRPHY_R29, 0x00000000 }, + {DDRPHY_R11, 0x0A020419 }, + {DDRPHY_R29, 0x00000001 }, + {DDRPHY_R11, 0x03161701 }, + {DDRPHY_R29, 0x00000002 }, + {DDRPHY_R11, 0x0D000807 }, + {DDRPHY_R29, 0x00000003 }, + {DDRPHY_R11, 0x0F0B0518 }, + {DDRPHY_R29, 0x00000004 }, + {DDRPHY_R11, 0x13121110 }, + {DDRPHY_R29, 0x00000005 }, + {DDRPHY_R11, 0x14091506 }, + {DDRPHY_R29, 0x00000006 }, + {DDRPHY_R11, 0x1A1D1B0E }, + {DDRPHY_R29, 0x00000007 }, + {DDRPHY_R11, 0x001E1C0C } +}; diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/ddr/param_swizzle_T3bc.c b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/ddr/param_swizzle_T3bc.c new file mode 100644 index 00000000..5fdcd734 --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/ddr/param_swizzle_T3bc.c @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2020-2022, Renesas Electronics Corporation. All rights reserved. + * SPDX-License-Identifier: BSD-3-Clause + * This code was generated with RZ/G2L, G2UL, Five, A3UL DDR config generation tool v3.0.0 + */ + +#include +#include + +const uint32_t mc_odt_pins_tbl[4] = { + 0x00000001 , + 0x00000000 , + 0x00000000 , + 0x00000000 +}; + +const uint32_t mc_mr1_tbl[2] = { + 0x00000706 , + 0x00000100 +}; + +const uint32_t mc_mr2_tbl[2] = { + 0x00000E00 , + 0x00000000 +}; + +const uint32_t mc_mr5_tbl[2] = { + 0x000001C0 , + 0x000001C0 +}; + +const uint32_t mc_mr6_tbl[2] = { + 0x0000007F , + 0x0000000F +}; + +const uint32_t mc_phy_settings_tbl[MC_PHYSET_NUM][2] = { + {DDRMC_R040, 0x57630BB8 }, + {DDRMC_R041, 0x00002828 }, + {DDRMC_R042, 0x00003C22 }, + {DDRMC_R043, 0x00102611 } +}; + +const uint32_t swizzle_mc_tbl[SWIZZLE_MC_NUM][2] = { + {DDRMC_R030, 0x00000000 }, + {DDRMC_R031, 0x00000000 }, + {DDRMC_R032, 0x1C191E13 }, + {DDRMC_R033, 0x12000A18 }, + {DDRMC_R034, 0x100B1D00 }, + {DDRMC_R035, 0x1F0C1B09 }, + {DDRMC_R036, 0x151A1614 }, + {DDRMC_R037, 0x000D0E17 }, + {DDRMC_R038, 0x00000000 } +}; + +const uint32_t swizzle_phy_tbl[SIZZLE_PHY_NUM][2] = { + {DDRPHY_R29, 0x00000000 }, + {DDRPHY_R11, 0x0A070E16 }, + {DDRPHY_R29, 0x00000001 }, + {DDRPHY_R11, 0x18140B08 }, + {DDRPHY_R29, 0x00000002 }, + {DDRPHY_R11, 0x00170409 }, + {DDRPHY_R29, 0x00000003 }, + {DDRPHY_R11, 0x0F030619 }, + {DDRPHY_R29, 0x00000004 }, + {DDRPHY_R11, 0x13121110 }, + {DDRPHY_R29, 0x00000005 }, + {DDRPHY_R11, 0x05020C0D }, + {DDRPHY_R29, 0x00000006 }, + {DDRPHY_R11, 0x1B1A1501 }, + {DDRPHY_R29, 0x00000007 }, + {DDRPHY_R11, 0x001E1D1C } +}; diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/ddr/param_swizzle_T3bcud.c b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/ddr/param_swizzle_T3bcud.c new file mode 100644 index 00000000..10a1b3a2 --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/ddr/param_swizzle_T3bcud.c @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2020-2022, Renesas Electronics Corporation. All rights reserved. + * SPDX-License-Identifier: BSD-3-Clause + * This code was generated with RZ/G2L, G2UL, Five, A3UL DDR config generation tool v3.0.0 + */ + +#include +#include + +const uint32_t mc_odt_pins_tbl[4] = { + 0x00000001 , + 0x00000000 , + 0x00000000 , + 0x00000000 +}; + +const uint32_t mc_mr1_tbl[2] = { + 0x00000706 , + 0x00000100 +}; + +const uint32_t mc_mr2_tbl[2] = { + 0x00000E00 , + 0x00000000 +}; + +const uint32_t mc_mr5_tbl[2] = { + 0x000001C0 , + 0x000001C0 +}; + +const uint32_t mc_mr6_tbl[2] = { + 0x0000007F , + 0x0000000F +}; + +const uint32_t mc_phy_settings_tbl[MC_PHYSET_NUM][2] = { + {DDRMC_R040, 0x57630BB8 }, + {DDRMC_R041, 0x00002828 }, + {DDRMC_R042, 0x00003C22 }, + {DDRMC_R043, 0x00102611 } +}; + +const uint32_t swizzle_mc_tbl[SWIZZLE_MC_NUM][2] = { + {DDRMC_R030, 0x00000000 }, + {DDRMC_R031, 0x00000000 }, + {DDRMC_R032, 0x18171D1C }, + {DDRMC_R033, 0x0D000A09 }, + {DDRMC_R034, 0x1F0B1000 }, + {DDRMC_R035, 0x1E140E0C }, + {DDRMC_R036, 0x191A121B }, + {DDRMC_R037, 0x00131516 }, + {DDRMC_R038, 0x00000000 } +}; + +const uint32_t swizzle_phy_tbl[SIZZLE_PHY_NUM][2] = { + {DDRPHY_R29, 0x00000000 }, + {DDRPHY_R11, 0x0C050D08 }, + {DDRPHY_R29, 0x00000001 }, + {DDRPHY_R11, 0x0A17180B }, + {DDRPHY_R29, 0x00000002 }, + {DDRPHY_R11, 0x190E0709 }, + {DDRPHY_R29, 0x00000003 }, + {DDRPHY_R11, 0x0F140206 }, + {DDRPHY_R29, 0x00000004 }, + {DDRPHY_R11, 0x13121110 }, + {DDRPHY_R29, 0x00000005 }, + {DDRPHY_R11, 0x03000416 }, + {DDRPHY_R29, 0x00000006 }, + {DDRPHY_R11, 0x1B1A1501 }, + {DDRPHY_R29, 0x00000007 }, + {DDRPHY_R11, 0x001E1D1C } +}; diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/ddr/param_swizzle_T3bcud2.c b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/ddr/param_swizzle_T3bcud2.c new file mode 100644 index 00000000..dce1284b --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/ddr/param_swizzle_T3bcud2.c @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2020-2022, Renesas Electronics Corporation. All rights reserved. + * SPDX-License-Identifier: BSD-3-Clause + * This code was generated with RZ/G2L, G2UL, Five, A3UL DDR config generation tool v3.0.0 + */ + +#include +#include + +const uint32_t mc_odt_pins_tbl[4] = { + 0x00000001 , + 0x00000000 , + 0x00000000 , + 0x00000000 +}; + +const uint32_t mc_mr1_tbl[2] = { + 0x00000706 , + 0x00000100 +}; + +const uint32_t mc_mr2_tbl[2] = { + 0x00000E00 , + 0x00000000 +}; + +const uint32_t mc_mr5_tbl[2] = { + 0x000001C0 , + 0x000001C0 +}; + +const uint32_t mc_mr6_tbl[2] = { + 0x0000007F , + 0x0000000F +}; + +const uint32_t mc_phy_settings_tbl[MC_PHYSET_NUM][2] = { + {DDRMC_R040, 0x57630BB8 }, + {DDRMC_R041, 0x00002828 }, + {DDRMC_R042, 0x00003C22 }, + {DDRMC_R043, 0x00102611 } +}; + +const uint32_t swizzle_mc_tbl[SWIZZLE_MC_NUM][2] = { + {DDRMC_R030, 0x00000000 }, + {DDRMC_R031, 0x00000000 }, + {DDRMC_R032, 0x1E191117 }, + {DDRMC_R033, 0x1D000A16 }, + {DDRMC_R034, 0x000B0D12 }, + {DDRMC_R035, 0x1B180C1A }, + {DDRMC_R036, 0x15101C1F }, + {DDRMC_R037, 0x00090E13 }, + {DDRMC_R038, 0x00000000 } +}; + +const uint32_t swizzle_phy_tbl[SIZZLE_PHY_NUM][2] = { + {DDRPHY_R29, 0x00000000 }, + {DDRPHY_R11, 0x0A020B0F }, + {DDRPHY_R29, 0x00000001 }, + {DDRPHY_R11, 0x18050E14 }, + {DDRPHY_R29, 0x00000002 }, + {DDRPHY_R11, 0x16080603 }, + {DDRPHY_R29, 0x00000003 }, + {DDRPHY_R11, 0x190D0717 }, + {DDRPHY_R29, 0x00000004 }, + {DDRPHY_R11, 0x13121110 }, + {DDRPHY_R29, 0x00000005 }, + {DDRPHY_R11, 0x04090C00 }, + {DDRPHY_R29, 0x00000006 }, + {DDRPHY_R11, 0x1B1A1501 }, + {DDRPHY_R29, 0x00000007 }, + {DDRPHY_R11, 0x001E1D1C } +}; diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/ddr/param_swizzle_T3bcul.c b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/ddr/param_swizzle_T3bcul.c new file mode 100644 index 00000000..28bf31ad --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/ddr/param_swizzle_T3bcul.c @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2020-2022, Renesas Electronics Corporation. All rights reserved. + * SPDX-License-Identifier: BSD-3-Clause + * This code was generated with RZ/G2L, G2UL, Five, A3UL DDR config generation tool v3.0.0 + */ + +#include +#include + +const uint32_t mc_odt_pins_tbl[4] = { + 0x00000001 , + 0x00000000 , + 0x00000000 , + 0x00000000 +}; + +const uint32_t mc_mr1_tbl[2] = { + 0x00000266 , + 0x00000006 +}; + +const uint32_t mc_mr2_tbl[2] = { + 0x00000600 , + 0x00000000 +}; + +const uint32_t mc_mr5_tbl[2] = { + 0x00000000 , + 0x00000000 +}; + +const uint32_t mc_mr6_tbl[2] = { + 0x00000000 , + 0x00000000 +}; + +const uint32_t mc_phy_settings_tbl[MC_PHYSET_NUM][2] = { + {DDRMC_R040, 0x4F7F06E8 }, + {DDRMC_R041, 0x00002822 }, + {DDRMC_R042, 0x00003C22 }, + {DDRMC_R043, 0x00000000 } +}; + +const uint32_t swizzle_mc_tbl[SWIZZLE_MC_NUM][2] = { + {DDRMC_R030, 0x00000000 }, + {DDRMC_R031, 0x00000000 }, + {DDRMC_R032, 0x151A2100 }, + {DDRMC_R033, 0x00200014 }, + {DDRMC_R034, 0x1F1E1900 }, + {DDRMC_R035, 0x000B120C }, + {DDRMC_R036, 0x000A1B17 }, + {DDRMC_R037, 0x161D0F13 }, + {DDRMC_R038, 0x0000000D } +}; + +const uint32_t swizzle_phy_tbl[SIZZLE_PHY_NUM][2] = { + {DDRPHY_R29, 0x00000000 }, + {DDRPHY_R11, 0x17140B04 }, + {DDRPHY_R29, 0x00000001 }, + {DDRPHY_R11, 0x0006070E }, + {DDRPHY_R29, 0x00000002 }, + {DDRPHY_R11, 0x0D0A0818 }, + {DDRPHY_R29, 0x00000003 }, + {DDRPHY_R11, 0x19160201 }, + {DDRPHY_R29, 0x00000004 }, + {DDRPHY_R11, 0x13121110 }, + {DDRPHY_R29, 0x00000005 }, + {DDRPHY_R11, 0x030C150F }, + {DDRPHY_R29, 0x00000006 }, + {DDRPHY_R11, 0x1B1A0905 }, + {DDRPHY_R29, 0x00000007 }, + {DDRPHY_R11, 0x001E1D1C } +}; diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/ddr/param_swizzle_T3cl.c b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/ddr/param_swizzle_T3cl.c new file mode 100644 index 00000000..7a891213 --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/ddr/param_swizzle_T3cl.c @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2020-2022, Renesas Electronics Corporation. All rights reserved. + * SPDX-License-Identifier: BSD-3-Clause + * This code was generated with RZ/G2L, G2UL, Five, A3UL DDR config generation tool v3.0.0 + */ + +#include +#include + +const uint32_t mc_odt_pins_tbl[4] = { + 0x00000002 , + 0x00000001 , + 0x00000002 , + 0x00000001 +}; + +const uint32_t mc_mr1_tbl[2] = { + 0x00000266 , + 0x00000206 +}; + +const uint32_t mc_mr2_tbl[2] = { + 0x00000600 , + 0x00000200 +}; + +const uint32_t mc_mr5_tbl[2] = { + 0x00000000 , + 0x00000000 +}; + +const uint32_t mc_mr6_tbl[2] = { + 0x00000000 , + 0x00000000 +}; + +const uint32_t mc_phy_settings_tbl[MC_PHYSET_NUM][2] = { + {DDRMC_R040, 0x4F7F01E8 }, + {DDRMC_R041, 0x00007822 }, + {DDRMC_R042, 0x1E1E3C22 }, + {DDRMC_R043, 0x00000000 } +}; + +const uint32_t swizzle_mc_tbl[SWIZZLE_MC_NUM][2] = { + {DDRMC_R030, 0x00000A00 }, + {DDRMC_R031, 0x00001E00 }, + {DDRMC_R032, 0x1D131500 }, + {DDRMC_R033, 0x00001217 }, + {DDRMC_R034, 0x180E2000 }, + {DDRMC_R035, 0x0D1F0B1B }, + {DDRMC_R036, 0x021A1400 }, + {DDRMC_R037, 0x0C1C0616 }, + {DDRMC_R038, 0x00000000 } +}; + +const uint32_t swizzle_phy_tbl[SIZZLE_PHY_NUM][2] = { + {DDRPHY_R29, 0x00000000 }, + {DDRPHY_R11, 0x19081815 }, + {DDRPHY_R29, 0x00000001 }, + {DDRPHY_R11, 0x0702140B }, + {DDRPHY_R29, 0x00000002 }, + {DDRPHY_R11, 0x170D0309 }, + {DDRPHY_R29, 0x00000003 }, + {DDRPHY_R11, 0x0F00051D }, + {DDRPHY_R29, 0x00000004 }, + {DDRPHY_R11, 0x13121110 }, + {DDRPHY_R29, 0x00000005 }, + {DDRPHY_R11, 0x0E160106 }, + {DDRPHY_R29, 0x00000006 }, + {DDRPHY_R11, 0x0A1A1B04 }, + {DDRPHY_R29, 0x00000007 }, + {DDRPHY_R11, 0x001E0C1C } +}; diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/emmc/emmc_cmd.c b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/emmc/emmc_cmd.c new file mode 100644 index 00000000..8323ae42 --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/emmc/emmc_cmd.c @@ -0,0 +1,492 @@ +/* + * Copyright (c) 2015-2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include "emmc_config.h" +#include "emmc_def.h" +#include "emmc_hal.h" +#include "emmc_registers.h" +#include "emmc_std.h" + +static void emmc_little_to_big(uint8_t *p, uint32_t value) +{ + if (p == NULL) + return; + + p[0] = (uint8_t) (value >> 24); + p[1] = (uint8_t) (value >> 16); + p[2] = (uint8_t) (value >> 8); + p[3] = (uint8_t) value; + +} + +static void emmc_softreset(void) +{ + int32_t loop = 10000; + int32_t retry = 1000; + + /* flag clear */ + mmc_drv_obj.during_cmd_processing = FALSE; + mmc_drv_obj.during_transfer = FALSE; + mmc_drv_obj.during_dma_transfer = FALSE; + mmc_drv_obj.state_machine_blocking = FALSE; + mmc_drv_obj.force_terminate = FALSE; + mmc_drv_obj.dma_error_flag = FALSE; + + /* during operation ? */ + if ((GETR_32(SD_INFO2) & SD_INFO2_CBSY) == 0) + goto reset; + + /* wait CMDSEQ = 0 */ + while (loop > 0) { + if ((GETR_32(SD_INFO2) & SD_INFO2_CBSY) == 0) + break; /* ready */ + + loop--; + if ((loop == 0) && (retry > 0)) { + udelay(1000U); /* wait 1ms */ + loop = 10000; + retry--; + } + } + +reset: + /* reset */ + SETR_32(SOFT_RST, (GETR_32(SOFT_RST) & (~SOFT_RST_SDRST))); + SETR_32(SOFT_RST, (GETR_32(SOFT_RST) | SOFT_RST_SDRST)); + + /* initialize */ + SETR_32(SD_INFO1, 0x00000000U); + SETR_32(SD_INFO2, SD_INFO2_CLEAR); + SETR_32(SD_INFO1_MASK, 0x00000000U); /* all interrupt disable */ + SETR_32(SD_INFO2_MASK, SD_INFO2_CLEAR); /* all interrupt disable */ +} + +static void emmc_read_response(uint32_t *response) +{ + uint8_t *p; + + if (response == NULL) + return; + + /* read response */ + if (mmc_drv_obj.response_length != EMMC_MAX_RESPONSE_LENGTH) { + *response = GETR_32(SD_RSP10); /* [39:8] */ + return; + } + + /* CSD or CID */ + p = (uint8_t *) (response); + emmc_little_to_big(p, ((GETR_32(SD_RSP76) << 8) + | (GETR_32(SD_RSP54) >> 24))); /* [127:96] */ + emmc_little_to_big(p + 4, ((GETR_32(SD_RSP54) << 8) + | (GETR_32(SD_RSP32) >> 24))); /* [95:64] */ + emmc_little_to_big(p + 8, ((GETR_32(SD_RSP32) << 8) + | (GETR_32(SD_RSP10) >> 24))); /* [63:32] */ + emmc_little_to_big(p + 12, (GETR_32(SD_RSP10) << 8)); +} + +static EMMC_ERROR_CODE emmc_response_check(uint32_t *response, + uint32_t error_mask) +{ + + HAL_MEMCARD_RESPONSE_TYPE response_type = + ((HAL_MEMCARD_RESPONSE_TYPE)mmc_drv_obj.cmd_info.cmd & HAL_MEMCARD_RESPONSE_TYPE_MASK); + + if (response == NULL) + return EMMC_ERR_PARAM; + + if (response_type == HAL_MEMCARD_RESPONSE_NONE) + return EMMC_SUCCESS; + + + if (response_type <= HAL_MEMCARD_RESPONSE_R1b) { + /* R1 or R1b */ + mmc_drv_obj.current_state = + (EMMC_R1_STATE) ((*response & EMMC_R1_STATE_MASK) >> + EMMC_R1_STATE_SHIFT); + if ((*response & error_mask) != 0) { + if ((0x80 & *response) != 0) { + ERROR("BL2: emmc SWITCH_ERROR\n"); + } + return EMMC_ERR_CARD_STATUS_BIT; + } + return EMMC_SUCCESS; + } + + if (response_type == HAL_MEMCARD_RESPONSE_R4) { + if ((*response & EMMC_R4_STATUS) != 0) + return EMMC_ERR_CARD_STATUS_BIT; + } + + return EMMC_SUCCESS; +} + +static void emmc_WaitCmd2Cmd_8Cycle(void) +{ + uint32_t dataL, wait = 0; + + dataL = GETR_32(SD_CLK_CTRL); + dataL &= 0x000000FF; + + switch (dataL) { + case 0xFF: + case 0x00: + case 0x01: + case 0x02: + case 0x04: + case 0x08: + case 0x10: + case 0x20: + wait = 10U; + break; + case 0x40: + wait = 20U; + break; + case 0x80: + wait = 30U; + break; + } + + udelay(wait); +} + +static void cmdErrSdInfo2Log(void) +{ + ERROR("BL2: emmc ERR SD_INFO2 = 0x%x\n", mmc_drv_obj.error_info.info2); +} + +static void emmc_data_transfer_dma(void) +{ + mmc_drv_obj.during_dma_transfer = TRUE; + mmc_drv_obj.dma_error_flag = FALSE; + + SETR_32(SD_INFO1_MASK, 0x00000000U); + SETR_32(SD_INFO2_MASK, (SD_INFO2_ALL_ERR | SD_INFO2_CLEAR)); + + /* DMAC setting */ + if (mmc_drv_obj.cmd_info.dir == HAL_MEMCARD_WRITE) { + /* transfer complete interrupt enable */ + SETR_32(DM_CM_INFO1_MASK, + (DM_CM_INFO_MASK_CLEAR | DM_CM_INFO_CH0_ENABLE)); + SETR_32(DM_CM_INFO2_MASK, + (DM_CM_INFO_MASK_CLEAR | DM_CM_INFO_CH0_ENABLE)); + /* BUFF --> FIFO */ + SETR_32(DM_CM_DTRAN_MODE, (DM_CM_DTRAN_MODE_CH0 | + DM_CM_DTRAN_MODE_BIT_WIDTH)); + } else { + /* transfer complete interrupt enable */ + SETR_32(DM_CM_INFO1_MASK, + (DM_CM_INFO_MASK_CLEAR | DM_CM_INFO_CH1_ENABLE)); + SETR_32(DM_CM_INFO2_MASK, + (DM_CM_INFO_MASK_CLEAR | DM_CM_INFO_CH1_ENABLE)); + /* FIFO --> BUFF */ + SETR_32(DM_CM_DTRAN_MODE, (DM_CM_DTRAN_MODE_CH1 + | DM_CM_DTRAN_MODE_BIT_WIDTH)); + } + SETR_32(DM_DTRAN_ADDR, (((uintptr_t) mmc_drv_obj.buff_address_virtual & + DM_DTRAN_ADDR_WRITE_MASK))); + + SETR_32(DM_CM_DTRAN_CTRL, DM_CM_DTRAN_CTRL_START); +} + +EMMC_ERROR_CODE emmc_exec_cmd(uint32_t error_mask, uint32_t *response) +{ + EMMC_ERROR_CODE rtn_code = EMMC_SUCCESS; + HAL_MEMCARD_RESPONSE_TYPE response_type; + HAL_MEMCARD_COMMAND_TYPE cmd_type; + EMMC_INT_STATE state; + uint32_t err_not_care_flag = FALSE; + + /* parameter check */ + if (response == NULL) { + emmc_write_error_info(EMMC_FUNCNO_EXEC_CMD, EMMC_ERR_PARAM); + return EMMC_ERR_PARAM; + } + + /* state check */ + if (mmc_drv_obj.clock_enable != TRUE) { + emmc_write_error_info(EMMC_FUNCNO_EXEC_CMD, EMMC_ERR_STATE); + return EMMC_ERR_STATE; + } + + if (mmc_drv_obj.state_machine_blocking == TRUE) { + emmc_write_error_info(EMMC_FUNCNO_EXEC_CMD, EMMC_ERR); + return EMMC_ERR; + } + + state = ESTATE_BEGIN; + response_type = + ((HAL_MEMCARD_RESPONSE_TYPE)mmc_drv_obj.cmd_info.cmd & + HAL_MEMCARD_RESPONSE_TYPE_MASK); + cmd_type = + ((HAL_MEMCARD_COMMAND_TYPE) mmc_drv_obj.cmd_info.cmd & + HAL_MEMCARD_COMMAND_TYPE_MASK); + + /* state machine */ + while ((mmc_drv_obj.force_terminate != TRUE) && (state != ESTATE_END)) { + /* The interrupt factor flag is observed. */ + emmc_interrupt(); + + /* wait interrupt */ + if (mmc_drv_obj.state_machine_blocking == TRUE) + continue; + + switch (state) { + case ESTATE_BEGIN: + /* Busy check */ + if ((mmc_drv_obj.error_info.info2 & SD_INFO2_CBSY) != 0) { + emmc_write_error_info(EMMC_FUNCNO_EXEC_CMD, + EMMC_ERR_CARD_BUSY); + return EMMC_ERR_CARD_BUSY; + } + + /* clear register */ + SETR_32(SD_INFO1, 0x00000000U); + SETR_32(SD_INFO2, SD_INFO2_CLEAR); + SETR_32(SD_INFO1_MASK, SD_INFO1_INFO0); + SETR_32(SD_INFO2_MASK, + (SD_INFO2_ALL_ERR | SD_INFO2_CLEAR)); + + state = ESTATE_ISSUE_CMD; + /* through */ + + case ESTATE_ISSUE_CMD: + /* ARG */ + SETR_32(SD_ARG, mmc_drv_obj.cmd_info.arg); + /* issue cmd */ + SETR_32(SD_CMD, mmc_drv_obj.cmd_info.hw); + /* Set driver flag */ + mmc_drv_obj.during_cmd_processing = TRUE; + mmc_drv_obj.state_machine_blocking = TRUE; + + if (response_type == HAL_MEMCARD_RESPONSE_NONE) { + state = ESTATE_NON_RESP_CMD; + } else { + state = ESTATE_RCV_RESP; + } + + break; + + case ESTATE_NON_RESP_CMD: + /* interrupt disable */ + SETR_32(SD_INFO1_MASK, 0x00000000U); + SETR_32(SD_INFO2_MASK, SD_INFO2_CLEAR); + + /* check interrupt */ + if ((mmc_drv_obj.int_event2 & SD_INFO2_ALL_ERR) != 0) { + /* error interrupt */ + cmdErrSdInfo2Log(); + rtn_code = EMMC_ERR_INFO2; + state = ESTATE_ERROR; + } else if ((mmc_drv_obj.int_event1 & SD_INFO1_INFO0) == + 0) { + /* not receive expected interrupt */ + rtn_code = EMMC_ERR_RESPONSE; + state = ESTATE_ERROR; + } else { + emmc_WaitCmd2Cmd_8Cycle(); + state = ESTATE_END; + } + break; + + case ESTATE_RCV_RESP: + /* interrupt disable */ + SETR_32(SD_INFO1_MASK, 0x00000000U); + SETR_32(SD_INFO2_MASK, SD_INFO2_CLEAR); + + /* check interrupt */ + if ((mmc_drv_obj.int_event2 & SD_INFO2_ALL_ERR) != 0) { + if ((mmc_drv_obj.get_partition_access_flag == + TRUE) + && ((mmc_drv_obj.int_event2 & SD_INFO2_ERR6) + != 0U)) { + err_not_care_flag = TRUE; + rtn_code = EMMC_ERR_CMD_TIMEOUT; + } else { + /* error interrupt */ + cmdErrSdInfo2Log(); + rtn_code = EMMC_ERR_INFO2; + } + state = ESTATE_ERROR; + break; + } else if ((mmc_drv_obj.int_event1 & SD_INFO1_INFO0) == + 0) { + /* not receive expected interrupt */ + rtn_code = EMMC_ERR_RESPONSE; + state = ESTATE_ERROR; + break; + } + + /* read response */ + emmc_read_response(response); + + /* check response */ + rtn_code = emmc_response_check(response, error_mask); + if (rtn_code != EMMC_SUCCESS) { + state = ESTATE_ERROR; + break; + } + + if (response_type == HAL_MEMCARD_RESPONSE_R1b) { + /* R1b */ + SETR_32(SD_INFO2_MASK, + (SD_INFO2_ALL_ERR | SD_INFO2_CLEAR)); + state = ESTATE_RCV_RESPONSE_BUSY; + } else { + state = ESTATE_CHECK_RESPONSE_COMPLETE; + } + break; + + case ESTATE_RCV_RESPONSE_BUSY: + /* check interrupt */ + if ((mmc_drv_obj.int_event2 & SD_INFO2_ALL_ERR) != 0) { + /* error interrupt */ + cmdErrSdInfo2Log(); + rtn_code = EMMC_ERR_INFO2; + state = ESTATE_ERROR; + break; + } + /* DAT0 not Busy */ + if ((SD_INFO2_DAT0 & mmc_drv_obj.error_info.info2) != 0) { + state = ESTATE_CHECK_RESPONSE_COMPLETE; + break; + } + break; + + case ESTATE_CHECK_RESPONSE_COMPLETE: + if (cmd_type >= HAL_MEMCARD_COMMAND_TYPE_ADTC_WRITE) { + state = ESTATE_DATA_TRANSFER; + } else { + emmc_WaitCmd2Cmd_8Cycle(); + state = ESTATE_END; + } + break; + + case ESTATE_DATA_TRANSFER: + /* ADTC command */ + mmc_drv_obj.during_transfer = TRUE; + mmc_drv_obj.state_machine_blocking = TRUE; + + if (mmc_drv_obj.transfer_mode == HAL_MEMCARD_DMA) { + /* DMA */ + emmc_data_transfer_dma(); + } else { + /* PIO */ + /* interrupt enable (FIFO read/write enable) */ + if (mmc_drv_obj.cmd_info.dir == + HAL_MEMCARD_WRITE) { + SETR_32(SD_INFO2_MASK, + (SD_INFO2_BWE | SD_INFO2_ALL_ERR + | SD_INFO2_CLEAR)); + } else { + SETR_32(SD_INFO2_MASK, + (SD_INFO2_BRE | SD_INFO2_ALL_ERR + | SD_INFO2_CLEAR)); + } + } + state = ESTATE_DATA_TRANSFER_COMPLETE; + break; + + case ESTATE_DATA_TRANSFER_COMPLETE: + /* check interrupt */ + if ((mmc_drv_obj.int_event2 & SD_INFO2_ALL_ERR) != 0) { + /* error interrupt */ + cmdErrSdInfo2Log(); + rtn_code = EMMC_ERR_INFO2; + state = ESTATE_TRANSFER_ERROR; + break; + } + + /* DMAC error ? */ + if (mmc_drv_obj.dma_error_flag == TRUE) { + /* Error occurred in DMAC driver. */ + rtn_code = EMMC_ERR_FROM_DMAC_TRANSFER; + state = ESTATE_TRANSFER_ERROR; + } else if (mmc_drv_obj.during_dma_transfer == TRUE) { + /* DMAC not finished. unknown error */ + rtn_code = EMMC_ERR; + state = ESTATE_TRANSFER_ERROR; + } else { + SETR_32(SD_INFO1_MASK, SD_INFO1_INFO2); + SETR_32(SD_INFO2_MASK, + (SD_INFO2_ALL_ERR | SD_INFO2_CLEAR)); + + mmc_drv_obj.state_machine_blocking = TRUE; + + state = ESTATE_ACCESS_END; + } + break; + + case ESTATE_ACCESS_END: + + /* clear flag */ + if (mmc_drv_obj.transfer_mode == HAL_MEMCARD_DMA) { + /* W (CC_EXT_MODE, H'0000_1010) SD_BUF DMA transfer disabled */ + SETR_32(CC_EXT_MODE, CC_EXT_MODE_CLEAR); + SETR_32(SD_STOP, 0x00000000U); + mmc_drv_obj.during_dma_transfer = FALSE; + } + + SETR_32(SD_INFO1_MASK, 0x00000000U); + SETR_32(SD_INFO2_MASK, SD_INFO2_CLEAR); + SETR_32(SD_INFO1, 0x00000000U); + SETR_32(SD_INFO2, SD_INFO2_CLEAR); + + if ((mmc_drv_obj.int_event1 & SD_INFO1_INFO2) != 0) { + emmc_WaitCmd2Cmd_8Cycle(); + state = ESTATE_END; + } else { + state = ESTATE_ERROR; + } + break; + + case ESTATE_TRANSFER_ERROR: + /* The error occurred in the Data transfer. */ + if (mmc_drv_obj.transfer_mode == HAL_MEMCARD_DMA) { + /* W (CC_EXT_MODE, H'0000_1010) SD_BUF DMA transfer disabled */ + SETR_32(CC_EXT_MODE, CC_EXT_MODE_CLEAR); + SETR_32(SD_STOP, 0x00000000U); + mmc_drv_obj.during_dma_transfer = FALSE; + } + /* through */ + + case ESTATE_ERROR: + if (err_not_care_flag == TRUE) { + mmc_drv_obj.during_cmd_processing = FALSE; + } else { + emmc_softreset(); + emmc_write_error_info(EMMC_FUNCNO_EXEC_CMD, + rtn_code); + } + return rtn_code; + + default: + state = ESTATE_END; + break; + } /* switch (state) */ + } /* while ( (mmc_drv_obj.force_terminate != TRUE) && (state != ESTATE_END) ) */ + + /* force terminate */ + if (mmc_drv_obj.force_terminate == TRUE) { + /* timeout timer is expired. Or, PIO data transfer error. */ + /* Timeout occurred in the DMA transfer. */ + if (mmc_drv_obj.during_dma_transfer == TRUE) { + mmc_drv_obj.during_dma_transfer = FALSE; + } + ERROR("BL2: emmc exec_cmd:EMMC_ERR_FORCE_TERMINATE\n"); + emmc_softreset(); + + return EMMC_ERR_FORCE_TERMINATE; /* error information has already been written. */ + } + + /* success */ + mmc_drv_obj.during_cmd_processing = FALSE; + mmc_drv_obj.during_transfer = FALSE; + + return EMMC_SUCCESS; +} diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/emmc/emmc_config.h b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/emmc/emmc_config.h new file mode 100644 index 00000000..16b6b8aa --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/emmc/emmc_config.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2015-2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef EMMC_CONFIG_H +#define EMMC_CONFIG_H + +/* RCA */ +#define EMMC_RCA 1UL +/* 314ms (freq = 400KHz, timeout Counter = 0x04(SDCLK * 2^17) */ +#define EMMC_RW_DATA_TIMEOUT 0x40UL +/* how many times to try after fail. Don't change. */ +#define EMMC_RETRY_COUNT 0 +#define EMMC_CMD_MAX 60UL /* Don't change. */ + +#define LOADIMAGE_FLAGS_DMA_ENABLE 0x00000001UL + +#endif /* EMMC_CONFIG_H */ diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/emmc/emmc_def.h b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/emmc/emmc_def.h new file mode 100644 index 00000000..46c45745 --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/emmc/emmc_def.h @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2015-2017, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/** + * @file emmc_def.h + * @brief eMMC boot is expecting this header file + * + */ + +#ifndef EMMC_DEF_H +#define EMMC_DEF_H + +#include "emmc_std.h" + +/* ************************ HEADER (INCLUDE) SECTION *********************** */ + +/* ***************** MACROS, CONSTANTS, COMPILATION FLAGS ****************** */ +#define EMMC_POWER_ON (1U) + +/* ********************** STRUCTURES, TYPE DEFINITIONS ********************* */ + +/* ********************** DECLARATION OF EXTERNAL DATA ********************* */ +extern st_mmc_base mmc_drv_obj; + +/* ************************** FUNCTION PROTOTYPES ************************** */ + +/** @brief for assembler program + */ +uint32_t _rom_emmc_finalize(void); + +/** @brief eMMC driver API + */ +EMMC_ERROR_CODE emmc_init(void); +EMMC_ERROR_CODE emmc_terminate(void); +EMMC_ERROR_CODE emmc_memcard_power(uint8_t mode); +EMMC_ERROR_CODE emmc_mount(void); +EMMC_ERROR_CODE emmc_set_request_mmc_clock(uint32_t *freq); +EMMC_ERROR_CODE emmc_send_idle_cmd(uint32_t arg); +EMMC_ERROR_CODE emmc_select_partition(EMMC_PARTITION_ID id); +EMMC_ERROR_CODE emmc_read_sector(uint32_t *buff_address_virtual, + uint32_t sector_number, uint32_t count, + uint32_t feature_flags); +EMMC_ERROR_CODE emmc_write_sector(uint32_t *buff_address_virtual, + uint32_t sector_number, uint32_t count, + uint32_t feature_flags); +EMMC_ERROR_CODE emmc_erase_sector(uint32_t *start_address, + uint32_t *end_address); +uint32_t emmc_bit_field(uint8_t *data, uint32_t top, uint32_t bottom); + +/** @brief interrupt service + */ +uint32_t emmc_interrupt(void); + +/** @brief DMA + */ + +/** @brief send command API + */ +EMMC_ERROR_CODE emmc_exec_cmd(uint32_t error_mask, uint32_t *response); +void emmc_make_nontrans_cmd(HAL_MEMCARD_COMMAND cmd, uint32_t arg); +void emmc_make_trans_cmd(HAL_MEMCARD_COMMAND cmd, uint32_t arg, + uint32_t *buff_address_virtual, uint32_t len, + HAL_MEMCARD_OPERATION dir, + HAL_MEMCARD_DATA_TRANSFER_MODE transfer_mode); +EMMC_ERROR_CODE emmc_set_ext_csd(uint32_t arg); + +/** @brief for error information + */ +void emmc_write_error_info(uint16_t func_no, EMMC_ERROR_CODE error_code); +void emmc_write_error_info_func_no(uint16_t func_no); + +/* ********************************* CODE ********************************** */ + +#endif /* EMMC_DEF_H */ +/* ******************************** END ************************************ */ diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/emmc/emmc_hal.h b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/emmc/emmc_hal.h new file mode 100644 index 00000000..0a855171 --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/emmc/emmc_hal.h @@ -0,0 +1,535 @@ +/* + * Copyright (c) 2015-2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef EMMC_HAL_H +#define EMMC_HAL_H + +/* memory card error/status types */ +#define HAL_MEMCARD_OUT_OF_RANGE 0x80000000L +#define HAL_MEMCARD_ADDRESS_ERROR 0x40000000L +#define HAL_MEMCARD_BLOCK_LEN_ERROR 0x20000000L +#define HAL_MEMCARD_ERASE_SEQ_ERROR 0x10000000L +#define HAL_MEMCARD_ERASE_PARAM 0x08000000L +#define HAL_MEMCARD_WP_VIOLATION 0x04000000L +#define HAL_MEMCARD_CARD_IS_LOCKED 0x02000000L +#define HAL_MEMCARD_LOCK_UNLOCK_FAILED 0x01000000L +#define HAL_MEMCARD_COM_CRC_ERROR 0x00800000L +#define HAL_MEMCARD_ILEGAL_COMMAND 0x00400000L +#define HAL_MEMCARD_CARD_ECC_FAILED 0x00200000L +#define HAL_MEMCARD_CC_ERROR 0x00100000L +#define HAL_MEMCARD_ERROR 0x00080000L +#define HAL_MEMCARD_UNDERRUN 0x00040000L +#define HAL_MEMCARD_OVERRUN 0x00020000L +#define HAL_MEMCARD_CIDCSD_OVERWRITE 0x00010000L +#define HAL_MEMCARD_WP_ERASE_SKIP 0x00008000L +#define HAL_MEMCARD_CARD_ECC_DISABLED 0x00004000L +#define HAL_MEMCARD_ERASE_RESET 0x00002000L +#define HAL_MEMCARD_CARD_STATE 0x00001E00L +#define HAL_MEMCARD_CARD_READY_FOR_DATA 0x00000100L +#define HAL_MEMCARD_APP_CMD 0x00000020L +#define HAL_MEMCARD_SWITCH_ERROR 0x00000080L +#define HAL_MEMCARD_AKE_SEQ_ERROR 0x00000008L +#define HAL_MEMCARD_NO_ERRORS 0x00000000L + +/* Memory card response types */ +#define HAL_MEMCARD_COMMAND_INDEX_MASK 0x0003f + +/* Type of the return value. */ +typedef enum { + HAL_MEMCARD_FAIL = 0U, + HAL_MEMCARD_OK = 1U, + HAL_MEMCARD_DMA_ALLOC_FAIL = 2U, /* DMA channel allocation failed */ + HAL_MEMCARD_DMA_TRANSFER_FAIL = 3U, /* DMA transfer failed */ + HAL_MEMCARD_CARD_STATUS_ERROR = 4U, /* card status non-masked error */ + HAL_MEMCARD_CMD_TIMEOUT = 5U, /* Command timeout occurred */ + HAL_MEMCARD_DATA_TIMEOUT = 6U, /* Data timeout occurred */ + HAL_MEMCARD_CMD_CRC_ERROR = 7U, /* Command CRC error occurred */ + HAL_MEMCARD_DATA_CRC_ERROR = 8U /* Data CRC error occurred */ +} HAL_MEMCARD_RETURN; + +/* memory access operation */ +typedef enum { + HAL_MEMCARD_READ = 0U, /* read */ + HAL_MEMCARD_WRITE = 1U /* write */ +} HAL_MEMCARD_OPERATION; + +/* Type of data width on memorycard bus */ +typedef enum { + HAL_MEMCARD_DATA_WIDTH_1_BIT = 0U, + HAL_MEMCARD_DATA_WIDTH_4_BIT = 1U, + HAL_MEMCARD_DATA_WIDTH_8_BIT = 2U +} HAL_MEMCARD_DATA_WIDTH; /* data (bus) width types */ + +/* Presence of the memory card */ +typedef enum { + HAL_MEMCARD_CARD_IS_IN = 0U, + HAL_MEMCARD_CARD_IS_OUT = 1U +} HAL_MEMCARD_PRESENCE_STATUS; /* presence status of the memory card */ + +/* mode of data transfer */ +typedef enum { + HAL_MEMCARD_DMA = 0U, + HAL_MEMCARD_NOT_DMA = 1U +} HAL_MEMCARD_DATA_TRANSFER_MODE; + +/* Memory card response types. */ +typedef enum hal_memcard_response_type { + HAL_MEMCARD_RESPONSE_NONE = 0x00000U, + HAL_MEMCARD_RESPONSE_R1 = 0x00100U, + HAL_MEMCARD_RESPONSE_R1b = 0x00200U, + HAL_MEMCARD_RESPONSE_R2 = 0x00300U, + HAL_MEMCARD_RESPONSE_R3 = 0x00400U, + HAL_MEMCARD_RESPONSE_R4 = 0x00500U, + HAL_MEMCARD_RESPONSE_R5 = 0x00600U, + HAL_MEMCARD_RESPONSE_R6 = 0x00700U, + HAL_MEMCARD_RESPONSE_R7 = 0x00800U, + HAL_MEMCARD_RESPONSE_TYPE_MASK = 0x00f00U +} HAL_MEMCARD_RESPONSE_TYPE; + +/* Memory card command types. */ +typedef enum hal_memcard_command_type { + HAL_MEMCARD_COMMAND_TYPE_BC = 0x00000U, + HAL_MEMCARD_COMMAND_TYPE_BCR = 0x01000U, + HAL_MEMCARD_COMMAND_TYPE_AC = 0x02000U, + HAL_MEMCARD_COMMAND_TYPE_ADTC_WRITE = 0x03000U, + HAL_MEMCARD_COMMAND_TYPE_ADTC_READ = 0x04000U, + HAL_MEMCARD_COMMAND_TYPE_MASK = 0x07000U +} HAL_MEMCARD_COMMAND_TYPE; + +/* Type of memory card */ +typedef enum hal_memcard_command_card_type { + HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON = 0x00000U, + HAL_MEMCARD_COMMAND_CARD_TYPE_MMC = 0x08000U, + HAL_MEMCARD_COMMAND_CARD_TYPE_SD = 0x10000U, + HAL_MEMCARD_COMMAND_CARD_TYPE_MASK = 0x18000U +} HAL_MEMCARD_COMMAND_CARD_TYPE; + +/* Memory card application command. */ +typedef enum hal_memcard_command_app_norm { + HAL_MEMCARD_COMMAND_NORMAL = 0x00000U, + HAL_MEMCARD_COMMAND_APP = 0x20000U, + HAL_MEMCARD_COMMAND_APP_NORM_MASK = 0x20000U +} HAL_MEMCARD_COMMAND_APP_NORM; + +/* Memory card command codes. */ +typedef enum { +/* class 0 and class 1 */ + /* CMD0 */ + CMD0_GO_IDLE_STATE = + 0U | (uint32_t)HAL_MEMCARD_RESPONSE_NONE | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_BC | + (uint32_t) HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD1 */ + CMD1_SEND_OP_COND = + 1U | (uint32_t)HAL_MEMCARD_RESPONSE_R3 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_BCR | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_MMC | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD2 */ + CMD2_ALL_SEND_CID_MMC = + 2U | (uint32_t)HAL_MEMCARD_RESPONSE_R2 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_BCR | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_MMC | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + CMD2_ALL_SEND_CID_SD = + 2U | (uint32_t)HAL_MEMCARD_RESPONSE_R2 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_BCR | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_SD | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD3 */ + CMD3_SET_RELATIVE_ADDR = + 3U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_AC | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_MMC | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + CMD3_SEND_RELATIVE_ADDR = + 3U | (uint32_t)HAL_MEMCARD_RESPONSE_R6 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_AC | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_SD | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD4 */ + CMD4_SET_DSR = + 4U | (uint32_t)HAL_MEMCARD_RESPONSE_NONE | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_BC | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD5 */ + CMD5_SLEEP_AWAKE = + 5U | (uint32_t)HAL_MEMCARD_RESPONSE_R1b | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_AC | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_MMC | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD6 */ + CMD6_SWITCH = + 6U | (uint32_t)HAL_MEMCARD_RESPONSE_R1b | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_AC | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_MMC | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + CMD6_SWITCH_FUNC = + 6U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_AC | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_SD | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + ACMD6_SET_BUS_WIDTH = + 6U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_AC | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_SD | + (uint32_t)HAL_MEMCARD_COMMAND_APP, + /* CMD7 */ + CMD7_SELECT_CARD = + 7U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_AC | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD7(from Disconnected State to Programming State) */ + CMD7_SELECT_CARD_PROG = + 7U | (uint32_t)HAL_MEMCARD_RESPONSE_R1b | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_AC | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + CMD7_DESELECT_CARD = + 7U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_AC | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD8 */ + CMD8_SEND_EXT_CSD = + 8U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_ADTC_READ | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_MMC | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + CMD8_SEND_IF_COND = + 8U | (uint32_t)HAL_MEMCARD_RESPONSE_R7 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_BCR | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_SD | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD9 */ + CMD9_SEND_CSD = + 9U | (uint32_t)HAL_MEMCARD_RESPONSE_R2 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_AC | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD10 */ + CMD10_SEND_CID = + 10U | (uint32_t)HAL_MEMCARD_RESPONSE_R2 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_AC | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD11 */ + CMD11_READ_DAT_UNTIL_STOP = + 11U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_ADTC_READ | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_SD | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD12 */ + CMD12_STOP_TRANSMISSION = + 12U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_AC | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD12(R1b : write case) */ + CMD12_STOP_TRANSMISSION_WRITE = + 12U | (uint32_t)HAL_MEMCARD_RESPONSE_R1b | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_AC | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD13 */ + CMD13_SEND_STATUS = + 13U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_AC | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + ACMD13_SD_STATUS = + 13U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_ADTC_READ | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_SD | + (uint32_t)HAL_MEMCARD_COMMAND_APP, + /* CMD14 */ + CMD14_BUSTEST_R = + 14U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_ADTC_READ | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_MMC | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD15 */ + CMD15_GO_INACTIVE_STATE = + 15U | (uint32_t)HAL_MEMCARD_RESPONSE_NONE | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_AC | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + +/* class 2 */ + /* CMD16 */ + CMD16_SET_BLOCKLEN = + 16U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_AC | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD17 */ + CMD17_READ_SINGLE_BLOCK = + 17U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_ADTC_READ | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD18 */ + CMD18_READ_MULTIPLE_BLOCK = + 18U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_ADTC_READ | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD19 */ + CMD19_BUS_TEST_W = + 19U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_ADTC_WRITE | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_MMC | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + +/* class 3 */ + /* CMD20 */ + CMD20_WRITE_DAT_UNTIL_STOP = + 20U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_ADTC_WRITE | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_MMC | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD21 */ + CMD21 = 21U, + /* CMD22 */ + CMD22 = 22U, + ACMD22_SEND_NUM_WR_BLOCKS = + 22U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_AC | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_SD | + (uint32_t)HAL_MEMCARD_COMMAND_APP, + +/* class 4 */ + /* CMD23 */ + CMD23_SET_BLOCK_COUNT = + 23U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_AC | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_MMC | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + ACMD23_SET_WR_BLK_ERASE_COUNT = + 23U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_AC | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_SD | + (uint32_t)HAL_MEMCARD_COMMAND_APP, + /* CMD24 */ + CMD24_WRITE_BLOCK = + 24U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_ADTC_WRITE | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD25 */ + CMD25_WRITE_MULTIPLE_BLOCK = + 25U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_ADTC_WRITE | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD26 */ + CMD26_PROGRAM_CID = + 26U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_ADTC_WRITE | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_MMC | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD27 */ + CMD27_PROGRAM_CSD = + 27U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_ADTC_WRITE | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + +/* class 6 */ + /* CMD28 */ + CMD28_SET_WRITE_PROT = + 28U | (uint32_t)HAL_MEMCARD_RESPONSE_R1b | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_AC | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD29 */ + CMD29_CLR_WRITE_PROT = + 29U | (uint32_t)HAL_MEMCARD_RESPONSE_R1b | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_AC | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD30 */ + CMD30_SEND_WRITE_PROT = + 30U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_ADTC_READ | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD31 */ + CMD30_SEND_WRITE_PROT_TYPE = + 31U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_ADTC_READ | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + +/* class 5 */ + /* CMD32 */ + CMD32_ERASE_WR_BLK_START = + 32U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_AC | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_SD | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD33 */ + CMD33_ERASE_WR_BLK_END = + 33U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_AC | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_SD | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD34 */ + CMD34 = 34U, + /* CMD35 */ + CMD35_ERASE_GROUP_START = + 35U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_AC | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_MMC | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD36 */ + CMD36_ERASE_GROUP_END = + 36U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_AC | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_MMC | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD37 */ + CMD37 = 37U, + /* CMD38 */ + CMD38_ERASE = + 38U | (uint32_t)HAL_MEMCARD_RESPONSE_R1b | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_AC | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + +/* class 9 */ + /* CMD39 */ + CMD39_FASTIO = + 39U | (uint32_t)HAL_MEMCARD_RESPONSE_R4 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_AC | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_MMC | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD40 */ + CMD40_GO_IRQSTATE = + 40U | (uint32_t)HAL_MEMCARD_RESPONSE_R5 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_BCR | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_MMC | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD41 */ + CMD41 = 41, + ACMD41_SD_SEND_OP_COND = + 41U | (uint32_t)HAL_MEMCARD_RESPONSE_R3 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_BCR | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_SD | + (uint32_t)HAL_MEMCARD_COMMAND_APP, + +/* class 7 */ + /* CMD42 */ + CMD42_LOCK_UNLOCK = + 42U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_ADTC_WRITE | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + ACMD42_SET_CLR_CARD_DETECT = + 42U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_AC | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_SD | + (uint32_t)HAL_MEMCARD_COMMAND_APP, + CMD43 = 43U, /* CMD43 */ + CMD44 = 44U, /* CMD44 */ + CMD45 = 45U, /* CMD45 */ + CMD46 = 46U, /* CMD46 */ + CMD47 = 47U, /* CMD47 */ + CMD48 = 48U, /* CMD48 */ + CMD49 = 49U, /* CMD49 */ + CMD50 = 50U, /* CMD50 */ + CMD51 = 51U, /* CMD51 */ + ACMD51_SEND_SCR = + 51U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_ADTC_READ | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_SD | + (uint32_t)HAL_MEMCARD_COMMAND_APP, + CMD52 = 52U, /* CMD52 */ + CMD53 = 53U, /* CMD53 */ + CMD54 = 54U, /* CMD54 */ + +/* class 8 */ + /* CMD55 */ + CMD55_APP_CMD = + 55U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_AC | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD56 */ + CMD56_GEN_CMD = + 56U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_ADTC_WRITE | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + CMD57 = 57U, /* CMD57 */ + CMD58 = 58U, /* CMD58 */ + CMD59 = 59U, /* CMD59 */ + CMD60 = 60U, /* CMD60 */ + CMD61 = 61U, /* CMD61 */ + CMD62 = 62U, /* CMD62 */ + CMD63 = 63U /* CMD63 */ +} HAL_MEMCARD_COMMAND; + +/* + * Configuration structure from HAL layer. + * + * If some field is not available it should be filled with 0xFF. + * The API version is 32-bit unsigned integer telling the version of the API. + * The integer is divided to four sections which each can be treated as a 8-bit + * unsigned number: + * Bits 31-24 make the most significant part of the version number. This number + * starts from 1 i.e. the second version of the API will be 0x02xxxxxx. This + * number changes only, if the API itself changes so much that it is not + * compatible anymore with older releases. + * Bits 23-16 API minor version number. For example API version 2.1 would be + * 0x0201xxxx. + * Bits 15-8 are the number of the year when release is done. The 0 is year + * 2000, 1 is year 2001 and so on + * Bits 7- are the week number when release is done. First full week of the + * year is 1 + * + * Example: let's assume that release 2.1 is done on week 10 year 2008 + * the version will get the value 0x0201080A + */ +typedef struct { + /* + * Version of the chipset API implementation + * + * bits [31:24] API specification major version number.
+ * bits [23:16] API specification minor version number.
+ * bits [15:8] API implementation year. (2000 = 0, 2001 = 1, ...) + * bits [7:0] API implementation week. + * Example: API spec version 4.0, implementation w46 2008 => 0x0400082E + */ + uint32_t api_version; + + /* maximum block count which can be transferred at once */ + uint32_t max_block_count; + + /* maximum clock frequence in Hz supported by HW */ + uint32_t max_clock_freq; + + /* maximum data bus width supported by HW */ + uint16_t max_data_width; + + /* Is high-speed mode supported by HW (yes=1, no=0) */ + uint8_t hs_mode_supported; + + /* Is memory card removable (yes=1, no=0) */ + uint8_t card_removable; + +} HAL_MEMCARD_HW_CONF; + +/* Configuration structure to HAL layer. */ +typedef struct { + /* how many times to try after fail, for instance sending command */ + uint32_t retries_after_fail; +} HAL_MEMCARD_INIT_CONF; + +#endif /* EMMC_HAL_H */ diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/emmc/emmc_init.c b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/emmc/emmc_init.c new file mode 100644 index 00000000..e332c5fc --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/emmc/emmc_init.c @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2015-2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include "emmc_config.h" +#include "emmc_hal.h" +#include "emmc_std.h" +#include "emmc_registers.h" +#include "emmc_def.h" + +st_mmc_base mmc_drv_obj; + +EMMC_ERROR_CODE emmc_memcard_power(uint8_t mode) +{ + + if (mode == TRUE) { + /* power on (Vcc&Vccq is always power on) */ + mmc_drv_obj.card_power_enable = TRUE; + } else { + /* power off (Vcc&Vccq is always power on) */ + mmc_drv_obj.card_power_enable = FALSE; + mmc_drv_obj.mount = FALSE; + mmc_drv_obj.selected = FALSE; + } + + return EMMC_SUCCESS; +} +static inline void emmc_set_retry_count(uint32_t retry) +{ + mmc_drv_obj.retries_after_fail = retry; +} + +static inline void emmc_set_data_timeout(uint32_t data_timeout) +{ + mmc_drv_obj.data_timeout = data_timeout; +} + +static void emmc_memset(uint8_t *buff, uint8_t data, uint32_t cnt) +{ + if (buff == NULL) { + return; + } + + while (cnt > 0) { + *buff++ = data; + cnt--; + } +} + +static void emmc_driver_config(void) +{ + emmc_set_retry_count(EMMC_RETRY_COUNT); + emmc_set_data_timeout(EMMC_RW_DATA_TIMEOUT); +} + +static void emmc_drv_init(void) +{ + emmc_memset((uint8_t *) (&mmc_drv_obj), 0, sizeof(st_mmc_base)); + mmc_drv_obj.card_present = HAL_MEMCARD_CARD_IS_IN; + mmc_drv_obj.data_timeout = EMMC_RW_DATA_TIMEOUT; + mmc_drv_obj.bus_width = HAL_MEMCARD_DATA_WIDTH_1_BIT; +} + +static EMMC_ERROR_CODE emmc_dev_finalize(void) +{ + EMMC_ERROR_CODE result; + + /* + * MMC power off + * the power supply of eMMC device is always turning on. + * RST_n : Hi --> Low level. + */ + result = emmc_memcard_power(FALSE); + + /* host controller reset */ + SETR_32(SD_INFO1, 0x00000000U); /* all interrupt clear */ + SETR_32(SD_INFO2, SD_INFO2_CLEAR); /* all interrupt clear */ + SETR_32(SD_INFO1_MASK, 0x00000000U); /* all interrupt disable */ + SETR_32(SD_INFO2_MASK, SD_INFO2_CLEAR); /* all interrupt disable */ + SETR_32(SD_CLK_CTRL, 0x00000000U); /* MMC clock stop */ + + + return result; +} + +static EMMC_ERROR_CODE emmc_dev_init(void) +{ + + /* MMCIF initialize */ + SETR_32(SD_INFO1, 0x00000000U); /* all interrupt clear */ + SETR_32(SD_INFO2, SD_INFO2_CLEAR); /* all interrupt clear */ + SETR_32(SD_INFO1_MASK, 0x00000000U); /* all interrupt disable */ + SETR_32(SD_INFO2_MASK, SD_INFO2_CLEAR); /* all interrupt disable */ + + SETR_32(HOST_MODE, 0x00000000U); /* SD_BUF access width = 64-bit */ + SETR_32(SD_OPTION, 0x0000C0EEU); /* Bus width = 1bit, timeout=MAX */ + SETR_32(SD_CLK_CTRL, 0x00000000U); /* Disable Automatic Control & Clock Output */ + + return EMMC_SUCCESS; +} + +static EMMC_ERROR_CODE emmc_reset_controller(void) +{ + EMMC_ERROR_CODE result; + + /* initialize mmc driver */ + emmc_drv_init(); + + /* initialize H/W */ + result = emmc_dev_init(); + if (result == EMMC_SUCCESS) { + mmc_drv_obj.initialize = TRUE; + } + + return result; + +} + +EMMC_ERROR_CODE emmc_terminate(void) +{ + EMMC_ERROR_CODE result; + + result = emmc_dev_finalize(); + + emmc_memset((uint8_t *) (&mmc_drv_obj), 0, sizeof(st_mmc_base)); + + return result; +} + +EMMC_ERROR_CODE emmc_init(void) +{ + EMMC_ERROR_CODE result; + + result = emmc_reset_controller(); + if (result == EMMC_SUCCESS) { + emmc_driver_config(); + } + + return result; +} diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/emmc/emmc_interrupt.c b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/emmc/emmc_interrupt.c new file mode 100644 index 00000000..44cf3347 --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/emmc/emmc_interrupt.c @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2015-2020, Renesas Electronics Corporation. All rights + * reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include "emmc_config.h" +#include "emmc_def.h" +#include "emmc_hal.h" +#include "emmc_registers.h" +#include "emmc_std.h" + +static EMMC_ERROR_CODE emmc_trans_sector(uint32_t *buff_address_virtual); + +uint32_t emmc_interrupt(void) +{ + EMMC_ERROR_CODE result; + uint32_t end_bit=BIT20; + + /* SD_INFO */ + mmc_drv_obj.error_info.info1 = GETR_32(SD_INFO1); + mmc_drv_obj.error_info.info2 = GETR_32(SD_INFO2); + + /* SD_INFO EVENT */ + mmc_drv_obj.int_event1 = + mmc_drv_obj.error_info.info1 & GETR_32(SD_INFO1_MASK); + mmc_drv_obj.int_event2 = + mmc_drv_obj.error_info.info2 & GETR_32(SD_INFO2_MASK); + + /* ERR_STS */ + mmc_drv_obj.error_info.status1 = GETR_32(SD_ERR_STS1); + mmc_drv_obj.error_info.status2 = GETR_32(SD_ERR_STS2); + + /* DM_CM_INFO */ + mmc_drv_obj.error_info.dm_info1 = GETR_32(DM_CM_INFO1); + mmc_drv_obj.error_info.dm_info2 = GETR_32(DM_CM_INFO2); + + /* DM_CM_INFO EVENT */ + mmc_drv_obj.dm_event1 = + mmc_drv_obj.error_info.dm_info1 & GETR_32(DM_CM_INFO1_MASK); + mmc_drv_obj.dm_event2 = + mmc_drv_obj.error_info.dm_info2 & GETR_32(DM_CM_INFO2_MASK); + + /* ERR SD_INFO2 */ + if ((SD_INFO2_ALL_ERR & mmc_drv_obj.int_event2) != 0) { + SETR_32(SD_INFO1_MASK, 0x00000000U); /* interrupt disable */ + SETR_32(SD_INFO2_MASK, SD_INFO2_CLEAR); /* interrupt disable */ + SETR_32(SD_INFO1, 0x00000000U); /* interrupt clear */ + SETR_32(SD_INFO2, SD_INFO2_CLEAR); /* interrupt clear */ + mmc_drv_obj.state_machine_blocking = FALSE; + } + + /* PIO Transfer */ + /* BWE/BRE */ + else if (((SD_INFO2_BWE | SD_INFO2_BRE) & mmc_drv_obj.int_event2)) { + /* BWE */ + if (SD_INFO2_BWE & mmc_drv_obj.int_event2) { + SETR_32(SD_INFO2, (GETR_32(SD_INFO2) & ~SD_INFO2_BWE)); + } + /* BRE */ + else { + SETR_32(SD_INFO2, (GETR_32(SD_INFO2) & ~SD_INFO2_BRE)); + } + + result = emmc_trans_sector(mmc_drv_obj.buff_address_virtual); + mmc_drv_obj.buff_address_virtual += EMMC_BLOCK_LENGTH; + mmc_drv_obj.remain_size -= EMMC_BLOCK_LENGTH; + + if (result != EMMC_SUCCESS) { + /* data transfer error */ + emmc_write_error_info(EMMC_FUNCNO_NONE, result); + + /* Panic */ + SETR_32(SD_INFO1_MASK, 0x00000000U); + SETR_32(SD_INFO2_MASK, SD_INFO2_CLEAR); + SETR_32(SD_INFO1, 0x00000000U); + /* interrupt clear */ + SETR_32(SD_INFO2, SD_INFO2_CLEAR); + mmc_drv_obj.force_terminate = TRUE; + } else { + mmc_drv_obj.during_transfer = FALSE; + } + mmc_drv_obj.state_machine_blocking = FALSE; + } + + /* DMA_TRANSFER */ + /* DM_CM_INFO1: DMA-ch0 transfer complete or error occurred */ + else if ((BIT16 & mmc_drv_obj.dm_event1) != 0) { + SETR_32(DM_CM_INFO1, 0x00000000U); + SETR_32(DM_CM_INFO2, 0x00000000U); + /* interrupt clear */ + SETR_32(SD_INFO2, (GETR_32(SD_INFO2) & ~SD_INFO2_BWE)); + /* DM_CM_INFO2: DMA-ch0 error occurred */ + if ((BIT16 & mmc_drv_obj.dm_event2) != 0) { + mmc_drv_obj.dma_error_flag = TRUE; + } else { + mmc_drv_obj.during_dma_transfer = FALSE; + mmc_drv_obj.during_transfer = FALSE; + } + /* wait next interrupt */ + mmc_drv_obj.state_machine_blocking = FALSE; + } + /* DM_CM_INFO1: DMA-ch1 transfer complete or error occurred */ + else if ((end_bit & mmc_drv_obj.dm_event1) != 0U) { + SETR_32(DM_CM_INFO1, 0x00000000U); + SETR_32(DM_CM_INFO2, 0x00000000U); + /* interrupt clear */ + SETR_32(SD_INFO2, (GETR_32(SD_INFO2) & ~SD_INFO2_BRE)); + /* DM_CM_INFO2: DMA-ch1 error occurred */ + if ((BIT17 & mmc_drv_obj.dm_event2) != 0) { + mmc_drv_obj.dma_error_flag = TRUE; + } else { + mmc_drv_obj.during_dma_transfer = FALSE; + mmc_drv_obj.during_transfer = FALSE; + } + /* wait next interrupt */ + mmc_drv_obj.state_machine_blocking = FALSE; + } + + /* Response end */ + else if ((SD_INFO1_INFO0 & mmc_drv_obj.int_event1) != 0) { + /* interrupt clear */ + SETR_32(SD_INFO1, (GETR_32(SD_INFO1) & ~SD_INFO1_INFO0)); + mmc_drv_obj.state_machine_blocking = FALSE; + } + /* Access end */ + else if ((SD_INFO1_INFO2 & mmc_drv_obj.int_event1) != 0) { + /* interrupt clear */ + SETR_32(SD_INFO1, (GETR_32(SD_INFO1) & ~SD_INFO1_INFO2)); + mmc_drv_obj.state_machine_blocking = FALSE; + } else { + /* nothing to do. */ + } + + return (uint32_t) 0; +} + +static EMMC_ERROR_CODE emmc_trans_sector(uint32_t *buff_address_virtual) +{ + uint32_t length, i; + uint64_t *bufPtrLL; + + if (buff_address_virtual == NULL) { + return EMMC_ERR_PARAM; + } + + if ((mmc_drv_obj.during_transfer != TRUE) + || (mmc_drv_obj.remain_size == 0)) { + return EMMC_ERR_STATE; + } + + bufPtrLL = (uint64_t *) buff_address_virtual; + length = mmc_drv_obj.remain_size; + + /* data transefer */ + for (i = 0; i < (length >> 3); i++) { + /* Write */ + if (mmc_drv_obj.cmd_info.dir == HAL_MEMCARD_WRITE) { + SETR_64(SD_BUF0, *bufPtrLL); /* buffer --> FIFO */ + } + /* Read */ + else { + /* Checks when the read data reaches SD_SIZE. */ + /* The BRE bit is cleared at emmc_interrupt function. */ + if (((i % + (uint32_t) (EMMC_BLOCK_LENGTH >> + EMMC_BUF_SIZE_SHIFT)) == 0U) + && (i != 0U)) { + /* BRE check */ + while (((GETR_32(SD_INFO2)) & SD_INFO2_BRE) == + 0U) { + /* ERROR check */ + if (((GETR_32(SD_INFO2)) & + SD_INFO2_ALL_ERR) != 0U) { + return EMMC_ERR_TRANSFER; + } + } + /* BRE clear */ + SETR_32(SD_INFO2, + (uint32_t) (GETR_32(SD_INFO2) & + ~SD_INFO2_BRE)); + } + *bufPtrLL = GETR_64(SD_BUF0); /* FIFO --> buffer */ + } + bufPtrLL++; + } + + return EMMC_SUCCESS; +} diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/emmc/emmc_mount.c b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/emmc/emmc_mount.c new file mode 100644 index 00000000..bd8c2576 --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/emmc/emmc_mount.c @@ -0,0 +1,665 @@ +/* + * Copyright (c) 2015-2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include "emmc_config.h" +#include "emmc_def.h" +#include "emmc_hal.h" +#include "emmc_registers.h" +#include "emmc_std.h" + +static EMMC_ERROR_CODE emmc_clock_ctrl(uint8_t mode); +static EMMC_ERROR_CODE emmc_card_init(void); +static EMMC_ERROR_CODE emmc_high_speed(void); +static EMMC_ERROR_CODE emmc_bus_width(uint32_t width); +static uint32_t emmc_set_timeout_register_value(uint32_t freq); +static void set_sd_clk(uint32_t clkDiv); +static uint32_t emmc_calc_tran_speed(uint32_t *freq); +static void emmc_get_partition_access(void); +static void emmc_set_bootpartition(void); + +static void emmc_set_bootpartition(void) +{ + mmc_drv_obj.boot_partition_en = + (EMMC_PARTITION_ID) ((mmc_drv_obj.ext_csd_data[179] & + EMMC_BOOT_PARTITION_EN_MASK) >> + EMMC_BOOT_PARTITION_EN_SHIFT); +} + +static EMMC_ERROR_CODE emmc_card_init(void) +{ + int32_t retry; + uint32_t freq = MMC_400KHZ; /* 390KHz */ + EMMC_ERROR_CODE result; + uint32_t result_calc; + + /* state check */ + if ((mmc_drv_obj.initialize != TRUE) + || (mmc_drv_obj.card_power_enable != TRUE) + || ((GETR_32(SD_INFO2) & SD_INFO2_CBSY) != 0) + ) { + emmc_write_error_info(EMMC_FUNCNO_CARD_INIT, EMMC_ERR_STATE); + return EMMC_ERR_STATE; + } + + /* clock on (force change) */ + mmc_drv_obj.current_freq = 0; + mmc_drv_obj.max_freq = MMC_20MHZ; + result = emmc_set_request_mmc_clock(&freq); + if (result != EMMC_SUCCESS) { + emmc_write_error_info_func_no(EMMC_FUNCNO_CARD_INIT); + return EMMC_ERR; + } + + udelay(1000U); /* wait 1ms */ + + /* Get current access partition */ + emmc_get_partition_access(); + + /* CMD0, arg=0x00000000 */ + result = emmc_send_idle_cmd(0x00000000); + if (result != EMMC_SUCCESS) { + emmc_write_error_info_func_no(EMMC_FUNCNO_CARD_INIT); + return result; + } + + udelay(200U); /* wait 74clock 390kHz(189.74us) */ + + /* CMD1 */ + emmc_make_nontrans_cmd(CMD1_SEND_OP_COND, EMMC_HOST_OCR_VALUE); + for (retry = 300; retry > 0; retry--) { + result = + emmc_exec_cmd(EMMC_R1_ERROR_MASK, mmc_drv_obj.response); + if (result != EMMC_SUCCESS) { + emmc_write_error_info_func_no(EMMC_FUNCNO_CARD_INIT); + return result; + } + + if ((mmc_drv_obj.r3_ocr & EMMC_OCR_STATUS_BIT) != 0) { + break; /* card is ready. exit loop */ + } + udelay(1000U); /* wait 1ms */ + } + + if (retry == 0) { + emmc_write_error_info(EMMC_FUNCNO_CARD_INIT, EMMC_ERR_TIMEOUT); + return EMMC_ERR_TIMEOUT; + } + + switch (mmc_drv_obj.r3_ocr & EMMC_OCR_ACCESS_MODE_MASK) { + case EMMC_OCR_ACCESS_MODE_SECT: + mmc_drv_obj.access_mode = TRUE; /* sector mode */ + break; + default: + /* unknown value */ + emmc_write_error_info(EMMC_FUNCNO_CARD_INIT, EMMC_ERR); + return EMMC_ERR; + } + + /* CMD2 */ + emmc_make_nontrans_cmd(CMD2_ALL_SEND_CID_MMC, 0x00000000); + mmc_drv_obj.response = (uint32_t *) (&mmc_drv_obj.cid_data[0]); /* use CID special buffer */ + result = emmc_exec_cmd(EMMC_R1_ERROR_MASK, mmc_drv_obj.response); + if (result != EMMC_SUCCESS) { + emmc_write_error_info_func_no(EMMC_FUNCNO_CARD_INIT); + return result; + } + + /* CMD3 */ + emmc_make_nontrans_cmd(CMD3_SET_RELATIVE_ADDR, EMMC_RCA << 16); + result = emmc_exec_cmd(EMMC_R1_ERROR_MASK, mmc_drv_obj.response); + if (result != EMMC_SUCCESS) { + emmc_write_error_info_func_no(EMMC_FUNCNO_CARD_INIT); + return result; + } + + /* CMD9 (CSD) */ + emmc_make_nontrans_cmd(CMD9_SEND_CSD, EMMC_RCA << 16); + mmc_drv_obj.response = (uint32_t *) (&mmc_drv_obj.csd_data[0]); /* use CSD special buffer */ + result = emmc_exec_cmd(EMMC_R1_ERROR_MASK, mmc_drv_obj.response); + if (result != EMMC_SUCCESS) { + emmc_write_error_info_func_no(EMMC_FUNCNO_CARD_INIT); + return result; + } + + /* card version check */ + if (EMMC_CSD_SPEC_VARS() < 4) { + emmc_write_error_info(EMMC_FUNCNO_CARD_INIT, + EMMC_ERR_ILLEGAL_CARD); + return EMMC_ERR_ILLEGAL_CARD; + } + + /* CMD7 (select card) */ + emmc_make_nontrans_cmd(CMD7_SELECT_CARD, EMMC_RCA << 16); + result = emmc_exec_cmd(EMMC_R1_ERROR_MASK, mmc_drv_obj.response); + if (result != EMMC_SUCCESS) { + emmc_write_error_info_func_no(EMMC_FUNCNO_CARD_INIT); + return result; + } + + mmc_drv_obj.selected = TRUE; + + /* + * card speed check + * Card spec is calculated from TRAN_SPEED(CSD) + */ + result_calc = emmc_calc_tran_speed(&freq); + if (result_calc == 0) { + emmc_write_error_info(EMMC_FUNCNO_CARD_INIT, + EMMC_ERR_ILLEGAL_CARD); + return EMMC_ERR_ILLEGAL_CARD; + } + mmc_drv_obj.max_freq = freq; /* max frequency (card spec) */ + + result = emmc_set_request_mmc_clock(&freq); + if (result != EMMC_SUCCESS) { + emmc_write_error_info_func_no(EMMC_FUNCNO_CARD_INIT); + return EMMC_ERR; + } + + /* set read/write timeout */ + mmc_drv_obj.data_timeout = emmc_set_timeout_register_value(freq); + SETR_32(SD_OPTION, + ((GETR_32(SD_OPTION) & ~(SD_OPTION_TIMEOUT_CNT_MASK)) | + mmc_drv_obj.data_timeout)); + + /* SET_BLOCKLEN(512byte) */ + /* CMD16 */ + emmc_make_nontrans_cmd(CMD16_SET_BLOCKLEN, EMMC_BLOCK_LENGTH); + result = emmc_exec_cmd(EMMC_R1_ERROR_MASK, mmc_drv_obj.response); + if (result != EMMC_SUCCESS) { + emmc_write_error_info_func_no(EMMC_FUNCNO_CARD_INIT); + return result; + } + + /* Transfer Data Length */ + SETR_32(SD_SIZE, EMMC_BLOCK_LENGTH); + + /* CMD8 (EXT_CSD) */ + emmc_make_trans_cmd(CMD8_SEND_EXT_CSD, 0x00000000, + (uint32_t *) (&mmc_drv_obj.ext_csd_data[0]), + EMMC_MAX_EXT_CSD_LENGTH, HAL_MEMCARD_READ, + HAL_MEMCARD_NOT_DMA); + result = emmc_exec_cmd(EMMC_R1_ERROR_MASK, mmc_drv_obj.response); + if (result != EMMC_SUCCESS) { + /* + * CMD12 is not send. + * If BUS initialization is failed, user must be execute Bus initialization again. + * Bus initialization is start CMD0(soft reset command). + */ + emmc_write_error_info_func_no(EMMC_FUNCNO_CARD_INIT); + return result; + } + + /* Set boot partition */ + emmc_set_bootpartition(); + + return EMMC_SUCCESS; +} + +static EMMC_ERROR_CODE emmc_high_speed(void) +{ + uint32_t freq; /* High speed mode clock frequency */ + EMMC_ERROR_CODE result; + uint8_t cardType; + + /* state check */ + if (mmc_drv_obj.selected != TRUE) { + emmc_write_error_info(EMMC_FUNCNO_HIGH_SPEED, EMMC_ERR_STATE); + return EMMC_ERR_STATE; + } + + /* max frequency */ + cardType = (uint8_t) mmc_drv_obj.ext_csd_data[EMMC_EXT_CSD_CARD_TYPE]; + if ((cardType & EMMC_EXT_CSD_CARD_TYPE_52MHZ) != 0) + freq = MMC_52MHZ; + else if ((cardType & EMMC_EXT_CSD_CARD_TYPE_26MHZ) != 0) + freq = MMC_26MHZ; + else + freq = MMC_20MHZ; + + /* Hi-Speed-mode selection */ + if ((freq == MMC_52MHZ) || (freq == MMC_26MHZ)) { + /* CMD6 */ + emmc_make_nontrans_cmd(CMD6_SWITCH, EMMC_SWITCH_HS_TIMING); + result = + emmc_exec_cmd(EMMC_R1_ERROR_MASK, mmc_drv_obj.response); + if (result != EMMC_SUCCESS) { + emmc_write_error_info_func_no(EMMC_FUNCNO_HIGH_SPEED); + return result; + } + + mmc_drv_obj.hs_timing = TIMING_HIGH_SPEED; /* High-Speed */ + } + + /* set mmc clock */ + mmc_drv_obj.max_freq = freq; + result = emmc_set_request_mmc_clock(&freq); + if (result != EMMC_SUCCESS) { + emmc_write_error_info_func_no(EMMC_FUNCNO_HIGH_SPEED); + return EMMC_ERR; + } + + /* set read/write timeout */ + mmc_drv_obj.data_timeout = emmc_set_timeout_register_value(freq); + SETR_32(SD_OPTION, + ((GETR_32(SD_OPTION) & ~(SD_OPTION_TIMEOUT_CNT_MASK)) | + mmc_drv_obj.data_timeout)); + + /* CMD13 */ + emmc_make_nontrans_cmd(CMD13_SEND_STATUS, EMMC_RCA << 16); + result = + emmc_exec_cmd(EMMC_R1_ERROR_MASK_WITHOUT_CRC, mmc_drv_obj.response); + if (result != EMMC_SUCCESS) { + emmc_write_error_info_func_no(EMMC_FUNCNO_HIGH_SPEED); + return result; + } + + return EMMC_SUCCESS; +} + +static EMMC_ERROR_CODE emmc_clock_ctrl(uint8_t mode) +{ + uint32_t value; + + /* busy check */ + if ((GETR_32(SD_INFO2) & SD_INFO2_CBSY) != 0) { + emmc_write_error_info(EMMC_FUNCNO_SET_CLOCK, + EMMC_ERR_CARD_BUSY); + return EMMC_ERR; + } + + if (mode == TRUE) { + /* clock ON */ + value = + ((GETR_32(SD_CLK_CTRL) | MMC_SD_CLK_START) & + SD_CLK_WRITE_MASK); + SETR_32(SD_CLK_CTRL, value); /* on */ + mmc_drv_obj.clock_enable = TRUE; + } else { + /* clock OFF */ + value = + ((GETR_32(SD_CLK_CTRL) & MMC_SD_CLK_STOP) & + SD_CLK_WRITE_MASK); + SETR_32(SD_CLK_CTRL, value); /* off */ + mmc_drv_obj.clock_enable = FALSE; + } + + return EMMC_SUCCESS; +} + +static EMMC_ERROR_CODE emmc_bus_width(uint32_t width) +{ + EMMC_ERROR_CODE result = EMMC_ERR; + + /* parameter check */ + if ((width != 8) && (width != 4) && (width != 1)) { + emmc_write_error_info(EMMC_FUNCNO_BUS_WIDTH, EMMC_ERR_PARAM); + return EMMC_ERR_PARAM; + } + + /* state check */ + if (mmc_drv_obj.selected != TRUE) { + emmc_write_error_info(EMMC_FUNCNO_BUS_WIDTH, EMMC_ERR_STATE); + return EMMC_ERR_STATE; + } + + /* 2 = 8bit, 1 = 4bit, 0 =1bit */ + mmc_drv_obj.bus_width = (HAL_MEMCARD_DATA_WIDTH) (width >> 2); + + /* CMD6 */ + emmc_make_nontrans_cmd(CMD6_SWITCH, + (EMMC_SWITCH_BUS_WIDTH_1 | + (mmc_drv_obj.bus_width << 8))); + result = emmc_exec_cmd(EMMC_R1_ERROR_MASK, mmc_drv_obj.response); + if (result != EMMC_SUCCESS) { + /* occurred error */ + mmc_drv_obj.bus_width = HAL_MEMCARD_DATA_WIDTH_1_BIT; + goto EXIT; + } + + switch (mmc_drv_obj.bus_width) { + case HAL_MEMCARD_DATA_WIDTH_1_BIT: + SETR_32(SD_OPTION, + ((GETR_32(SD_OPTION) & ~(BIT15 | BIT13)) | BIT15)); + break; + case HAL_MEMCARD_DATA_WIDTH_4_BIT: + SETR_32(SD_OPTION, (GETR_32(SD_OPTION) & ~(BIT15 | BIT13))); + break; + case HAL_MEMCARD_DATA_WIDTH_8_BIT: + SETR_32(SD_OPTION, + ((GETR_32(SD_OPTION) & ~(BIT15 | BIT13)) | BIT13)); + break; + default: + goto EXIT; + } + + /* CMD13 */ + emmc_make_nontrans_cmd(CMD13_SEND_STATUS, EMMC_RCA << 16); + result = emmc_exec_cmd(EMMC_R1_ERROR_MASK, mmc_drv_obj.response); + if (result != EMMC_SUCCESS) { + goto EXIT; + } + + /* CMD8 (EXT_CSD) */ + emmc_make_trans_cmd(CMD8_SEND_EXT_CSD, 0x00000000, + (uint32_t *) (&mmc_drv_obj.ext_csd_data[0]), + EMMC_MAX_EXT_CSD_LENGTH, HAL_MEMCARD_READ, + HAL_MEMCARD_NOT_DMA); + result = emmc_exec_cmd(EMMC_R1_ERROR_MASK, mmc_drv_obj.response); + if (result != EMMC_SUCCESS) { + goto EXIT; + } + + return EMMC_SUCCESS; + +EXIT: + emmc_write_error_info(EMMC_FUNCNO_BUS_WIDTH, result); + ERROR("BL2: emmc bus_width error end\n"); + return result; +} + +EMMC_ERROR_CODE emmc_select_partition(EMMC_PARTITION_ID id) +{ + EMMC_ERROR_CODE result; + uint32_t arg; + uint32_t partition_config; + + /* state check */ + if (mmc_drv_obj.mount != TRUE) { + emmc_write_error_info(EMMC_FUNCNO_NONE, EMMC_ERR_STATE); + return EMMC_ERR_STATE; + } + + /* id = PARTITION_ACCESS(Bit[2:0]) */ + if ((id & ~PARTITION_ID_MASK) != 0) { + emmc_write_error_info(EMMC_FUNCNO_NONE, EMMC_ERR_PARAM); + return EMMC_ERR_PARAM; + } + + /* EXT_CSD[179] value */ + partition_config = + (uint32_t) mmc_drv_obj.ext_csd_data[EMMC_EXT_CSD_PARTITION_CONFIG]; + if ((partition_config & PARTITION_ID_MASK) == id) { + result = EMMC_SUCCESS; + } else { + + partition_config = + (uint32_t) ((partition_config & ~PARTITION_ID_MASK) | id); + arg = EMMC_SWITCH_PARTITION_CONFIG | (partition_config << 8); + + result = emmc_set_ext_csd(arg); + } + + return result; +} + +static void set_sd_clk(uint32_t clkDiv) +{ + uint32_t dataL; + + dataL = (GETR_32(SD_CLK_CTRL) & (~SD_CLK_CTRL_CLKDIV_MASK)); + + switch (clkDiv) { + case 1: + dataL |= 0x000000FFU; + break; /* 1/1 */ + case 2: + dataL |= 0x00000000U; + break; /* 1/2 */ + case 4: + dataL |= 0x00000001U; + break; /* 1/4 */ + case 8: + dataL |= 0x00000002U; + break; /* 1/8 */ + case 16: + dataL |= 0x00000004U; + break; /* 1/16 */ + case 32: + dataL |= 0x00000008U; + break; /* 1/32 */ + case 64: + dataL |= 0x00000010U; + break; /* 1/64 */ + case 128: + dataL |= 0x00000020U; + break; /* 1/128 */ + case 256: + dataL |= 0x00000040U; + break; /* 1/256 */ + case 512: + dataL |= 0x00000080U; + break; /* 1/512 */ + } + + SETR_32(SD_CLK_CTRL, dataL); + mmc_drv_obj.current_freq = (uint32_t) clkDiv; +} + +static void emmc_get_partition_access(void) +{ + EMMC_ERROR_CODE result; + + SETR_32(SD_OPTION, 0x000060EEU); /* 8 bits width */ + /* CMD8 (EXT_CSD) */ + emmc_make_trans_cmd(CMD8_SEND_EXT_CSD, 0x00000000U, + (uint32_t *) (&mmc_drv_obj.ext_csd_data[0]), + EMMC_MAX_EXT_CSD_LENGTH, + HAL_MEMCARD_READ, HAL_MEMCARD_NOT_DMA); + mmc_drv_obj.get_partition_access_flag = TRUE; + result = + emmc_exec_cmd(EMMC_R1_ERROR_MASK, mmc_drv_obj.response); + mmc_drv_obj.get_partition_access_flag = FALSE; + if (result == EMMC_SUCCESS) { + mmc_drv_obj.partition_access = + (EMMC_PARTITION_ID) (mmc_drv_obj.ext_csd_data[179] + & PARTITION_ID_MASK); + } else if (result == EMMC_ERR_CMD_TIMEOUT) { + mmc_drv_obj.partition_access = PARTITION_ID_BOOT_1; + } else { + emmc_write_error_info(EMMC_FUNCNO_GET_PERTITION_ACCESS, + result); + panic(); + } + SETR_32(SD_OPTION, 0x0000C0EEU); /* Initialize */ +} + +static uint32_t emmc_calc_tran_speed(uint32_t *freq) +{ + const uint32_t unit[8] = { 10000U, 100000U, 1000000U, 10000000U, + 0U, 0U, 0U, 0U }; /* frequency unit (1/10) */ + const uint32_t mult[16] = { 0U, 10U, 12U, 13U, 15U, 20U, 26U, 30U, 35U, + 40U, 45U, 52U, 55U, 60U, 70U, 80U }; + uint32_t tran_speed = EMMC_CSD_TRAN_SPEED(); + uint32_t max_freq; + uint32_t result; + + /* + * tran_speed = 0x32 + * unit[tran_speed&0x7] = uint[0x2] = 1000000 + * mult[(tran_speed&0x78)>>3] = mult[0x30>>3] = mult[6] = 26 + * 1000000 * 26 = 26000000 (26MHz) + */ + + result = 1; + max_freq = + unit[tran_speed & EMMC_TRANSPEED_FREQ_UNIT_MASK] * + mult[(tran_speed & EMMC_TRANSPEED_MULT_MASK) >> + EMMC_TRANSPEED_MULT_SHIFT]; + + if (max_freq == 0) { + result = 0; + } else if (max_freq >= MMC_FREQ_52MHZ) { + *freq = MMC_52MHZ; + } else if (max_freq >= MMC_FREQ_26MHZ) { + *freq = MMC_26MHZ; + } else if (max_freq >= MMC_FREQ_20MHZ) { + *freq = MMC_20MHZ; + } else { + *freq = MMC_400KHZ; + } + + return result; +} + +static uint32_t emmc_set_timeout_register_value(uint32_t freq) +{ + uint32_t timeout_cnt; /* SD_OPTION - Timeout Counter */ + + switch (freq) { + case 1U: + timeout_cnt = 0xE0U; + break; /* SDCLK * 2^27 */ + case 2U: + timeout_cnt = 0xE0U; + break; /* SDCLK * 2^27 */ + case 4U: + timeout_cnt = 0xD0U; + break; /* SDCLK * 2^26 */ + case 8U: + timeout_cnt = 0xC0U; + break; /* SDCLK * 2^25 */ + case 16U: + timeout_cnt = 0xB0U; + break; /* SDCLK * 2^24 */ + case 32U: + timeout_cnt = 0xA0U; + break; /* SDCLK * 2^23 */ + case 64U: + timeout_cnt = 0x90U; + break; /* SDCLK * 2^22 */ + case 128U: + timeout_cnt = 0x80U; + break; /* SDCLK * 2^21 */ + case 256U: + timeout_cnt = 0x70U; + break; /* SDCLK * 2^20 */ + case 512U: + timeout_cnt = 0x70U; + break; /* SDCLK * 2^20 */ + default: + timeout_cnt = 0xE0U; + break; /* SDCLK * 2^27 */ + } + + return timeout_cnt; +} + +EMMC_ERROR_CODE emmc_set_ext_csd(uint32_t arg) +{ + EMMC_ERROR_CODE result; + + /* CMD6 */ + emmc_make_nontrans_cmd(CMD6_SWITCH, arg); + result = emmc_exec_cmd(EMMC_R1_ERROR_MASK, mmc_drv_obj.response); + if (result != EMMC_SUCCESS) { + return result; + } + + /* CMD13 */ + emmc_make_nontrans_cmd(CMD13_SEND_STATUS, EMMC_RCA << 16); + result = emmc_exec_cmd(EMMC_R1_ERROR_MASK, mmc_drv_obj.response); + if (result != EMMC_SUCCESS) { + return result; + } + + /* CMD8 (EXT_CSD) */ + emmc_make_trans_cmd(CMD8_SEND_EXT_CSD, 0x00000000, + (uint32_t *) (&mmc_drv_obj.ext_csd_data[0]), + EMMC_MAX_EXT_CSD_LENGTH, HAL_MEMCARD_READ, + HAL_MEMCARD_NOT_DMA); + result = emmc_exec_cmd(EMMC_R1_ERROR_MASK, mmc_drv_obj.response); + if (result != EMMC_SUCCESS) { + return result; + } + return EMMC_SUCCESS; +} + +EMMC_ERROR_CODE emmc_set_request_mmc_clock(uint32_t *freq) +{ + /* parameter check */ + if (freq == NULL) { + emmc_write_error_info(EMMC_FUNCNO_SET_CLOCK, EMMC_ERR_PARAM); + return EMMC_ERR_PARAM; + } + + /* state check */ + if ((mmc_drv_obj.initialize != TRUE) + || (mmc_drv_obj.card_power_enable != TRUE)) { + emmc_write_error_info(EMMC_FUNCNO_SET_CLOCK, EMMC_ERR_STATE); + return EMMC_ERR_STATE; + } + + /* clock is already running in the desired frequency. */ + if ((mmc_drv_obj.clock_enable == TRUE) + && (mmc_drv_obj.current_freq == *freq)) { + return EMMC_SUCCESS; + } + + /* busy check */ + if ((GETR_32(SD_INFO2) & SD_INFO2_CBSY) != 0) { + emmc_write_error_info(EMMC_FUNCNO_SET_CLOCK, + EMMC_ERR_CARD_BUSY); + return EMMC_ERR; + } + + set_sd_clk(*freq); + mmc_drv_obj.clock_enable = FALSE; + + return emmc_clock_ctrl(TRUE); /* clock on */ +} + +EMMC_ERROR_CODE emmc_mount(void) +{ + EMMC_ERROR_CODE result; + + /* state check */ + if ((mmc_drv_obj.initialize != TRUE) + || (mmc_drv_obj.card_power_enable != TRUE) + || ((GETR_32(SD_INFO2) & SD_INFO2_CBSY) != 0) + ) { + emmc_write_error_info(EMMC_FUNCNO_MOUNT, EMMC_ERR_STATE); + return EMMC_ERR_STATE; + } + + /* initialize card (IDLE state --> Transfer state) */ + result = emmc_card_init(); + if (result != EMMC_SUCCESS) { + emmc_write_error_info_func_no(EMMC_FUNCNO_CARD_INIT); + if (emmc_clock_ctrl(FALSE) != EMMC_SUCCESS) { + /* nothing to do. */ + } + return result; + } + + /* Switching high speed mode */ + result = emmc_high_speed(); + if (result != EMMC_SUCCESS) { + emmc_write_error_info_func_no(EMMC_FUNCNO_HIGH_SPEED); + if (emmc_clock_ctrl(FALSE) != EMMC_SUCCESS) { + /* nothing to do. */ + } + return result; + } + + /* Changing the data bus width */ + result = emmc_bus_width(8); + if (result != EMMC_SUCCESS) { + emmc_write_error_info_func_no(EMMC_FUNCNO_BUS_WIDTH); + if (emmc_clock_ctrl(FALSE) != EMMC_SUCCESS) { + /* nothing to do. */ + } + return result; + } + + /* mount complete */ + mmc_drv_obj.mount = TRUE; + + return EMMC_SUCCESS; +} diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/emmc/emmc_read.c b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/emmc/emmc_read.c new file mode 100644 index 00000000..bf5045e8 --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/emmc/emmc_read.c @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2015-2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include "emmc_config.h" +#include "emmc_def.h" +#include "emmc_hal.h" +#include "emmc_registers.h" +#include "emmc_std.h" + +#define MIN_EMMC(a, b) (((a) < (b)) ? (a) : (b)) +#define EMMC_RW_SECTOR_COUNT_MAX 0x0000ffffU + +static EMMC_ERROR_CODE emmc_multiple_block_read(uint32_t *buff_address_virtual, + uint32_t sector_number, uint32_t count, + HAL_MEMCARD_DATA_TRANSFER_MODE transfer_mode) +{ + EMMC_ERROR_CODE result; + + /* parameter check */ + if ((count > EMMC_RW_SECTOR_COUNT_MAX) + || (count == 0) + || ((transfer_mode != HAL_MEMCARD_DMA) + && (transfer_mode != HAL_MEMCARD_NOT_DMA)) + ) { + emmc_write_error_info(EMMC_FUNCNO_READ_SECTOR, EMMC_ERR_PARAM); + return EMMC_ERR_PARAM; + } + + /* CMD23 */ + emmc_make_nontrans_cmd(CMD23_SET_BLOCK_COUNT, count); + result = emmc_exec_cmd(EMMC_R1_ERROR_MASK, mmc_drv_obj.response); + if (result != EMMC_SUCCESS) { + return result; + } + SETR_32(SD_SECCNT, count); + SETR_32(SD_STOP, 0x00000100); + /* SD_BUF Read/Write DMA Transfer enable */ + SETR_32(CC_EXT_MODE, (CC_EXT_MODE_CLEAR | CC_EXT_MODE_DMASDRW_ENABLE)); + + /* CMD18 */ + emmc_make_trans_cmd(CMD18_READ_MULTIPLE_BLOCK, sector_number, + buff_address_virtual, + count << EMMC_SECTOR_SIZE_SHIFT, HAL_MEMCARD_READ, + transfer_mode); + result = emmc_exec_cmd(EMMC_R1_ERROR_MASK, mmc_drv_obj.response); + if (result != EMMC_SUCCESS) { + return result; /* CMD18 error code */ + } + + /* CMD13 */ + emmc_make_nontrans_cmd(CMD13_SEND_STATUS, EMMC_RCA << 16); + result = emmc_exec_cmd(EMMC_R1_ERROR_MASK, mmc_drv_obj.response); + if (result != EMMC_SUCCESS) { + return result; + } + + if (transfer_mode == HAL_MEMCARD_NOT_DMA) { + flush_dcache_range((uint64_t) buff_address_virtual, + ((size_t) count << EMMC_SECTOR_SIZE_SHIFT)); + } + + /* ready status check */ + if ((mmc_drv_obj.r1_card_status & EMMC_R1_READY) == 0) { + emmc_write_error_info(EMMC_FUNCNO_READ_SECTOR, + EMMC_ERR_CARD_BUSY); + return EMMC_ERR_CARD_BUSY; + } + + /* state check */ + if (mmc_drv_obj.current_state != EMMC_R1_STATE_TRAN) { + emmc_write_error_info(EMMC_FUNCNO_READ_SECTOR, + EMMC_ERR_CARD_STATE); + return EMMC_ERR_CARD_STATE; + } + + return EMMC_SUCCESS; +} + +EMMC_ERROR_CODE emmc_read_sector(uint32_t *buff_address_virtual, + uint32_t sector_number, + uint32_t count, uint32_t feature_flags) +{ + uint32_t trans_count; + uint32_t remain; + EMMC_ERROR_CODE result; + HAL_MEMCARD_DATA_TRANSFER_MODE transfer_mode; + + /* parameter check */ + if (count == 0) { + emmc_write_error_info(EMMC_FUNCNO_READ_SECTOR, EMMC_ERR_PARAM); + return EMMC_ERR_PARAM; + } + + /* state check */ + if (mmc_drv_obj.mount != TRUE) { + emmc_write_error_info(EMMC_FUNCNO_READ_SECTOR, EMMC_ERR_STATE); + return EMMC_ERR_STATE; + } + + /* DMA? */ + if ((feature_flags & LOADIMAGE_FLAGS_DMA_ENABLE) != 0) { + transfer_mode = HAL_MEMCARD_DMA; + } else { + transfer_mode = HAL_MEMCARD_NOT_DMA; + } + + remain = count; + while (remain != 0) { + trans_count = MIN_EMMC(remain, EMMC_RW_SECTOR_COUNT_MAX); + result = + emmc_multiple_block_read(buff_address_virtual, + sector_number, trans_count, + transfer_mode); + if (result != EMMC_SUCCESS) { + return result; + } + + buff_address_virtual += (EMMC_BLOCK_LENGTH_DW * trans_count); + sector_number += trans_count; + remain -= trans_count; + } + + return EMMC_SUCCESS; +} diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/emmc/emmc_registers.h b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/emmc/emmc_registers.h new file mode 100644 index 00000000..8b586cdd --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/emmc/emmc_registers.h @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2015-2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef EMMC_REGISTERS_H +#define EMMC_REGISTERS_H + +/* MMC channel select */ +#define MMC_CH0 (0U) /* SDHI2/MMC0 */ +#define MMC_CH1 (1U) /* SDHI3/MMC1 */ + +#define USE_MMC_CH (MMC_CH0) + +#define BIT0 (0x00000001U) +#define BIT1 (0x00000002U) +#define BIT2 (0x00000004U) +#define BIT3 (0x00000008U) +#define BIT4 (0x00000010U) +#define BIT5 (0x00000020U) +#define BIT6 (0x00000040U) +#define BIT7 (0x00000080U) +#define BIT8 (0x00000100U) +#define BIT9 (0x00000200U) +#define BIT10 (0x00000400U) +#define BIT11 (0x00000800U) +#define BIT12 (0x00001000U) +#define BIT13 (0x00002000U) +#define BIT14 (0x00004000U) +#define BIT15 (0x00008000U) +#define BIT16 (0x00010000U) +#define BIT17 (0x00020000U) +#define BIT18 (0x00040000U) +#define BIT19 (0x00080000U) +#define BIT20 (0x00100000U) +#define BIT21 (0x00200000U) +#define BIT22 (0x00400000U) +#define BIT23 (0x00800000U) +#define BIT24 (0x01000000U) +#define BIT25 (0x02000000U) +#define BIT26 (0x04000000U) +#define BIT27 (0x08000000U) +#define BIT28 (0x10000000U) +#define BIT29 (0x20000000U) +#define BIT30 (0x40000000U) +#define BIT31 (0x80000000U) + + +/* eMMC registers */ +#define MMC0_SD_BASE (0x11C00000U) +#define MMC1_SD_BASE (0x11C10000U) + +#if USE_MMC_CH == MMC_CH0 +#define MMC_SD_BASE (MMC0_SD_BASE) +#else /* USE_MMC_CH == MMC_CH0 */ +#define MMC_SD_BASE (MMC1_SD_BASE) +#endif /* USE_MMC_CH == MMC_CH0 */ + +#define SD_CMD (MMC_SD_BASE + 0x0000U) +#define SD_PORTSEL (MMC_SD_BASE + 0x0008U) +#define SD_ARG (MMC_SD_BASE + 0x0010U) +#define SD_ARG1 (MMC_SD_BASE + 0x0018U) +#define SD_STOP (MMC_SD_BASE + 0x0020U) +#define SD_SECCNT (MMC_SD_BASE + 0x0028U) +#define SD_RSP10 (MMC_SD_BASE + 0x0030U) +#define SD_RSP1 (MMC_SD_BASE + 0x0038U) +#define SD_RSP32 (MMC_SD_BASE + 0x0040U) +#define SD_RSP3 (MMC_SD_BASE + 0x0048U) +#define SD_RSP54 (MMC_SD_BASE + 0x0050U) +#define SD_RSP5 (MMC_SD_BASE + 0x0058U) +#define SD_RSP76 (MMC_SD_BASE + 0x0060U) +#define SD_RSP7 (MMC_SD_BASE + 0x0068U) +#define SD_INFO1 (MMC_SD_BASE + 0x0070U) +#define SD_INFO2 (MMC_SD_BASE + 0x0078U) +#define SD_INFO1_MASK (MMC_SD_BASE + 0x0080U) +#define SD_INFO2_MASK (MMC_SD_BASE + 0x0088U) +#define SD_CLK_CTRL (MMC_SD_BASE + 0x0090U) +#define SD_SIZE (MMC_SD_BASE + 0x0098U) +#define SD_OPTION (MMC_SD_BASE + 0x00A0U) +#define SD_ERR_STS1 (MMC_SD_BASE + 0x00B0U) +#define SD_ERR_STS2 (MMC_SD_BASE + 0x00B8U) +#define SD_BUF0 (MMC_SD_BASE + 0x00C0U) +#define SDIO_MODE (MMC_SD_BASE + 0x00D0U) +#define SDIO_INFO1 (MMC_SD_BASE + 0x00D8U) +#define SDIO_INFO1_MASK (MMC_SD_BASE + 0x00E0U) +#define CC_EXT_MODE (MMC_SD_BASE + 0x0360U) +#define SOFT_RST (MMC_SD_BASE + 0x0380U) +#define VERSION (MMC_SD_BASE + 0x0388U) +#define HOST_MODE (MMC_SD_BASE + 0x0390U) +#define DM_CM_DTRAN_MODE (MMC_SD_BASE + 0x0820U) +#define DM_CM_DTRAN_CTRL (MMC_SD_BASE + 0x0828U) +#define DM_CM_RST (MMC_SD_BASE + 0x0830U) +#define DM_CM_INFO1 (MMC_SD_BASE + 0x0840U) +#define DM_CM_INFO1_MASK (MMC_SD_BASE + 0x0848U) +#define DM_CM_INFO2 (MMC_SD_BASE + 0x0850U) +#define DM_CM_INFO2_MASK (MMC_SD_BASE + 0x0858U) +#define DM_DTRAN_ADDR (MMC_SD_BASE + 0x0880U) + +/* SD_INFO1 Registers */ +#define SD_INFO1_HPIRES 0x00010000UL /* Response Reception Completion */ +#define SD_INFO1_INFO10 0x00000400UL /* Indicates the SDDAT3 state */ +#define SD_INFO1_INFO9 0x00000200UL /* SDDAT3 Card Insertion */ +#define SD_INFO1_INFO8 0x00000100UL /* SDDAT3 Card Removal */ +#define SD_INFO1_INFO7 0x00000080UL /* Write Protect */ +#define SD_INFO1_INFO5 0x00000020UL /* Indicates the ISDCD state */ +#define SD_INFO1_INFO4 0x00000010UL /* ISDCD Card Insertion */ +#define SD_INFO1_INFO3 0x00000008UL /* ISDCD Card Removal */ +#define SD_INFO1_INFO2 0x00000004UL /* Access end */ +#define SD_INFO1_INFO0 0x00000001UL /* Response end */ + +/* SD_INFO2 Registers */ +#define SD_INFO2_ILA 0x00008000UL /* Illegal Access Error */ +#define SD_INFO2_CBSY 0x00004000UL /* Command Type Register Busy */ +#define SD_INFO2_SCLKDIVEN 0x00002000UL +#define SD_INFO2_BWE 0x00000200UL /* SD_BUF Write Enable */ +#define SD_INFO2_BRE 0x00000100UL /* SD_BUF Read Enable */ +#define SD_INFO2_DAT0 0x00000080UL /* SDDAT0 */ +#define SD_INFO2_ERR6 0x00000040UL /* Response Timeout */ +#define SD_INFO2_ERR5 0x00000020UL /* SD_BUF Illegal Read Access */ +#define SD_INFO2_ERR4 0x00000010UL /* SD_BUF Illegal Write Access */ +#define SD_INFO2_ERR3 0x00000008UL /* Data Timeout */ +#define SD_INFO2_ERR2 0x00000004UL /* END Error */ +#define SD_INFO2_ERR1 0x00000002UL /* CRC Error */ +#define SD_INFO2_ERR0 0x00000001UL /* CMD Error */ +#define SD_INFO2_ALL_ERR 0x0000807FUL +#define SD_INFO2_CLEAR 0x00000800UL /* BIT11 write value should always be 1. HWM_0003 */ + +/* SOFT_RST */ +#define SOFT_RST_SDRST 0x00000001UL + +/* SD_CLK_CTRL */ +#define SD_CLK_CTRL_SDCLKOFFEN 0x00000200UL +#define SD_CLK_CTRL_SCLKEN 0x00000100UL +#define SD_CLK_CTRL_CLKDIV_MASK 0x000000FFUL +#define SD_CLOCK_ENABLE 0x00000100UL +#define SD_CLOCK_DISABLE 0x00000000UL +#define SD_CLK_WRITE_MASK 0x000003FFUL +#define SD_CLK_CLKDIV_CLEAR_MASK 0xFFFFFF0FUL + +/* SD_OPTION */ +#define SD_OPTION_TIMEOUT_CNT_MASK 0x000000F0UL + +/* + * MMC Clock Frequency + * (533MHz/4) * 1/x = output clock + */ +#define MMC_CLK_OFF 0UL /* Clock output is disabled */ +#define MMC_400KHZ 512UL /* (533MHz/4) * 1/512 = 260 KHz */ +#define MMC_20MHZ 8UL /* (533MHz/4) * 1/8 = 16.7 MHz Normal speed mode */ +#define MMC_26MHZ 8UL /* (533MHz/4) * 1/8 = 16.7 MHz High speed mode 26Mhz */ +#define MMC_52MHZ 4UL /* (533MHz/4) * 1/4 = 33.3 MHz High speed mode 52Mhz */ +#define MMC_100MHZ 2UL /* (533MHz/4) * 1/2 = 66.6 MHz */ +#define MMC_200MHZ 1UL /* (533MHz/4) * 1/1 = 133.3 MHz */ + +#define MMC_FREQ_52MHZ 52000000UL +#define MMC_FREQ_26MHZ 26000000UL +#define MMC_FREQ_20MHZ 20000000UL + +/* MMC Clock DIV */ +#define MMC_SD_CLK_START 0x00000100UL /* CLOCK On */ +#define MMC_SD_CLK_STOP (~0x00000100UL) /* CLOCK stop */ +#define MMC_SD_CLK_DIV1 0x000000FFUL /* 1/1 */ +#define MMC_SD_CLK_DIV2 0x00000000UL /* 1/2 */ +#define MMC_SD_CLK_DIV4 0x00000001UL /* 1/4 */ +#define MMC_SD_CLK_DIV8 0x00000002UL /* 1/8 */ +#define MMC_SD_CLK_DIV16 0x00000004UL /* 1/16 */ +#define MMC_SD_CLK_DIV32 0x00000008UL /* 1/32 */ +#define MMC_SD_CLK_DIV64 0x00000010UL /* 1/64 */ +#define MMC_SD_CLK_DIV128 0x00000020UL /* 1/128 */ +#define MMC_SD_CLK_DIV256 0x00000040UL /* 1/256 */ +#define MMC_SD_CLK_DIV512 0x00000080UL /* 1/512 */ + +/* DM_CM_DTRAN_MODE */ +#define DM_CM_DTRAN_MODE_CH0 0x00000000UL /* CH0(downstream) */ +#define DM_CM_DTRAN_MODE_CH1 0x00010000UL /* CH1(upstream) */ +#define DM_CM_DTRAN_MODE_BIT_WIDTH 0x00000030UL + +/* CC_EXT_MODE */ +#define CC_EXT_MODE_DMASDRW_ENABLE 0x00000002UL /* SD_BUF Read/Write DMA Transfer */ +#define CC_EXT_MODE_CLEAR 0x00001010UL /* BIT 12 & 4 always 1. */ + +/* DM_CM_INFO_MASK */ +#define DM_CM_INFO_MASK_CLEAR 0xFFFCFFFEUL +#define DM_CM_INFO_CH0_ENABLE 0x00010001UL +#define DM_CM_INFO_CH1_ENABLE 0x00020001UL + +/* DM_DTRAN_ADDR */ +#define DM_DTRAN_ADDR_WRITE_MASK 0xFFFFFFF8UL + +/* DM_CM_DTRAN_CTRL */ +#define DM_CM_DTRAN_CTRL_START 0x00000001UL + +#endif /* EMMC_REGISTERS_H */ diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/emmc/emmc_std.h b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/emmc/emmc_std.h new file mode 100644 index 00000000..47d021c9 --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/emmc/emmc_std.h @@ -0,0 +1,475 @@ +/* + * Copyright (c) 2015-2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef EMMC_STD_H +#define EMMC_STD_H + +#include "emmc_hal.h" + +#ifndef FALSE +#define FALSE 0U +#endif +#ifndef TRUE +#define TRUE 1U +#endif + +/* 64bit registers */ +#define SETR_64(r, v) (*(volatile uint64_t *)(r) = (v)) +#define GETR_64(r) (*(volatile uint64_t *)(r)) + +/* 32bit registers */ +#define SETR_32(r, v) (*(volatile uint32_t *)(r) = (v)) +#define GETR_32(r) (*(volatile uint32_t *)(r)) + +/* 16bit registers */ +#define SETR_16(r, v) (*(volatile uint16_t *)(r) = (v)) +#define GETR_16(r) (*(volatile uint16_t *)(r)) + +/* 8bit registers */ +#define SETR_8(r, v) (*(volatile uint8_t *)(r) = (v)) +#define GETR_8(r) (*(volatile uint8_t *)(r)) + +/* CSD register Macros */ +#define EMMC_GET_CID(x, y) (emmc_bit_field(mmc_drv_obj.cid_data, (x), (y))) + +#define EMMC_CID_MID() (EMMC_GET_CID(127, 120)) +#define EMMC_CID_CBX() (EMMC_GET_CID(113, 112)) +#define EMMC_CID_OID() (EMMC_GET_CID(111, 104)) +#define EMMC_CID_PNM1() (EMMC_GET_CID(103, 88)) +#define EMMC_CID_PNM2() (EMMC_GET_CID(87, 56)) +#define EMMC_CID_PRV() (EMMC_GET_CID(55, 48)) +#define EMMC_CID_PSN() (EMMC_GET_CID(47, 16)) +#define EMMC_CID_MDT() (EMMC_GET_CID(15, 8)) +#define EMMC_CID_CRC() (EMMC_GET_CID(7, 1)) + +/* CSD register Macros */ +#define EMMC_GET_CSD(x, y) (emmc_bit_field(mmc_drv_obj.csd_data, (x), (y))) + +#define EMMC_CSD_CSD_STRUCTURE() (EMMC_GET_CSD(127, 126)) +#define EMMC_CSD_SPEC_VARS() (EMMC_GET_CSD(125, 122)) +#define EMMC_CSD_TAAC() (EMMC_GET_CSD(119, 112)) +#define EMMC_CSD_NSAC() (EMMC_GET_CSD(111, 104)) +#define EMMC_CSD_TRAN_SPEED() (EMMC_GET_CSD(103, 96)) +#define EMMC_CSD_CCC() (EMMC_GET_CSD(95, 84)) +#define EMMC_CSD_READ_BL_LEN() (EMMC_GET_CSD(83, 80)) +#define EMMC_CSD_READ_BL_PARTIAL() (EMMC_GET_CSD(79, 79)) +#define EMMC_CSD_WRITE_BLK_MISALIGN() (EMMC_GET_CSD(78, 78)) +#define EMMC_CSD_READ_BLK_MISALIGN() (EMMC_GET_CSD(77, 77)) +#define EMMC_CSD_DSR_IMP() (EMMC_GET_CSD(76, 76)) +#define EMMC_CSD_C_SIZE() (EMMC_GET_CSD(73, 62)) +#define EMMC_CSD_VDD_R_CURR_MIN() (EMMC_GET_CSD(61, 59)) +#define EMMC_CSD_VDD_R_CURR_MAX() (EMMC_GET_CSD(58, 56)) +#define EMMC_CSD_VDD_W_CURR_MIN() (EMMC_GET_CSD(55, 53)) +#define EMMC_CSD_VDD_W_CURR_MAX() (EMMC_GET_CSD(52, 50)) +#define EMMC_CSD_C_SIZE_MULT() (EMMC_GET_CSD(49, 47)) +#define EMMC_CSD_ERASE_GRP_SIZE() (EMMC_GET_CSD(46, 42)) +#define EMMC_CSD_ERASE_GRP_MULT() (EMMC_GET_CSD(41, 37)) +#define EMMC_CSD_WP_GRP_SIZE() (EMMC_GET_CSD(36, 32)) +#define EMMC_CSD_WP_GRP_ENABLE() (EMMC_GET_CSD(31, 31)) +#define EMMC_CSD_DEFALT_ECC() (EMMC_GET_CSD(30, 29)) +#define EMMC_CSD_R2W_FACTOR() (EMMC_GET_CSD(28, 26)) +#define EMMC_CSD_WRITE_BL_LEN() (EMMC_GET_CSD(25, 22)) +#define EMMC_CSD_WRITE_BL_PARTIAL() (EMMC_GET_CSD(21, 21)) +#define EMMC_CSD_CONTENT_PROT_APP() (EMMC_GET_CSD(16, 16)) +#define EMMC_CSD_FILE_FORMAT_GRP() (EMMC_GET_CSD(15, 15)) +#define EMMC_CSD_COPY() (EMMC_GET_CSD(14, 14)) +#define EMMC_CSD_PERM_WRITE_PROTECT() (EMMC_GET_CSD(13, 13)) +#define EMMC_CSD_TMP_WRITE_PROTECT() (EMMC_GET_CSD(12, 12)) +#define EMMC_CSD_FILE_FORMAT() (EMMC_GET_CSD(11, 10)) +#define EMMC_CSD_ECC() (EMMC_GET_CSD(9, 8)) +#define EMMC_CSD_CRC() (EMMC_GET_CSD(7, 1)) + +/* sector access */ +#define EMMC_4B_BOUNDARY_CHECK_MASK 0x00000003 +#define EMMC_SECTOR_SIZE_SHIFT 9U /* 512 = 2^9 */ +#define EMMC_SECTOR_SIZE 512 +#define EMMC_BLOCK_LENGTH 512 +#define EMMC_BLOCK_LENGTH_DW 128 +#define EMMC_BUF_SIZE_SHIFT 3U /* 8byte = 2^3 */ + +/* eMMC specification clock */ +#define EMMC_CLOCK_SPEC_400K 400000UL /* initialize clock 400KHz */ +#define EMMC_CLOCK_SPEC_20M 20000000UL /* normal speed 20MHz */ +#define EMMC_CLOCK_SPEC_26M 26000000UL /* high speed 26MHz */ +#define EMMC_CLOCK_SPEC_52M 52000000UL /* high speed 52MHz */ +#define EMMC_CLOCK_SPEC_100M 100000000UL /* high speed 100MHz */ + +/* EMMC driver error code. (extended HAL_MEMCARD_RETURN) */ +typedef enum { + EMMC_ERR = 0, /* unknown error */ + EMMC_SUCCESS, /* OK */ + EMMC_ERR_FROM_DMAC, /* DMAC allocation error */ + EMMC_ERR_FROM_DMAC_TRANSFER, /* DMAC transfer error */ + EMMC_ERR_CARD_STATUS_BIT, /* card status error */ + EMMC_ERR_CMD_TIMEOUT, /* command timeout error */ + EMMC_ERR_DATA_TIMEOUT, /* data timeout error */ + EMMC_ERR_CMD_CRC, /* command CRC error */ + EMMC_ERR_DATA_CRC, /* data CRC error */ + EMMC_ERR_PARAM, /* parameter error */ + EMMC_ERR_RESPONSE, /* response error */ + EMMC_ERR_RESPONSE_BUSY, /* response busy error */ + EMMC_ERR_TRANSFER, /* data transfer error */ + EMMC_ERR_READ_SECTOR, /* read sector error */ + EMMC_ERR_WRITE_SECTOR, /* write sector error */ + EMMC_ERR_STATE, /* state error */ + EMMC_ERR_TIMEOUT, /* timeout error */ + EMMC_ERR_ILLEGAL_CARD, /* illegal card */ + EMMC_ERR_CARD_BUSY, /* Busy state */ + EMMC_ERR_CARD_STATE, /* card state error */ + EMMC_ERR_SET_TRACE, /* trace information error */ + EMMC_ERR_FROM_TIMER, /* Timer error */ + EMMC_ERR_FORCE_TERMINATE, /* Force terminate */ + EMMC_ERR_CARD_POWER, /* card power fail */ + EMMC_ERR_ERASE_SECTOR, /* erase sector error */ + EMMC_ERR_INFO2 /* exec cmd error info2 */ +} EMMC_ERROR_CODE; + +/* Function number */ +#define EMMC_FUNCNO_NONE 0U +#define EMMC_FUNCNO_DRIVER_INIT 1U +#define EMMC_FUNCNO_CARD_POWER_ON 2U +#define EMMC_FUNCNO_MOUNT 3U +#define EMMC_FUNCNO_CARD_INIT 4U +#define EMMC_FUNCNO_HIGH_SPEED 5U +#define EMMC_FUNCNO_BUS_WIDTH 6U +#define EMMC_FUNCNO_MULTI_BOOT_SELECT_PARTITION 7U +#define EMMC_FUNCNO_MULTI_BOOT_READ_SECTOR 8U +#define EMMC_FUNCNO_TRANS_DATA_READ_SECTOR 9U +#define EMMC_FUNCNO_UBOOT_IMAGE_SELECT_PARTITION 10U +#define EMMC_FUNCNO_UBOOT_IMAGE_READ_SECTOR 11U +#define EMMC_FUNCNO_SET_CLOCK 12U +#define EMMC_FUNCNO_EXEC_CMD 13U +#define EMMC_FUNCNO_READ_SECTOR 14U +#define EMMC_FUNCNO_WRITE_SECTOR 15U +#define EMMC_FUNCNO_ERASE_SECTOR 16U +#define EMMC_FUNCNO_GET_PERTITION_ACCESS 17U +/* + * Response + * R1 + * Type 'E' bit and bit14(must be 0). ignore bit22 + */ +#define EMMC_R1_ERROR_MASK 0xFDBFE080U +/* Ignore bit23 (Not check CRC error) */ +#define EMMC_R1_ERROR_MASK_WITHOUT_CRC (0xFD3FE080U) +#define EMMC_R1_STATE_MASK 0x00001E00U /* [12:9] */ +#define EMMC_R1_READY 0x00000100U /* bit8 */ +#define EMMC_R1_STATE_SHIFT 9 + +/* R4 */ +#define EMMC_R4_RCA_MASK 0xFFFF0000UL +#define EMMC_R4_STATUS 0x00008000UL + +/* CSD */ +#define EMMC_TRANSPEED_FREQ_UNIT_MASK 0x07 /* bit[2:0] */ +#define EMMC_TRANSPEED_FREQ_UNIT_SHIFT 0 +#define EMMC_TRANSPEED_MULT_MASK 0x78 /* bit[6:3] */ +#define EMMC_TRANSPEED_MULT_SHIFT 3 + +/* OCR */ +#define EMMC_HOST_OCR_VALUE 0x40FF8080 +#define EMMC_OCR_STATUS_BIT 0x80000000L /* Card power up status bit */ +#define EMMC_OCR_ACCESS_MODE_MASK 0x60000000L /* bit[30:29] */ +#define EMMC_OCR_ACCESS_MODE_SECT 0x40000000L +#define EMMC_OCR_ACCESS_MODE_BYTE 0x00000000L + +/* EXT_CSD */ +#define EMMC_EXT_CSD_S_CMD_SET 504 +#define EMMC_EXT_CSD_INI_TIMEOUT_AP 241 +#define EMMC_EXT_CSD_PWR_CL_DDR_52_360 239 +#define EMMC_EXT_CSD_PWR_CL_DDR_52_195 238 +#define EMMC_EXT_CSD_MIN_PERF_DDR_W_8_52 235 +#define EMMC_EXT_CSD_MIN_PERF_DDR_R_8_52 234 +#define EMMC_EXT_CSD_TRIM_MULT 232 +#define EMMC_EXT_CSD_SEC_FEATURE_SUPPORT 231 +#define EMMC_EXT_CSD_SEC_ERASE_MULT 229 +#define EMMC_EXT_CSD_BOOT_INFO 228 +#define EMMC_EXT_CSD_BOOT_SIZE_MULTI 226 +#define EMMC_EXT_CSD_ACC_SIZE 225 +#define EMMC_EXT_CSD_HC_ERASE_GRP_SIZE 224 +#define EMMC_EXT_CSD_ERASE_TIMEOUT_MULT 223 +#define EMMC_EXT_CSD_PEL_WR_SEC_C 222 +#define EMMC_EXT_CSD_HC_WP_GRP_SIZE 221 +#define EMMC_EXT_CSD_S_C_VCC 220 +#define EMMC_EXT_CSD_S_C_VCCQ 219 +#define EMMC_EXT_CSD_S_A_TIMEOUT 217 +#define EMMC_EXT_CSD_SEC_COUNT 215 +#define EMMC_EXT_CSD_MIN_PERF_W_8_52 210 +#define EMMC_EXT_CSD_MIN_PERF_R_8_52 209 +#define EMMC_EXT_CSD_MIN_PERF_W_8_26_4_52 208 +#define EMMC_EXT_CSD_MIN_PERF_R_8_26_4_52 207 +#define EMMC_EXT_CSD_MIN_PERF_W_4_26 206 +#define EMMC_EXT_CSD_MIN_PERF_R_4_26 205 +#define EMMC_EXT_CSD_PWR_CL_26_360 203 +#define EMMC_EXT_CSD_PWR_CL_52_360 202 +#define EMMC_EXT_CSD_PWR_CL_26_195 201 +#define EMMC_EXT_CSD_PWR_CL_52_195 200 +#define EMMC_EXT_CSD_CARD_TYPE 196 +#define EMMC_EXT_CSD_CSD_STRUCTURE 194 +#define EMMC_EXT_CSD_EXT_CSD_REV 192 +#define EMMC_EXT_CSD_CMD_SET 191 +#define EMMC_EXT_CSD_CMD_SET_REV 189 +#define EMMC_EXT_CSD_POWER_CLASS 187 +#define EMMC_EXT_CSD_HS_TIMING 185 +#define EMMC_EXT_CSD_BUS_WIDTH 183 +#define EMMC_EXT_CSD_ERASED_MEM_CONT 181 +#define EMMC_EXT_CSD_PARTITION_CONFIG 179 +#define EMMC_EXT_CSD_BOOT_CONFIG_PROT 178 +#define EMMC_EXT_CSD_BOOT_BUS_WIDTH 177 +#define EMMC_EXT_CSD_ERASE_GROUP_DEF 175 +#define EMMC_EXT_CSD_BOOT_WP 173 +#define EMMC_EXT_CSD_USER_WP 171 +#define EMMC_EXT_CSD_FW_CONFIG 169 +#define EMMC_EXT_CSD_RPMB_SIZE_MULT 168 +#define EMMC_EXT_CSD_RST_n_FUNCTION 162 +#define EMMC_EXT_CSD_PARTITIONING_SUPPORT 160 +#define EMMC_EXT_CSD_MAX_ENH_SIZE_MULT 159 +#define EMMC_EXT_CSD_PARTITIONS_ATTRIBUTE 156 +#define EMMC_EXT_CSD_PARTITION_SETTING_COMPLETED 155 +#define EMMC_EXT_CSD_GP_SIZE_MULT 154 +#define EMMC_EXT_CSD_ENH_SIZE_MULT 142 +#define EMMC_EXT_CSD_ENH_START_ADDR 139 +#define EMMC_EXT_CSD_SEC_BAD_BLK_MGMNT 134 + +#define EMMC_EXT_CSD_CARD_TYPE_26MHZ 0x01 +#define EMMC_EXT_CSD_CARD_TYPE_52MHZ 0x02 +#define EMMC_EXT_CSD_CARD_TYPE_DDR_52MHZ_12V 0x04 +#define EMMC_EXT_CSD_CARD_TYPE_DDR_52MHZ_18V 0x08 +#define EMMC_EXT_CSD_CARD_TYPE_52MHZ_MASK 0x0e + +/* SWITCH (CMD6) argument */ +#define EXTCSD_ACCESS_BYTE (BIT25 | BIT24) +#define EXTCSD_SET_BITS BIT24 + +#define HS_TIMING_ADD (185 << 16) /* H'b9 */ +#define HS_TIMING_1 (1 << 8) +#define HS_TIMING_HS200 (2 << 8) +#define HS_TIMING_HS400 (3 << 8) + +#define BUS_WIDTH_ADD (183 << 16) /* H'b7 */ +#define BUS_WIDTH_1 (0 << 8) +#define BUS_WIDTH_4 (1 << 8) +#define BUS_WIDTH_8 (2 << 8) +#define BUS_WIDTH_4DDR (5 << 8) +#define BUS_WIDTH_8DDR (6 << 8) + +#define EMMC_SWITCH_HS_TIMING (EXTCSD_ACCESS_BYTE | HS_TIMING_ADD |\ + HS_TIMING_1) /* H'03b90100 */ +#define EMMC_SWITCH_HS_TIMING_OFF (EXTCSD_ACCESS_BYTE |\ + HS_TIMING_ADD) /* H'03b90000 */ + +#define EMMC_SWITCH_BUS_WIDTH_1 (EXTCSD_ACCESS_BYTE | BUS_WIDTH_ADD |\ + BUS_WIDTH_1) /* H'03b70000 */ +#define EMMC_SWITCH_BUS_WIDTH_4 (EXTCSD_ACCESS_BYTE | BUS_WIDTH_ADD |\ + BUS_WIDTH_4) /* H'03b70100 */ +#define EMMC_SWITCH_BUS_WIDTH_8 (EXTCSD_ACCESS_BYTE | BUS_WIDTH_ADD |\ + BUS_WIDTH_8) /* H'03b70200 */ +#define EMMC_SWITCH_BUS_WIDTH_4DDR (EXTCSD_ACCESS_BYTE | BUS_WIDTH_ADD |\ + BUS_WIDTH_4DDR) /* H'03b70500 */ +#define EMMC_SWITCH_BUS_WIDTH_8DDR (EXTCSD_ACCESS_BYTE | BUS_WIDTH_ADD |\ + BUS_WIDTH_8DDR) /* H'03b70600 */ +/* Partition config = 0x00 */ +#define EMMC_SWITCH_PARTITION_CONFIG 0x03B30000UL + +#define TIMING_HIGH_SPEED 1UL +#define EMMC_BOOT_PARTITION_EN_MASK 0x38U +#define EMMC_BOOT_PARTITION_EN_SHIFT 3U + +/* Bus width */ +#define EMMC_BUSWIDTH_1BIT CE_CMD_SET_DATW_1BIT +#define EMMC_BUSWIDTH_4BIT CE_CMD_SET_DATW_4BIT +#define EMMC_BUSWIDTH_8BIT CE_CMD_SET_DATW_8BIT + +/* for st_mmc_base */ +#define EMMC_MAX_RESPONSE_LENGTH 17 +#define EMMC_MAX_CID_LENGTH 16 +#define EMMC_MAX_CSD_LENGTH 16 +#define EMMC_MAX_EXT_CSD_LENGTH 512U +#define EMMC_RES_REG_ALIGNED 4U +#define EMMC_BUF_REG_ALIGNED 8U + +/* TAAC mask */ +#define TAAC_TIME_UNIT_MASK (0x07) +#define TAAC_MULTIPLIER_FACTOR_MASK (0x0F) + +/* Partition id */ +typedef enum { + PARTITION_ID_USER = 0x0, /* User Area */ + PARTITION_ID_BOOT_1 = 0x1, /* boot partition 1 */ + PARTITION_ID_BOOT_2 = 0x2, /* boot partition 2 */ + PARTITION_ID_RPMB = 0x3, /* Replay Protected Memory Block */ + PARTITION_ID_GP_1 = 0x4, /* General Purpose partition 1 */ + PARTITION_ID_GP_2 = 0x5, /* General Purpose partition 2 */ + PARTITION_ID_GP_3 = 0x6, /* General Purpose partition 3 */ + PARTITION_ID_GP_4 = 0x7, /* General Purpose partition 4 */ + PARTITION_ID_MASK = 0x7, /* [2:0] */ +} EMMC_PARTITION_ID; + +/* card state in R1 response [12:9] */ +typedef enum { + EMMC_R1_STATE_IDLE = 0, + EMMC_R1_STATE_READY, + EMMC_R1_STATE_IDENT, + EMMC_R1_STATE_STBY, + EMMC_R1_STATE_TRAN, + EMMC_R1_STATE_DATA, + EMMC_R1_STATE_RCV, + EMMC_R1_STATE_PRG, + EMMC_R1_STATE_DIS, + EMMC_R1_STATE_BTST, + EMMC_R1_STATE_SLEP +} EMMC_R1_STATE; + +typedef enum { + ESTATE_BEGIN = 0, + ESTATE_ISSUE_CMD, + ESTATE_NON_RESP_CMD, + ESTATE_RCV_RESP, + ESTATE_RCV_RESPONSE_BUSY, + ESTATE_CHECK_RESPONSE_COMPLETE, + ESTATE_DATA_TRANSFER, + ESTATE_DATA_TRANSFER_COMPLETE, + ESTATE_ACCESS_END, + ESTATE_TRANSFER_ERROR, + ESTATE_ERROR, + ESTATE_END +} EMMC_INT_STATE; + +/* eMMC boot driver error information */ +typedef struct { + uint16_t num; /* error no */ + uint16_t code; /* error code */ + + volatile uint32_t info1; /* SD_INFO1. (hw dependent) */ + volatile uint32_t info2; /* SD_INFO2. (hw dependent) */ + volatile uint32_t status1; /* SD_ERR_STS1. (hw dependent) */ + volatile uint32_t status2; /* SD_ERR_STS2. (hw dependent) */ + volatile uint32_t dm_info1; /* DM_CM_INFO1. (hw dependent) */ + volatile uint32_t dm_info2; /* DM_CM_INFO2. (hw dependent) */ +} st_error_info; + +/* Command information */ +typedef struct { + HAL_MEMCARD_COMMAND cmd; /* Command information */ + uint32_t arg; /* argument */ + HAL_MEMCARD_OPERATION dir; /* direction */ + uint32_t hw; /* SD_CMD register value. */ +} st_command_info; + +/* MMC driver base */ +typedef struct { + st_error_info error_info; /* error information */ + st_command_info cmd_info; /* command information */ + + /* for data transfer */ + uint32_t *buff_address_virtual; /* Dest or Src buff */ + uint32_t *buff_address_physical; /* Dest or Src buff */ + HAL_MEMCARD_DATA_WIDTH bus_width; /* bus width */ + + uint32_t trans_size; /* transfer size for this command */ + uint32_t remain_size; /* remain size for this command */ + uint32_t response_length; /* response length for this command */ + uint32_t sector_size; /* sector_size */ + + /* clock */ + uint32_t base_clock; /* MMC host controller clock */ + /* + * Max freq (Card Spec)[Hz]. It changes dynamically by CSD and + * EXT_CSD. + */ + uint32_t max_freq; + /* request freq [Hz] (400K, 26MHz, 52MHz, etc) */ + uint32_t request_freq; + /* current MMC clock[Hz] (the closest frequency supported by HW) */ + uint32_t current_freq; + + /* state flag */ + /* presence status of the memory card */ + HAL_MEMCARD_PRESENCE_STATUS card_present; + + uint32_t card_power_enable; + uint32_t clock_enable; + /* True : initialize complete. */ + uint32_t initialize; + /* True : sector access, FALSE : byte access */ + uint32_t access_mode; + /* True : mount complete. */ + uint32_t mount; + /* True : selected card. */ + uint32_t selected; + /* 0: DMA, 1:PIO */ + HAL_MEMCARD_DATA_TRANSFER_MODE transfer_mode; + + /* loaded ISSW image No. ISSW have copy image. */ + uint32_t image_num; + /* card state */ + EMMC_R1_STATE current_state; + /* True : during command processing */ + volatile uint32_t during_cmd_processing; + /* True : during transfer */ + volatile uint32_t during_transfer; + /* True : during transfer (DMA) */ + volatile uint32_t during_dma_transfer; + /* True : occurred DMAC error */ + volatile uint32_t dma_error_flag; + /* force terminate flag */ + volatile uint32_t force_terminate; + /* state machine blocking flag : True or False */ + volatile uint32_t state_machine_blocking; + /* True : get partition access processing */ + volatile uint32_t get_partition_access_flag; + + EMMC_PARTITION_ID boot_partition_en; /* Boot partition */ + EMMC_PARTITION_ID partition_access; /* Current access partition */ + + /* timeout */ + uint32_t hs_timing; + + /* read and write data timeout */ + uint32_t data_timeout; + + /* retry */ + uint32_t retries_after_fail; + + /* interrupt */ + volatile uint32_t int_event1; /* interrupt SD_INFO1 Event */ + volatile uint32_t int_event2; /* interrupt SD_INFO2 Event */ + volatile uint32_t dm_event1; /* interrupt DM_CM_INFO1 Event */ + volatile uint32_t dm_event2; /* interrupt DM_CM_INFO2 Event */ + + /* response */ + uint32_t *response; /* buffer ptr for executing command. */ + uint32_t r1_card_status; /* R1 response data */ + uint32_t r3_ocr; /* R3 response data */ + uint32_t r4_resp; /* R4 response data */ + uint32_t r5_resp; /* R5 response data */ + + /* True : clock mode is low. (MMC clock = Max26MHz) */ + uint32_t low_clock_mode_enable; + + uint32_t reserved2; + uint32_t reserved3; + uint32_t reserved4; + + /* CSD registers (4byte align) */ + uint8_t csd_data[EMMC_MAX_CSD_LENGTH] /* CSD */ + __attribute__ ((aligned(EMMC_RES_REG_ALIGNED))); + /* CID registers (4byte align) */ + uint8_t cid_data[EMMC_MAX_CID_LENGTH] /* CID */ + __attribute__ ((aligned(EMMC_RES_REG_ALIGNED))); + /* EXT CSD registers (8byte align) */ + uint8_t ext_csd_data[EMMC_MAX_EXT_CSD_LENGTH] /* EXT_CSD */ + __attribute__ ((aligned(EMMC_BUF_REG_ALIGNED))); + /* Response registers (4byte align) */ + uint8_t response_data[EMMC_MAX_RESPONSE_LENGTH] /* other response */ + __attribute__ ((aligned(EMMC_RES_REG_ALIGNED))); +} st_mmc_base; + +typedef int (*func) (void); + +uint32_t emmc_get_csd_time(void); + +#define MMC_DEBUG +#endif /* EMMC_STD_H */ diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/emmc/emmc_utility.c b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/emmc/emmc_utility.c new file mode 100644 index 00000000..2e88abc7 --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/emmc/emmc_utility.c @@ -0,0 +1,226 @@ +/* + * Copyright (c) 2015-2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include "emmc_config.h" +#include "emmc_def.h" +#include "emmc_hal.h" +#include "emmc_registers.h" +#include "emmc_std.h" + +static const uint32_t cmd_reg_hw[EMMC_CMD_MAX + 1] = { + 0x00000000, /* CMD0 */ + 0x00000701, /* CMD1 */ + 0x00000002, /* CMD2 */ + 0x00000003, /* CMD3 */ + 0x00000004, /* CMD4 */ + 0x00000505, /* CMD5 */ + 0x00000406, /* CMD6 */ + 0x00000007, /* CMD7 */ + 0x00001C08, /* CMD8 */ + 0x00000009, /* CMD9 */ + 0x0000000A, /* CMD10 */ + 0x00000000, /* reserved */ + 0x0000000C, /* CMD12 */ + 0x0000000D, /* CMD13 */ + 0x00001C0E, /* CMD14 */ + 0x0000000F, /* CMD15 */ + 0x00000010, /* CMD16 */ + 0x00000011, /* CMD17 */ + 0x00007C12, /* CMD18 */ + 0x00000C13, /* CMD19 */ + 0x00000000, + 0x00001C15, /* CMD21 */ + 0x00000000, + 0x00000017, /* CMD23 */ + 0x00000018, /* CMD24 */ + 0x00006C19, /* CMD25 */ + 0x00000C1A, /* CMD26 */ + 0x0000001B, /* CMD27 */ + 0x0000001C, /* CMD28 */ + 0x0000001D, /* CMD29 */ + 0x0000001E, /* CMD30 */ + 0x00001C1F, /* CMD31 */ + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000423, /* CMD35 */ + 0x00000424, /* CMD36 */ + 0x00000000, + 0x00000026, /* CMD38 */ + 0x00000427, /* CMD39 */ + 0x00000428, /* CMD40(send cmd) */ + 0x00000000, + 0x0000002A, /* CMD42 */ + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000C31, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00007C35, + 0x00006C36, + 0x00000037, /* CMD55 */ + 0x00000038, /* CMD56(Read) */ + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000 +}; + +uint32_t emmc_bit_field(uint8_t *data, uint32_t top, uint32_t bottom) +{ + uint32_t value; + + uint32_t index_top = (uint32_t) (15 - (top >> 3)); + uint32_t index_bottom = (uint32_t) (15 - (bottom >> 3)); + + if (index_top == index_bottom) { + value = data[index_top]; + } else if ((index_top + 1) == index_bottom) { + value = + (uint32_t) ((data[index_top] << 8) | data[index_bottom]); + } else if ((index_top + 2) == index_bottom) { + value = + (uint32_t) ((data[index_top] << 16) | + (data[index_top + 1] << 8) | data[index_top + + 2]); + } else { + value = + (uint32_t) ((data[index_top] << 24) | + (data[index_top + 1] << 16) | + (data[index_top + 2] << 8) | + data[index_top + 3]); + } + + value = ((value >> (bottom & 0x07)) & ((1 << (top - bottom + 1)) - 1)); + + return value; +} + +void emmc_write_error_info(uint16_t func_no, EMMC_ERROR_CODE error_code) +{ + + mmc_drv_obj.error_info.num = func_no; + mmc_drv_obj.error_info.code = (uint16_t) error_code; + + ERROR("BL2: emmc err:func_no=0x%x code=0x%x\n", func_no, error_code); +} + +void emmc_write_error_info_func_no(uint16_t func_no) +{ + + mmc_drv_obj.error_info.num = func_no; + + ERROR("BL2: emmc err:func_no=0x%x\n", func_no); +} + +void emmc_make_nontrans_cmd(HAL_MEMCARD_COMMAND cmd, uint32_t arg) +{ + /* command information */ + mmc_drv_obj.cmd_info.cmd = cmd; + mmc_drv_obj.cmd_info.arg = arg; + mmc_drv_obj.cmd_info.dir = HAL_MEMCARD_READ; + mmc_drv_obj.cmd_info.hw = + cmd_reg_hw[cmd & HAL_MEMCARD_COMMAND_INDEX_MASK]; + + /* clear data transfer information */ + mmc_drv_obj.trans_size = 0; + mmc_drv_obj.remain_size = 0; + mmc_drv_obj.buff_address_virtual = NULL; + mmc_drv_obj.buff_address_physical = NULL; + + /* response information */ + mmc_drv_obj.response_length = 6; + + switch (mmc_drv_obj.cmd_info.cmd & HAL_MEMCARD_RESPONSE_TYPE_MASK) { + case HAL_MEMCARD_RESPONSE_NONE: + mmc_drv_obj.response = (uint32_t *) mmc_drv_obj.response_data; + mmc_drv_obj.response_length = 0; + break; + case HAL_MEMCARD_RESPONSE_R1: + mmc_drv_obj.response = &mmc_drv_obj.r1_card_status; + break; + case HAL_MEMCARD_RESPONSE_R1b: + mmc_drv_obj.cmd_info.hw |= BIT10; /* bit10 = R1 busy bit */ + mmc_drv_obj.response = &mmc_drv_obj.r1_card_status; + break; + case HAL_MEMCARD_RESPONSE_R2: + mmc_drv_obj.response = (uint32_t *) mmc_drv_obj.response_data; + mmc_drv_obj.response_length = 17; + break; + case HAL_MEMCARD_RESPONSE_R3: + mmc_drv_obj.response = &mmc_drv_obj.r3_ocr; + break; + case HAL_MEMCARD_RESPONSE_R4: + mmc_drv_obj.response = &mmc_drv_obj.r4_resp; + break; + case HAL_MEMCARD_RESPONSE_R5: + mmc_drv_obj.response = &mmc_drv_obj.r5_resp; + break; + default: + mmc_drv_obj.response = (uint32_t *) mmc_drv_obj.response_data; + break; + } +} + +void emmc_make_trans_cmd(HAL_MEMCARD_COMMAND cmd, uint32_t arg, + uint32_t *buff_address_virtual, + uint32_t len, + HAL_MEMCARD_OPERATION dir, + HAL_MEMCARD_DATA_TRANSFER_MODE transfer_mode) +{ + emmc_make_nontrans_cmd(cmd, arg); /* update common information */ + + /* for data transfer command */ + mmc_drv_obj.cmd_info.dir = dir; + mmc_drv_obj.buff_address_virtual = buff_address_virtual; + mmc_drv_obj.buff_address_physical = buff_address_virtual; + mmc_drv_obj.trans_size = len; + mmc_drv_obj.remain_size = len; + mmc_drv_obj.transfer_mode = transfer_mode; +} + +EMMC_ERROR_CODE emmc_send_idle_cmd(uint32_t arg) +{ + EMMC_ERROR_CODE result; + uint32_t freq; + + /* initialize state */ + mmc_drv_obj.mount = FALSE; + mmc_drv_obj.selected = FALSE; + mmc_drv_obj.during_transfer = FALSE; + mmc_drv_obj.during_cmd_processing = FALSE; + mmc_drv_obj.during_dma_transfer = FALSE; + mmc_drv_obj.dma_error_flag = FALSE; + mmc_drv_obj.force_terminate = FALSE; + mmc_drv_obj.state_machine_blocking = FALSE; + + mmc_drv_obj.bus_width = HAL_MEMCARD_DATA_WIDTH_1_BIT; + mmc_drv_obj.max_freq = MMC_20MHZ; /* 20MHz */ + mmc_drv_obj.current_state = EMMC_R1_STATE_IDLE; + + /* CMD0 (MMC clock is current frequency. if Data transfer mode, 20MHz or higher.) */ + emmc_make_nontrans_cmd(CMD0_GO_IDLE_STATE, arg); /* CMD0 */ + result = emmc_exec_cmd(EMMC_R1_ERROR_MASK, mmc_drv_obj.response); + if (result != EMMC_SUCCESS) { + return result; + } + + /* change MMC clock(400KHz) */ + freq = MMC_400KHZ; + result = emmc_set_request_mmc_clock(&freq); + if (result != EMMC_SUCCESS) { + return result; + } + + return EMMC_SUCCESS; +} diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/io/io_emmcdrv.c b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/io/io_emmcdrv.c new file mode 100644 index 00000000..f8c4f74d --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/io/io_emmcdrv.c @@ -0,0 +1,202 @@ +/* + * Copyright (c) 2015-2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +#include "emmc_config.h" +#include "emmc_def.h" +#include "emmc_hal.h" +#include "emmc_std.h" +#include "io_common.h" +#include "io_emmcdrv.h" +#include "io_private.h" + +static int32_t emmcdrv_dev_open(const uintptr_t spec __attribute__ ((unused)), + io_dev_info_t **dev_info); +static int32_t emmcdrv_dev_close(io_dev_info_t *dev_info); + +typedef struct { + uint32_t in_use; + uintptr_t base; + signed long long file_pos; + EMMC_PARTITION_ID partition; +} file_state_t; + +static file_state_t current_file = { 0 }; + +static io_type_t device_type_emmcdrv(void) +{ + return IO_TYPE_MEMMAP; +} + +static int32_t emmcdrv_block_seek(io_entity_t *entity, int32_t mode, + signed long long offset) +{ + if (mode != IO_SEEK_SET) { + return IO_FAIL; + } + + ((file_state_t *) entity->info)->file_pos = offset; + + return IO_SUCCESS; +} + +static int32_t emmcdrv_block_read(io_entity_t *entity, uintptr_t buffer, + size_t length, size_t *length_read) +{ + file_state_t *fp = (file_state_t *) entity->info; + uint32_t first_sector, last_sector, sector_count, emmc_dma = 0; + uint8_t sector_buf[EMMC_SECTOR_SIZE]; + size_t buffer_offset = 0; + int32_t result = IO_SUCCESS; + + first_sector = (fp->base + fp->file_pos) >> EMMC_SECTOR_SIZE_SHIFT; + last_sector = (fp->base + fp->file_pos + length -1 ) >> EMMC_SECTOR_SIZE_SHIFT; + sector_count = last_sector - first_sector + 1; + + NOTICE("BL2: Load dst=0x%lx src=(p:%d)0x%llx(%d) len=0x%lx(%d)\n", + buffer, + fp->partition, (fp->base + fp->file_pos), + first_sector, length, sector_count); + +// Temporarily disable DMA. +// if ((buffer + length - 1U) <= (uintptr_t)UINT32_MAX) { +// emmc_dma = LOADIMAGE_FLAGS_DMA_ENABLE; +// } + + // first sector + uint32_t first_offset = (fp->base + fp->file_pos) % EMMC_SECTOR_SIZE; + if( 0 < first_offset ) { + memset(sector_buf, 0x00, EMMC_SECTOR_SIZE); + if(emmc_read_sector((uint32_t*)sector_buf, + first_sector, 1, emmc_dma) != EMMC_SUCCESS) { + result = IO_FAIL; + goto block_read_done; + } + else { + buffer_offset = EMMC_SECTOR_SIZE - first_offset; + buffer_offset = (length < buffer_offset) ? length : buffer_offset; + + memcpy((uint8_t *)buffer, §or_buf[first_offset], buffer_offset); + + first_sector++; + sector_count--; + } + } + + // last sector + uint32_t last_offset = (fp->base + fp->file_pos + length) % EMMC_SECTOR_SIZE; + if(0 < sector_count && 0 < last_offset) { + memset(sector_buf, 0x00, EMMC_SECTOR_SIZE); + if (emmc_read_sector((uint32_t*)sector_buf, + last_sector, 1, emmc_dma) != EMMC_SUCCESS) { + result = IO_FAIL; + goto block_read_done; + } + else { + memcpy((uint8_t *) buffer + (length - last_offset), §or_buf[0], last_offset); + sector_count--; + } + } + + // middle sector + if(0 < sector_count) { + if (emmc_read_sector((uint32_t *)(buffer + buffer_offset), + first_sector, sector_count, emmc_dma) != EMMC_SUCCESS) { + result = IO_FAIL; + goto block_read_done; + } + } + + *length_read = length; + fp->file_pos += (signed long long)length; +block_read_done: + return result; +} + +static int32_t emmcdrv_block_open(io_dev_info_t *dev_info, + const uintptr_t spec, io_entity_t *entity) +{ + const io_drv_spec_t *block_spec = (io_drv_spec_t *) spec; + + if (current_file.in_use != 0U) { + WARN("mmc_block: Only one open spec at a time\n"); + return IO_RESOURCES_EXHAUSTED; + } + + current_file.base = block_spec->offset; + current_file.file_pos = 0; + current_file.in_use = 1; + + current_file.partition = mmc_drv_obj.boot_partition_en; + NOTICE("BL2: eMMC boot from partition %d\n", current_file.partition); + + if (emmc_select_partition(current_file.partition) != EMMC_SUCCESS) { + return IO_FAIL; + } + + entity->info = (uintptr_t) ¤t_file; + + return IO_SUCCESS; +} + +static int32_t emmcdrv_block_close(io_entity_t *entity) +{ + memset((void *)¤t_file, 0, sizeof(current_file)); + entity->info = 0U; + + return IO_SUCCESS; +} + +static const io_dev_funcs_t emmcdrv_dev_funcs = { + .type = &device_type_emmcdrv, + .open = &emmcdrv_block_open, + .seek = &emmcdrv_block_seek, + .size = NULL, + .read = &emmcdrv_block_read, + .write = NULL, + .close = &emmcdrv_block_close, + .dev_init = NULL, + .dev_close = &emmcdrv_dev_close +}; + +static const io_dev_info_t emmcdrv_dev_info = { + .funcs = &emmcdrv_dev_funcs, + .info = (uintptr_t) 0 +}; + +static const io_dev_connector_t emmcdrv_dev_connector = { + &emmcdrv_dev_open, +}; + +static int32_t emmcdrv_dev_open(const uintptr_t spec __attribute__ ((unused)), + io_dev_info_t **dev_info) +{ + *dev_info = (io_dev_info_t *) &emmcdrv_dev_info; + + return IO_SUCCESS; +} + +static int32_t emmcdrv_dev_close(io_dev_info_t *dev_info) +{ + return IO_SUCCESS; +} + +int32_t register_io_dev_emmcdrv(const io_dev_connector_t **dev_con) +{ + int32_t rc; + + rc = io_register_device(&emmcdrv_dev_info); + if (rc == IO_SUCCESS) { + *dev_con = &emmcdrv_dev_connector; + } + + return rc; +} diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/io/io_emmcdrv.h b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/io/io_emmcdrv.h new file mode 100644 index 00000000..71c6f515 --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/io/io_emmcdrv.h @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2015-2017, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef IO_EMMCDRV_H +#define IO_EMMCDRV_H + +struct io_dev_connector; +int32_t register_io_dev_emmcdrv(const io_dev_connector_t **connector); + +#endif /* IO_EMMCDRV_H */ diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/pfc.c b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/pfc.c new file mode 100644 index 00000000..53d16991 --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/pfc.c @@ -0,0 +1,356 @@ +/* + * Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +static PFC_REGS pfc_mux_reg_tbl[] = { +#if (RZG2UL||RZA3) +#if RZA3M + /* P22(sd0) */ + { + { PFC_ON, (uintptr_t)PFC_PMC04, 0x3e }, /* PMC */ + { PFC_ON, (uintptr_t)PFC_PFC04, 0 }, /* PFC */ + { PFC_OFF, (uintptr_t)PFC_IOLH04, 0x0000010101010101 }, /* IOLH */ + { PFC_OFF, (uintptr_t)PFC_PUPD04, 0x0000000000000000 }, /* PUPD */ + { PFC_OFF, (uintptr_t)PFC_SR04, 0x0000010101010101 }, /* SR */ + { PFC_ON, (uintptr_t)NULL, 0 } /* IEN */ + }, +#else /* RZA3M */ + /* P0(sd0) & P0(sd1) */ + { + { PFC_ON, (uintptr_t)PFC_PMC10, 0x0F }, /* PMC */ + { PFC_ON, (uintptr_t)PFC_PFC10, 0x00001111 }, /* PFC */ + { PFC_OFF, (uintptr_t)PFC_IOLH10, 0x0000000001010101 }, /* IOLH */ + { PFC_OFF, (uintptr_t)PFC_PUPD10, 0x0000000000000000 }, /* PUPD */ + { PFC_OFF, (uintptr_t)PFC_SR10, 0x0000000001010101 }, /* SR */ + { PFC_OFF, (uintptr_t)NULL, 0 } /* IEN */ + }, +#endif /* RZA3M */ +#else + /* P18(sd0) */ + { + { PFC_ON, (uintptr_t)PFC_PMC22, 0x03 }, /* PMC */ + { PFC_ON, (uintptr_t)PFC_PFC22, 0x00000011 }, /* PFC */ + { PFC_OFF, (uintptr_t)PFC_IOLH22, 0x0000000000000101 }, /* IOLH */ + { PFC_OFF, (uintptr_t)PFC_PUPD22, 0x0000000000000000 }, /* PUPD */ + { PFC_OFF, (uintptr_t)PFC_SR22, 0x0000000000000101 }, /* SR */ + { PFC_OFF, (uintptr_t)NULL, 0 } /* IEN */ + }, + /* P19(sd1) */ + { + { PFC_ON, (uintptr_t)PFC_PMC23, 0x03 }, /* PMC */ + { PFC_ON, (uintptr_t)PFC_PFC23, 0x00000011 }, /* PFC */ + { PFC_OFF, (uintptr_t)PFC_IOLH23, 0x0000000000000101 }, /* IOLH */ + { PFC_OFF, (uintptr_t)PFC_PUPD23, 0x0000000000000000 }, /* PUPD */ + { PFC_OFF, (uintptr_t)PFC_SR23, 0x0000000000000101 }, /* SR */ + { PFC_OFF, (uintptr_t)NULL, 0 } /* IEN */ + }, +#endif +#if (RZG2UL||RZA3) +#if RZA3M + /* P6(scif0) */ + { + { PFC_ON, (uintptr_t)PFC_PMC16, 0x3 }, /* PMC */ + { PFC_ON, (uintptr_t)PFC_PFC16, 0x11 }, /* PFC */ + { PFC_OFF, (uintptr_t)PFC_IOLH16, 0x0000000000000101 }, /* IOLH */ + { PFC_OFF, (uintptr_t)PFC_PUPD16, 0x0000000000000000 }, /* PUPD */ + { PFC_OFF, (uintptr_t)PFC_SR16, 0x0000000000000101 }, /* SR */ + { PFC_OFF, (uintptr_t)NULL, 0 } /* IEN */ + }, +#else /* RZA3M */ +#if (DEVICE_TYPE == 1) + /* P6(scif0) */ + { + { PFC_ON, (uintptr_t)PFC_PMC16, 0x18 }, /* PMC */ + { PFC_ON, (uintptr_t)PFC_PFC16, 0x00066000 }, /* PFC */ + { PFC_OFF, (uintptr_t)PFC_IOLH16, 0x0000000101000000 }, /* IOLH */ + { PFC_OFF, (uintptr_t)PFC_PUPD16, 0x0000000000000000 }, /* PUPD */ + { PFC_OFF, (uintptr_t)PFC_SR16, 0x0000000101000000 }, /* SR */ + { PFC_OFF, (uintptr_t)NULL, 0 } /* IEN */ + }, +#else + /* P13(scif0) */ + { + { PFC_ON, (uintptr_t)PFC_PMC1D, 0x03 }, /* PMC */ + { PFC_ON, (uintptr_t)PFC_PFC1D, 0x00000011 }, /* PFC */ + { PFC_OFF, (uintptr_t)PFC_IOLH1D, 0x0000000000000101 }, /* IOLH */ + { PFC_OFF, (uintptr_t)PFC_PUPD1D, 0x0000000000000000 }, /* PUPD */ + { PFC_OFF, (uintptr_t)PFC_SR1D, 0x0000000000000101 }, /* SR */ + { PFC_OFF, (uintptr_t)NULL, 0 } /* IEN */ + }, +#endif +#endif /* RZA3M */ +#else + /* P38(scif0) */ + { + { PFC_ON, (uintptr_t)PFC_PMC36, 0x03 }, /* PMC */ + { PFC_ON, (uintptr_t)PFC_PFC36, 0x00000011 }, /* PFC */ + { PFC_OFF, (uintptr_t)PFC_IOLH36, 0x0000000000000101 }, /* IOLH */ + { PFC_OFF, (uintptr_t)PFC_PUPD36, 0x0000000000000000 }, /* PUPD */ + { PFC_OFF, (uintptr_t)PFC_SR36, 0x0000000000000101 }, /* SR */ + { PFC_OFF, (uintptr_t)NULL, 0 } /* IEN */ + }, + /* P39(scif0) */ + { + { PFC_ON, (uintptr_t)PFC_PMC37, 0x07 }, /* PMC */ + { PFC_ON, (uintptr_t)PFC_PFC37, 0x00000111 }, /* PFC */ + { PFC_OFF, (uintptr_t)PFC_IOLH37, 0x0000000000010101 }, /* IOLH */ + { PFC_OFF, (uintptr_t)PFC_PUPD37, 0x0000000000000000 }, /* PUPD */ + { PFC_OFF, (uintptr_t)PFC_SR37, 0x0000000000010101 }, /* SR */ + { PFC_OFF, (uintptr_t)NULL, 0 } /* IEN */ + } +#endif +}; + +static PFC_REGS pfc_qspi_reg_tbl[] = { +#if RZA3 +#if RZA3M + /* QSPI0 */ + { + { PFC_OFF, (uintptr_t)NULL, 0 }, /* PMC */ + { PFC_OFF, (uintptr_t)NULL, 0 }, /* PFC */ + { PFC_ON, (uintptr_t)PFC_IOLH05, 0x0000010101010101 }, /* IOLH */ + { PFC_ON, (uintptr_t)PFC_PUPD05, 0x0000000000000000 }, /* PUPD */ + { PFC_ON, (uintptr_t)PFC_SR05, 0x0000010101010101 }, /* SR */ + { PFC_OFF, (uintptr_t)NULL, 0 } /* IEN */ + }, +#else /* RZA3M */ + /* QSPI0 */ + { + { PFC_OFF, (uintptr_t)NULL, 0 }, /* PMC */ + { PFC_OFF, (uintptr_t)NULL, 0 }, /* PFC */ + { PFC_ON, (uintptr_t)PFC_IOLH0A, 0x0000010101010101 }, /* IOLH */ + { PFC_ON, (uintptr_t)PFC_PUPD0A, 0x0000000000000000 }, /* PUPD */ + { PFC_ON, (uintptr_t)PFC_SR0A, 0x0000010101010101 }, /* SR */ + { PFC_OFF, (uintptr_t)NULL, 0 } /* IEN */ + }, + /* QSPI1 */ + { + { PFC_OFF, (uintptr_t)NULL, 0 }, /* PMC */ + { PFC_OFF, (uintptr_t)NULL, 0 }, /* PFC */ + { PFC_ON, (uintptr_t)PFC_IOLH0B, 0x0000010101010101 }, /* IOLH */ + { PFC_ON, (uintptr_t)PFC_PUPD0B, 0x0000000000000000 }, /* PUPD */ + { PFC_ON, (uintptr_t)PFC_SR0B, 0x0000010101010101 }, /* SR */ + { PFC_OFF, (uintptr_t)NULL, 0 } /* IEN */ + }, + /* QSPIn */ + { + { PFC_OFF, (uintptr_t)NULL, 0 }, /* PMC */ + { PFC_OFF, (uintptr_t)NULL, 0 }, /* PFC */ + { PFC_ON, (uintptr_t)PFC_IOLH0C, 0x0000000000000101 }, /* IOLH */ + { PFC_ON, (uintptr_t)PFC_PUPD0C, 0x0000000000000000 }, /* PUPD */ + { PFC_ON, (uintptr_t)PFC_SR0C, 0x0000000000000000 }, /* SR */ + { PFC_OFF, (uintptr_t)NULL, 0 } /* IEN */ + } +#endif /* RZA3M */ +#else + /* QSPI0 */ + { + { PFC_OFF, (uintptr_t)NULL, 0 }, /* PMC */ + { PFC_OFF, (uintptr_t)NULL, 0 }, /* PFC */ + { PFC_ON, (uintptr_t)PFC_IOLH0A, 0x0000020202020202 }, /* IOLH */ + { PFC_ON, (uintptr_t)PFC_PUPD0A, 0x0000000000000000 }, /* PUPD */ + { PFC_ON, (uintptr_t)PFC_SR0A, 0x0000010101010101 }, /* SR */ + { PFC_OFF, (uintptr_t)NULL, 0 } /* IEN */ + }, + /* QSPI1 */ + { + { PFC_OFF, (uintptr_t)NULL, 0 }, /* PMC */ + { PFC_OFF, (uintptr_t)NULL, 0 }, /* PFC */ + { PFC_ON, (uintptr_t)PFC_IOLH0B, 0x0000020202020202 }, /* IOLH */ + { PFC_ON, (uintptr_t)PFC_PUPD0B, 0x0000000000000000 }, /* PUPD */ + { PFC_ON, (uintptr_t)PFC_SR0B, 0x0000010101010101 }, /* SR */ + { PFC_OFF, (uintptr_t)NULL, 0 } /* IEN */ + }, + /* QSPIn */ + { + { PFC_OFF, (uintptr_t)NULL, 0 }, /* PMC */ + { PFC_OFF, (uintptr_t)NULL, 0 }, /* PFC */ + { PFC_ON, (uintptr_t)PFC_IOLH0C, 0x0000000000020202 }, /* IOLH */ + { PFC_ON, (uintptr_t)PFC_PUPD0C, 0x0000000000000000 }, /* PUPD */ + { PFC_ON, (uintptr_t)PFC_SR0C, 0x0000000000010000 }, /* SR */ + { PFC_OFF, (uintptr_t)NULL, 0 } /* IEN */ + } +#endif +}; + +#ifndef RZA3 +static PFC_REGS pfc_sd_reg_tbl[] = { + /* SD0_CLK */ + { +#if RZG2UL + { PFC_OFF, (uintptr_t)NULL, 0 }, /* PMC */ + { PFC_OFF, (uintptr_t)NULL, 0 }, /* PFC */ +#else + { PFC_ON, (uintptr_t)PFC_PMC22, 0x0003 }, /* PMC */ + { PFC_ON, (uintptr_t)PFC_PFC22, 0x00000003 }, /* PFC */ +#endif + { PFC_ON, (uintptr_t)PFC_IOLH06, 0x0000000000020202 }, /* IOLH */ + { PFC_ON, (uintptr_t)PFC_PUPD06, 0x0000000000000000 }, /* PUPD */ + { PFC_ON, (uintptr_t)PFC_SR06, 0x0000000000010101 }, /* SR */ + { PFC_ON, (uintptr_t)PFC_IEN06, 0x0000000000000100 } /* IEN */ + }, + /* SD0_DATA */ + { + { PFC_OFF, (uintptr_t)NULL, 0 }, /* PMC */ + { PFC_OFF, (uintptr_t)NULL, 0 }, /* PFC */ + { PFC_ON, (uintptr_t)PFC_IOLH07, 0x0202020202020202 }, /* IOLH */ + { PFC_ON, (uintptr_t)PFC_PUPD07, 0x0000000000000000 }, /* PUPD */ + { PFC_ON, (uintptr_t)PFC_SR07, 0x0101010101010101 }, /* SR */ + { PFC_ON, (uintptr_t)PFC_IEN07, 0x0101010101010101 } /* IEN */ + }, + /* SD1_CLK */ + { +#if RZG2UL + { PFC_OFF, (uintptr_t)NULL, 0 }, /* PMC */ + { PFC_OFF, (uintptr_t)NULL, 0 }, /* PFC */ +#else + { PFC_ON, (uintptr_t)PFC_PMC23, 0x0003 }, /* PMC */ + { PFC_ON, (uintptr_t)PFC_PFC23, 0x00000003 }, /* PFC */ +#endif + { PFC_ON, (uintptr_t)PFC_IOLH08, 0x0000000000000202 }, /* IOLH */ + { PFC_ON, (uintptr_t)PFC_PUPD08, 0x0000000000000000 }, /* PUPD */ + { PFC_ON, (uintptr_t)PFC_SR08, 0x0000000000000101 }, /* SR */ + { PFC_ON, (uintptr_t)PFC_IEN08, 0x0000000000000100 } /* IEN */ + }, + /* SD1_DATA */ + { + { PFC_OFF, (uintptr_t)NULL, 0 }, /* PMC */ + { PFC_OFF, (uintptr_t)NULL, 0 }, /* PFC */ + { PFC_ON, (uintptr_t)PFC_IOLH09, 0x0000000002020202 }, /* IOLH */ + { PFC_ON, (uintptr_t)PFC_PUPD09, 0x0000000000000000 }, /* PUPD */ + { PFC_ON, (uintptr_t)PFC_SR09, 0x0000000001010101 }, /* SR */ + { PFC_ON, (uintptr_t)PFC_IEN09, 0x0000000001010101 } /* IEN */ + } +}; +#endif + +static void pfc_mux_setup(void) +{ + int cnt; + int size = ARRAY_SIZE(pfc_mux_reg_tbl); + + for (cnt = 0; cnt < size; cnt++) { + /* PMC */ + if (pfc_mux_reg_tbl[cnt].pmc.flg == PFC_ON) { + mmio_write_8(pfc_mux_reg_tbl[cnt].pmc.reg, pfc_mux_reg_tbl[cnt].pmc.val); + } + /* IOLH */ + if (pfc_mux_reg_tbl[cnt].iolh.flg == PFC_ON) { + mmio_write_64(pfc_mux_reg_tbl[cnt].iolh.reg, pfc_mux_reg_tbl[cnt].iolh.val); + } + /* PUPD */ + if (pfc_mux_reg_tbl[cnt].pupd.flg == PFC_ON) { + mmio_write_64(pfc_mux_reg_tbl[cnt].pupd.reg, pfc_mux_reg_tbl[cnt].pupd.val); + } + /* SR */ + if (pfc_mux_reg_tbl[cnt].sr.flg == PFC_ON) { + mmio_write_64(pfc_mux_reg_tbl[cnt].sr.reg, pfc_mux_reg_tbl[cnt].sr.val); + } + } + /* multiplexer terminal switching */ + mmio_write_32(PFC_PWPR, 0x0); + mmio_write_32(PFC_PWPR, PWPR_PFCWE); + + for (cnt = 0; cnt < size; cnt++) { + /* PFC */ + if (pfc_mux_reg_tbl[cnt].pfc.flg == PFC_ON) { + mmio_write_32(pfc_mux_reg_tbl[cnt].pfc.reg, pfc_mux_reg_tbl[cnt].pfc.val); + } + } + + mmio_write_32(PFC_PWPR, 0x0); + mmio_write_32(PFC_PWPR, PWPR_B0Wl); +} + +static void pfc_qspi_setup(void) +{ + int cnt; + int size = ARRAY_SIZE(pfc_qspi_reg_tbl); + + for (cnt = 0; cnt < size; cnt++) { + /* PMC */ + if (pfc_qspi_reg_tbl[cnt].pmc.flg == PFC_ON) { + mmio_write_64(pfc_qspi_reg_tbl[cnt].pmc.reg, pfc_qspi_reg_tbl[cnt].pmc.val); + } + /* IOLH */ + if (pfc_qspi_reg_tbl[cnt].iolh.flg == PFC_ON) { + mmio_write_64(pfc_qspi_reg_tbl[cnt].iolh.reg, pfc_qspi_reg_tbl[cnt].iolh.val); + } + /* PUPD */ + if (pfc_qspi_reg_tbl[cnt].pupd.flg == PFC_ON) { + mmio_write_64(pfc_qspi_reg_tbl[cnt].pupd.reg, pfc_qspi_reg_tbl[cnt].pupd.val); + } + /* SR */ + if (pfc_qspi_reg_tbl[cnt].sr.flg == PFC_ON) { + mmio_write_64(pfc_qspi_reg_tbl[cnt].sr.reg, pfc_qspi_reg_tbl[cnt].sr.val); + } + } + /* multiplexer terminal switching */ + mmio_write_32(PFC_PWPR, 0x0); + mmio_write_32(PFC_PWPR, PWPR_PFCWE); + for (cnt = 0; cnt < size; cnt++) { + /* SR */ + if (pfc_qspi_reg_tbl[cnt].pfc.flg == PFC_ON) { + mmio_write_64(pfc_qspi_reg_tbl[cnt].pfc.reg, pfc_qspi_reg_tbl[cnt].pfc.val); + } + } + + mmio_write_32(PFC_PWPR, 0x0); + mmio_write_32(PFC_PWPR, PWPR_B0Wl); +} + +#ifndef RZA3 +static void pfc_sd_setup(void) +{ + int cnt; + int size = ARRAY_SIZE(pfc_sd_reg_tbl); + + /* Since SDx is 3.3V, the initial value will be set. */ + mmio_write_32(PFC_SD_ch0, 1); + mmio_write_32(PFC_SD_ch1, 0); + + for (cnt = 0; cnt < size; cnt++) { + /* PMC */ + if (pfc_sd_reg_tbl[cnt].pmc.flg == PFC_ON) { + mmio_write_8(pfc_sd_reg_tbl[cnt].pmc.reg, pfc_sd_reg_tbl[cnt].pmc.val); + } + /* PFC */ + if (pfc_sd_reg_tbl[cnt].pfc.flg == PFC_ON) { + mmio_write_32(pfc_sd_reg_tbl[cnt].pfc.reg, pfc_sd_reg_tbl[cnt].pfc.val); + } + /* IOLH */ + if (pfc_sd_reg_tbl[cnt].iolh.flg == PFC_ON) { + mmio_write_64(pfc_sd_reg_tbl[cnt].iolh.reg, pfc_sd_reg_tbl[cnt].iolh.val); + } + /* PUPD */ + if (pfc_sd_reg_tbl[cnt].pupd.flg == PFC_ON) { + mmio_write_64(pfc_sd_reg_tbl[cnt].pupd.reg, pfc_sd_reg_tbl[cnt].pupd.val); + } + /* SR */ + if (pfc_sd_reg_tbl[cnt].sr.flg == PFC_ON) { + mmio_write_64(pfc_sd_reg_tbl[cnt].sr.reg, pfc_sd_reg_tbl[cnt].sr.val); + } + /* IEN */ + if (pfc_sd_reg_tbl[cnt].ien.flg == PFC_ON) { + mmio_write_64(pfc_sd_reg_tbl[cnt].ien.reg, pfc_sd_reg_tbl[cnt].ien.val); + } + } +} +#endif + +void pfc_setup(void) +{ + pfc_mux_setup(); + pfc_qspi_setup(); +#ifndef RZA3 + pfc_sd_setup(); +#endif +} diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/rza_mmu/ARMv8A/rza_mmu.c b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/rza_mmu/ARMv8A/rza_mmu.c new file mode 100644 index 00000000..43286264 --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/rza_mmu/ARMv8A/rza_mmu.c @@ -0,0 +1,285 @@ +/* + * Copyright (c) 2022, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include + +#include +#include + +static int rz_mmu_check_tbl(const rza_mmu_pgtbl_cfg_t *config_table); +static void rz_mmu_write_tbl(const rza_mmu_pgtbl_cfg_t *config_table); +static void rz_mmu_write_ttbr0_el3(const uint64_t addr); +static void rz_mmu_write_mair_el3(const uint64_t mair); +static void rz_mmu_write_tcr_el3(const uint64_t tcr); +static uint32_t rz_mmu_get_current_el(void); + +/* MMU allocation area */ +uint64_t __attribute__ ((section("base_xlat_table"))) mmu_level1_table[RZA_MMU_LEVEL2_TABLE_INDEX_MAX]; +uint64_t __attribute__ ((section("xlat_table"), aligned(0x1000))) mmu_level2_table[RZA_MMU_TABLE_ENTRY * RZA_MMU_LEVEL2_TABLE_INDEX_MAX]; +uint64_t level2_table[RZA_MMU_LEVEL2_TABLE_INDEX_MAX]; + +int plat_mmu_init(const rza_mmu_pgtbl_cfg_t *config_table) +{ + int ret; + int index; + uint64_t mair; + uint64_t tcr; + int t0sz; + uintptr_t virtual_addr_space_size; + + ret = rz_mmu_check_tbl(config_table); + + if (0 == ret) { + /* get the start address for each Level2 MMU table entry */ + for (index = 0; index < RZA_MMU_LEVEL2_TABLE_INDEX_MAX; index++) { + level2_table[index] = (uint64_t)&mmu_level2_table[RZA_MMU_TABLE_ENTRY * index]; + } + + /* Set the address of the level 2 MMU table in the level 1 MMU table */ + for (index = 0; index < RZA_MMU_LEVEL2_TABLE_INDEX_MAX; index++) { + *((uint64_t *) &mmu_level1_table[index]) = (level2_table[index] | RZA_MMU_ATTR_NEXT_TBL); + } + + rz_mmu_write_tbl(config_table); + + /* create a pattern of attributes to set in the MAIR register */ + mair = RZA_MMU_MAIR_ATTR_SET(RZA_MMU_ATTR_DEVICE, RZA_MMU_ATTR_DEVICE_INDEX); + mair |= RZA_MMU_MAIR_ATTR_SET(RZA_MMU_ATTR_IWBWA_OWBWA_NTR, RZA_MMU_ATTR_IWBWA_OWBWA_NTR_INDEX); + mair |= RZA_MMU_MAIR_ATTR_SET(RZA_MMU_ATTR_NON_CACHEABLE, RZA_MMU_ATTR_NON_CACHEABLE_INDEX); + + /* create TTB operation settings to set in TCR register */ + tcr = TCR_EL3_RES1; + + virtual_addr_space_size = (uintptr_t)RZA_MMU_VIRT_SIZE_MAX; + + t0sz = 64 - __builtin_ctzll(virtual_addr_space_size); + + tcr |= (uint64_t)t0sz << TCR_T0SZ_SHIFT; + + /* TTB cache enable */ + tcr |= (TCR_SH_INNER_SHAREABLE | TCR_RGN_OUTER_WBA | TCR_RGN_INNER_WBA); + + /* address range check */ + if ((RZA_MMU_PHY_ADDR_MAX & ADDR_MASK_40_TO_41) != 0U) { + tcr |= TCR_PS_BITS_4TB << TCR_EL3_PS_SHIFT; /* 42bit */ + } + else if ((RZA_MMU_PHY_ADDR_MAX & ADDR_MASK_36_TO_39) != 0U) { + tcr |= TCR_PS_BITS_1TB << TCR_EL3_PS_SHIFT; /* 40bit */ + } + /* 36 bits address */ + else if ((RZA_MMU_PHY_ADDR_MAX & ADDR_MASK_32_TO_35) != 0U) { + tcr|= TCR_PS_BITS_64GB << TCR_EL3_PS_SHIFT; /* 36 bit */ + } + /* 32bits address */ + else { + tcr|= TCR_PS_BITS_4GB << TCR_EL3_PS_SHIFT; /* 32 bit */ + } + + __asm__ volatile ("tlbi alle3\n"); + + rz_mmu_write_mair_el3(mair); + + rz_mmu_write_tcr_el3(tcr); + + rz_mmu_write_ttbr0_el3(((uint64_t)mmu_level1_table | TTBR_CNP_BIT)); + } + + return ret; +} + +void plat_mmu_enable(void) +{ + /* set MMU and data cache enable, Disable the function to forcibly + set the execute-never attribute when setting the writable memory */ + __asm__ volatile ( + ".equ SCTLR_C, (1 << 2)\n" + ".equ SCTLR_M, (1 << 0)\n" + ".equ SCTLR_WXN, (1 << 19)\n" + + "dsb ish\n" + "isb\n" + "mrs x0, SCTLR_EL3\n" + "mov x1, #(SCTLR_C | SCTLR_M)\n" + "orr x0, x0, x1\n" + "bic x0, x0, SCTLR_WXN\n" + "msr SCTLR_EL3, x0\n" + "isb\n" + : + : + : "x0", "x1" + ); + + return; +} + +int rz_mmu_check_tbl(const rza_mmu_pgtbl_cfg_t *config_table) +{ + int ret = 0; + int index; + uint32_t current_el; + + current_el = rz_mmu_get_current_el(); + if (RZA_MMU_CURRENT_EL3 == current_el) { + for (index = 0; ((0 == ret) && (RZA_MMU_ATTRIBUTE_CONFIG_END != config_table[index].attribute)); index++) { + if ((config_table[index].vaddress % RZA_MMU_L2_ENTRY_SIZE) != 0) { + ret = -1; + } + + if ((config_table[index].paddress % RZA_MMU_L2_ENTRY_SIZE) != 0) { + ret = -1; + } + + if ((config_table[index].size % RZA_MMU_L2_ENTRY_SIZE) != 0) { + ret = -1; + } + + if (RZA_MMU_PHY_SIZE_MAX < (uint64_t)(config_table[index].paddress + config_table[index].size)) { + ret = -1; + } + + if (RZA_MMU_VIRT_SIZE_MAX < (uint64_t)(config_table[index].vaddress + config_table[index].size)) { + ret = -1; + } + } + } + else { + ret = -1; + } + + return ret; +} + +void rz_mmu_write_tbl(const rza_mmu_pgtbl_cfg_t *config_table) +{ + int desc; + int num_of_desc; + int ttb_index; + int ttb_num; + int index; + uint64_t *desc_ptr; + uint64_t paddress; + uint64_t ttb_base_ptr; + uint64_t ttb_start_vaddr; + uint64_t attribute; + + for (index = 0; RZA_MMU_ATTRIBUTE_CONFIG_END != config_table[index].attribute; index++) + { + /************** serach TTB address, index, number of desctiptor from config_table parameters ************** + Example of config_table[index].vaddress = 0x0040000, config_table[index].size = 0x00600000 + + TTB + | ... | + + |---------------------------------| | TTB1 + | Vaddress:0x40200000, ttb_index1 | | 512entry descriptor + |---------------------------------| | 1descriptor = 8byte + ttb_start_vaddr1(0x40000000)----------------------->Vaddress:0x40000000, ttb_index0 | + + ttb_base_ptr1(=&mmu_level2_table[1])------------->|---------------------------------| + | ... | + + | | | + | ... | | + |---------------------------------| | + + | Vaddress:0x00800000, ttb_index4 | | TTB0 + target descriptor | |---------------------------------| | 512entry descriptor + num_of_desc (=3entry) | | Vaddress:0x00600000, ttb_index3 | | 1descriptor = 8byte + | |---------------------------------| | + + | Vaddress:0x00400000, ttb_index2 | | + desc_ptr((=&mmu_level2_table[0]) + (8byte * 2))-->|---------------------------------| | + | Vaddress:0x00200000, ttb_index1 | | + |---------------------------------| | + ttb_start_vaddr0(=0x00000000)---------------------->Vaddress:0x00000000, ttb_index0 | + + ttb_base_ptr0(=&mmu_level2_table[0])------------->|---------------------------------| + + **********************************************************************************************************/ + + /* get target TTB block number + RZA_MMU_TTB_BLOCK_WIDTH is TTB block width(0x40000000) */ + ttb_num = config_table[index].vaddress / RZA_MMU_TTB_BLOCK_WIDTH; + /* get target TTB block pointer */ + ttb_base_ptr = (uint64_t)&mmu_level2_table[RZA_MMU_TABLE_ENTRY * ttb_num]; + /* get first virtual address on target TTB block */ + ttb_start_vaddr = RZA_MMU_TTB_BLOCK_WIDTH * ttb_num; + + /* get number of descriptor for setting attribute + RZA_MMU_L2_ENTRY_SIZE is virtual address entry size per descriptor */ + num_of_desc = config_table[index].size / RZA_MMU_L2_ENTRY_SIZE; + /* get index of descriptor for setting attribute */ + ttb_index = (config_table[index].vaddress - ttb_start_vaddr) / RZA_MMU_L2_ENTRY_SIZE; + /* get pointer of descriptor */ + desc_ptr = (uint64_t *) (ttb_base_ptr + (ttb_index * RZA_MMU_TABLE_DESC_SIZE)); + + /* set attribute to descriptor */ + if (RZA_MMU_ATTRIBUTE_ACCESS_FAULT != config_table[index].attribute) { + attribute = (config_table[index].attribute | RZA_MMU_DESC_BLOCK_ENTRY_L12); + paddress = config_table[index].paddress; + for (desc = 0; desc < num_of_desc; desc++) { + *desc_ptr++ = paddress | attribute; + paddress += RZA_MMU_L2_ENTRY_SIZE; + } + } + else { + for (desc = 0; desc < num_of_desc; desc++) { + *desc_ptr++ = 0; + } + } + } + + return; +} + +void rz_mmu_write_ttbr0_el3(const uint64_t addr) +{ + __asm__ volatile ( + "msr TTBR0_EL3, %0\n" + : + : "r"(addr) + : + ); + + return; +} + +void rz_mmu_write_mair_el3(const uint64_t mair) +{ + __asm__ volatile ( + "msr MAIR_EL3, %0\n" + : + : "r"(mair) + : + ); + + return; +} + +void rz_mmu_write_tcr_el3(const uint64_t tcr) +{ + __asm__ volatile ( + "msr TCR_EL3, %0\n" + : + : "r"(tcr) + : + ); + + return; +} + +uint32_t rz_mmu_get_current_el(void) +{ + uint32_t current_el; + + __asm__ volatile ( + "mrs %0, CurrentEL\n" + : "=r"(current_el) + : + : + ); + + return current_el; +} + diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/scifa.S b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/scifa.S new file mode 100644 index 00000000..0185a4e1 --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/scifa.S @@ -0,0 +1,229 @@ +/* + * Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#define SMR (0x00) +#define BRR (0x02) +#define MDDR (0x02) +#define SCR (0x04) +#define FTDR (0x06) +#define FSR (0x08) +#define FRDR (0x0A) +#define FCR (0x0C) +#define FDR (0x0E) +#define SPTR (0x10) +#define LSR (0x12) +#define SEMR (0x14) +#define FTCR (0x16) + +#define SCR_CKE_MASK (0x03) +#define SCR_CKE_INTERN (0x00) +#define SCR_RE_ON (0x10) +#define SCR_TE_ON (0x20) +#define SCR_INIT (0x00) +#define SCR_READY (SCR_INIT | SCR_RE_ON | SCR_TE_ON) + +#define FCR_RFRST_RST (0x02) +#define FCR_TFRST_RST (0x04) +#define FCR_BASE (0x00) +#define FCR_RST (FCR_BASE | FCR_RFRST_RST | FCR_TFRST_RST) +#define FCR_RUN (FCR_BASE) + +#define SMR_INIT (0x00) + +#define SEMR_NFEN_ON (0x04) +#define SEMR_MDDRS_BRR (0x00) +#define SEMR_MDDRS_MDDR (0x10) +#define SEMR_BRME_ON (0x20) +//#define SEMR_BASE (SEMR_NFEN_ON) +#define SEMR_BASE (0x00) +#define SEMR_BRR (SEMR_BASE | SEMR_MDDRS_BRR) +#define SEMR_MDDR (SEMR_BASE | SEMR_MDDRS_MDDR | SEMR_BRME_ON) + +#define FTCR_TTRGS (0x0080) +#define FTCR_RTRGS (0x8000) + +#define FSR_TDFE_SHIFT (5) +#define FSR_TEND_SHIFT (6) +#define FSR_TEND (1< +#include +#include +#include +#include +#include +#include + +#include + +void spi_multi_setup_device( void ) +{ + + uint32_t val; + uint8_t read_status; + + mmio_write_32(SPIM_PHYOFFSET1, SPIM_PHYOFFSET1_SET_VALUE); + mmio_write_32(SPIM_PHYOFFSET2, SPIM_PHYOFFSET2_SET_VALUE); + spi_multi_timing_set(); + + /* Set Data read option */ + /* Required when command 0xEB is specified. + * Not required when a command other than is specified, + * but there is no problem in operation. + */ + val = SPIM_DROPR_SET_VALUE; + mmio_write_32(SPIM_DROPR, val); + + read_status = spi_multi_cmd_read(SMCMR_CMD_READ_STATUS_REGISTER_2); + if ((read_status & STATUS_2_QE) == STATUS_2_QE) { + return; + } + /* Write Enable Command */ + spi_multi_cmd_write(SMCMR_CMD_WRITE_ENABLE,SPI_MANUAL_COMMAND_SIZE_0,0); + /* Write Status Register-2 Command Quad Enable */ + val = ((STATUS_2_QE | read_status) << SMWDR0_1BYTE_DATA_BIT_SHIFT); + spi_multi_cmd_write(SMCMR_CMD_WRITE_STATUS_REGISTER_2,SPI_MANUAL_COMMAND_SIZE_8_BIT,val); + /* status 1 BUSY check */ + while(1) { + read_status = spi_multi_cmd_read(SMCMR_CMD_READ_STATUS_REGISTER_1); + if (( read_status & STATUS_1_BUSY_BIT) == STATUS_1_BUSY) { + udelay(STATUS_BUSY_READ_DELAY_TIME); + continue; + } else { + break; + } + } + return; +} diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/spi_multi/MT25QU512ABB/spi_multi_device.c b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/spi_multi/MT25QU512ABB/spi_multi_device.c new file mode 100644 index 00000000..dab52bf4 --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/spi_multi/MT25QU512ABB/spi_multi_device.c @@ -0,0 +1,10 @@ +/* + * Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +void spi_multi_setup_device( void ) +{ + return; +} diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/spi_multi/spi_multi.c b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/spi_multi/spi_multi.c new file mode 100644 index 00000000..a30438a9 --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/spi_multi/spi_multi.c @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include + +void spi_multi_timing_set(void) +{ + + /* Timing adjustment register setting */ + mmio_write_32(SPIM_PHYADJ2, 0xA5390000); + mmio_write_32(SPIM_PHYADJ1, 0x80000000); + mmio_write_32(SPIM_PHYADJ2, 0x00008080); + mmio_write_32(SPIM_PHYADJ1, 0x80000022); + mmio_write_32(SPIM_PHYADJ2, 0x00008080); + mmio_write_32(SPIM_PHYADJ1, 0x80000024); + + /* SDR mode serial flash settings */ + mmio_write_32(SPIM_PHYCNT, SPIM_PHYCNT_SDR_TIM_ADJ_SET_VALUE); + + /* Timing adjustment register setting */ + mmio_write_32(SPIM_PHYADJ2, 0x00000030); + mmio_write_32(SPIM_PHYADJ1, 0x80000032); + + dmbsy(); +} + +uint8_t spi_multi_cmd_read(uint8_t command) +{ + uint32_t val; + uint8_t r_status; + + /* SDR mode serial flash settings */ + mmio_write_32(SPIM_PHYCNT, SPIM_PHYCNT_SET_VALUE); + mmio_write_32(SPIM_PHYCNT, SPIM_PHYCNT_SDR_TIM_ADJ_SET_VALUE); + + /* Set the QSPIn_SSL setting value & Manual Mode */ + mmio_write_32(SPIM_CMNCR, SPIM_CMNCR_MANUAL_SET_VALUE); + + val = command << SMCMR_CMD_BIT_SHIFT; + mmio_write_32(SPIM_SMCMR, val); + + /* Set the Transfer Data size setting value & command output enable */ + val = SMENR_CDE | SPI_MANUAL_COMMAND_SIZE_16_BIT; + mmio_write_32(SPIM_SMENR, val); + + /* Set the SDR transfer & SPI flash mode setting value */ + mmio_write_32(SPIM_SMDRENR, SPIM_SMDRENR_SET_VALUE); + + val = SMCR_SPIE | SMCR_SPIRE; + mmio_write_32(SPIM_SMCR, val); + + /* Wait until the transfer is complete */ + do { + val = mmio_read_32(SPIM_CMNSR); + } while ((val & CMNSR_TEND) == 0); + + val=mmio_read_32(SPIM_SMRDR0); + + r_status = (uint8_t)val; + return(r_status); +} + +void spi_multi_cmd_write(uint8_t command,uint8_t size,uint32_t data) +{ + uint32_t val; + + /* SDR mode serial flash settings */ + mmio_write_32(SPIM_PHYCNT, SPIM_PHYCNT_SET_VALUE); + mmio_write_32(SPIM_PHYCNT, SPIM_PHYCNT_SDR_TIM_ADJ_SET_VALUE); + + /* Set the QSPIn_SSL setting value & Manual Mode */ + mmio_write_32(SPIM_CMNCR, SPIM_CMNCR_MANUAL_SET_VALUE); + + /* Set the Manual Mode Command */ + val = command << SMCMR_CMD_BIT_SHIFT; + mmio_write_32(SPIM_SMCMR, val); + + /* Set the Transfer Data size setting value & command output enable */ + val = SMENR_CDE | size; + mmio_write_32(SPIM_SMENR, val); + + /* Set the write data in Manual mode */ + mmio_write_32(SPIM_SMWDR0, data); + + /* Set the SDR transfer & SPI flash mode setting value */ + mmio_write_32(SPIM_SMDRENR, SPIM_SMDRENR_SET_VALUE); + + /* Set the data transfer enable & data write enable */ + if (size == SPI_MANUAL_COMMAND_SIZE_0) + { + val = SMCR_SPIE; + } else { + val = SMCR_SPIE | SMCR_SPIWE; + } + mmio_write_32(SPIM_SMCR, val); + + /* Wait until the transfer is complete */ + do { + val = mmio_read_32(SPIM_CMNSR); + } while ((val & CMNSR_TEND) == 0); +} + +int spi_multi_setup( void ) +{ + uint32_t val; + + /* Wait until the transfer is complete */ + do { + val = mmio_read_32(SPIM_CMNSR); + } while ((val & CMNSR_TEND) == 0); + + /* Device-specific settings */ + spi_multi_setup_device(); + /* SDR mode serial flash settings */ + mmio_write_32(SPIM_PHYCNT, SPIM_PHYCNT_SET_VALUE); + + /* Read timing setting */ + mmio_write_32(SPIM_PHYOFFSET1, SPIM_PHYOFFSET1_SET_VALUE); + mmio_write_32(SPIM_PHYOFFSET2, SPIM_PHYOFFSET2_SET_VALUE); + + /* Set the QSPIn_SSL setting value */ + mmio_write_32(SPIM_CMNCR, SPIM_CMNCR_EXTREAD_SET_VALUE); + /* Set SSL delay setting value */ + mmio_write_32(SPIM_SSLDR, SPIM_SSLDR_SET_VALUE); + + /* Clear the RBE bit */ + mmio_write_32(SPIM_DRCR, SPIM_DRCR_SET_VALUE); + mmio_read_32(SPIM_DRCR); + + /* Set the data read command */ + mmio_write_32(SPIM_DRCMR, SPIM_DRCMR_SET_VALUE); + + /* Extended external address setting */ + mmio_write_32(SPIM_DREAR, SPIM_DREAR_SET_VALUE); + + /* Set the bit width of command and address output to 1 bit and */ + /* the address size to 4 byte */ + mmio_write_32(SPIM_DRENR, SPIM_DRENR_SET_VALUE); + + /* Dummy cycle setting */ + mmio_write_32(SPIM_DRDMCR, SPIM_DRDMCR_SET_VALUE); + + /* Change to SPI flash mode */ + mmio_write_32(SPIM_DRDRENR, SPIM_DRDRENR_SET_VALUE); + + /* Timing adjustment register setting */ + spi_multi_timing_set(); + + return SPI_MULTI_SUCCESS; +} diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/syc.c b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/syc.c new file mode 100644 index 00000000..8b7212df --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/syc.c @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#define SYC_BASE RZG2L_SYC_BASE + +#define CNTCR (0x000) +#define CNTFID0 (0x020) + +#define CNTCR_EN (1 << 0) + +static inline void syc_reg_write(uint32_t offset, uint32_t val) +{ + mmio_write_32(SYC_BASE + offset, val); +} + +static inline uint32_t syc_reg_read(uint32_t offset) +{ + return mmio_read_32(SYC_BASE + offset); +} + +static void enable_counter(unsigned int enable) +{ + syc_reg_write(CNTCR, enable & CNTCR_EN); +} + +void syc_init(unsigned int freq) +{ + syc_reg_write(CNTFID0, freq); + enable_counter(CNTCR_EN); +} + +unsigned int syc_get_freq(void) +{ + return syc_reg_read(CNTFID0); +} diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/xspi/octa.c b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/xspi/octa.c new file mode 100644 index 00000000..ddad2d28 --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/xspi/octa.c @@ -0,0 +1,1157 @@ +/* + * Copyright (c) 2022, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Defaults */ +#define DEFAULT_SPI_FREQUENCY 66666667 +#define RESET_DURATION_US 10 +#define DEFAULT_VOLTAGE_IS_1800MV 1 +#define DEFAULT_CH0_CALIBRATION_OFFSET 0x1C0 +#define DEFAULT_CH1_CALIBRATION_OFFSET 0 + +/* Static function pre-definition */ +static int octa_open(xspi_ctrl_t * ctrl, xspi_cfg_t const * const cfg); +static int octa_close(xspi_ctrl_t * const ctrl); +static int octa_post_init(xspi_ctrl_t * const ctrl); +static int octa_exec_op(xspi_ctrl_t * const ctrl, xspi_op_t const * const op, bool is_write); +static int octa_configure_xip(xspi_ctrl_t * const ctrl, xspi_op_t const * const rop, xspi_op_t const * const wop); +static int octa_start_xip(xspi_ctrl_t * const ctrl); +static int octa_stop_xip(xspi_ctrl_t * const ctrl); +static int octa_run_manual_calibration(xspi_ctrl_t * const ctrl); +static int octa_enable_auto_calibration(xspi_ctrl_t * const ctrl); +static int octa_disable_auto_calibration(xspi_ctrl_t * const ctrl); +static int octa_set_frequency(xspi_ctrl_t * const ctrl, int frequency_hz); +static int octa_clean_mmap(xspi_ctrl_t * const ctrl); +static int octa_inv_mmap(xspi_ctrl_t * const ctrl); +static uintptr_t octa_get_mmap_base(xspi_ctrl_t * const ctrl); +static size_t octa_get_mmap_size(xspi_ctrl_t * const ctrl); +static uint32_t octa_get_features(xspi_ctrl_t * const ctrl); + +/* API function table definition */ +const xspi_api_t octa_api = { + .open = octa_open, + .close = octa_close, + .post_init = octa_post_init, + .exec_op = octa_exec_op, + .configure_xip = octa_configure_xip, + .start_xip = octa_start_xip, + .stop_xip = octa_stop_xip, + .run_manual_calibration = octa_run_manual_calibration, + .enable_auto_calibration = octa_enable_auto_calibration, + .disable_auto_calibration = octa_disable_auto_calibration, + .set_frequency = octa_set_frequency, + .clean_mmap = octa_clean_mmap, + .inv_mmap = octa_inv_mmap, + .get_mmap_base = octa_get_mmap_base, + .get_mmap_size = octa_get_mmap_size, + .get_features = octa_get_features, +}; + +/* Preamble pattern (aligned to 16byte boundary) */ +static const uint32_t preamble[4] __aligned(16) = { + 0xFFFF0000, + 0x000800FF, + 0x00FFF700, + 0xF700F708, +}; + +/* Static variables */ +static bool globally_initialised = false; +static bool post_init_done = false; +static int spi_clock = DEFAULT_SPI_FREQUENCY; +static bool initialised[2] = {false, false}; +static int freq[2] = {INT_MAX, INT_MAX}; +static bool is_calibrated[2] = {false, false}; + +static const uintptr_t ch0_mmap_base = 0x20000000; +static const size_t ch0_mmap_size = 0x08000000; +static const uintptr_t ch1_mmap_base = 0x28000000; +static const size_t ch1_mmap_size = 0x08000000; + +/* !!! DO NOT TOUCH THESE SETTINGS !!! They are used for doing initialize. */ +static const uint32_t init_octa_dcr_value = 0; +static const uint32_t init_octa_dar_value = 0; +static const uint32_t init_octa_dcsr_value = 0 | + 0u << OCTA_DCSR_ACDA_POS | + 0u << OCTA_DCSR_DOPI_POS | + 0u << OCTA_DCSR_ADLEN_POS | + 0u << OCTA_DCSR_DAOR_POS | + 0u << OCTA_DCSR_CMDLEN_POS | + 0u << OCTA_DCSR_ACDV_POS | + 0u << OCTA_DCSR_DMLEN_POS | + 0u << OCTA_DCSR_DALEN_POS; +static const uint32_t init_octa_dsr0_value = 0 | + OCTA_DSR_TYP_NONE >> OCTA_DSR0_DV0TYP_POS | + 0u << OCTA_DSR0_DV0SZ_POS; +static const uint32_t init_octa_dsr1_value = 0 | + OCTA_DSR_TYP_NONE >> OCTA_DSR1_DV1TYP_POS | + 0u << OCTA_DSR1_DV1SZ_POS; +static const uint32_t init_octa_mdtr_value = 0 | + 6u << OCTA_MDTR_DQSEDOPI_POS | + 0x50u << OCTA_MDTR_DV1DEL_POS | + 9u << OCTA_MDTR_DQSESOPI_POS | + 4u << OCTA_MDTR_DQSERAM_POS | + 0x50u << OCTA_MDTR_DV0DEL_POS; +static const uint32_t init_octa_actr_value = 268435456; +static const uint32_t init_octa_acar0_value = 0x00000000; +static const uint32_t init_octa_acar1_value = 0x00000000; +static const uint32_t init_octa_drcstr_value = 0 | + 0u << OCTA_DRCSTR_DVRDLO1_POS | + 0u << OCTA_DRCSTR_DVRDHI1_POS | + 0u << OCTA_DRCSTR_DVRDCMD1_POS | +#if !RZA3 + 0u << OCTA_DRCSTR_CTR1_POS | + 127u << OCTA_DRCSTR_CTRW1_POS | +#endif + 0u << OCTA_DRCSTR_DVRDLO0_POS | + 0u << OCTA_DRCSTR_DVRDHI0_POS | + 0u << OCTA_DRCSTR_DVRDCMD0_POS | + 1u << OCTA_DRCSTR_CTR0_POS | + 127u << OCTA_DRCSTR_CTRW0_POS; +static const uint32_t init_octa_dwcstr_value = 0 | + 0u << OCTA_DWCSTR_DVWLO1_POS | + 0u << OCTA_DWCSTR_DVWHI1_POS | + 0u << OCTA_DWCSTR_DVWCMD1_POS | + 0u << OCTA_DWCSTR_DVWLO0_POS | + 0u << OCTA_DWCSTR_DVWHI0_POS | + 0u << OCTA_DWCSTR_DVWCMD0_POS; +static const uint32_t init_octa_dcstr_value = 0 | + 0u << OCTA_DCSTR_DVSELLO_POS | + 0u << OCTA_DCSTR_DVSELHI_POS | + 0u << OCTA_DCSTR_DVSELCMD_POS; +static const uint32_t init_octa_cdsr_value = 0 | + 1u << OCTA_CDSR_DLFT_POS | + 0u << OCTA_CDSR_ACMEME1_POS | + 0u << OCTA_CDSR_ACMEME0_POS | + 0u << OCTA_CDSR_DV1PC_POS | + 0u << OCTA_CDSR_DV0PC_POS | + OCTA_CDSR_DVTTYP_SPI << OCTA_CDSR_DV1TTYP_POS | + OCTA_CDSR_DVTTYP_SPI << OCTA_CDSR_DV0TTYP_POS; +static const uint32_t init_octa_mdlr_value = 0 | + 0u << OCTA_MDLR_DV1WDL_POS | + 0u << OCTA_MDLR_DV1RDL_POS | + 0u << OCTA_MDLR_DV0WDL_POS | + 0u << OCTA_MDLR_DV0RDL_POS; +static const uint32_t init_octa_mrwcr0_value = 0 | + 0u << OCTA_MRWCR0_D0MWCMD1_POS | + 0u << OCTA_MRWCR0_D0MWCMD0_POS | + 0u << OCTA_MRWCR0_D0MRCMD1_POS | + 0u << OCTA_MRWCR0_D0MRCMD0_POS; +static const uint32_t init_octa_mrwcr1_value = 0 | + 0u << OCTA_MRWCR1_D1MWCMD1_POS | + 0u << OCTA_MRWCR1_D1MWCMD0_POS | + 0u << OCTA_MRWCR1_D1MRCMD1_POS | + 0u << OCTA_MRWCR1_D1MRCMD0_POS; +static const uint32_t init_octa_mrwcsr_value = 0 | + 0u << OCTA_MRWCSR_MWO1_POS | + 0u << OCTA_MRWCSR_MWCL1_POS | + 0u << OCTA_MRWCSR_MWAL1_POS | + 0u << OCTA_MRWCSR_MRO1_POS | + 0u << OCTA_MRWCSR_MRCL1_POS | + 0u << OCTA_MRWCSR_MRAL1_POS | + 0u << OCTA_MRWCSR_MWO0_POS | + 0u << OCTA_MRWCSR_MWCL0_POS | + 0u << OCTA_MRWCSR_MWAL0_POS | + 0u << OCTA_MRWCSR_MRO0_POS | + 0u << OCTA_MRWCSR_MRCL0_POS | + 0u << OCTA_MRWCSR_MRAL0_POS; + +/* Function definitions */ +static void select_octa(octa_ctrl_t *myctrl, xspi_cfg_t const * const cfg) +{ + if (RZ_XSPI_EXCLUSIVE_SELECTOR) { + /* Check if SPIM selected */ + uint32_t ipcont_spi_octa = mmio_read_32(SYS_IPCONT); + if ((ipcont_spi_octa & IPCONT_SEL_SPI_OCTA) == IPCONT_SEL_SPI_OCTA_SPI) { + /* Reset SPIM controller */ + cpg_reset_on(CPG_CLOCK_SPIM); + + /* Stop SPIM clock */ + cpg_clock_off(CPG_CLOCK_SPIM); + } + else { + /* Reset the devices connected, required to change the device mode + * from OPI to SPI. + * Otherwise, the octa devices can not initialize by the SPI mode. + */ + mmio_clrbits_32(myctrl->reg_base + OCTA_RSTCNT, OCTA_RSTCNT_RSTVAL); + } + } + + /* Wait for reset SPI device */ + udelay(RESET_DURATION_US); + + if (RZ_XSPI_FORCE_VOLTAGE_SETTING) { + /* force voltage setting + * Note: This is required if the boot mode is neither 3 nor 4. + */ + uint8_t voltage = DEFAULT_VOLTAGE_IS_1800MV; + mmio_write_8(PFC_QSPI, voltage); + mmio_read_8(PFC_QSPI); + } + + /* Supply OCTA clock */ + cpg_clock_on(CPG_CLOCK_OCTA); + + /* Resume OCTA controller */ + cpg_reset_off(CPG_CLOCK_OCTA); + + if (RZ_XSPI_EXCLUSIVE_SELECTOR) { + /* Select OCTA for SPI controller */ + uint32_t ipcont_spi_octa = mmio_read_32(SYS_IPCONT); + ipcont_spi_octa &= ~IPCONT_SEL_SPI_OCTA; + ipcont_spi_octa |= IPCONT_SEL_SPI_OCTA_OCTA << IPCONT_SEL_SPI_OCTA_POS; + mmio_write_32(SYS_IPCONT, ipcont_spi_octa); + mmio_read_32(SYS_IPCONT); + } + + /* De-assert reset line */ + mmio_setbits_32(myctrl->reg_base + OCTA_RSTCNT, OCTA_RSTCNT_RSTVAL); +} + +static void octa_init(octa_ctrl_t *myctrl) +{ + mmio_write_32(myctrl->reg_base+OCTA_DCR, init_octa_dcr_value); + mmio_write_32(myctrl->reg_base+OCTA_DAR, init_octa_dar_value); + mmio_write_32(myctrl->reg_base+OCTA_DCSR, init_octa_dcsr_value); + mmio_write_32(myctrl->reg_base+OCTA_DSR0, init_octa_dsr0_value); + mmio_write_32(myctrl->reg_base+OCTA_DSR1, init_octa_dsr1_value); + mmio_write_32(myctrl->reg_base+OCTA_MDTR, init_octa_mdtr_value); + mmio_write_32(myctrl->reg_base+OCTA_ACTR, init_octa_actr_value); + mmio_write_32(myctrl->reg_base+OCTA_ACAR0, init_octa_acar0_value); + mmio_write_32(myctrl->reg_base+OCTA_ACAR1, init_octa_acar1_value); + mmio_write_32(myctrl->reg_base+OCTA_DRCSTR, init_octa_drcstr_value); + mmio_write_32(myctrl->reg_base+OCTA_DWCSTR, init_octa_dwcstr_value); + mmio_write_32(myctrl->reg_base+OCTA_DCSTR, init_octa_dcstr_value); + mmio_write_32(myctrl->reg_base+OCTA_CDSR, init_octa_cdsr_value); + mmio_write_32(myctrl->reg_base+OCTA_MDLR, init_octa_mdlr_value); + mmio_write_32(myctrl->reg_base+OCTA_MRWCR0, init_octa_mrwcr0_value); + mmio_write_32(myctrl->reg_base+OCTA_MRWCR1, init_octa_mrwcr1_value); + mmio_write_32(myctrl->reg_base+OCTA_MRWCSR, init_octa_mrwcsr_value); +} + +static int octa_open(xspi_ctrl_t * ctrl, xspi_cfg_t const * const cfg) +{ + int result = -1; + assert(ctrl); + assert(cfg); + assert(cfg->channel == 0 || cfg->channel == 1); + octa_ctrl_t * myctrl = (octa_ctrl_t *)ctrl; + octa_ext_t * ext = (octa_ext_t*)cfg->extend; + assert(cfg->base); + + if (myctrl->opened) return -1; + + myctrl->reg_base = cfg->base; + myctrl->channel = cfg->channel; + + result = 0; + + if (!globally_initialised) { + /* Initialize IP (once) */ + select_octa(myctrl, cfg); + octa_init(myctrl); + + globally_initialised = true; + } + + /* Initialize MMAP base and initial size */ + size_t mmap_size; + if (myctrl->channel) { + myctrl->mmap_base = ch1_mmap_base; + mmap_size = ch1_mmap_size; + } + else { + myctrl->mmap_base = ch0_mmap_base; + mmap_size = ch0_mmap_size; + } + + /* Override size if specified and is smaller */ + if (ext && mmap_size > (size_t)ext->device_size) { + mmap_size = (size_t)ext->device_size; + } + + /* Store mmap size */ + myctrl->mmap_size = mmap_size; + + /* Set device type and calibrate address */ + uint8_t device_type; + if (myctrl->channel) { + device_type = OCTA_DSR_TYP_RAM; + /* Override calibration base if specified */ + uint32_t ch1_calibration_offset = DEFAULT_CH1_CALIBRATION_OFFSET; + if (ext && ext->calibration_base != UINT32_MAX) { + ch1_calibration_offset = ext->calibration_base; + } + myctrl->calibration_base = ch1_calibration_offset; + mmio_write_32(myctrl->reg_base + OCTA_ACAR1, myctrl->calibration_base); + } + else { + device_type = OCTA_DSR_TYP_FLASH; + /* Override calibration base if specified */ + uint32_t ch0_calibration_offset = DEFAULT_CH0_CALIBRATION_OFFSET; + if (ext && ext->calibration_base != 0) { + ch0_calibration_offset = ext->calibration_base; + } + myctrl->calibration_base = ch0_calibration_offset; + mmio_write_32(myctrl->reg_base + OCTA_ACAR0, myctrl->calibration_base); + } + myctrl->device_type = device_type; + + /* Sets DVnSZ only first per channel */ + if (!initialised[myctrl->channel]) { + uint32_t dsr; + if (ext) { + dsr = ext->device_size; + } + else { + dsr = mmap_size; + } + + if (myctrl->channel) { + uint32_t aer; + if (dsr <= 8*1024*1024) aer = OCTA_AER_LE64MB; + else if (dsr <= 16*1024*1024) aer = OCTA_AER_128MB; + else if (dsr <= 32*1024*1024) aer = OCTA_AER_256MB; + else aer = OCTA_AER_512MB; + dsr <<= OCTA_DSR1_DV1SZ_POS; + dsr |= (uint32_t)device_type << OCTA_DSR1_DV1TYP_POS; + mmio_write_32(myctrl->reg_base + OCTA_AER, aer); + mmio_write_32(myctrl->reg_base + OCTA_DSR1, dsr); + } + else { + dsr <<= OCTA_DSR0_DV0SZ_POS; + dsr |= (uint32_t)device_type << OCTA_DSR0_DV0TYP_POS; + mmio_write_32(myctrl->reg_base + OCTA_DSR0, dsr); + } + initialised[myctrl->channel] = true; + } + + myctrl->opened = true; + + return result; +} + +static int octa_close(xspi_ctrl_t * const ctrl) +{ + int result = -1; + assert(ctrl); + octa_ctrl_t * myctrl = (octa_ctrl_t *)ctrl; + if (myctrl->opened) { + myctrl->opened = false; + result = 0; + } + return result; + +} + +static bool octa_check_acmode_ready(bool acmeme, bool is_dopi, int channel) +{ + if (!initialised[channel]) return true; /* Ignore for empty channel */ + if (!is_dopi) return true; /* Ignore or SPI/SOPI channel */ + if (!is_calibrated[channel]) return true; /* Ignore if failed the manual calibration */ + return acmeme; /* On DOPI, Follow acmeme setting */ +} + +static void octa_set_acmode(uint32_t * cdsr) +{ + if (post_init_done) { + bool flag_0, flag_1, acmeme0, acmeme1, is_dopi; + + /* Check if CH0 is ready for enabling ACMODE */ + acmeme0 = (*cdsr & OCTA_CDSR_ACMEME0) != 0; + is_dopi = (*cdsr & OCTA_CDSR_DV0TTYP) == (OCTA_CDSR_DVTTYP_DOPI << OCTA_CDSR_DV0TTYP_POS); + flag_0 = octa_check_acmode_ready(acmeme0, is_dopi, 0); + + /* Check if CH1 is ready for enabling ACMODE */ + acmeme1 = (*cdsr & OCTA_CDSR_ACMEME1) != 0; + is_dopi = (*cdsr & OCTA_CDSR_DV1TTYP) == (OCTA_CDSR_DVTTYP_DOPI << OCTA_CDSR_DV1TTYP_POS); + flag_1 = octa_check_acmode_ready(acmeme1, is_dopi, 1); + + /* mask old value */ + *cdsr &= ~OCTA_CDSR_ACMODE; + + /* When both CH0/CH1 are ready for enabling ACMODE and either ACMEME0 or ACMEME1 is enabled */ + if (flag_0 && flag_1 && (acmeme0 || acmeme1)) { + *cdsr |= OCTA_CDSR_ACMODE_ENABLE << OCTA_CDSR_ACMODE_POS; + } + } +} + +static void octa_set_auto_calibration(octa_ctrl_t *myctrl) +{ + uint32_t cdsr = mmio_read_32(myctrl->reg_base + OCTA_CDSR); + + /* Set/reset ACMODE */ + octa_set_acmode(&cdsr); + mmio_write_32(myctrl->reg_base + OCTA_CDSR, cdsr & ~OCTA_CDSR_ACMODE); + mmio_write_32(myctrl->reg_base + OCTA_CDSR, cdsr); +} + +static int octa_post_init(xspi_ctrl_t * const ctrl) +{ + int result = 0; + assert(ctrl); + octa_ctrl_t * myctrl = (octa_ctrl_t *)ctrl; + + if (!post_init_done) { + post_init_done = true; + octa_set_auto_calibration(myctrl); + } + + return result; +} + +static int octa_test_ddr(xspi_op_t const * const op) +{ + if (!(op->op_is_ddr == op->address_is_ddr)) return -1; + if (!op->op_is_ddr && !op->address_is_ddr && op->transfer_is_ddr) return -1; + return 0; +} + +static int octa_test_form(octa_ctrl_t const * const myctrl, xspi_op_t const * const op) +{ + if (!(myctrl->device_type!=OCTA_DSR_TYP_NONE)) return -1; + if (!((myctrl->device_type==OCTA_DSR_TYP_FLASH && + (op->form==SPI_FORM_8_8_8 || (op->form==SPI_FORM_1_1_1 && !op->op_is_ddr && !op->address_is_ddr && !op->transfer_is_ddr))) || + (myctrl->device_type==OCTA_DSR_TYP_RAM && op->form==SPI_FORM_8_8_8 && op->op_is_ddr && op->address_is_ddr && op->transfer_is_ddr))) return -1; + return 0; +} + +static int octa_exec_op(xspi_ctrl_t * const ctrl, xspi_op_t const * const op, bool is_write) +{ + assert(!!ctrl); + assert(!!op); + int res; + octa_ctrl_t * myctrl = (octa_ctrl_t *)ctrl; + res = octa_test_ddr(op); + if (!!res) return res; + res = octa_test_form(myctrl, op); + if (!!res) return res; + + assert( op->transfer_size==0 || + op->transfer_size==1 || + op->transfer_size==2 || + op->transfer_size==4 || + (op->transfer_size==3 && op->transfer_is_ddr==false && is_write==false)); + + uint32_t dcstr; + uint32_t dcsr_clear, dcsr_set; + dcsr_clear = dcsr_set = 0; + uint32_t cdsr_clear, cdsr_set, save_cdsr; + cdsr_clear = cdsr_set = 0; + uint32_t mdtr_clear, mdtr_set, save_mdtr; + mdtr_clear = mdtr_set = 0; + + /* change write flag if no transfer phase required */ + if (op->transfer_size == 0) is_write = true; + + /* select and check memory type */ + int transfer_type; + int enable_counter; + switch (op->form) { + case SPI_FORM_8_8_8: + if (op->op_is_ddr) { + /* DOPI */ + if (myctrl->device_type == OCTA_DSR_TYP_RAM) { + transfer_type = OCTA_CDSR_DVTTYP_DOPI; + enable_counter = op->dummy_cycles + 1; + if (enable_counter > 15) enable_counter = 15; + mdtr_clear |= OCTA_MDTR_DQSERAM; + mdtr_set |= enable_counter << OCTA_MDTR_DQSERAM_POS; + } + else { + transfer_type = OCTA_CDSR_DVTTYP_DOPI; + enable_counter = op->dummy_cycles + 2; + if (enable_counter > 15) enable_counter = 15; + mdtr_clear |= OCTA_MDTR_DQSEDOPI; + mdtr_set |= enable_counter << OCTA_MDTR_DQSEDOPI_POS; + } + } + else { + /* SOPI */ + transfer_type = OCTA_CDSR_DVTTYP_SOPI; + enable_counter = op->dummy_cycles + 4; + if (enable_counter > 15) enable_counter = 15; + mdtr_clear |= OCTA_MDTR_DQSESOPI; + mdtr_set |= enable_counter << OCTA_MDTR_DQSESOPI_POS; + } + break; + case SPI_FORM_1_1_1: + transfer_type = OCTA_CDSR_DVTTYP_SPI; + break; + default: + ERROR("Unsupported transfer form %d\n", op->form); + return -1; + } + + /* lock channel (not implemented) */ + + /* save shared parameters */ + save_cdsr = mmio_read_32(myctrl->reg_base + OCTA_CDSR); + save_mdtr = mmio_read_32(myctrl->reg_base + OCTA_MDTR); + + /* set controller operation parameters */ + mmio_write_32(myctrl->reg_base + OCTA_DCR, (uint32_t)op->op); + mmio_write_32(myctrl->reg_base + OCTA_DAR, op->address); + dcstr = op->slch_value << OCTA_DCSTR_DVSELLO_POS; + dcstr |= op->clsh_value << OCTA_DCSTR_DVSELHI_POS; + dcstr |= op->shsl_value << OCTA_DCSTR_DVSELCMD_POS; + mmio_write_32(myctrl->reg_base + OCTA_DCSTR, dcstr); + cdsr_clear |= OCTA_CDSR_ACMODE; + dcsr_clear |= OCTA_DCSR_ADLEN; + dcsr_set |= op->address_size << OCTA_DCSR_ADLEN_POS; + dcsr_clear |= OCTA_DCSR_CMDLEN; + dcsr_set |= op->op_size << OCTA_DCSR_CMDLEN_POS; + dcsr_clear |= OCTA_DCSR_DMLEN; + dcsr_set |= op->dummy_cycles << OCTA_DCSR_DMLEN_POS; + dcsr_clear |= OCTA_DCSR_DALEN; + /* For 3-byte transfer, modify as 4byte transfer */ + dcsr_set |= (op->transfer_size == 3 ? 4u : op->transfer_size) << OCTA_DCSR_DALEN_POS; + /* Force data access method */ + dcsr_clear |= OCTA_DCSR_ACDA; + if (op->transfer_flag & XSPI_FLAGS_DATA_ACCESS) { + dcsr_set |= OCTA_DCSR_ACDA; + } + + /* set channel related parameters */ + dcsr_clear |= OCTA_DCSR_ACDV; + dcsr_set |= myctrl->channel << OCTA_DCSR_ACDV_POS; + if (myctrl->channel) { + /* Channel 1 */ + cdsr_clear |= OCTA_CDSR_DV1PC | OCTA_CDSR_DV1TTYP; + cdsr_set |= transfer_type << OCTA_CDSR_DV1TTYP_POS; + } + else { + /* Channel 0 */ + cdsr_clear |= OCTA_CDSR_DV0PC | OCTA_CDSR_DV0TTYP; + cdsr_set |= transfer_type << OCTA_CDSR_DV0TTYP_POS; + } + + /* change transfer order */ + dcsr_clear |= OCTA_DCSR_DAOR; + if (~op->transfer_flag & XSPI_FLAGS_SEQUENTIAL_DDR) { + if (op->transfer_is_ddr) { + dcsr_set |= OCTA_DCSR_DAOR; + } + } + /* change SDR mode (DOPI mode with SDR transfer) */ + dcsr_clear |= OCTA_DCSR_DOPI; + if (transfer_type == OCTA_CDSR_DVTTYP_DOPI && !op->transfer_is_ddr) { + dcsr_set |= OCTA_DCSR_DOPI; + } + + mmio_clrsetbits_32(myctrl->reg_base + OCTA_DCSR, dcsr_clear, dcsr_set); + mmio_clrsetbits_32(myctrl->reg_base + OCTA_CDSR, cdsr_clear, cdsr_set); + mmio_clrsetbits_32(myctrl->reg_base + OCTA_MDTR, mdtr_clear, mdtr_set); + + if (is_write) { + switch(op->transfer_size) { + case 0: + mmio_write_32(myctrl->reg_base + OCTA_CWNDR, 0); + break; + case 1: + mmio_write_8(myctrl->reg_base + OCTA_CWDR, *(uint8_t*)op->transfer_buffer); + break; + case 2: + mmio_write_16(myctrl->reg_base + OCTA_CWDR, *(uint16_t*)op->transfer_buffer); + break; + case 4: + mmio_write_32(myctrl->reg_base + OCTA_CWDR, *(uint32_t*)op->transfer_buffer); + break; + } + } + else { + mmio_read_32(myctrl->reg_base + OCTA_CDSR); + switch(op->transfer_size) { + case 1: + *(uint8_t*)op->transfer_buffer = mmio_read_8(myctrl->reg_base + OCTA_CRR); + break; + case 2: + *(uint16_t*)op->transfer_buffer = mmio_read_16(myctrl->reg_base + OCTA_CRR); + break; + case 3: { + uint32_t tmp = mmio_read_32(myctrl->reg_base + OCTA_CRR); + uint8_t * u8p = (uint8_t*)op->transfer_buffer; + u8p[0] = tmp & 0xff; + u8p[1] = tmp & 0xff00 >> 8; + u8p[2] = tmp & 0xff0000 >> 16; + break; + } + case 4: + *(uint32_t*)op->transfer_buffer = mmio_read_32(myctrl->reg_base + OCTA_CRR); + break; + } + } + + /* restore shared parameters */ + mmio_write_32(myctrl->reg_base + OCTA_MDTR, save_mdtr); + mmio_write_32(myctrl->reg_base + OCTA_CDSR, save_cdsr); + + /* unlock channel (not implemented) */ + + return 0; +} + +static void octa_configure_xip_ch1(octa_ctrl_t * const myctrl, xspi_op_t const * const rop, xspi_op_t const * const wop) +{ + uint32_t mdlr_clear, mdlr_set; + mdlr_clear = mdlr_set = 0; + uint32_t mrwcr_clear, mrwcr_set; + mrwcr_clear = mrwcr_set = 0; + uint32_t mrwcsr_clear, mrwcsr_set; + mrwcsr_clear = mrwcsr_set = 0; + + if (rop) { + uint32_t drcstr_clear, drcstr_set; + drcstr_clear = drcstr_set = 0; + drcstr_clear |= OCTA_DRCSTR_DVRDLO1|OCTA_DRCSTR_DVRDHI1|OCTA_DRCSTR_DVRDCMD1; + drcstr_set |= rop->slch_value << OCTA_DRCSTR_DVRDLO1_POS; + drcstr_set |= rop->clsh_value << OCTA_DRCSTR_DVRDHI1_POS; + drcstr_set |= rop->shsl_value << OCTA_DRCSTR_DVRDCMD1_POS; + mdlr_clear |= OCTA_MDLR_DV1RDL; + mdlr_set |= rop->dummy_cycles << OCTA_MDLR_DV1RDL_POS; + mrwcr_clear |= OCTA_MRWCR1_D1MRCMD0 | OCTA_MRWCR1_D1MRCMD1; + mrwcr_set |= (uint32_t)rop->op << OCTA_MRWCR1_D1MRCMD0_POS; + mrwcsr_clear |= OCTA_MRWCSR_MRO1 | OCTA_MRWCSR_MRCL1 | OCTA_MRWCSR_MRAL1; + if (rop->transfer_is_ddr && ~rop->transfer_flag & XSPI_FLAGS_SEQUENTIAL_DDR) { + mrwcsr_set |= 1u << OCTA_MRWCSR_MRO1_POS; + } + mrwcsr_set |= rop->op_size << OCTA_MRWCSR_MRCL1_POS; + mrwcsr_set |= rop->address_size << OCTA_MRWCSR_MRAL1_POS; + mmio_clrsetbits_32(myctrl->reg_base + OCTA_DRCSTR, drcstr_clear, drcstr_set); + } + if (wop) { + uint32_t dwcstr_clear, dwcstr_set; + dwcstr_clear = dwcstr_set = 0; + dwcstr_clear |= OCTA_DWCSTR_DVWLO1|OCTA_DWCSTR_DVWHI1|OCTA_DWCSTR_DVWCMD1; + dwcstr_set |= wop->slch_value << OCTA_DWCSTR_DVWLO1_POS; + dwcstr_set |= wop->clsh_value << OCTA_DWCSTR_DVWHI1_POS; + dwcstr_set |= wop->shsl_value << OCTA_DWCSTR_DVWCMD1_POS; + mdlr_clear |= OCTA_MDLR_DV1WDL; + mdlr_set |= wop->dummy_cycles << OCTA_MDLR_DV1WDL_POS; + mrwcr_clear |= OCTA_MRWCR1_D1MWCMD0 | OCTA_MRWCR1_D1MWCMD1; + mrwcr_set |= (uint32_t)wop->op << OCTA_MRWCR1_D1MWCMD0_POS; + mrwcsr_clear |= OCTA_MRWCSR_MWO1 | OCTA_MRWCSR_MWCL1 | OCTA_MRWCSR_MWAL1; + if (wop->transfer_is_ddr && ~wop->transfer_flag & XSPI_FLAGS_SEQUENTIAL_DDR) { + mrwcsr_set |= 1u << OCTA_MRWCSR_MWO1_POS; + } + mrwcsr_set |= wop->op_size << OCTA_MRWCSR_MWCL1_POS; + mrwcsr_set |= wop->address_size << OCTA_MRWCSR_MWAL1_POS; + mmio_clrsetbits_32(myctrl->reg_base + OCTA_DWCSTR, dwcstr_clear, dwcstr_set); + } + mmio_clrsetbits_32(myctrl->reg_base + OCTA_MDLR, mdlr_clear, mdlr_set); + mmio_clrsetbits_32(myctrl->reg_base + OCTA_MRWCR1, mrwcr_clear, mrwcr_set); + mmio_clrsetbits_32(myctrl->reg_base + OCTA_MRWCSR, mrwcsr_clear, mrwcsr_set); +} + +static void octa_configure_xip_ch0(octa_ctrl_t * const myctrl, xspi_op_t const * const rop, xspi_op_t const * const wop) +{ + uint32_t mdlr_clear, mdlr_set; + mdlr_clear = mdlr_set = 0; + uint32_t mrwcr_clear, mrwcr_set; + mrwcr_clear = mrwcr_set = 0; + uint32_t mrwcsr_clear, mrwcsr_set; + mrwcsr_clear = mrwcsr_set = 0; + + if (rop) { + uint32_t drcstr_clear, drcstr_set; + drcstr_clear = drcstr_set = 0; + drcstr_clear |= OCTA_DRCSTR_DVRDLO0|OCTA_DRCSTR_DVRDHI0|OCTA_DRCSTR_DVRDCMD0; + drcstr_set |= rop->slch_value << OCTA_DRCSTR_DVRDLO0_POS; + drcstr_set |= rop->clsh_value << OCTA_DRCSTR_DVRDHI0_POS; + drcstr_set |= rop->shsl_value << OCTA_DRCSTR_DVRDCMD0_POS; + mdlr_clear |= OCTA_MDLR_DV0RDL; + mdlr_set |= rop->dummy_cycles << OCTA_MDLR_DV0RDL_POS; + mrwcr_clear |= OCTA_MRWCR0_D0MRCMD0 | OCTA_MRWCR0_D0MRCMD1; + mrwcr_set |= (uint32_t)rop->op << OCTA_MRWCR0_D0MRCMD0_POS; + mrwcsr_clear |= OCTA_MRWCSR_MRO0 | OCTA_MRWCSR_MRCL0 | OCTA_MRWCSR_MRAL0; + if (rop->transfer_is_ddr && ~rop->transfer_flag & XSPI_FLAGS_SEQUENTIAL_DDR) { + mrwcsr_set |= 1u << OCTA_MRWCSR_MRO0_POS; + } + mrwcsr_set |= rop->op_size << OCTA_MRWCSR_MRCL0_POS; + mrwcsr_set |= rop->address_size << OCTA_MRWCSR_MRAL0_POS; + mmio_clrsetbits_32(myctrl->reg_base + OCTA_DRCSTR, drcstr_clear, drcstr_set); + } + if (wop) { + uint32_t dwcstr_clear, dwcstr_set; + dwcstr_clear = dwcstr_set = 0; + dwcstr_clear |= OCTA_DWCSTR_DVWLO0|OCTA_DWCSTR_DVWHI0|OCTA_DWCSTR_DVWCMD0; + dwcstr_set |= wop->slch_value << OCTA_DWCSTR_DVWLO0_POS; + dwcstr_set |= wop->clsh_value << OCTA_DWCSTR_DVWHI0_POS; + dwcstr_set |= wop->shsl_value << OCTA_DWCSTR_DVWCMD0_POS; + mdlr_clear |= OCTA_MDLR_DV0WDL; + mdlr_set |= wop->dummy_cycles << OCTA_MDLR_DV0WDL_POS; + mrwcr_clear |= OCTA_MRWCR0_D0MWCMD0 | OCTA_MRWCR0_D0MWCMD1; + mrwcr_set |= (uint32_t)wop->op << OCTA_MRWCR0_D0MWCMD0_POS; + mrwcsr_clear |= OCTA_MRWCSR_MWO0 | OCTA_MRWCSR_MWCL0 | OCTA_MRWCSR_MWAL0; + if (wop->transfer_is_ddr && ~wop->transfer_flag & XSPI_FLAGS_SEQUENTIAL_DDR) { + mrwcsr_set |= 1u << OCTA_MRWCSR_MWO0_POS; + } + mrwcsr_set |= wop->op_size << OCTA_MRWCSR_MWCL0_POS; + mrwcsr_set |= wop->address_size << OCTA_MRWCSR_MWAL0_POS; + mmio_clrsetbits_32(myctrl->reg_base + OCTA_DWCSTR, dwcstr_clear, dwcstr_set); + } + mmio_clrsetbits_32(myctrl->reg_base + OCTA_MDLR, mdlr_clear, mdlr_set); + mmio_clrsetbits_32(myctrl->reg_base + OCTA_MRWCR0, mrwcr_clear, mrwcr_set); + mmio_clrsetbits_32(myctrl->reg_base + OCTA_MRWCSR, mrwcsr_clear, mrwcsr_set); +} + +static int octa_configure_xip(xspi_ctrl_t * const ctrl, xspi_op_t const * const rop, xspi_op_t const * const wop) +{ + assert(ctrl); + assert(!!rop||!!wop); + if (!rop && !wop) return -1; + octa_ctrl_t * myctrl = (octa_ctrl_t *)ctrl; + xspi_op_t const * op = NULL; + if (wop) { + op = wop; + octa_test_ddr(wop); + octa_test_form(myctrl, wop); + } + if (rop) { + op = rop; + octa_test_ddr(rop); + octa_test_form(myctrl, rop); + } + if (rop && wop) { + assert(rop->form==wop->form); + assert(rop->op_is_ddr==wop->op_is_ddr && rop->address_is_ddr==wop->address_is_ddr && rop->transfer_is_ddr==wop->transfer_is_ddr); + } + + uint32_t cdsr_clear, cdsr_set, mdtr_clear, mdtr_set; + cdsr_clear = cdsr_set = mdtr_clear = mdtr_set = 0; + + int transfer_type; + int enable_counter; + + switch (op->form) { + case SPI_FORM_8_8_8: + if (op->op_is_ddr) { + /* DOPI */ + if (myctrl->device_type == OCTA_DSR_TYP_RAM) { + transfer_type = OCTA_CDSR_DVTTYP_DOPI; + if (rop) { + enable_counter = rop->dummy_cycles + 1; + if (enable_counter > 15) enable_counter = 15; + mdtr_clear |= OCTA_MDTR_DQSERAM; + mdtr_set |= enable_counter << OCTA_MDTR_DQSERAM_POS; + } + if (myctrl->channel && !RZA3) { + mmio_clrsetbits_32(myctrl->reg_base + OCTA_DRCSTR, OCTA_DRCSTR_CTR1, 0); + } + else if (!myctrl->channel) { + mmio_clrsetbits_32(myctrl->reg_base + OCTA_DRCSTR, OCTA_DRCSTR_CTR0, 0); + } + } + else { + transfer_type = OCTA_CDSR_DVTTYP_DOPI; + if (rop) { + enable_counter = rop->dummy_cycles + 2; + if (enable_counter > 15) enable_counter = 15; + mdtr_clear |= OCTA_MDTR_DQSEDOPI; + mdtr_set |= enable_counter << OCTA_MDTR_DQSEDOPI_POS; + } + if (myctrl->channel && !RZA3) { + mmio_clrsetbits_32(myctrl->reg_base + OCTA_DRCSTR, OCTA_DRCSTR_CTR1, OCTA_DRCSTR_CTR1); + } + else if (!myctrl->channel) { + mmio_clrsetbits_32(myctrl->reg_base + OCTA_DRCSTR, OCTA_DRCSTR_CTR0, OCTA_DRCSTR_CTR0); + } + } + } + else { + /* SOPI */ + transfer_type = OCTA_CDSR_DVTTYP_SOPI; + if (rop) { + enable_counter = rop->dummy_cycles + 4; + if (enable_counter > 15) enable_counter = 15; + mdtr_clear |= OCTA_MDTR_DQSESOPI; + mdtr_set |= enable_counter << OCTA_MDTR_DQSESOPI_POS; + } + if (myctrl->channel && !RZA3) { + mmio_clrsetbits_32(myctrl->reg_base + OCTA_DRCSTR, OCTA_DRCSTR_CTR1, 0); + } + else if (!myctrl->channel) { + mmio_clrsetbits_32(myctrl->reg_base + OCTA_DRCSTR, OCTA_DRCSTR_CTR0, 0); + } + } + break; + case SPI_FORM_1_1_1: + transfer_type = OCTA_CDSR_DVTTYP_SPI; + break; + default: + ERROR("Unsupported transfer form %d\n", rop->form); + return -1; + } + + if (myctrl->channel) { + octa_configure_xip_ch1(myctrl, rop, wop); + cdsr_clear |= OCTA_CDSR_DV1TTYP; + cdsr_set |= transfer_type << OCTA_CDSR_DV1TTYP_POS; + cdsr_clear |= OCTA_CDSR_DV1PC; + } + else { + octa_configure_xip_ch0(myctrl, rop, wop); + cdsr_clear |= OCTA_CDSR_DV0TTYP; + cdsr_set |= transfer_type << OCTA_CDSR_DV0TTYP_POS; + cdsr_clear |= OCTA_CDSR_DV0PC; + } + + mmio_clrsetbits_32(myctrl->reg_base + OCTA_MDTR, mdtr_clear, mdtr_set); + mmio_clrsetbits_32(myctrl->reg_base + OCTA_CDSR, cdsr_clear, cdsr_set); + + return 0; +} + +static int octa_start_xip(xspi_ctrl_t * const ctrl) +{ + assert(ctrl); + octa_ctrl_t * myctrl = (octa_ctrl_t *)ctrl; + /* Flush write buffer for OCTA controller register space */ + mmio_read_32(myctrl->reg_base + OCTA_DCR); + /* Invalidate cache */ + inv_dcache_range(myctrl->mmap_base, myctrl->mmap_size); + + return 0; +} + +static int octa_stop_xip(xspi_ctrl_t * const ctrl) +{ + assert(ctrl); + octa_ctrl_t * myctrl = (octa_ctrl_t *)ctrl; + /* Clean cache */ + clean_dcache_range(myctrl->mmap_base, myctrl->mmap_size); + + return 0; +} + +#define DELAY_LEVELS 16 +static int get_ok_area_start(bool *p_s_ok_ng_result) +{ + int index; /**< loop counter */ + int index_start = -1; + + /* detect ok area index start */ + for (index = 0; index < DELAY_LEVELS; index++ ) { + if (p_s_ok_ng_result[index]) { + index_start = index; + break; + } + } + return index_start; +} + +static int get_ok_area_count(bool *p_s_ok_ng_result, int index_start) +{ + int index; /**< loop counter */ + int ok_cnt = 0; + + /* count number of ok */ + for (index = index_start; index < DELAY_LEVELS; index++) { + if (p_s_ok_ng_result[index]) { + ok_cnt++; + } + else + { + break; + } + + } + return ok_cnt; +} + +static int octa_manual_calibration_common(octa_ctrl_t *myctrl) +{ + volatile uint32_t * p_preamble; + int judge_result; + int i; + int index; /**< loop counter */ + int index_start = -1; + int ok_cnt = 0; + bool is_ok[DELAY_LEVELS]; + + uint32_t mdtr = mmio_read_32(myctrl->reg_base + OCTA_MDTR); + uint32_t mdtr_save = mdtr; + int mdtr_pos; + if (myctrl->channel) { + mdtr &= ~OCTA_MDTR_DV1DEL; + mdtr_pos = OCTA_MDTR_DV1DEL_POS; + } + else { + mdtr &= ~OCTA_MDTR_DV0DEL; + mdtr_pos = OCTA_MDTR_DV0DEL_POS; + } + + /* detect ok/ng area */ + uintptr_t offset = (uintptr_t)myctrl->calibration_base; + offset += myctrl->mmap_base; + p_preamble = (uint32_t*)offset; + for (index = 0; index < DELAY_LEVELS; index++) { + /* Set DQS delay value */ + mmio_write_32(myctrl->reg_base + OCTA_MDTR, mdtr | (index * 256 / DELAY_LEVELS) << mdtr_pos); + mmio_read_32(myctrl->reg_base + OCTA_MDTR); + + /* Read preamble data and test */ + judge_result = 0; + + inv_dcache_range((uintptr_t)p_preamble, 16); + for (i = 0; i < 4; i++) { + if (preamble[i] != p_preamble[i]) { + judge_result = 1; + break; + } + } + + /* Store the judgement result in the table */ + if (0 == judge_result) { + is_ok[index] = true; + } + else { /* Continuous OK region */ + is_ok[index] = false; + } + } + + /* Search for the start index of the OK area */ + index_start = get_ok_area_start(is_ok); + if ((-1) == index_start) { + /* restore old value */ + mmio_write_32(myctrl->reg_base + OCTA_MDTR, mdtr_save); + mmio_read_32(myctrl->reg_base + OCTA_MDTR); + return -1; /* OK area not found */ + } + + /* Find the number of OK areas */ + ok_cnt = get_ok_area_count(is_ok, index_start); + + if (3 < ok_cnt) { + /* Set DQS delay value */ + uint32_t delay = (index_start + (ok_cnt >> 1)) * (256 / DELAY_LEVELS); + mmio_write_32(myctrl->reg_base + OCTA_MDTR, mdtr | delay << mdtr_pos); + mmio_read_32(myctrl->reg_base + OCTA_MDTR); + return 0; + } + else { + /* restore old value */ + mmio_write_32(myctrl->reg_base + OCTA_MDTR, mdtr_save); + mmio_read_32(myctrl->reg_base + OCTA_MDTR); + return -1; + } +} + +static void octa_write_preamble_pattern(octa_ctrl_t *myctrl) +{ + const uint32_t * pattern = &preamble[0]; + uintptr_t wp = myctrl->mmap_base; + wp += (uintptr_t)myctrl->calibration_base; + volatile uint32_t * w_pattern = (uint32_t*)wp; + *w_pattern++ = *pattern++; + *w_pattern++ = *pattern++; + *w_pattern++ = *pattern++; + *w_pattern++ = *pattern++; + clean_dcache_range(wp, 16); +} + +static int octa_manual_calibration_ch0(octa_ctrl_t *myctrl) +{ + int result; + static bool is_prepared = false; + uint32_t cdsr = mmio_read_32(myctrl->reg_base + OCTA_CDSR); + uint32_t ch0_transfer_type = (cdsr & OCTA_CDSR_DV0TTYP) >> OCTA_CDSR_DV0TTYP_POS; + if (ch0_transfer_type != OCTA_CDSR_DVTTYP_DOPI) return 0; + if (!is_prepared) { + uint32_t dsr0 = mmio_read_32(myctrl->reg_base + OCTA_DSR0); + uint32_t ch0_device_type = (dsr0 & OCTA_DSR0_DV0TYP) >> OCTA_DSR0_DV0TYP_POS; + if (ch0_device_type == OCTA_DSR_TYP_RAM) { + octa_write_preamble_pattern(myctrl); + } + is_prepared = true; + } + if (octa_manual_calibration_common(myctrl) < 0) { + ERROR("octa.c:%s Fail on manual calibration\n", __func__); + result = -1; + } + else { + is_calibrated[0] = true; + result = 0; + } + return result; +} + +static int octa_manual_calibration_ch1(octa_ctrl_t *myctrl) +{ + int result; + static bool is_prepared = false; + uint32_t cdsr = mmio_read_32(myctrl->reg_base + OCTA_CDSR); + uint32_t ch1_transfer_type = (cdsr & OCTA_CDSR_DV1TTYP) >> OCTA_CDSR_DV1TTYP_POS; + if (ch1_transfer_type != OCTA_CDSR_DVTTYP_DOPI) return 0; + if (!is_prepared) { + uint32_t dsr1 = mmio_read_32(myctrl->reg_base + OCTA_DSR1); + uint32_t ch1_device_type = (dsr1 & OCTA_DSR1_DV1TYP) >> OCTA_DSR1_DV1TYP_POS; + if (ch1_device_type == OCTA_DSR_TYP_RAM) { + octa_write_preamble_pattern(myctrl); + } + is_prepared = true; + } + if (octa_manual_calibration_common(myctrl) < 0) { + ERROR("octa.c:%s Fail on manual calibration\n", __func__); + result = -1; + } + else { + is_calibrated[1] = true; + result = 0; + } + return result; +} + +static int octa_run_manual_calibration(xspi_ctrl_t * const ctrl) +{ + assert(ctrl); + int result; + octa_ctrl_t * myctrl = (octa_ctrl_t *)ctrl; + if (myctrl->channel) { + /* Channel 1 */ + result = octa_manual_calibration_ch1(myctrl); + } + else { + /* Channel 0 */ + result = octa_manual_calibration_ch0(myctrl); + } + + return result; +} + +static int octa_enable_auto_calibration(xspi_ctrl_t * const ctrl) +{ + assert(ctrl); + octa_ctrl_t * myctrl = (octa_ctrl_t *)ctrl; + uint32_t cdsr = mmio_read_32(myctrl->reg_base + OCTA_CDSR); + bool en; + + /* Check condition per channel and set/reset ACMEME */ + if (myctrl->channel) { + en = is_calibrated[1] && + (cdsr & OCTA_CDSR_DV1TTYP) == (OCTA_CDSR_DVTTYP_DOPI << OCTA_CDSR_DV1TTYP_POS); + if (en) cdsr |= OCTA_CDSR_ACMEME1; + else cdsr &= ~OCTA_CDSR_ACMEME1; + } + else { + en = is_calibrated[0] && + (cdsr & OCTA_CDSR_DV0TTYP) == (OCTA_CDSR_DVTTYP_DOPI << OCTA_CDSR_DV0TTYP_POS); + if (en) cdsr |= OCTA_CDSR_ACMEME0; + else cdsr &= ~OCTA_CDSR_ACMEME0; + } + + /* Set/reset ACMODE */ + octa_set_acmode(&cdsr); + mmio_write_32(myctrl->reg_base + OCTA_CDSR, cdsr & ~OCTA_CDSR_ACMODE); + mmio_write_32(myctrl->reg_base + OCTA_CDSR, cdsr); + + return 0; +} + +static int octa_disable_auto_calibration(xspi_ctrl_t * const ctrl) +{ + assert(ctrl); + octa_ctrl_t * myctrl = (octa_ctrl_t *)ctrl; + uint32_t cdsr = mmio_read_32(myctrl->reg_base + OCTA_CDSR); + + /* Reset ACMEMEn */ + if (myctrl->channel) { + cdsr &= ~OCTA_CDSR_ACMEME1; + } + else { + cdsr &= ~OCTA_CDSR_ACMEME0; + } + + /* Reset ACMODE */ + cdsr &= ~OCTA_CDSR_ACMODE; + mmio_write_32(myctrl->reg_base + OCTA_CDSR, cdsr); + + return 0; +} + +static int octa_set_frequency(xspi_ctrl_t * const ctrl, int frequency_hz) +{ + assert(ctrl); + assert(frequency_hz > 0); + octa_ctrl_t * myctrl = (octa_ctrl_t *)ctrl; + + freq[myctrl->channel] = frequency_hz; + int freq_request; + + freq_request = freq[0]; + if (freq_request > freq[1]) freq_request = freq[1]; + + int result = cpg_set_xspi_clock(XSPI_CLOCK_OCTA, freq_request * 4); + if (result != 0) return result; + int actual_freq = cpg_get_xspi_clock(XSPI_CLOCK_OCTA); + if (actual_freq == -1) return -1; + spi_clock = actual_freq / 4; + + return 0; +} + +static int octa_clean_mmap(xspi_ctrl_t * const ctrl) +{ + assert(ctrl); + octa_ctrl_t * myctrl = (octa_ctrl_t *)ctrl; + clean_dcache_range(myctrl->mmap_base, myctrl->mmap_size); + + return 0; +} + +static int octa_inv_mmap(xspi_ctrl_t * const ctrl) +{ + assert(ctrl); + octa_ctrl_t * myctrl = (octa_ctrl_t *)ctrl; + inv_dcache_range(myctrl->mmap_base, myctrl->mmap_size); + + return 0; +} + +static uintptr_t octa_get_mmap_base(xspi_ctrl_t * const ctrl) +{ + assert(ctrl); + octa_ctrl_t * myctrl = (octa_ctrl_t *)ctrl; + return myctrl->mmap_base; +} + +static size_t octa_get_mmap_size(xspi_ctrl_t * const ctrl) +{ + assert(ctrl); + octa_ctrl_t * myctrl = (octa_ctrl_t *)ctrl; + return myctrl->mmap_size; +} + +static uint32_t octa_get_features(xspi_ctrl_t * const ctrl) +{ + (void)ctrl; + uint32_t features = 0; + features |= XSPI_FEATURE_FORM888; + features |= XSPI_FEATURE_DDR; + features |= XSPI_FEATURE_DDROP; + features |= XSPI_FEATURE_XIP_READ; + features |= XSPI_FEATURE_XIP_WRITE; + + return features; +} diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/xspi/spim.c b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/xspi/spim.c new file mode 100644 index 00000000..3d9c27e4 --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/xspi/spim.c @@ -0,0 +1,1226 @@ +/* + * Copyright (c) 2022, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Defaults */ +#define DEFAULT_SPI_FREQUENCY 66666667 +#define RESET_DURATION_US 10 +#define DEFAULT_VOLTAGE_IS_1800MV 1 + +/* Static function pre-definition */ +static int spim_open(xspi_ctrl_t * ctrl, xspi_cfg_t const * const cfg); +static int spim_close(xspi_ctrl_t * const ctrl); +static int spim_post_init(xspi_ctrl_t * const ctrl); +static int spim_exec_op(xspi_ctrl_t * const ctrl, xspi_op_t const * const op, bool is_write); +static int spim_configure_xip(xspi_ctrl_t * const ctrl, xspi_op_t const * const rop, xspi_op_t const * const wop); +static int spim_start_xip(xspi_ctrl_t * const ctrl); +static int spim_stop_xip(xspi_ctrl_t * const ctrl); +static int spim_run_manual_calibration(xspi_ctrl_t * const ctrl); +static int spim_enable_auto_calibration(xspi_ctrl_t * const ctrl); +static int spim_disable_auto_calibration(xspi_ctrl_t * const ctrl); +static int spim_set_frequency(xspi_ctrl_t * const ctrl, int frequency_hz); +static int spim_clean_mmap(xspi_ctrl_t * const ctrl); +static int spim_inv_mmap(xspi_ctrl_t * const ctrl); +static uintptr_t spim_get_mmap_base(xspi_ctrl_t * const ctrl); +static size_t spim_get_mmap_size(xspi_ctrl_t * const ctrl); +static uint32_t spim_get_features(xspi_ctrl_t * const ctrl); + +/* API function table definition */ +const xspi_api_t spim_api = { + .open = spim_open, + .close = spim_close, + .post_init = spim_post_init, + .exec_op = spim_exec_op, + .configure_xip = spim_configure_xip, + .start_xip = spim_start_xip, + .stop_xip = spim_stop_xip, + .run_manual_calibration = spim_run_manual_calibration, + .enable_auto_calibration = spim_enable_auto_calibration, + .disable_auto_calibration = spim_disable_auto_calibration, + .set_frequency = spim_set_frequency, + .clean_mmap = spim_clean_mmap, + .inv_mmap = spim_inv_mmap, + .get_mmap_base = spim_get_mmap_base, + .get_mmap_size = spim_get_mmap_size, + .get_features = spim_get_features, +}; + +/* Static variables */ +static bool globally_initialised = false; +static int spi_clock = DEFAULT_SPI_FREQUENCY; + +/* Function definitions */ +static void wait_until_32(uintptr_t addr, uint32_t mask, uint32_t data) +{ + while((mmio_read_32(addr) & mask) != data) {}; +} + +static void select_spim(spim_ctrl_t *myctrl, xspi_cfg_t const * const cfg) +{ + if (RZ_XSPI_EXCLUSIVE_SELECTOR) { + /* Check if OCTA selected */ + uint32_t ipcont_spi_octa = mmio_read_32(SYS_IPCONT); + if ((ipcont_spi_octa & IPCONT_SEL_SPI_OCTA) == IPCONT_SEL_SPI_OCTA_OCTA) { + /* Reset the OCTA controller and the devices connected, + * required to change the device mode from OPI to SPI. + * Otherwise, the octa devices can not communicate with the SPIM controller. + */ + /* Assert reset line */ + mmio_clrbits_32(myctrl->reg_base + OCTA_RSTCNT, OCTA_RSTCNT_RSTVAL); + + /* Reset OCTA controller */ + cpg_reset_on(CPG_CLOCK_OCTA); + + /* Stop OCTA clock */ + cpg_clock_off(CPG_CLOCK_OCTA); + } + } + + /* Wait for reset SPI device */ + udelay(RESET_DURATION_US); + + if (RZ_XSPI_FORCE_VOLTAGE_SETTING) { + /* force voltage setting + * Note: This is required if the boot mode is neither 3 nor 4. + */ + uint8_t voltage = DEFAULT_VOLTAGE_IS_1800MV; + if (cfg->extend) { + const spim_ext_t * ext = (const spim_ext_t*)cfg->extend; + if (ext->voltage_is_3300mv) voltage = 0; + } + mmio_write_8(PFC_QSPI, voltage); + mmio_read_8(PFC_QSPI); + } + + /* Supply SPIM clock (currently not implemented) */ + cpg_clock_on(CPG_CLOCK_SPIM); + + /* Resume SPIM controller (currently not implemented) */ + cpg_reset_off(CPG_CLOCK_SPIM); + + if (RZ_XSPI_EXCLUSIVE_SELECTOR) { + /* Select SPIM for SPI controller */ + uint32_t ipcont_spi_octa = mmio_read_32(SYS_IPCONT); + ipcont_spi_octa &= ~IPCONT_SEL_SPI_OCTA; + ipcont_spi_octa |= IPCONT_SEL_SPI_OCTA_SPI << IPCONT_SEL_SPI_OCTA_POS; + mmio_write_32(SYS_IPCONT, ipcont_spi_octa); + mmio_read_32(SYS_IPCONT); + } +} + +static void test_tend(const spim_ctrl_t * myctrl) +{ + wait_until_32(myctrl->reg_base + SPIM_CMNSR, SPIM_CMNSR_TEND, SPIM_CMNSR_TEND); +} + +static void spim_init_phy(const spim_ctrl_t * myctrl) +{ + mmio_write_32(myctrl->reg_base + SPIM_PHYADJ2, 0xa5390000); + mmio_write_32(myctrl->reg_base + SPIM_PHYADJ1, 0x80000000); + mmio_write_32(myctrl->reg_base + SPIM_PHYADJ2, 0x00008080); + mmio_write_32(myctrl->reg_base + SPIM_PHYADJ1, 0x80000022); + mmio_write_32(myctrl->reg_base + SPIM_PHYADJ2, 0x00008080); + mmio_write_32(myctrl->reg_base + SPIM_PHYADJ1, 0x80000024); + mmio_write_32(myctrl->reg_base + SPIM_PHYADJ2, 0x00000030); + mmio_write_32(myctrl->reg_base + SPIM_PHYADJ1, 0x80000032); +} + +static const uint32_t cmncr_init_mask = + SPIM_CMNCR_BSZ | + SPIM_CMNCR_IO0FV | + SPIM_CMNCR_IO2FV | + SPIM_CMNCR_IO3FV | + SPIM_CMNCR_MOIIO0 | + SPIM_CMNCR_MOIIO1 | + SPIM_CMNCR_MOIIO2 | + SPIM_CMNCR_MOIIO3; +/* IOn maintained as Hi-Z at idle + * IO0 Value sets Hi-Z while dummy and 1-bit read transfer phase + * IO2/IO3 Value sets high while 1-bit command/address/additional-data phase + */ +static const uint32_t cmncr_init_value = + 1u << SPIM_CMNCR_MD_POS | + SPIM_CMNCR_BSZ_SINGLE << SPIM_CMNCR_BSZ_POS | + SPIM_CMNCR_IO_HIZ << SPIM_CMNCR_IO0FV_POS | + SPIM_CMNCR_IO_HIGH << SPIM_CMNCR_IO2FV_POS | + SPIM_CMNCR_IO_HIGH << SPIM_CMNCR_IO3FV_POS | + SPIM_CMNCR_IO_HIZ << SPIM_CMNCR_MOIIO0_POS | + SPIM_CMNCR_IO_HIZ << SPIM_CMNCR_MOIIO1_POS | + SPIM_CMNCR_IO_HIZ << SPIM_CMNCR_MOIIO2_POS | + SPIM_CMNCR_IO_HIZ << SPIM_CMNCR_MOIIO3_POS; + +static const uint32_t ssldr_init_mask = + SPIM_SSLDR_SCKDL | + SPIM_SSLDR_SLNDL | + SPIM_SSLDR_SPNDL; +static const uint32_t ssldr_init_value = + 0u << SPIM_SSLDR_SCKDL_POS | + 0u << SPIM_SSLDR_SLNDL_POS | + 0u << SPIM_SSLDR_SPNDL_POS; + +static const uint32_t drcr_init_mask = + SPIM_DRCR_RBURST | + SPIM_DRCR_RCF | + SPIM_DRCR_RBE | + SPIM_DRCR_SSLE; +static const uint32_t drcr_init_value = + 7u << SPIM_DRCR_RBURST_POS | + 1u << SPIM_DRCR_RCF_POS | + 1u << SPIM_DRCR_RBE_POS | + 1u << SPIM_DRCR_SSLE_POS; + +static const uint32_t drear_init_mask = + SPIM_DREAR_EAC | + SPIM_DREAR_EAV; +static const uint32_t drear_init_value = + 3u << SPIM_DREAR_EAC_POS | + 0u << SPIM_DREAR_EAV_POS; + +static const uint32_t drdrenr_init_mask = + SPIM_DRDRENR_HYPE | + SPIM_DRDRENR_ADDRE | + SPIM_DRDRENR_OPDRE | + SPIM_DRDRENR_DRDRE; +static const uint32_t drdrenr_init_value = + 0u << SPIM_DRDRENR_HYPE_POS | + 0u << SPIM_DRDRENR_ADDRE_POS | + 0u << SPIM_DRDRENR_OPDRE_POS | + 0u << SPIM_DRDRENR_DRDRE_POS; + +static const uint32_t phycnt_init_mask = + SPIM_PHYCNT_ALT_ALIGN | + SPIM_PHYCNT_CAL | + SPIM_PHYCNT_CKSEL | + SPIM_PHYCNT_EXDS | + SPIM_PHYCNT_HS | + SPIM_PHYCNT_OCT | + SPIM_PHYCNT_OCTA | + SPIM_PHYCNT_PHYMEM | + SPIM_PHYCNT_WBUF2 | + SPIM_PHYCNT_WBUF; +static const uint32_t phycnt_init_value = + 0u << SPIM_PHYCNT_ALT_ALIGN_POS | + 0u << SPIM_PHYCNT_CAL_POS | + 3u << SPIM_PHYCNT_CKSEL_POS | + 0u << SPIM_PHYCNT_EXDS_POS | + 0u << SPIM_PHYCNT_HS_POS | + 0u << SPIM_PHYCNT_OCT_POS | + 0u << SPIM_PHYCNT_OCTA_POS | + 0u << SPIM_PHYCNT_PHYMEM_POS | + 0u << SPIM_PHYCNT_WBUF2_POS | + 0u << SPIM_PHYCNT_WBUF_POS; + +static const uint32_t phyoffset1_init_mask = + SPIM_PHYOFFSET1_DDRTMG; +static const uint32_t phyoffset1_init_value = + SPIM_PHYOFFSET1_SDR << SPIM_PHYOFFSET1_DDRTMG_POS; + +static const uint32_t phyoffset2_init_mask = + SPIM_PHYOFFSET2_OCTTMG; +static const uint32_t phyoffset2_init_value = + SPIM_PHYOFFSET2_SPI << SPIM_PHYOFFSET2_OCTTMG_POS; + +static void spim_ip_init(spim_ctrl_t *myctrl) +{ + cpg_set_xspi_clock(XSPI_CLOCK_SPIM, spi_clock * 4); + mmio_clrsetbits_32(myctrl->reg_base + SPIM_CMNCR, cmncr_init_mask, cmncr_init_value); + mmio_clrsetbits_32(myctrl->reg_base + SPIM_SSLDR, ssldr_init_mask, ssldr_init_value); + mmio_clrsetbits_32(myctrl->reg_base + SPIM_DRCR, drcr_init_mask, drcr_init_value); + mmio_clrsetbits_32(myctrl->reg_base + SPIM_DREAR, drear_init_mask, drear_init_value); + mmio_clrsetbits_32(myctrl->reg_base + SPIM_DRDRENR, drdrenr_init_mask, drdrenr_init_value); + mmio_clrsetbits_32(myctrl->reg_base + SPIM_PHYCNT, phycnt_init_mask, phycnt_init_value|SPIM_PHYCNT_CAL); + mmio_clrsetbits_32(myctrl->reg_base + SPIM_PHYOFFSET1, phyoffset1_init_mask, phyoffset1_init_value); + mmio_clrsetbits_32(myctrl->reg_base + SPIM_PHYOFFSET2, phyoffset2_init_mask, phyoffset2_init_value); + spim_init_phy(myctrl); +} + +static int spim_open(xspi_ctrl_t * ctrl, xspi_cfg_t const * const cfg) +{ + int result = -1; + assert(ctrl); + assert(cfg); + spim_ctrl_t * myctrl = (spim_ctrl_t *)ctrl; + + if (myctrl->opened) return -1; + + myctrl->reg_base = cfg->base; + myctrl->mmap_base = 0x20000000; + myctrl->mmap_size = 0x10000000; + assert(myctrl->reg_base); + + if (!globally_initialised) { + select_spim(myctrl, cfg); + spim_ip_init(myctrl); + + globally_initialised = true; + } + + result = 0; + myctrl->opened = true; + + return result; +} + +static int spim_close(xspi_ctrl_t * const ctrl) +{ + int result = -1; + assert(ctrl); + spim_ctrl_t * myctrl = (spim_ctrl_t *)ctrl; + if (myctrl->opened) { + myctrl->opened = false; + result = 0; + } + return result; + +} + +static int spim_post_init(xspi_ctrl_t * const ctrl) +{ + int result = 0; + return result; +} + +static const uint32_t spim_cmncr_set(uint8_t mask, uint8_t value, int pos) +{ + int moiionpos = -1; + int ionfvpos = -1; + uint32_t cmncr_set = 0; + uint32_t moiio = 0; + uint32_t ionfv = 0; + + switch(pos) { + case 1: + moiionpos = SPIM_CMNCR_MOIIO1_POS; + break; + case 2: + moiionpos = SPIM_CMNCR_MOIIO2_POS; + ionfvpos = SPIM_CMNCR_IO2FV_POS; + break; + case 3: + moiionpos = SPIM_CMNCR_MOIIO3_POS; + ionfvpos = SPIM_CMNCR_IO3FV_POS; + break; + } + + if (mask & (1 << pos)) { + moiio = value & 1 << pos ? SPIM_CMNCR_IO_HIGH : SPIM_CMNCR_IO_LOW; + ionfv = SPIM_CMNCR_IO_KEEP; + } + else { + moiio = SPIM_CMNCR_IO_HIZ; + ionfv = SPIM_CMNCR_IO_HIZ; + } + + if (moiionpos >= 0) cmncr_set |= moiio << moiionpos; + if (ionfvpos >= 0) cmncr_set |= ionfv << ionfvpos; + + return cmncr_set; +} + +static void spim_set_idlelevel(spim_ctrl_t * const myctrl, const xspi_op_t * const op) +{ + static const uint32_t cmncr_mask = + SPIM_CMNCR_IO2FV | + SPIM_CMNCR_IO3FV | + SPIM_CMNCR_MOIIO1 | + SPIM_CMNCR_MOIIO2 | + SPIM_CMNCR_MOIIO3; + + uint32_t cmncr_set = 0; + + cmncr_set |= spim_cmncr_set(op->force_idle_level_mask, op->force_idle_level_value, 1); + cmncr_set |= spim_cmncr_set(op->force_idle_level_mask, op->force_idle_level_value, 2); + cmncr_set |= spim_cmncr_set(op->force_idle_level_mask, op->force_idle_level_value, 3); + + mmio_clrsetbits_32(myctrl->reg_base + SPIM_CMNCR, cmncr_mask, cmncr_set); +} + +static int spim_reduce_frequency(spim_ctrl_t * const ctrl) +{ + int old_freq = spi_clock; + assert(ctrl); + if (spi_clock > RZ_SPIM_SDR_FREQ_LIMIT) { + spi_clock = RZ_SPIM_SDR_FREQ_LIMIT; + } + else { + /* We do not need to reduce the current SPI frequency */ + return 0; + } + + int result = cpg_set_xspi_clock(XSPI_CLOCK_SPIM, spi_clock * 4 + 1); + if (result != 0) { + return result; + } + + int actual_freq = cpg_get_xspi_clock(XSPI_CLOCK_SPIM); + if (actual_freq == -1) return -1; + spi_clock = actual_freq / 4; + + INFO("SPIM: Reduces the SPI frequency from %d to %d.\n", old_freq, spi_clock); + + return 0; +} + +static void spim_start_xip_internal(spim_ctrl_t * const ctrl) +{ + spim_reduce_frequency(ctrl); + mmio_clrbits_32(ctrl->reg_base + SPIM_CMNCR, SPIM_CMNCR_MD); + mmio_read_32(ctrl->reg_base + SPIM_CMNCR); +} + +static void test_sslf(spim_ctrl_t * myctrl) +{ + wait_until_32(myctrl->reg_base + SPIM_CMNSR, SPIM_CMNSR_SSLF, 0); +} + +static int spim_stop_xip_internal(spim_ctrl_t * myctrl) +{ + int result = 0; + uint32_t drcr = mmio_read_32(myctrl->reg_base + SPIM_DRCR); + if ((drcr & (SPIM_DRCR_RBE|SPIM_DRCR_SSLE)) == (SPIM_DRCR_RBE|SPIM_DRCR_SSLE)) { + /* Set SSLN and wait for sslf */ + mmio_write_32(myctrl->reg_base + SPIM_DRCR, drcr|SPIM_DRCR_SSLN); + test_sslf(myctrl); + } + test_tend(myctrl); + + /* Set MD bit */ + mmio_setbits_32(myctrl->reg_base + SPIM_CMNCR, SPIM_CMNCR_MD); + + return result; +} + +static bool spim_stop_xip_temporarily(spim_ctrl_t * myctrl) +{ + /* Stop XIP and return previous state*/ + bool state = !(mmio_read_32(myctrl->reg_base + SPIM_CMNCR) & SPIM_CMNCR_MD); + spim_stop_xip_internal(myctrl); + return state; +} + +static const uint32_t smcmr_clearmask = + SPIM_SMCMR_CMD | + SPIM_SMCMR_OCMD; + +static const uint32_t smenr_clearmask = + SPIM_SMENR_ADB| + SPIM_SMENR_ADE| + SPIM_SMENR_CDB| + SPIM_SMENR_CDE| + SPIM_SMENR_DME| + SPIM_SMENR_SPIDB| + SPIM_SMENR_OCDB| + SPIM_SMENR_OCDE| + SPIM_SMENR_OPDB| + SPIM_SMENR_OPDE| + SPIM_SMENR_SPIDE; + +static const uint32_t smdrenr_clearmask = + SPIM_SMDRENR_ADDRE | + SPIM_SMDRENR_DRDRE | + SPIM_SMDRENR_HYPE | + SPIM_SMDRENR_OPDRE; + +static const uint32_t smdmcr_clearmask = + SPIM_SMDMCR_DMCYC; + +static const uint32_t ssldr_clearmask = + SPIM_SSLDR_SCKDL | + SPIM_SSLDR_SLNDL | + SPIM_SSLDR_SPNDL; + +/* SMENR value for 1-1-1 command */ +static const uint32_t smenr_form_111 = + SPIM_SMENR_DB_1BIT << SPIM_SMENR_CDB_POS | + SPIM_SMENR_DB_1BIT << SPIM_SMENR_OCDB_POS | + SPIM_SMENR_DB_1BIT << SPIM_SMENR_ADB_POS | + SPIM_SMENR_DB_1BIT << SPIM_SMENR_OPDB_POS | + SPIM_SMENR_DB_1BIT << SPIM_SMENR_SPIDB_POS; + +/* SMENR value for 1-1-4 command */ +static const uint32_t smenr_form_114 = + SPIM_SMENR_DB_1BIT << SPIM_SMENR_CDB_POS | + SPIM_SMENR_DB_1BIT << SPIM_SMENR_OCDB_POS | + SPIM_SMENR_DB_1BIT << SPIM_SMENR_ADB_POS | + SPIM_SMENR_DB_1BIT << SPIM_SMENR_OPDB_POS | + SPIM_SMENR_DB_4BIT << SPIM_SMENR_SPIDB_POS; + +/* SMENR value for 1-4-4 command */ +static const uint32_t smenr_form_144 = + SPIM_SMENR_DB_1BIT << SPIM_SMENR_CDB_POS | + SPIM_SMENR_DB_1BIT << SPIM_SMENR_OCDB_POS | + SPIM_SMENR_DB_4BIT << SPIM_SMENR_ADB_POS | + SPIM_SMENR_DB_4BIT << SPIM_SMENR_OPDB_POS | + SPIM_SMENR_DB_4BIT << SPIM_SMENR_SPIDB_POS; + +/* SMENR value for no opcode */ +static const uint32_t smenr_op_none = + 0u << SPIM_SMENR_CDE_POS | + 0u << SPIM_SMENR_OCDE_POS; + +/* SMENR value for 1-byte opcode */ +static const uint32_t smenr_op_1byte = + 1u << SPIM_SMENR_CDE_POS | + 0u << SPIM_SMENR_OCDE_POS; + +/* SMENR value for 2-byte opcode */ +static const uint32_t smenr_op_2byte = + 1u << SPIM_SMENR_CDE_POS | + 1u << SPIM_SMENR_OCDE_POS; + +/* SMENR value for no address */ +static const uint32_t smenr_addr_none = + SPIM_SMENR_ADE_NONE << SPIM_SMENR_ADE_POS; + +/* SMENR value for 3-byte address */ +static const uint32_t smenr_addr_3byte = + SPIM_SMENR_ADE_3BYTE << SPIM_SMENR_ADE_POS; + +/* SMENR value for 4-byte address */ +static const uint32_t smenr_addr_4byte = + SPIM_SMENR_ADE_4BYTE << SPIM_SMENR_ADE_POS; + +/* SMENR value for no additional data */ +static const uint32_t smenr_additional_none = + SPIM_SMENR_OPDE_NONE << SPIM_SMENR_OPDE_POS; + +/* SMENR value for 1-byte additional data */ +static const uint32_t smenr_additional_1byte = + SPIM_SMENR_OPDE_1BYTE << SPIM_SMENR_OPDE_POS; + +/* SMENR value for 2-byte additional data */ +static const uint32_t smenr_additional_2byte = + SPIM_SMENR_OPDE_2BYTE << SPIM_SMENR_OPDE_POS; + +/* SMENR value for 3-byte additional data */ +static const uint32_t smenr_additional_3byte = + SPIM_SMENR_OPDE_3BYTE << SPIM_SMENR_OPDE_POS; + +/* SMENR value for 4-byte additional data */ +static const uint32_t smenr_additional_4byte = + SPIM_SMENR_OPDE_4BYTE << SPIM_SMENR_OPDE_POS; + +static void send_256(spim_ctrl_t * myctrl, xspi_transfer_form_t form, uintptr_t buffer, uint32_t smenr) +{ + /* Use wbuffer for transfer */ + mmio_setbits_32(myctrl->reg_base + SPIM_DRCR, SPIM_DRCR_RCF); + mmio_setbits_32(myctrl->reg_base + SPIM_PHYCNT, SPIM_PHYCNT_WBUF2|SPIM_PHYCNT_WBUF|SPIM_PHYCNT_CAL); + if (form == SPI_FORM_1_1_4 || form == SPI_FORM_1_4_4) { + uint32_t phyoffset2_msk = SPIM_PHYOFFSET2_OCTTMG; + uint32_t phyoffset2_set = SPIM_PHYOFFSET2_SPI_WBUF << SPIM_PHYOFFSET2_OCTTMG_POS; + mmio_clrsetbits_32(myctrl->reg_base + SPIM_PHYOFFSET2, phyoffset2_msk, phyoffset2_set); + } + mmio_clrsetbits_32(myctrl->reg_base + SPIM_SMENR, smenr_clearmask ,smenr | (SPIM_SMENR_SPIDE_LONG<reg_base + SPIM_BUFFER + bytes, *(uint64_t*)(buffer+bytes)); + } +} + +static void send_4(spim_ctrl_t * myctrl, uintptr_t buffer, uint32_t smenr) +{ + /* Set SPIDE */ + mmio_clrsetbits_32(myctrl->reg_base + SPIM_SMENR, smenr_clearmask, smenr | (SPIM_SMENR_SPIDE_LONG<reg_base + SPIM_SMWDR0, *(uint32_t*)buffer); +} + +static void send_2(spim_ctrl_t * myctrl, uintptr_t buffer, uint32_t smenr) +{ + /* Set SPIDE */ + mmio_clrsetbits_32(myctrl->reg_base + SPIM_SMENR, smenr_clearmask, smenr | (SPIM_SMENR_SPIDE_WORD<reg_base + SPIM_SMWDR0, *(uint16_t*)buffer); +} + +static void send_1(spim_ctrl_t * myctrl, uintptr_t buffer, uint32_t smenr) +{ + /* Set SPIDE */ + mmio_clrsetbits_32(myctrl->reg_base + SPIM_SMENR, smenr_clearmask, smenr | (SPIM_SMENR_SPIDE_BYTE<reg_base + SPIM_SMWDR0, *(uint8_t*)buffer); +} + +static void receive(spim_ctrl_t * myctrl, uintptr_t buffer, uint32_t smenr) +{ + /* Set SPIDE */ + mmio_clrsetbits_32(myctrl->reg_base + SPIM_SMENR, smenr_clearmask, smenr | (SPIM_SMENR_SPIDE_LONG<reg_base + SPIM_SMENR, smenr_clearmask, smenr | (SPIM_SMENR_SPIDE_NONE<transfer_size == 0 || (op->transfer_size && op->transfer_buffer)); + spim_ctrl_t * myctrl = (spim_ctrl_t *)ctrl; + bool is_xip; + + switch (op->form) { + case SPI_FORM_1_1_1: + case SPI_FORM_1_1_4: + case SPI_FORM_1_4_4: + break; + default: + ERROR("Unsupported transfer form %d\n", op->form); + return -1; + } + + /* Save XIP state and stop XIP */ + is_xip = spim_stop_xip_temporarily(myctrl); + + /* Reduce freq for MPU's AC characteristics */ + spim_reduce_frequency(ctrl); + + /* Wait for transaction end */ + test_tend(myctrl); + + /* Change I/O level while idle state */ + spim_set_idlelevel(myctrl, op); + + /* Create values to write the registers */ + uint32_t smcmr_set = 0; + uint32_t smenr_set = 0; + uint32_t smdrenr_set = 0; + uint32_t smopr = 0; + uint32_t smadr = op->address; + uint32_t smdmcr_set = 0; + uint32_t ssldr_set = 0; + uint32_t save_ssldr = mmio_read_32(myctrl->reg_base + SPIM_SSLDR); + uint32_t save_phyoffset1 = mmio_read_32(myctrl->reg_base + SPIM_PHYOFFSET1); + uint32_t save_phyoffset2 = mmio_read_32(myctrl->reg_base + SPIM_PHYOFFSET2); + uint32_t save_phycnt = mmio_read_32(myctrl->reg_base + SPIM_PHYCNT); + + /* Command form */ + switch (op->form) { + case SPI_FORM_1_1_1: + smenr_set |= smenr_form_111; + break; + case SPI_FORM_1_1_4: + smenr_set |= smenr_form_114; + break; + case SPI_FORM_1_4_4: + smenr_set |= smenr_form_144; + break; + default: + ERROR("Unsupported transfer form %d\n", op->form); + return -1; + } + + /* Opcode */ + switch (op->op_size) { + case 0: + smenr_set |= smenr_op_none; + break; + case 1: + smenr_set |= smenr_op_1byte; + smcmr_set |= (op->op & 0xff) << SPIM_SMCMR_CMD_POS; + break; + case 2: + smenr_set |= smenr_op_2byte; + smcmr_set |= (op->op & 0xff) << SPIM_SMCMR_OCMD_POS; + smcmr_set |= (op->op & 0xff00) >> 8 << SPIM_SMCMR_CMD_POS; + break; + default: + ERROR("Unsupported op size %d\n", op->op_size); + return -1; + } + + /* Address */ + switch (op->address_size) { + case 0: + smenr_set |= smenr_addr_none; + break; + case 3: + smenr_set |= smenr_addr_3byte; + break; + case 4: + smenr_set |= smenr_addr_4byte; + break; + default: + ERROR("Unsupported address size %d\n", op->address_size); + return -1; + } + + /* Additional data */ + switch (op->additional_size) { + case 0: + smenr_set |= smenr_additional_none; + break; + case 1: + smenr_set |= smenr_additional_1byte; + smopr = (op->additional_value & 0xff) << SPIM_SMOPR_OPD3_POS; + break; + case 2: + smenr_set |= smenr_additional_2byte; + smopr = (op->additional_value & 0xff) << SPIM_SMOPR_OPD2_POS; + smopr |= (op->additional_value & 0xff00) >> 8 << SPIM_SMOPR_OPD3_POS; + break; + case 3: + smenr_set |= smenr_additional_3byte; + smopr = (op->additional_value & 0xff) << SPIM_SMOPR_OPD1_POS; + smopr |= (op->additional_value & 0xff00) >> 8 << SPIM_SMOPR_OPD2_POS; + smopr |= (op->additional_value & 0xff0000) >> 16 << SPIM_SMOPR_OPD3_POS; + break; + case 4: + smenr_set |= smenr_additional_4byte; + smopr = (op->additional_value & 0xff) << SPIM_SMOPR_OPD0_POS; + smopr |= (op->additional_value & 0xff00) >> 8 << SPIM_SMOPR_OPD1_POS; + smopr |= (op->additional_value & 0xff0000) >> 16 << SPIM_SMOPR_OPD2_POS; + smopr |= (op->additional_value & 0xff000000) >> 24 << SPIM_SMOPR_OPD3_POS; + break; + default: + ERROR("Unsupported additional size %d\n", op->additional_size); + return -1; + } + + /* Dummy cycle */ + if (op->dummy_cycles == 0) { + smenr_set |= 0u << SPIM_SMENR_DME_POS; + smdmcr_set |= 0u << SPIM_SMDMCR_DMCYC_POS; + } + else if (op->dummy_cycles == 1 || op->dummy_cycles > 20) { + ERROR("Unsupported dummy cycle count %d\n", op->dummy_cycles); + return -1; + } + else { + smenr_set |= 1u << SPIM_SMENR_DME_POS; + smdmcr_set |= (op->dummy_cycles - 1) << SPIM_SMDMCR_DMCYC_POS; + } + + /* PHYOFFSET1 setting */ + uint32_t phyoffset1_msk = SPIM_PHYOFFSET1_DDRTMG; + uint32_t phyoffset1_set; + phyoffset1_set = SPIM_PHYOFFSET1_SDR << SPIM_PHYOFFSET1_DDRTMG_POS; + + /* PHYCNT setting */ + uint32_t phycnt_msk = SPIM_PHYCNT_PHYMEM; + uint32_t phycnt_set; + phycnt_set = SPIM_PHYCNT_SDR << SPIM_PHYCNT_PHYMEM_POS; + + /* SLCH (SSL assert to CLK high) */ + if (op->slch_value < 8) { + ssldr_set |= op->slch_value << SPIM_SSLDR_SCKDL_POS; + } + else { + ERROR("Unsupported slch_value %d\n", op->slch_value); + return -1; + } + + /* CLSH (CLK low tp SSL negative) */ + if (op->clsh_value < 8) { + ssldr_set |= op->clsh_value << SPIM_SSLDR_SLNDL_POS; + } + else { + ERROR("Unsupported clsh_value %d\n", op->clsh_value); + return -1; + } + + /* SHSL (SSL negative to SSL assert) */ + if (op->shsl_value < 8) { + ssldr_set |= op->shsl_value << SPIM_SSLDR_SPNDL_POS; + } + else { + ERROR("Unsupported shsl_value %d\n", op->shsl_value); + return -1; + } + + /* Write the register */ + mmio_clrsetbits_32(myctrl->reg_base + SPIM_SMCMR, smcmr_clearmask, smcmr_set); + mmio_clrsetbits_32(myctrl->reg_base + SPIM_SMDRENR, smdrenr_clearmask, smdrenr_set); + mmio_write_32(myctrl->reg_base + SPIM_SMADR, smadr); + mmio_write_32(myctrl->reg_base + SPIM_SMOPR, smopr); + mmio_clrsetbits_32(myctrl->reg_base + SPIM_SMDMCR, smdmcr_clearmask, smdmcr_set); + mmio_write_32(myctrl->reg_base + SPIM_SSLDR, (save_ssldr & ~ssldr_clearmask) | ssldr_set); + mmio_write_32(myctrl->reg_base + SPIM_PHYOFFSET1, (save_phyoffset1 & ~phyoffset1_msk) | phyoffset1_set); + mmio_write_32(myctrl->reg_base + SPIM_PHYCNT, (save_phycnt & ~phycnt_msk) | phycnt_set | SPIM_PHYCNT_CAL); + + int64_t remain = (int64_t)op->transfer_size; + uintptr_t buffer = (uintptr_t)op->transfer_buffer; + uint32_t smcr; + + /* Enable transmit */ + if (is_write && remain) smcr = SPIM_SMCR_SPIWE | SPIM_SMCR_SPIE; + else if (remain) smcr = SPIM_SMCR_SPIRE | SPIM_SMCR_SPIE; + else smcr = SPIM_SMCR_SPIE; + + do { + uint32_t xfer_count; + + /* Block size per single transfer */ + if (is_write && remain >= 256) { + send_256(myctrl, op->form, buffer, smenr_set); + xfer_count = 256; + } + else if (is_write && remain >= 4) { + send_4(myctrl, buffer, smenr_set); + xfer_count = 4; + } + else if (is_write && remain >= 2) { + send_2(myctrl, buffer, smenr_set); + xfer_count = 2; + } + else if (is_write && remain) { + send_1(myctrl, buffer, smenr_set); + xfer_count = 1; + } + else if (remain) { + receive(myctrl, buffer, smenr_set); + xfer_count = 4; + } + else { + no_data(myctrl, buffer, smenr_set); + xfer_count = 0; + } + + /* Set SSLKP if transaction is remained and write transfer */ + if (is_write && remain > xfer_count) { + smcr |= SPIM_SMCR_SSLKP; + } + else { + smcr &= ~SPIM_SMCR_SSLKP; + } + + /* Exec transaction */ + mmio_write_32(myctrl->reg_base + SPIM_SMCR, smcr); + test_tend(myctrl); + + /* Store received data */ + if (!is_write && remain) { + uint32_t smrdr = mmio_read_32(myctrl->reg_base + SPIM_SMRDR0); + if (remain > 3) { + *(uint32_t*)buffer = smrdr; + } + else { + *(uint8_t*)buffer = (smrdr >> 24) & 255; + if (remain > 1) *(uint8_t*)(buffer+1) = (smrdr >> 16) & 255; + if (remain > 2) *(uint8_t*)(buffer+2) = (smrdr >> 8) & 255; + } + + } + remain -= xfer_count; + buffer += xfer_count; + + /* Clear write buffer flag and restore OCTTMG */ + mmio_clrsetbits_32(myctrl->reg_base + SPIM_PHYCNT, SPIM_PHYCNT_WBUF2|SPIM_PHYCNT_WBUF, SPIM_PHYCNT_CAL); + mmio_write_32(myctrl->reg_base + SPIM_PHYOFFSET2, save_phyoffset2); + + if (remain > 0) { + if (!is_write) { + /* Increment address */ + smadr += xfer_count; + mmio_write_32(myctrl->reg_base + SPIM_SMADR, smadr); + } + else { + /* Clear enabler bits for continuous write access */ + smenr_set &= ~(SPIM_SMENR_DME|SPIM_SMENR_CDE|SPIM_SMENR_OCDE|SPIM_SMENR_ADE|SPIM_SMENR_OPDE); + } + } + } while (remain > 0); + + /* Resume regs */ + mmio_write_32(myctrl->reg_base + SPIM_SSLDR, save_ssldr); + mmio_write_32(myctrl->reg_base + SPIM_PHYCNT, save_phycnt|SPIM_PHYCNT_CAL); + mmio_write_32(myctrl->reg_base + SPIM_PHYOFFSET1, save_phyoffset1); + + if (is_xip) { + /* Resume XIP state */ + spim_start_xip_internal(ctrl); + } + + return 0; +} + +static const uint32_t drcmr_clearmask = + SPIM_DRCMR_CMD | + SPIM_DRCMR_OCMD; + +static const uint32_t drenr_clearmask = + SPIM_DRENR_ADB| + SPIM_DRENR_ADE| + SPIM_DRENR_CDB| + SPIM_DRENR_CDE| + SPIM_DRENR_DME| + SPIM_DRENR_DRDB| + SPIM_DRENR_OCDB| + SPIM_DRENR_OCDE| + SPIM_DRENR_OPDB| + SPIM_DRENR_OPDE; + +static const uint32_t drdrenr_clearmask = + SPIM_DRDRENR_ADDRE | + SPIM_DRDRENR_DRDRE | + SPIM_DRDRENR_HYPE | + SPIM_DRDRENR_OPDRE; + +static const uint32_t drdmcr_clearmask = + SPIM_DRDMCR_DMCYC; + +/* DRENR value for 1-1-1 command */ +static const uint32_t drenr_form_111 = + SPIM_DRENR_DB_1BIT << SPIM_DRENR_CDB_POS | + SPIM_DRENR_DB_1BIT << SPIM_DRENR_OCDB_POS | + SPIM_DRENR_DB_1BIT << SPIM_DRENR_ADB_POS | + SPIM_DRENR_DB_1BIT << SPIM_DRENR_OPDB_POS | + SPIM_DRENR_DB_1BIT << SPIM_DRENR_DRDB_POS; + +/* DRENR value for 1-1-4 command */ +static const uint32_t drenr_form_114 = + SPIM_DRENR_DB_1BIT << SPIM_DRENR_CDB_POS | + SPIM_DRENR_DB_1BIT << SPIM_DRENR_OCDB_POS | + SPIM_DRENR_DB_1BIT << SPIM_DRENR_ADB_POS | + SPIM_DRENR_DB_1BIT << SPIM_DRENR_OPDB_POS | + SPIM_DRENR_DB_4BIT << SPIM_DRENR_DRDB_POS; + +/* DRENR value for 1-4-4 command */ +static const uint32_t drenr_form_144 = + SPIM_DRENR_DB_1BIT << SPIM_DRENR_CDB_POS | + SPIM_DRENR_DB_1BIT << SPIM_DRENR_OCDB_POS | + SPIM_DRENR_DB_4BIT << SPIM_DRENR_ADB_POS | + SPIM_DRENR_DB_4BIT << SPIM_DRENR_OPDB_POS | + SPIM_DRENR_DB_4BIT << SPIM_DRENR_DRDB_POS; + +/* DRENR value for no opcode */ +static const uint32_t drenr_op_none = + 0u << SPIM_DRENR_CDE_POS | + 0u << SPIM_DRENR_OCDE_POS; + +/* DRENR value for 1-byte opcode */ +static const uint32_t drenr_op_1byte = + 1u << SPIM_DRENR_CDE_POS | + 0u << SPIM_DRENR_OCDE_POS; + +/* DRENR value for 2-byte opcode */ +static const uint32_t drenr_op_2byte = + 1u << SPIM_DRENR_CDE_POS | + 1u << SPIM_DRENR_OCDE_POS; + +/* DRENR value for no address */ +static const uint32_t drenr_addr_none = + SPIM_DRENR_ADE_NONE << SPIM_DRENR_ADE_POS; + +/* DRENR value for 3-byte address */ +static const uint32_t drenr_addr_3byte = + SPIM_DRENR_ADE_3BYTE << SPIM_DRENR_ADE_POS; + +/* DRENR value for 4-byte address */ +static const uint32_t drenr_addr_4byte = + SPIM_DRENR_ADE_4BYTE << SPIM_DRENR_ADE_POS; + +/* DRENR value for no additional data */ +static const uint32_t drenr_additional_none = + SPIM_DRENR_OPDE_NONE << SPIM_DRENR_OPDE_POS; + +/* DRENR value for 1-byte additional data */ +static const uint32_t drenr_additional_1byte = + SPIM_DRENR_OPDE_1BYTE << SPIM_DRENR_OPDE_POS; + +/* DRENR value for 2-byte additional data */ +static const uint32_t drenr_additional_2byte = + SPIM_DRENR_OPDE_2BYTE << SPIM_DRENR_OPDE_POS; + +/* DRENR value for 3-byte additional data */ +static const uint32_t drenr_additional_3byte = + SPIM_DRENR_OPDE_3BYTE << SPIM_DRENR_OPDE_POS; + +/* DRENR value for 4-byte additional data */ +static const uint32_t drenr_additional_4byte = + SPIM_DRENR_OPDE_4BYTE << SPIM_DRENR_OPDE_POS; + +static int spim_configure_xip(xspi_ctrl_t * const ctrl, xspi_op_t const * const rop, xspi_op_t const * const wop) +{ + assert(ctrl); + if (!rop) return -1; + if (wop) return -1; + spim_ctrl_t * myctrl = (spim_ctrl_t *)ctrl; + + uint32_t drcmr = mmio_read_32(myctrl->reg_base + SPIM_DRCMR); + uint32_t drenr = mmio_read_32(myctrl->reg_base + SPIM_DRENR); + uint32_t drdrenr = mmio_read_32(myctrl->reg_base + SPIM_DRDRENR); + uint32_t dropr = 0; + uint32_t drdmcr = mmio_read_32(myctrl->reg_base + SPIM_DRDMCR); + uint32_t ssldr_clear = 0; + uint32_t ssldr_set = 0; + uint32_t phyoffset1_msk = SPIM_PHYOFFSET1_DDRTMG; + uint32_t phyoffset1_set = 0; + uint32_t phyoffset2_msk = SPIM_PHYOFFSET2_OCTTMG; + uint32_t phyoffset2_set = SPIM_PHYOFFSET2_SPI << SPIM_PHYOFFSET2_OCTTMG_POS; + uint32_t phycnt_msk = SPIM_PHYCNT_PHYMEM; + uint32_t phycnt_set = 0; + + /* Change I/O level while idle state */ + spim_set_idlelevel(myctrl, rop); + + drenr &= ~drenr_clearmask; + drcmr &= ~drcmr_clearmask; + drdrenr &= ~drdrenr_clearmask; + drdmcr &= ~drdmcr_clearmask; + + /* Command form */ + switch (rop->form) { + case SPI_FORM_1_1_1: + drenr |= drenr_form_111; + break; + case SPI_FORM_1_1_4: + drenr |= drenr_form_114; + break; + case SPI_FORM_1_4_4: + drenr |= drenr_form_144; + break; + default: + ERROR("Unsupported transfer form %d for rop\n", rop->form); + return -1; + } + + /* Opcode */ + switch (rop->op_size) { + case 0: + drenr |= drenr_op_none; + break; + case 1: + drenr |= drenr_op_1byte; + drcmr |= (rop->op & 0xff) << SPIM_DRCMR_CMD_POS; + break; + case 2: + drenr |= drenr_op_2byte; + drcmr |= (rop->op & 0xff) << SPIM_DRCMR_OCMD_POS; + drcmr |= (rop->op & 0xff00) >> 8 << SPIM_DRCMR_CMD_POS; + break; + default: + ERROR("Unsupported op size %d for rop\n", rop->op_size); + return -1; + } + + /* Address */ + switch (rop->address_size) { + case 0: + drenr |= drenr_addr_none; + break; + case 3: + drenr |= drenr_addr_3byte; + break; + case 4: + drenr |= drenr_addr_4byte; + break; + default: + ERROR("Unsupported address size %d for rop\n", rop->address_size); + return -1; + } + + /* Additional data */ + switch (rop->additional_size) { + case 0: + drenr |= drenr_additional_none; + break; + case 1: + drenr |= drenr_additional_1byte; + dropr |= (rop->additional_value & 0xff) << SPIM_DROPR_OPD3_POS; + break; + case 2: + drenr |= drenr_additional_2byte; + dropr |= (rop->additional_value & 0xff) << SPIM_DROPR_OPD2_POS; + dropr |= (rop->additional_value & 0xff00) >> 8 << SPIM_DROPR_OPD3_POS; + break; + case 3: + drenr |= drenr_additional_3byte; + dropr |= (rop->additional_value & 0xff) << SPIM_DROPR_OPD1_POS; + dropr |= (rop->additional_value & 0xff00) >> 8 << SPIM_DROPR_OPD2_POS; + dropr |= (rop->additional_value & 0xff0000) >> 16 << SPIM_DROPR_OPD3_POS; + break; + case 4: + drenr |= drenr_additional_4byte; + dropr |= (rop->additional_value & 0xff) << SPIM_DROPR_OPD0_POS; + dropr |= (rop->additional_value & 0xff00) >> 8 << SPIM_DROPR_OPD1_POS; + dropr |= (rop->additional_value & 0xff0000) >> 16 << SPIM_DROPR_OPD2_POS; + dropr |= (rop->additional_value & 0xff000000) >> 24 << SPIM_DROPR_OPD3_POS; + break; + default: + ERROR("Unsupported additional size %d for rop\n", rop->additional_size); + return -1; + } + + /* Dummy cycle */ + if (rop->dummy_cycles == 0) { + drenr |= 0u << SPIM_DRENR_DME_POS; + drdmcr |= 0u << SPIM_DRDMCR_DMCYC_POS; + } + else if (rop->dummy_cycles == 1 || rop->dummy_cycles > 20) { + ERROR("Unsupported dummy cycle count %d for rop\n", rop->dummy_cycles); + return -1; + } + else { + drenr |= 1u << SPIM_DRENR_DME_POS; + drdmcr |= (rop->dummy_cycles - 1) << SPIM_DRDMCR_DMCYC_POS; + } + + /* Set operation timing for PHYOFFSET1 */ + phyoffset1_set = SPIM_PHYOFFSET1_SDR << SPIM_PHYOFFSET1_DDRTMG_POS; + + /* Set data transfer mode for PHYCNT */ + phycnt_set = SPIM_PHYCNT_SDR << SPIM_PHYCNT_PHYMEM_POS; + + /* SLCH (SSL assert to CLK high) */ + if (rop->slch_value < 8) { + ssldr_clear |= SPIM_SSLDR_SCKDL; + ssldr_set |= rop->slch_value << SPIM_SSLDR_SCKDL_POS; + } + else { + ERROR("Unsupported slch_value %d for rop\n", rop->slch_value); + return -1; + } + + /* CLSH (CLK low tp SSL negative) */ + if (rop->clsh_value < 8) { + ssldr_clear |= SPIM_SSLDR_SLNDL; + ssldr_set |= rop->clsh_value << SPIM_SSLDR_SLNDL_POS; + } + else { + ERROR("Unsupported clsh_value %d for rop\n", rop->clsh_value); + return -1; + } + + /* SHSL (SSL negative to SSL assert) */ + if (rop->shsl_value < 8) { + ssldr_clear |= SPIM_SSLDR_SPNDL; + ssldr_set |= rop->shsl_value << SPIM_SSLDR_SPNDL_POS; + } + else { + ERROR("Unsupported shsl_value %d for rop\n", rop->shsl_value); + return -1; + } + + /* Write the register */ + mmio_write_32(myctrl->reg_base + SPIM_DRCMR, drcmr); + mmio_write_32(myctrl->reg_base + SPIM_DRENR, drenr); + mmio_write_32(myctrl->reg_base + SPIM_DRDRENR, drdrenr); + mmio_write_32(myctrl->reg_base + SPIM_DROPR, dropr); + mmio_write_32(myctrl->reg_base + SPIM_DRDMCR, drdmcr); + mmio_clrsetbits_32(myctrl->reg_base + SPIM_SSLDR, ssldr_clear, ssldr_set); + mmio_clrsetbits_32(myctrl->reg_base + SPIM_PHYOFFSET1, phyoffset1_msk, phyoffset1_set); + mmio_clrsetbits_32(myctrl->reg_base + SPIM_PHYOFFSET2, phyoffset2_msk, phyoffset2_set); + mmio_clrsetbits_32(myctrl->reg_base + SPIM_PHYCNT, phycnt_msk, phycnt_set|SPIM_PHYCNT_CAL); + + /* Reduce the SPI freq. */ + spim_reduce_frequency(ctrl); + + return 0; +} + +static int spim_start_xip(xspi_ctrl_t * const ctrl) +{ + assert(ctrl); + spim_ctrl_t * myctrl = (spim_ctrl_t *)ctrl; + mmio_setbits_32(myctrl->reg_base + SPIM_DRCR, SPIM_DRCR_RCF); + spim_start_xip_internal(myctrl); + spim_inv_mmap(ctrl); + + return 0; +} + +static int spim_stop_xip(xspi_ctrl_t * const ctrl) +{ + assert(ctrl); + spim_ctrl_t * myctrl = (spim_ctrl_t *)ctrl; + return spim_stop_xip_internal(myctrl); +} + +static int spim_run_manual_calibration(xspi_ctrl_t * const ctrl) +{ + return -1; + +} + +static int spim_enable_auto_calibration(xspi_ctrl_t * const ctrl) +{ + return -1; + +} + +static int spim_disable_auto_calibration(xspi_ctrl_t * const ctrl) +{ + return -1; + +} + +static int spim_set_frequency(xspi_ctrl_t * const ctrl, int frequency_hz) +{ + assert(ctrl); + + int result = cpg_set_xspi_clock(XSPI_CLOCK_SPIM, frequency_hz * 4 + 1); + if (result != 0) return result; + int actual_freq = cpg_get_xspi_clock(XSPI_CLOCK_SPIM); + if (actual_freq == -1) return -1; + actual_freq = actual_freq / 4; + if (frequency_hz != actual_freq) { + INFO("SPIM: Reduces the SPI frequency from requested %d to %d.\n", frequency_hz, actual_freq); + } + spi_clock = actual_freq; + + return 0; +} + +static int spim_clean_mmap(xspi_ctrl_t * const ctrl) +{ + return 0; +} + +static int spim_inv_mmap(xspi_ctrl_t * const ctrl) +{ + assert(ctrl); + spim_ctrl_t * myctrl = (spim_ctrl_t *)ctrl; + inv_dcache_range(myctrl->mmap_base, myctrl->mmap_size); + + return 0; +} + +static uintptr_t spim_get_mmap_base(xspi_ctrl_t * const ctrl) +{ + assert(ctrl); + spim_ctrl_t * myctrl = (spim_ctrl_t *)ctrl; + return myctrl->mmap_base; +} + +static size_t spim_get_mmap_size(xspi_ctrl_t * const ctrl) +{ + assert(ctrl); + spim_ctrl_t * myctrl = (spim_ctrl_t *)ctrl; + return myctrl->mmap_size; +} + +static uint32_t spim_get_features(xspi_ctrl_t * const ctrl) +{ + (void)ctrl; + uint32_t features = 0; + features |= XSPI_FEATURE_FORM114; + features |= XSPI_FEATURE_FORM144; + features |= XSPI_FEATURE_XIP_READ; + + return features; +} diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/xspidevice/octaflash_mx66uw/octaflash_mx66uw.c b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/xspidevice/octaflash_mx66uw/octaflash_mx66uw.c new file mode 100644 index 00000000..346c83df --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/xspidevice/octaflash_mx66uw/octaflash_mx66uw.c @@ -0,0 +1,515 @@ +/* + * Copyright (c) 2022, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +#include "octaflash_mx66uw_api.h" + +/* Defaults */ +#define DEFAULT_SPI_FREQUENCY 100000000 +#define SPI_POST_RESET_WAIT 50 + +/* Static function pre-definition */ +static int flash_open(xspidevice_ctrl_t * ctrl, xspidevice_cfg_t const * cfg); +static int flash_close(xspidevice_ctrl_t * ctrl); +static int flash_exec_op(xspidevice_ctrl_t * ctrl, xspi_op_t const * op, bool is_write); +static int flash_enter_xip(xspidevice_ctrl_t * ctrl); +static int flash_exit_xip(xspidevice_ctrl_t * ctrl); +static int flash_get_info(xspidevice_ctrl_t * ctrl, xspidevice_info_t * info); +static int flash_read(xspidevice_ctrl_t * ctrl, void * buffer, size_t address, size_t length); +static int flash_write(xspidevice_ctrl_t * ctrl, void const * buffer, size_t address, size_t length); +static int flash_erase(xspidevice_ctrl_t * ctrl, size_t address, size_t length); +static enum xspidevice_write_status flash_get_write_status(xspidevice_ctrl_t * ctrl); + +/* API function table definition */ +const xspidevice_api_t octaflash_mx66uw_api = { + .open = flash_open, + .close = flash_close, + .exec_op = flash_exec_op, + .enter_xip = flash_enter_xip, + .exit_xip = flash_exit_xip, + .get_info = flash_get_info, + .read = flash_read, + .write = flash_write, + .erase = flash_erase, + .get_write_status = flash_get_write_status, +}; + +/* Access timing parameters : 100MHz + DRCSTR : DVRDLO0=0, DVRDHI0=5, DVRDCMD0=1, CTR0=0, CTRW0=0 + DWCSTR : DVWLO0=0, DVWHI0=0, DVWCMD0=1 + DCSTR : DVSELLO=0, DVSELHI=5, DVSELCMD=1 */ + +/* Static variables */ +static int spi_frequency = DEFAULT_SPI_FREQUENCY + 1; + +/*** Flash Commands ***/ +/* Write Enable (SPI) */ +static const xspi_op_t op_write_enable_spi = { + .form = SPI_FORM_1_1_1, + .op = 0x06, + .op_size = 1, + .op_is_ddr = false, + .address = 0, + .address_is_ddr = false, + .address_size = 0, + .additional_value = 0, + .additional_size = 0, + .dummy_cycles = 0, + .transfer_buffer = NULL, + .transfer_is_ddr = false, + .transfer_size = 0, + .slch_value = 0, + .clsh_value = 5, + .shsl_value = 1 +}; + +/* Write Enable (DOPI) */ +static const xspi_op_t op_write_enable_dopi = { + .form = SPI_FORM_8_8_8, + .op = 0x06F9, + .op_size = 2, + .op_is_ddr = true, + .address = 0, + .address_is_ddr = true, + .address_size = 0, + .additional_value = 0, + .additional_size = 0, + .dummy_cycles = 0, + .transfer_buffer = NULL, + .transfer_is_ddr = true, + .transfer_size = 0, + .slch_value = 0, + .clsh_value = 5, + .shsl_value = 1 +}; + +/* Read Status Register (SPI) */ +static const xspi_op_t op_read_status_spi = { + .form = SPI_FORM_1_1_1, + .op = 0x05, + .op_size = 1, + .op_is_ddr = false, + .address = 0, + .address_is_ddr = false, + .address_size = 0, + .additional_value = 0, + .additional_size = 0, + .dummy_cycles = 0, + .transfer_buffer = NULL, + .transfer_is_ddr = false, + .transfer_size = 1, + .slch_value = 0, + .clsh_value = 5, + .shsl_value = 1 +}; + +/* Read Status Register - 1 (DOPI) */ +static const xspi_op_t op_read_status_dopi = { + .form = SPI_FORM_8_8_8, + .op = 0x05FA, + .op_size = 2, + .op_is_ddr = true, + .address = 0, + .address_is_ddr = true, + .address_size = 4, + .additional_value = 0, + .additional_size = 0, + .dummy_cycles = 4, + .transfer_buffer = NULL, + .transfer_is_ddr = false, + .transfer_size = 1, + .slch_value = 0, + .clsh_value = 5, + .shsl_value = 1 +}; + +/* Write Configuration Register2 (SPI) */ +static const xspi_op_t op_write_config2_spi = { + .form = SPI_FORM_1_1_1, + .op = 0x72, + .op_size = 1, + .op_is_ddr = false, + .address = 0, + .address_is_ddr = false, + .address_size = 4, + .additional_value = 0, + .additional_size = 0, + .dummy_cycles = 0, + .transfer_buffer = NULL, + .transfer_is_ddr = false, + .transfer_size = 1, + .slch_value = 0, + .clsh_value = 5, + .shsl_value = 1 +}; + +/* Read Command = 8 I/O DT Read (EEh/11h) */ +static const xspi_op_t rop = { + .form = SPI_FORM_8_8_8, + .op = 0xee11, + .op_size = 2, + .op_is_ddr = true, + .address = 0, + .address_is_ddr = true, + .address_size = 4, + .additional_value = 0, + .additional_size = 0, + .dummy_cycles = 10, + .transfer_buffer = NULL, + .transfer_is_ddr = true, + .transfer_size = 0, + .slch_value = 0, + .clsh_value = 5, + .shsl_value = 1 +}; + +/* Page Program 4B (DOPI) */ +static const xspi_op_t op_page_program_dopi = { + .form = SPI_FORM_8_8_8, + .op = 0x12ED, + .op_size = 2, + .op_is_ddr = true, + .address = 0, + .address_is_ddr = true, + .address_size = 4, + .additional_value = 0, + .additional_size = 0, + .dummy_cycles = 0, + .transfer_buffer = NULL, + .transfer_is_ddr = true, + .transfer_size = 0, + .slch_value = 0, + .clsh_value = 5, + .shsl_value = 1 +}; + +/* Erase 4k (DOPI) */ +static const xspi_op_t op_erase_4k_dopi = { + .form = SPI_FORM_8_8_8, + .op = 0x21DE, + .op_size = 2, + .op_is_ddr = true, + .address = 0, + .address_is_ddr = true, + .address_size = 4, + .additional_value = 0, + .additional_size = 0, + .dummy_cycles = 0, + .transfer_buffer = NULL, + .transfer_is_ddr = true, + .transfer_size = 0, + .slch_value = 0, + .clsh_value = 5, + .shsl_value = 1 +}; + +/* Erase 64k (DOPI) */ +static const xspi_op_t op_erase_64k_dopi = { + .form = SPI_FORM_8_8_8, + .op = 0xDC23, + .op_size = 2, + .op_is_ddr = true, + .address = 0, + .address_is_ddr = true, + .address_size = 4, + .additional_value = 0, + .additional_size = 0, + .dummy_cycles = 0, + .transfer_buffer = NULL, + .transfer_is_ddr = true, + .transfer_size = 0, + .slch_value = 0, + .clsh_value = 5, + .shsl_value = 1 +}; + +/* Function definitions */ +static int flash_write_enable_spi(octaflash_mx66uw_ctrl_t * myctrl) +{ + const xspi_instance_t * xspi = myctrl->xspi; + return xspi->api->exec_op(xspi->ctrl, &op_write_enable_spi, false); +} + +static int flash_write_enable_dopi(octaflash_mx66uw_ctrl_t * myctrl) +{ + const xspi_instance_t * xspi = myctrl->xspi; + return xspi->api->exec_op(xspi->ctrl, &op_write_enable_dopi, false); +} + +static int flash_read_status_register_spi(octaflash_mx66uw_ctrl_t * myctrl) +{ + int result; + const xspi_instance_t * xspi = myctrl->xspi; + + uint8_t status; + xspi_op_t op = op_read_status_spi; + op.transfer_buffer = &status; + result = xspi->api->exec_op(xspi->ctrl, &op, false); + if (result) return result; + return (int)status; +} + +static int flash_read_status_register_dopi(octaflash_mx66uw_ctrl_t * myctrl) +{ + int result; + const xspi_instance_t * xspi = myctrl->xspi; + uint8_t status; + xspi_op_t op = op_read_status_dopi; + op.transfer_buffer = &status; + result = xspi->api->exec_op(xspi->ctrl, &op, false); + if (result) return result; + return (int)status; +} + +static int flash_write_config_register2_spi(octaflash_mx66uw_ctrl_t * myctrl, uint32_t add, uint8_t data) +{ + const xspi_instance_t * xspi = myctrl->xspi; + xspi_op_t op = op_write_config2_spi; + op.address = add; + op.transfer_buffer = &data; + return xspi->api->exec_op(xspi->ctrl, &op, true); +} + +static int flash_open(xspidevice_ctrl_t * ctrl, xspidevice_cfg_t const * cfg) +{ + assert(ctrl); + assert(cfg); + int result; + enum xspidevice_write_status ws; + octaflash_mx66uw_ctrl_t * myctrl = (octaflash_mx66uw_ctrl_t *)ctrl; + const xspi_instance_t * xspi = cfg->xspi; + + if (myctrl->opened) return -1; + + myctrl->xspi = xspi; + result = xspi->api->open(xspi->ctrl, xspi->cfg); + if (result == 0) { + xspi->api->set_frequency(xspi->ctrl, spi_frequency); + if (false) flash_read_status_register_spi(myctrl); /* Avoiding build error */ + udelay(SPI_POST_RESET_WAIT); + flash_write_enable_spi(myctrl); + flash_write_config_register2_spi(myctrl, 0x00000300, 5); + + flash_write_enable_spi(myctrl); + flash_write_config_register2_spi(myctrl, 0x00000000, 2); + + do { + ws = flash_get_write_status(ctrl); + } while(ws == WRITE_STATUS_IN_PROGRESS); + + myctrl->opened = true; + } + + return result; +} + +static int flash_close(xspidevice_ctrl_t * ctrl) +{ + assert(ctrl); + int result = -1; + octaflash_mx66uw_ctrl_t * myctrl = (octaflash_mx66uw_ctrl_t *)ctrl; + const xspi_instance_t * xspi = myctrl->xspi; + if (myctrl->opened) { + result = xspi->api->close(xspi->ctrl); + myctrl->opened = false; + } + return result; + +} + +static int flash_exec_op(xspidevice_ctrl_t * ctrl, xspi_op_t const * op, bool is_write) +{ + assert(ctrl); + assert(op); + octaflash_mx66uw_ctrl_t * myctrl = (octaflash_mx66uw_ctrl_t *)ctrl; + const xspi_instance_t * xspi = myctrl->xspi; + + return xspi->api->exec_op(xspi->ctrl, op, is_write); +} + +static int flash_enter_xip(xspidevice_ctrl_t * ctrl) +{ + int result = -1; + assert(ctrl); + octaflash_mx66uw_ctrl_t * myctrl = (octaflash_mx66uw_ctrl_t *)ctrl; + const xspi_instance_t * xspi = myctrl->xspi; + + result = xspi->api->configure_xip(xspi->ctrl, &rop, NULL); + if (result == 0) { + result = xspi->api->run_manual_calibration(xspi->ctrl); + result = xspi->api->start_xip(xspi->ctrl); + } + + return result; +} + +static int flash_exit_xip(xspidevice_ctrl_t * ctrl) +{ + assert(ctrl); + octaflash_mx66uw_ctrl_t * myctrl = (octaflash_mx66uw_ctrl_t *)ctrl; + const xspi_instance_t * xspi = myctrl->xspi; + + return xspi->api->stop_xip(xspi->ctrl); +} + +static int flash_get_info(xspidevice_ctrl_t * ctrl, xspidevice_info_t * info) +{ + assert(ctrl); + assert(info); + info->capacity = 0; + strlcpy(info->device_vendor, "Macronix", sizeof(info->device_vendor)); + strlcpy(info->device_product, "MX66UW", sizeof(info->device_product)); + return 0; +} + +static int flash_read(xspidevice_ctrl_t * ctrl, void * buffer, size_t address, size_t length) +{ + assert(ctrl); + octaflash_mx66uw_ctrl_t * myctrl = (octaflash_mx66uw_ctrl_t *)ctrl; + const xspi_instance_t * xspi = myctrl->xspi; + + uintptr_t mmap_base = xspi->api->get_mmap_base(xspi->ctrl); + memcpy(buffer, (void*)(mmap_base+address), length); + + return 0; +} + +static int flash_write(xspidevice_ctrl_t * ctrl, void const * buffer, size_t address, size_t length) +{ + int result = 0; + if (RZ_XSPIFLASH_DISABLE_WRITE) { + result = -1; + } + else { + assert(ctrl); + octaflash_mx66uw_ctrl_t * myctrl = (octaflash_mx66uw_ctrl_t *)ctrl; + const xspi_instance_t * xspi = myctrl->xspi; + uintptr_t tmp_buffer = (uintptr_t)buffer; + xspi_op_t op = op_page_program_dopi; + + /* Stop XIP mode */ + xspi->api->stop_xip(xspi->ctrl); + + /* Stop Auto Calibration */ + xspi->api->disable_auto_calibration(xspi->ctrl); + + while (length && !result) { + /* Wait for previous command finished */ + enum xspidevice_write_status ws; + do { + ws = flash_get_write_status(ctrl); + } while(ws == WRITE_STATUS_IN_PROGRESS); + if (ws != WRITE_STATUS_OK) { + /* Error on previous command */ + result = -1; + break; + } + result = flash_write_enable_dopi(myctrl); + if (result) break; + + op.transfer_buffer = (void*)tmp_buffer; + op.address = address; + if (length > 4) op.transfer_size = 4; + else op.transfer_size = length; + + /* Execute page program */ + result = xspi->api->exec_op(xspi->ctrl, &op, true); + + /* Move pointer */ + address += op.transfer_size; + tmp_buffer += op.transfer_size; + length -= op.transfer_size; + } + + /* Restart Auto Calibration */ + xspi->api->enable_auto_calibration(xspi->ctrl); + + xspi->api->start_xip(xspi->ctrl); + + /* Invalidate dcache */ + xspi->api->inv_mmap(xspi->ctrl); + } + + return result; +} + +static int flash_erase_4k(octaflash_mx66uw_ctrl_t *myctrl, size_t address) +{ + xspi_op_t op = op_erase_4k_dopi; + op.address = address; + return myctrl->xspi->api->exec_op(myctrl->xspi->ctrl, &op, true); +} + +static int flash_erase_64k(octaflash_mx66uw_ctrl_t *myctrl, size_t address) +{ + xspi_op_t op = op_erase_64k_dopi; + op.address = address; + return myctrl->xspi->api->exec_op(myctrl->xspi->ctrl, &op, true); +} + +static int flash_erase(xspidevice_ctrl_t * ctrl, size_t address, size_t length) +{ + int result; + if (RZ_XSPIFLASH_DISABLE_WRITE) { + result = -1; + } + else { + assert(ctrl); + assert((address & 4095) == 0); + assert(length > 4095); + size_t over = address + length; + octaflash_mx66uw_ctrl_t * myctrl = (octaflash_mx66uw_ctrl_t *)ctrl; + + do { + /* Wait for previous command finished */ + enum xspidevice_write_status ws; + do { + ws = flash_get_write_status(ctrl); + } while(ws == WRITE_STATUS_IN_PROGRESS); + if (ws != WRITE_STATUS_OK) { + /* Error on previous command */ + return -1; + } + result = flash_write_enable_dopi(myctrl); + if (result) return result; + + /* Select erase size */ + if (!(address & 0xffff) && length >= 65536) { + /* 64K boundary */ + result = flash_erase_64k(myctrl, address); + address += 65536; + length -= 65536; + } + else { + /* 4K boundary */ + result = flash_erase_4k(myctrl, address); + address += 4096; + length -= 4096; + } + + if (result) return result; + } while (address < over); + } + + return result; +} + +static enum xspidevice_write_status flash_get_write_status(xspidevice_ctrl_t * ctrl) +{ + assert(ctrl); + int result; + octaflash_mx66uw_ctrl_t * myctrl = (octaflash_mx66uw_ctrl_t *)ctrl; + + /* Read Status Register - 1 */ + result = flash_read_status_register_dopi(myctrl); + if (result < 0) return WRITE_STATUS_FAIL; + if (result & 1) return WRITE_STATUS_IN_PROGRESS; + return WRITE_STATUS_OK; +} diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/xspidevice/octaflash_mx66uw/octaflash_mx66uw_api.h b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/xspidevice/octaflash_mx66uw/octaflash_mx66uw_api.h new file mode 100644 index 00000000..fb7d035c --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/xspidevice/octaflash_mx66uw/octaflash_mx66uw_api.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2022, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _OCTAFLASH_MX66UW_API_H_ +#define _OCTAFLASH_MX66UW_API_H_ +#include +#include + +#include "xspidevice_api.h" + +/** xSPI device control structure */ +typedef struct st_octaflash_mx66uw_ctrl +{ + bool opened; + const xspi_instance_t * xspi; +} octaflash_mx66uw_ctrl_t; + +/** xSPI device extended configuration structure */ +typedef struct st_octaflash_mx66uw_ext +{ + /* No additional configurations */ +} octaflash_mx66uw_ext_t; + +extern const xspidevice_api_t octaflash_mx66uw_api; + +#endif /* _OCTAFLASH_MX66UW_API_H_ */ + diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/xspidevice/octaflash_mx66uw/rz_xspidevice.mk b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/xspidevice/octaflash_mx66uw/rz_xspidevice.mk new file mode 100644 index 00000000..092d42b0 --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/xspidevice/octaflash_mx66uw/rz_xspidevice.mk @@ -0,0 +1,9 @@ +# +# Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# +_XSPI_DEVICE:=octaflash_mx66uw +RZ_XSPI_SOURCES:=$(RZ_XSPI_SOURCES) plat/renesas/rz/common/drivers/xspidevice/$(_XSPI_DEVICE)/$(_XSPI_DEVICE).c +PLAT_INCLUDES+=-Iplat/renesas/rz/common/drivers/xspidevice/$(_XSPI_DEVICE) +RZ_XSPI_HEADERS:=$(RZ_XSPI_HEADERS) $(_XSPI_DEVICE)_api.h diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/xspidevice/octaram_apsxx/octaram_apsxx.c b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/xspidevice/octaram_apsxx/octaram_apsxx.c new file mode 100644 index 00000000..a319cc09 --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/xspidevice/octaram_apsxx/octaram_apsxx.c @@ -0,0 +1,232 @@ +/* + * Copyright (c) 2022, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +#include "octaram_apsxx_api.h" + +/* Defaults */ +#define DEFAULT_SPI_FREQUENCY 100000000 +#define SPI_POST_RESET_WAIT 2 + +/* Static function pre-definition */ +static int octaram_open(xspidevice_ctrl_t * ctrl, xspidevice_cfg_t const * cfg); +static int octaram_close(xspidevice_ctrl_t * ctrl); +static int octaram_exec_op(xspidevice_ctrl_t * ctrl, xspi_op_t const * op, bool is_write); +static int octaram_enter_xip(xspidevice_ctrl_t * ctrl); +static int octaram_exit_xip(xspidevice_ctrl_t * ctrl); +static int octaram_get_info(xspidevice_ctrl_t * ctrl, xspidevice_info_t * info); +static int octaram_read(xspidevice_ctrl_t * ctrl, void * buffer, size_t address, size_t length); +static int octaram_write(xspidevice_ctrl_t * ctrl, void const * buffer, size_t address, size_t length); +static int octaram_erase(xspidevice_ctrl_t * ctrl, size_t address, size_t length); +static enum xspidevice_write_status octaram_get_write_status(xspidevice_ctrl_t * ctrl); + +/* API function table definition */ +const xspidevice_api_t octaram_apsxx_api = { + .open = octaram_open, + .close = octaram_close, + .exec_op = octaram_exec_op, + .enter_xip = octaram_enter_xip, + .exit_xip = octaram_exit_xip, + .get_info = octaram_get_info, + .read = octaram_read, + .write = octaram_write, + .erase = octaram_erase, + .get_write_status = octaram_get_write_status, +}; + +/* Access timing parameters : 100MHz + DRCSTR : DVRDLO1=0, DVRDHI1=5, DVRDCMD1=1 + DWCSTR : DVWLO1=0, DVWHI1=0, DVWCMD1=1 + DCSTR : DVSELLO=0, DVSELHI=5, DVSELCMD=1 */ + +/* Static variables */ +static int spi_frequency = DEFAULT_SPI_FREQUENCY + 1; + +/*** Operational Commands ***/ +/* Write Mode Register */ +static const xspi_op_t op_write_mode = { + .form = SPI_FORM_8_8_8, + .op = 0x4000, + .op_size = 2, + .op_is_ddr = true, + .address = 0x00040000, + .address_is_ddr = true, + .address_size = 4, + .additional_value = 0, + .additional_size = 0, + .dummy_cycles = 0, + .transfer_buffer = NULL, + .transfer_is_ddr = true, + .transfer_size = 2, + .slch_value = 0, + .clsh_value = 0, + .shsl_value = 1 +}; + +/* Read Command = Sync Read (80/xxh) */ +static const xspi_op_t rop = { + .form = SPI_FORM_8_8_8, + .op = 0x8000, + .op_size = 2, + .op_is_ddr = true, + .address = 0, + .address_is_ddr = true, + .address_size = 4, + .additional_value = 0, + .additional_size = 0, + .dummy_cycles = 4, + .transfer_buffer = NULL, + .transfer_is_ddr = true, + .transfer_size = 0, + .slch_value = 0, + .clsh_value = 5, + .shsl_value = 1 +}; + +/* Write Command = Sync Write (00/xxh) */ +static const xspi_op_t wop = { + .form = SPI_FORM_8_8_8, + .op = 0x0000, + .op_size = 2, + .op_is_ddr = true, + .address = 0, + .address_is_ddr = true, + .address_size = 4, + .additional_value = 0, + .additional_size = 0, + .dummy_cycles = 4, + .transfer_buffer = NULL, + .transfer_is_ddr = true, + .transfer_size = 0, + .slch_value = 0, + .clsh_value = 0, + .shsl_value = 1 +}; + +/* Function definitions */ +static int octaram_write_mode_register(octaram_apsxx_ctrl_t * myctrl, uint16_t data) +{ + const xspi_instance_t * xspi = myctrl->xspi; + xspi_op_t op = op_write_mode; + op.transfer_buffer = &data; + return xspi->api->exec_op(xspi->ctrl, &op, true); +} + +static int octaram_open(xspidevice_ctrl_t * ctrl, xspidevice_cfg_t const * cfg) +{ + assert(ctrl); + assert(cfg); + int result; + octaram_apsxx_ctrl_t * myctrl = (octaram_apsxx_ctrl_t *)ctrl; + const xspi_instance_t * xspi = cfg->xspi; + + if (myctrl->opened) return -1; + + myctrl->xspi = xspi; + result = xspi->api->open(xspi->ctrl, xspi->cfg); + if (result == 0) { + xspi->api->set_frequency(xspi->ctrl, spi_frequency); + udelay(SPI_POST_RESET_WAIT); + octaram_write_mode_register(myctrl, 0xF011); + /* [15] Deep Power Down Enable = 1 : Normal Operation + [14:12] Drive Strength = 111 : 25ohms 010 + [11:8] Reserved = 0000 + [7:4] Latency Code = 0001 : 4 clocks + [3] Latency Type = 0 : Variable Latency + [2] Burst Type = 0 : Wrapped + [1:0] Burst Length = 01 : 64 bytes */ + myctrl->opened = true; + } + + return result; +} + +static int octaram_close(xspidevice_ctrl_t * ctrl) +{ + assert(ctrl); + int result = -1; + octaram_apsxx_ctrl_t * myctrl = (octaram_apsxx_ctrl_t *)ctrl; + const xspi_instance_t * xspi = myctrl->xspi; + if (myctrl->opened) { + result = xspi->api->close(xspi->ctrl); + myctrl->opened = false; + } + return result; + +} + +static int octaram_exec_op(xspidevice_ctrl_t * ctrl, xspi_op_t const * op, bool is_write) +{ + assert(ctrl); + assert(op); + octaram_apsxx_ctrl_t * myctrl = (octaram_apsxx_ctrl_t *)ctrl; + const xspi_instance_t * xspi = myctrl->xspi; + + return xspi->api->exec_op(xspi->ctrl, op, is_write); +} + +static int octaram_enter_xip(xspidevice_ctrl_t * ctrl) +{ + int result = -1; + assert(ctrl); + octaram_apsxx_ctrl_t * myctrl = (octaram_apsxx_ctrl_t *)ctrl; + const xspi_instance_t * xspi = myctrl->xspi; + + result = xspi->api->configure_xip(xspi->ctrl, &rop, &wop); + if (result == 0) { + result = xspi->api->run_manual_calibration(xspi->ctrl); + result = xspi->api->start_xip(xspi->ctrl); + } + + return result; +} + +static int octaram_exit_xip(xspidevice_ctrl_t * ctrl) +{ + assert(ctrl); + octaram_apsxx_ctrl_t * myctrl = (octaram_apsxx_ctrl_t *)ctrl; + const xspi_instance_t * xspi = myctrl->xspi; + + return xspi->api->stop_xip(xspi->ctrl); +} + +static int octaram_get_info(xspidevice_ctrl_t * ctrl, xspidevice_info_t * info) +{ + assert(ctrl); + assert(info); + info->capacity = 0; + strlcpy(info->device_vendor, "APMemory", sizeof(info->device_vendor)); + strlcpy(info->device_product, "APSx", sizeof(info->device_product)); + return 0; +} + +static int octaram_read(xspidevice_ctrl_t * ctrl, void * buffer, size_t address, size_t length) +{ + return -1; + +} + +static int octaram_write(xspidevice_ctrl_t * ctrl, void const * buffer, size_t address, size_t length) +{ + return -1; + +} + +static int octaram_erase(xspidevice_ctrl_t * ctrl, size_t address, size_t length) +{ + return -1; + +} + +static enum xspidevice_write_status octaram_get_write_status(xspidevice_ctrl_t * ctrl) +{ + return -1; + +} diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/xspidevice/octaram_apsxx/octaram_apsxx_api.h b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/xspidevice/octaram_apsxx/octaram_apsxx_api.h new file mode 100644 index 00000000..079f6fea --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/xspidevice/octaram_apsxx/octaram_apsxx_api.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2022, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _OCTARAM_APSXX_API_H_ +#define _OCTARAM_APSXX_API_H_ +#include +#include + +#include "xspidevice_api.h" + +/** xSPI device control structure */ +typedef struct st_octaram_apsxx_ctrl +{ + bool opened; + const xspi_instance_t * xspi; +} octaram_apsxx_ctrl_t; + +/** xSPI device extended configuration structure */ +typedef struct st_octaram_apsxx_ext +{ + /* No additional configurations */ +} octaram_apsxx_ext_t; + +extern const xspidevice_api_t octaram_apsxx_api; + +#endif /* _OCTARAM_APSXX_API_H_ */ + diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/xspidevice/octaram_apsxx/rz_xspidevice.mk b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/xspidevice/octaram_apsxx/rz_xspidevice.mk new file mode 100644 index 00000000..eb75c7f1 --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/xspidevice/octaram_apsxx/rz_xspidevice.mk @@ -0,0 +1,9 @@ +# +# Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# +_XSPI_DEVICE:=octaram_apsxx +RZ_XSPI_SOURCES:=$(RZ_XSPI_SOURCES) plat/renesas/rz/common/drivers/xspidevice/$(_XSPI_DEVICE)/$(_XSPI_DEVICE).c +PLAT_INCLUDES+=-Iplat/renesas/rz/common/drivers/xspidevice/$(_XSPI_DEVICE) +RZ_XSPI_HEADERS:=$(RZ_XSPI_HEADERS) $(_XSPI_DEVICE)_api.h diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/xspidevice/qspiflash_at25/qspiflash_at25.c b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/xspidevice/qspiflash_at25/qspiflash_at25.c new file mode 100644 index 00000000..6d096d9f --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/xspidevice/qspiflash_at25/qspiflash_at25.c @@ -0,0 +1,546 @@ +/* + * Copyright (c) 2022, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +#include "qspiflash_at25_api.h" + +/* Defaults */ +#define DEFAULT_SPI_FREQUENCY 66666667 +#define SPI_POST_RESET_WAIT 50 + +/* Static function pre-definition */ +static int flash_open(xspidevice_ctrl_t * ctrl, xspidevice_cfg_t const * cfg); +static int flash_close(xspidevice_ctrl_t * ctrl); +static int flash_exec_op(xspidevice_ctrl_t * ctrl, xspi_op_t const * op, bool is_write); +static int flash_enter_xip(xspidevice_ctrl_t * ctrl); +static int flash_exit_xip(xspidevice_ctrl_t * ctrl); +static int flash_get_info(xspidevice_ctrl_t * ctrl, xspidevice_info_t * info); +static int flash_read(xspidevice_ctrl_t * ctrl, void * buffer, size_t address, size_t length); +static int flash_write(xspidevice_ctrl_t * ctrl, void const * buffer, size_t address, size_t length); +static int flash_erase(xspidevice_ctrl_t * ctrl, size_t address, size_t length); +static enum xspidevice_write_status flash_get_write_status(xspidevice_ctrl_t * ctrl); + +/* API function table definition */ +const xspidevice_api_t qspiflash_at25_api = { + .open = flash_open, + .close = flash_close, + .exec_op = flash_exec_op, + .enter_xip = flash_enter_xip, + .exit_xip = flash_exit_xip, + .get_info = flash_get_info, + .read = flash_read, + .write = flash_write, + .erase = flash_erase, + .get_write_status = flash_get_write_status, +}; + +/* Static variables */ +static int spi_frequency = DEFAULT_SPI_FREQUENCY; +static const uint8_t status2_srp1 = 0x01; +static const uint8_t status2_qe = 0x02; + +/*** Flash Commands ***/ +/* Write Enable */ +static const xspi_op_t op_write_enable = { + .form = SPI_FORM_1_1_1, + .op = 0x06, + .op_size = 1, + .op_is_ddr = false, + .address = 0, + .address_is_ddr = false, + .address_size = 0, + .additional_value = 0, + .additional_size = 0, + .dummy_cycles = 0, + .transfer_buffer = NULL, + .transfer_is_ddr = false, + .transfer_size = 0, + .force_idle_level_mask = 0x08, // Keep IO3/HOLD pin to High + .force_idle_level_value = 0x08, // Keep IO3/HOLD pin to High + .slch_value = 0, + .clsh_value = 0, + .shsl_value = 6 +}; + +/* Read Status Register - 1 */ +static const xspi_op_t op_read_status1 = { + .form = SPI_FORM_1_1_1, + .op = 0x05, + .op_size = 1, + .op_is_ddr = false, + .address = 0, + .address_is_ddr = false, + .address_size = 0, + .additional_value = 0, + .additional_size = 0, + .dummy_cycles = 0, + .transfer_buffer = NULL, + .transfer_is_ddr = false, + .transfer_size = 1, + .force_idle_level_mask = 0x08, // Keep IO3/HOLD pin to High + .force_idle_level_value = 0x08, // Keep IO3/HOLD pin to High + .slch_value = 0, + .clsh_value = 0, + .shsl_value = 6 +}; + +/* Read Status Register - 2 */ +static const xspi_op_t op_read_status2 = { + .form = SPI_FORM_1_1_1, + .op = 0x35, + .op_size = 1, + .op_is_ddr = false, + .address = 0, + .address_is_ddr = false, + .address_size = 0, + .additional_value = 0, + .additional_size = 0, + .dummy_cycles = 0, + .transfer_buffer = NULL, + .transfer_is_ddr = false, + .transfer_size = 1, + .force_idle_level_mask = 0x08, // Keep IO3/HOLD pin to High + .force_idle_level_value = 0x08, // Keep IO3/HOLD pin to High + .slch_value = 0, + .clsh_value = 0, + .shsl_value = 6 +}; + +/* Write Status Register - 2 */ +static const xspi_op_t op_write_status2 = { + .form = SPI_FORM_1_1_1, + .op = 0x31, + .op_size = 1, + .op_is_ddr = false, + .address = 0, + .address_is_ddr = false, + .address_size = 0, + .additional_value = 0, + .additional_size = 0, + .dummy_cycles = 0, + .transfer_buffer = NULL, + .transfer_is_ddr = false, + .transfer_size = 1, + .force_idle_level_mask = 0x08, // Keep IO3/HOLD pin to High + .force_idle_level_value = 0x08, // Keep IO3/HOLD pin to High + .slch_value = 0, + .clsh_value = 0, + .shsl_value = 6 +}; + +/* Read Command = Fast Read Quad I/O (EBh) */ +static const xspi_op_t rop = { + .form = SPI_FORM_1_4_4, + .op = 0xeb, + .op_size = 1, + .op_is_ddr = false, + .address = 0, + .address_is_ddr = false, + .address_size = 3, + .additional_value = 0x55555555, + .additional_size = 1, + .dummy_cycles = 4, + .transfer_buffer = NULL, + .transfer_is_ddr = false, + .transfer_size = 0, + .force_idle_level_mask = 0x08, // Keep IO3/HOLD pin to High + .force_idle_level_value = 0x08, // Keep IO3/HOLD pin to High + .slch_value = 0, + .clsh_value = 0, + .shsl_value = 6 +}; + +/* Quad Page Program */ +static const xspi_op_t op_page_program = { + .form = SPI_FORM_1_4_4, + .op = 0x33, + .op_size = 1, + .op_is_ddr = false, + .address = 0, + .address_is_ddr = false, + .address_size = 3, + .additional_value = 0, + .additional_size = 0, + .dummy_cycles = 0, + .transfer_buffer = NULL, + .transfer_is_ddr = false, + .transfer_size = 0, + .force_idle_level_mask = 0x08, // Keep IO3/HOLD pin to High + .force_idle_level_value = 0x08, // Keep IO3/HOLD pin to High + .slch_value = 0, + .clsh_value = 0, + .shsl_value = 6 +}; + +/* Erase 4k */ +static const xspi_op_t op_erase_4k = { + .form = SPI_FORM_1_1_1, + .op = 0x20, + .op_size = 1, + .op_is_ddr = false, + .address = 0, + .address_is_ddr = false, + .address_size = 3, + .additional_value = 0, + .additional_size = 0, + .dummy_cycles = 0, + .transfer_buffer = NULL, + .transfer_is_ddr = false, + .transfer_size = 0, + .force_idle_level_mask = 0x08, // Keep IO3/HOLD pin to High + .force_idle_level_value = 0x08, // Keep IO3/HOLD pin to High + .slch_value = 0, + .clsh_value = 0, + .shsl_value = 6 +}; + +/* Erase 32k */ +static const xspi_op_t op_erase_32k = { + .form = SPI_FORM_1_1_1, + .op = 0x52, + .op_size = 1, + .op_is_ddr = false, + .address = 0, + .address_is_ddr = false, + .address_size = 3, + .additional_value = 0, + .additional_size = 0, + .dummy_cycles = 0, + .transfer_buffer = NULL, + .transfer_is_ddr = false, + .transfer_size = 0, + .force_idle_level_mask = 0x08, // Keep IO3/HOLD pin to High + .force_idle_level_value = 0x08, // Keep IO3/HOLD pin to High + .slch_value = 0, + .clsh_value = 0, + .shsl_value = 6 +}; + +/* Erase 64k */ +static const xspi_op_t op_erase_64k = { + .form = SPI_FORM_1_1_1, + .op = 0xD8, + .op_size = 1, + .op_is_ddr = false, + .address = 0, + .address_is_ddr = false, + .address_size = 3, + .additional_value = 0, + .additional_size = 0, + .dummy_cycles = 0, + .transfer_buffer = NULL, + .transfer_is_ddr = false, + .transfer_size = 0, + .force_idle_level_mask = 0x08, // Keep IO3/HOLD pin to High + .force_idle_level_value = 0x08, // Keep IO3/HOLD pin to High + .slch_value = 0, + .clsh_value = 0, + .shsl_value = 6 +}; + +/* Function definitions */ +static int flash_write_enable(qspiflash_at25_ctrl_t * myctrl) +{ + const xspi_instance_t * xspi = myctrl->xspi; + return xspi->api->exec_op(xspi->ctrl, &op_write_enable, false); +} + +static int flash_read_status_register1(qspiflash_at25_ctrl_t * myctrl) +{ + int result; + const xspi_instance_t * xspi = myctrl->xspi; + + uint8_t status; + xspi_op_t op = op_read_status1; + op.transfer_buffer = &status; + result = xspi->api->exec_op(xspi->ctrl, &op, false); + if (result) return result; + return (int)status; +} + +static int flash_read_status_register2(qspiflash_at25_ctrl_t * myctrl) +{ + int result; + const xspi_instance_t * xspi = myctrl->xspi; + + uint8_t status; + xspi_op_t op = op_read_status2; + op.transfer_buffer = &status; + result = xspi->api->exec_op(xspi->ctrl, &op, false); + if (result) return result; + return (int)status; +} + +static int flash_write_status_register2(qspiflash_at25_ctrl_t * myctrl, uint8_t status) +{ + const xspi_instance_t * xspi = myctrl->xspi; + xspi_op_t op = op_write_status2; + op.transfer_buffer = &status; + return xspi->api->exec_op(xspi->ctrl, &op, true); +} + +static int flash_set_qe(qspiflash_at25_ctrl_t * myctrl) +{ + int result; + result = flash_read_status_register2(myctrl); + if (result < 0) return result; + uint8_t sr2 = (uint8_t)result; + + /* Check if QE is set or not */ + if (sr2 & status2_qe) return 0; + + /* Check if SRP1 is set or not : If set, can not set QE bit */ + if (sr2 & status2_srp1) return -1; + + /* Set QE bit */ + result = flash_write_enable(myctrl); + if (result < 0) return result; + sr2 |= status2_qe; + return flash_write_status_register2(myctrl, sr2); +} + +static int flash_open(xspidevice_ctrl_t * ctrl, xspidevice_cfg_t const * cfg) +{ + assert(ctrl); + assert(cfg); + int result; + qspiflash_at25_ctrl_t * myctrl = (qspiflash_at25_ctrl_t *)ctrl; + const xspi_instance_t * xspi = cfg->xspi; + + if (myctrl->opened) return -1; + + myctrl->xspi = xspi; + result = xspi->api->open(xspi->ctrl, xspi->cfg); + if (result == 0) { + result = xspi->api->set_frequency(xspi->ctrl, spi_frequency); + udelay(SPI_POST_RESET_WAIT); + } + if (result == 0) { + result = flash_set_qe(myctrl); + } + if (result == 0) { + myctrl->opened = true; + } + else { + xspi->api->close(xspi->ctrl); + } + + return result; +} +static int flash_close(xspidevice_ctrl_t * ctrl) +{ + assert(ctrl); + int result = -1; + qspiflash_at25_ctrl_t * myctrl = (qspiflash_at25_ctrl_t *)ctrl; + const xspi_instance_t * xspi = myctrl->xspi; + if (myctrl->opened) { + result = xspi->api->close(xspi->ctrl); + myctrl->opened = false; + } + return result; + +} +static int flash_exec_op(xspidevice_ctrl_t * ctrl, xspi_op_t const * op, bool is_write) +{ + assert(ctrl); + assert(op); + qspiflash_at25_ctrl_t * myctrl = (qspiflash_at25_ctrl_t *)ctrl; + const xspi_instance_t * xspi = myctrl->xspi; + + return xspi->api->exec_op(xspi->ctrl, op, is_write); +} + +static int flash_enter_xip(xspidevice_ctrl_t * ctrl) +{ + int result = -1; + assert(ctrl); + qspiflash_at25_ctrl_t * myctrl = (qspiflash_at25_ctrl_t *)ctrl; + const xspi_instance_t * xspi = myctrl->xspi; + + result = xspi->api->configure_xip(xspi->ctrl, &rop, NULL); + if (result == 0) { + result = xspi->api->set_frequency(xspi->ctrl, spi_frequency); + } + if (result == 0) { + result = xspi->api->start_xip(xspi->ctrl); + } + + return result; +} +static int flash_exit_xip(xspidevice_ctrl_t * ctrl) +{ + assert(ctrl); + qspiflash_at25_ctrl_t * myctrl = (qspiflash_at25_ctrl_t *)ctrl; + const xspi_instance_t * xspi = myctrl->xspi; + + return xspi->api->stop_xip(xspi->ctrl); +} +static int flash_get_info(xspidevice_ctrl_t * ctrl, xspidevice_info_t * info) +{ + assert(ctrl); + assert(info); + info->capacity = 0; + info->minimum_erase_size = 0; + + strlcpy(info->device_vendor, "Renesas", sizeof(info->device_vendor)); + strlcpy(info->device_product, "AT25x", sizeof(info->device_product)); + return 0; +} +static int flash_read(xspidevice_ctrl_t * ctrl, void * buffer, size_t address, size_t length) +{ + assert(ctrl); + qspiflash_at25_ctrl_t * myctrl = (qspiflash_at25_ctrl_t *)ctrl; + const xspi_instance_t * xspi = myctrl->xspi; + + uintptr_t mmap_base = xspi->api->get_mmap_base(xspi->ctrl); + memcpy(buffer, (void*)(mmap_base+address), length); + + return 0; +} + +static int flash_write(xspidevice_ctrl_t * ctrl, void const * buffer, size_t address, size_t length) +{ + int result = 0; + if (RZ_XSPIFLASH_DISABLE_WRITE) { + result = -1; + } + else { + assert(ctrl); + qspiflash_at25_ctrl_t * myctrl = (qspiflash_at25_ctrl_t *)ctrl; + const xspi_instance_t * xspi = myctrl->xspi; + uintptr_t tmp_buffer = (uintptr_t)buffer; + xspi_op_t op = op_page_program; + + /* Stop XIP mode */ + xspi->api->stop_xip(xspi->ctrl); + + while (length && !result) { + /* Wait for previous command finished */ + enum xspidevice_write_status ws; + do { + ws = flash_get_write_status(ctrl); + } while(ws == WRITE_STATUS_IN_PROGRESS); + if (ws != WRITE_STATUS_OK) { + /* Error on previous command */ + result = -1; + break; + } + result = flash_write_enable(myctrl); + if (result) break; + + op.transfer_buffer = (void*)tmp_buffer; + op.address = address; + if (length > 256) op.transfer_size = 256; + else op.transfer_size = length; + + /* Execute page program */ + result = xspi->api->exec_op(xspi->ctrl, &op, true); + + /* Move pointer */ + address += op.transfer_size; + tmp_buffer += op.transfer_size; + length -= op.transfer_size; + } + + xspi->api->start_xip(xspi->ctrl); + + /* Invalidate dcache */ + xspi->api->inv_mmap(xspi->ctrl); + } + + return result; +} + +static int flash_erase_4k(qspiflash_at25_ctrl_t *myctrl, size_t address) +{ + xspi_op_t op = op_erase_4k; + op.address = address; + return myctrl->xspi->api->exec_op(myctrl->xspi->ctrl, &op, true); +} + +static int flash_erase_32k(qspiflash_at25_ctrl_t *myctrl, size_t address) +{ + xspi_op_t op = op_erase_32k; + op.address = address; + return myctrl->xspi->api->exec_op(myctrl->xspi->ctrl, &op, true); +} + +static int flash_erase_64k(qspiflash_at25_ctrl_t *myctrl, size_t address) +{ + xspi_op_t op = op_erase_64k; + op.address = address; + return myctrl->xspi->api->exec_op(myctrl->xspi->ctrl, &op, true); +} + +static int flash_erase(xspidevice_ctrl_t * ctrl, size_t address, size_t length) +{ + int result; + if (RZ_XSPIFLASH_DISABLE_WRITE) { + result = -1; + } + else { + assert(ctrl); + assert((address & 4095) == 0); + assert(length > 4095); + size_t over = address + length; + qspiflash_at25_ctrl_t * myctrl = (qspiflash_at25_ctrl_t *)ctrl; + + do { + /* Wait for previous command finished */ + enum xspidevice_write_status ws; + do { + ws = flash_get_write_status(ctrl); + } while(ws == WRITE_STATUS_IN_PROGRESS); + if (ws != WRITE_STATUS_OK) { + /* Error on previous command */ + return -1; + } + result = flash_write_enable(myctrl); + if (result) return result; + + /* Select erase size */ + if (!(address & 0xffff) && length >= 65536) { + /* 64K boundary */ + result = flash_erase_64k(myctrl, address); + address += 65536; + length -= 65536; + } + else if (!(address & 0x7fff) && length >= 32768) { + /* 32K boundary */ + result = flash_erase_32k(myctrl, address); + address += 32768; + length -= 32768; + } + else { + /* 4K boundary */ + result = flash_erase_4k(myctrl, address); + address += 4096; + length -= 4096; + } + + if (result) return result; + } while (address < over); + } + + return result; +} + +static enum xspidevice_write_status flash_get_write_status(xspidevice_ctrl_t * ctrl) +{ + assert(ctrl); + int result; + qspiflash_at25_ctrl_t * myctrl = (qspiflash_at25_ctrl_t *)ctrl; + + /* Read Status Register - 1 */ + result = flash_read_status_register1(myctrl); + if (result < 0) return WRITE_STATUS_FAIL; + if (result & 1) return WRITE_STATUS_IN_PROGRESS; + return WRITE_STATUS_OK; +} diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/xspidevice/qspiflash_at25/qspiflash_at25_api.h b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/xspidevice/qspiflash_at25/qspiflash_at25_api.h new file mode 100644 index 00000000..5219ce3a --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/xspidevice/qspiflash_at25/qspiflash_at25_api.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2022, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _QSPIFLASH_AT25_API_H_ +#define _QSPIFLASH_AT25_API_H_ +#include +#include + +#include "xspidevice_api.h" + +/** xSPI device control structure */ +typedef struct st_qspiflash_at25_ctrl +{ + bool opened; + const xspi_instance_t * xspi; +} qspiflash_at25_ctrl_t; + +/** xSPI device extended configuration structure */ +typedef struct st_qspiflash_at25_ext +{ + /* No additional configurations */ +} qspiflash_at25_ext_t; + +extern const xspidevice_api_t qspiflash_at25_api; + +#endif /* _QSPIFLASH_AT25_API_H_ */ + diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/xspidevice/qspiflash_at25/rz_xspidevice.mk b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/xspidevice/qspiflash_at25/rz_xspidevice.mk new file mode 100644 index 00000000..730e772e --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/xspidevice/qspiflash_at25/rz_xspidevice.mk @@ -0,0 +1,9 @@ +# +# Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# +_XSPI_DEVICE:=qspiflash_at25 +RZ_XSPI_SOURCES:=$(RZ_XSPI_SOURCES) plat/renesas/rz/common/drivers/xspidevice/$(_XSPI_DEVICE)/$(_XSPI_DEVICE).c +PLAT_INCLUDES+=-Iplat/renesas/rz/common/drivers/xspidevice/$(_XSPI_DEVICE) +RZ_XSPI_HEADERS:=$(RZ_XSPI_HEADERS) $(_XSPI_DEVICE)_api.h diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/xspidevice/qspiflash_mx25l25645g/qspiflash_mx25l25645g.c b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/xspidevice/qspiflash_mx25l25645g/qspiflash_mx25l25645g.c new file mode 100644 index 00000000..9c74928b --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/xspidevice/qspiflash_mx25l25645g/qspiflash_mx25l25645g.c @@ -0,0 +1,712 @@ +/* + * Copyright (c) 2024, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include "errno.h" +#include "pfc_regs.h" +#include "lib/mmio.h" +#include "qspiflash_mx25l25645g_api.h" + +/* Defaults */ +static const bool DEFAULT_PBE_ENABLE = false; +static const uint32_t DEFAULT_TIMEOUT = 1000; /* usec */ +static const uint32_t DEFAULT_SPI_FREQUENCY = 66666666U; +static const e_read_mode_t DEFAULT_READ_MODE = READ_MODE_QUAD; +static const e_dummy_cycles_t DEFAULT_DUMMY_CYCLES = DUMMY_CYCLES_6; +static const e_burst_read_wrap_depth_t DEFAULT_BURST_READ_WRAP_DEPTH = BURST_READ_WRAP_DISABLE; +static const e_output_driver_strength_t DEFAULT_OUTPUT_DRIVER_STRENGTH = OUTPUT_DRIVER_STRENGTH_30_OHMS; + +static const uint32_t SPI_POST_RESET_WAIT = 50; /* usec */ +static const uint32_t FLASH_RESET_RECOVERY_WAIT = 40; /* usec */ +static const uint32_t MAX_FLASH_UNLOCK_RETRIES = 3; + +static const uintptr_t WP_IO2_PIN_PORT_ADDR = PFC_P05; +static const uintptr_t WP_IO2_PIN_PORT_MODE_ADDR = PFC_PMC05; +static const uint32_t WP_IO2_PIN_BIT = BIT(3); + +/* Static function pre-definition */ +static int flash_open(xspidevice_ctrl_t * ctrl, xspidevice_cfg_t const * cfg); +static int flash_close(xspidevice_ctrl_t * ctrl); +static int flash_exec_op(xspidevice_ctrl_t * ctrl, xspi_op_t const * op, bool is_write); +static int flash_enter_xip(xspidevice_ctrl_t * ctrl); +static int flash_exit_xip(xspidevice_ctrl_t * ctrl); +static int flash_get_info(xspidevice_ctrl_t * ctrl, xspidevice_info_t * info); +static int flash_read(xspidevice_ctrl_t * ctrl, void * buffer, size_t address, size_t length); +static int flash_write(xspidevice_ctrl_t * ctrl, void const * buffer, size_t address, size_t length); +static int flash_erase(xspidevice_ctrl_t * ctrl, size_t address, size_t length); +static enum xspidevice_write_status flash_get_write_status(xspidevice_ctrl_t * ctrl); + +/* API function table definition */ +const xspidevice_api_t qspiflash_mx25l25645g_api = { + .open = flash_open, + .close = flash_close, + .exec_op = flash_exec_op, + .enter_xip = flash_enter_xip, + .exit_xip = flash_exit_xip, + .get_info = flash_get_info, + .read = flash_read, + .write = flash_write, + .erase = flash_erase, + .get_write_status = flash_get_write_status, +}; + +/* Static variables */ +static const int spi_frequency = DEFAULT_SPI_FREQUENCY + 1; + +/*** Flash Commands ***/ +/* Write Enable */ +static const xspi_op_t op_write_enable = { + .form = SPI_FORM_1_1_1, + .op = 0x06, + .op_size = 1, + .op_is_ddr = false, + .address = 0, + .address_is_ddr = false, + .address_size = 0, + .additional_value = 0, + .additional_size = 0, + .dummy_cycles = 0, + .transfer_buffer = NULL, + .transfer_is_ddr = false, + .transfer_size = 0, + .force_idle_level_mask = 0x08, // Keep IO3/HOLDorRESET pin to High + .force_idle_level_value = 0x08, // Keep IO3/HOLDorRESET pin to High + .slch_value = 0, + .clsh_value = 0, + .shsl_value = 1 +}; + +/* Read Manufacturer ID */ +static const xspi_op_t op_read_id = { + .form = SPI_FORM_1_1_1, + .op = 0x9f, + .op_size = 1, + .op_is_ddr = false, + .address = 0, + .address_is_ddr = false, + .address_size = 0, + .additional_value = 0, + .additional_size = 0, + .dummy_cycles = 0, + .transfer_buffer = NULL, + .transfer_is_ddr = false, + .transfer_size = 0, + .force_idle_level_mask = 0x08, // Keep IO3/HOLDorRESET pin to High + .force_idle_level_value = 0x08, // Keep IO3/HOLDorRESET pin to High + .slch_value = 0, + .clsh_value = 0, + .shsl_value = 1 +}; + +/* Read Status Register */ +static const xspi_op_t op_read_status = { + .form = SPI_FORM_1_1_1, + .op = 0x05, + .op_size = 1, + .op_is_ddr = false, + .address = 0, + .address_is_ddr = false, + .address_size = 0, + .additional_value = 0, + .additional_size = 0, + .dummy_cycles = 0, + .transfer_buffer = NULL, + .transfer_is_ddr = false, + .transfer_size = 1, + .force_idle_level_mask = 0x08, // Keep IO3/HOLDorRESET pin to High + .force_idle_level_value = 0x08, // Keep IO3/HOLDorRESET pin to High + .slch_value = 0, + .clsh_value = 0, + .shsl_value = 1 +}; + +/* Read Configuration Register */ +static const xspi_op_t op_read_configuraton = { + .form = SPI_FORM_1_1_1, + .op = 0x15, + .op_size = 1, + .op_is_ddr = false, + .address = 0, + .address_is_ddr = false, + .address_size = 0, + .additional_value = 0, + .additional_size = 0, + .dummy_cycles = 0, + .transfer_buffer = NULL, + .transfer_is_ddr = false, + .transfer_size = 1, + .force_idle_level_mask = 0x08, // Keep IO3/HOLDorRESET pin to High + .force_idle_level_value = 0x08, // Keep IO3/HOLDorRESET pin to High + .slch_value = 0, + .clsh_value = 0, + .shsl_value = 1 +}; + +/* Write Status/Configuration Register */ +static const xspi_op_t op_write_sr = { + .form = SPI_FORM_1_1_1, + .op = 0x01, + .op_size = 1, + .op_is_ddr = false, + .address = 0, + .address_is_ddr = false, + .address_size = 0, + .additional_value = 0, + .additional_size = 0, + .dummy_cycles = 0, + .transfer_buffer = NULL, + .transfer_is_ddr = false, + .transfer_size = 2, + .force_idle_level_mask = 0x08, // Keep IO3/HOLDorRESET pin to High + .force_idle_level_value = 0x08, // Keep IO3/HOLDorRESET pin to High + .slch_value = 0, + .clsh_value = 0, + .shsl_value = 1 +}; + +/* RSTEN (Reset Enable) */ +static const xspi_op_t op_reset_enable = { + .form = SPI_FORM_1_1_1, + .op = 0x66, + .op_size = 1, + .op_is_ddr = false, + .address = 0, + .address_is_ddr = false, + .address_size = 0, + .additional_value = 0, + .additional_size = 0, + .dummy_cycles = 0, + .transfer_buffer = NULL, + .transfer_is_ddr = false, + .transfer_size = 0, + .force_idle_level_mask = 0x08, // Keep IO3/HOLDorRESET pin to High + .force_idle_level_value = 0x08, // Keep IO3/HOLDorRESET pin to High + .slch_value = 0, + .clsh_value = 0, + .shsl_value = 1 +}; + +/* RST (Reset) */ +static const xspi_op_t op_reset = { + .form = SPI_FORM_1_1_1, + .op = 0x99, + .op_size = 1, + .op_is_ddr = false, + .address = 0, + .address_is_ddr = false, + .address_size = 0, + .additional_value = 0, + .additional_size = 0, + .dummy_cycles = 0, + .transfer_buffer = NULL, + .transfer_is_ddr = false, + .transfer_size = 0, + .force_idle_level_mask = 0x08, // Keep IO3/HOLDorRESET pin to High + .force_idle_level_value = 0x08, // Keep IO3/HOLDorRESET pin to High + .slch_value = 0, + .clsh_value = 0, + .shsl_value = 1 +}; + +/* Burst Read */ +static const xspi_op_t op_burst_read = { + .form = SPI_FORM_1_1_1, + .op = 0xc0, + .op_size = 1, + .op_is_ddr = false, + .address = 0, + .address_is_ddr = false, + .address_size = 0, + .additional_value = 0, + .additional_size = 0, + .dummy_cycles = 0, + .transfer_buffer = NULL, + .transfer_is_ddr = false, + .transfer_size = 1, + .force_idle_level_mask = 0x08, // Keep IO3/HOLDorRESET pin to High + .force_idle_level_value = 0x08, // Keep IO3/HOLDorRESET pin to High + .slch_value = 0, + .clsh_value = 0, + .shsl_value = 1 +}; + +/* FASTREAD4B (Fast Read Mode with 4 Byte Address, 1-1-1) */ +static const xspi_op_t op_fast_read = { + .form = SPI_FORM_1_1_1, + .op = 0x0c, + .op_size = 1, + .op_is_ddr = false, + .address = 0, + .address_is_ddr = false, + .address_size = 4, + .additional_value = 0, + .additional_size = 0, + .dummy_cycles = 8, /* cannot change */ + .transfer_buffer = NULL, + .transfer_is_ddr = false, + .transfer_size = 0, + .force_idle_level_mask = 0x08, // Keep IO3/HOLDorRESET pin to High + .force_idle_level_value = 0x08, // Keep IO3/HOLDorRESET pin to High + .slch_value = 0, + .clsh_value = 0, + .shsl_value = 1 +}; + +/* 4READ4B (4x I/O Read Mode with 4 Byte Address, 1-4-4) */ +static const xspi_op_t op_quad_io_read = { + .form = SPI_FORM_1_4_4, + .op = 0xec, + .op_size = 1, + .op_is_ddr = false, + .address = 0, + .address_is_ddr = false, + .address_size = 4, + .additional_value = 0, + .additional_size = 0, + .dummy_cycles = (uint8_t) DEFAULT_DUMMY_CYCLES, + .transfer_buffer = NULL, + .transfer_is_ddr = false, + .transfer_size = 0, + .force_idle_level_mask = 0x08, // Keep IO3/HOLDorRESET pin to High + .force_idle_level_value = 0x08, // Keep IO3/HOLDorRESET pin to High + .slch_value = 0, + .clsh_value = 0, + .shsl_value = 1 +}; + +/* Function definitions */ +static int flash_write_enable(qspiflash_mx25l25645g_ctrl_t * myctrl) +{ + const xspi_instance_t * xspi = myctrl->xspi; + int timeout = DEFAULT_TIMEOUT; + enum xspidevice_write_status status = WRITE_STATUS_DISABLED; + while ((status != WRITE_STATUS_OK) && (timeout > 0)) { + xspi->api->exec_op(xspi->ctrl, &op_write_enable, false); + status = flash_get_write_status(myctrl); + timeout--; + udelay(1); + } + if (timeout == 0) { + ERROR("Timeout on write enable, status: %d\n", status); + return -1; + } + if (status != WRITE_STATUS_OK) { + ERROR("Write enable failed\n"); + return -1; + } + return 0; +} + +static int flash_check_manufacturer_id(qspiflash_mx25l25645g_ctrl_t * myctrl) +{ + int result; + const xspi_instance_t * xspi = myctrl->xspi; + + uint8_t id[3]; + xspi_op_t op = op_read_id; + op.transfer_buffer = id; + op.transfer_size = 3; + result = xspi->api->exec_op(xspi->ctrl, &op, false); + if (result < 0) return result; + const uint16_t device_id = (id[1] << 8) | id[2]; + if ((id[0] != MANUFACTURER_ID) || (device_id != DEVICE_ID)) { + ERROR("Flash device not found\n"); + VERBOSE("Manufacturer ID: 0x%02x, Device ID: 0x%04x\n", id[0], device_id); + return -1; + } + + return 0; +} + +static uint8_t flash_read_status_register(qspiflash_mx25l25645g_ctrl_t * myctrl) +{ + int result; + const xspi_instance_t * xspi = myctrl->xspi; + + uint8_t status; + xspi_op_t op = op_read_status; + op.transfer_buffer = &status; + result = xspi->api->exec_op(xspi->ctrl, &op, false); + if (result < 0) { + ERROR("Failed to read status register\n"); + panic(); + } + return status; +} + +static uint8_t flash_read_configuration_register(qspiflash_mx25l25645g_ctrl_t * myctrl) +{ + int result; + const xspi_instance_t * xspi = myctrl->xspi; + + uint8_t configuration; + xspi_op_t op = op_read_configuraton; + op.transfer_buffer = &configuration; + result = xspi->api->exec_op(xspi->ctrl, &op, false); + if (result < 0) { + ERROR("Failed to read configuration register\n"); + panic(); + } + return configuration; +} + +static int flash_wait_for_write_complete(qspiflash_mx25l25645g_ctrl_t * myctrl, uint32_t timeout /* usec */) +{ + assert(myctrl); + assert(timeout > 0); + + uint8_t status = 0; + do { + status = flash_read_status_register(myctrl); + timeout--; + udelay(1); + } while ((status & BIT(0)) != 0 && timeout > 0); + + if (timeout == 0) { + ERROR("Timeout after write operation, status: %d\n", status); + return -1; + } + + return 0; +} + +static int flash_reset(qspiflash_mx25l25645g_ctrl_t * myctrl) +{ + const xspi_instance_t * xspi = myctrl->xspi; + flash_wait_for_write_complete(myctrl, DEFAULT_TIMEOUT); + + /* Reset Enable */ + int result = xspi->api->exec_op(xspi->ctrl, &op_reset_enable, false); + if (result < 0) return result; + + /* Reset */ + result = xspi->api->exec_op(xspi->ctrl, &op_reset, false); + if (result < 0) return result; + + udelay(FLASH_RESET_RECOVERY_WAIT); + + return result; +} + +static int flash_prepare_unlock(qspiflash_mx25l25645g_ctrl_t * myctrl) +{ + /* Set WP#SIO2 as GPIO */ + mmio_write_8(WP_IO2_PIN_PORT_MODE_ADDR, mmio_read_8(WP_IO2_PIN_PORT_MODE_ADDR) & ~WP_IO2_PIN_BIT); + /* Set WP#SIO2 to high */ + mmio_write_8(WP_IO2_PIN_PORT_ADDR, mmio_read_8(WP_IO2_PIN_PORT_ADDR) | WP_IO2_PIN_BIT); + + /* Check if WP#SIO2 is high */ + if ((mmio_read_8(WP_IO2_PIN_PORT_ADDR) & WP_IO2_PIN_BIT) == 0) { + ERROR("Failed to pull up WP#SIO2\n"); + return -1; + } + return 0; +} + +static int flash_finish_unlock(qspiflash_mx25l25645g_ctrl_t * myctrl) +{ + /* Set WP#SIO2 as peripheral */ + mmio_write_8(WP_IO2_PIN_PORT_MODE_ADDR, mmio_read_8(WP_IO2_PIN_PORT_MODE_ADDR) | WP_IO2_PIN_BIT); + return 0; +} + +static void flash_hw_protect_unlock(qspiflash_mx25l25645g_ctrl_t * myctrl) +{ + VERBOSE("Trying to unlock the flash HW protection\n"); + + int result = flash_reset(myctrl); + if (result < 0) { + ERROR("Failed to reset the flash while unlocking HW protection\n"); + goto err; + } + + /* Write enable */ + result = flash_write_enable(myctrl); + if (result < 0) { + ERROR("Failed to enable write while unlocking HW protection\n"); + goto err; + } + + const xspi_instance_t * xspi = myctrl->xspi; + + if (flash_prepare_unlock(myctrl) < 0) goto err; + + xspi_op_t op = op_write_sr; + uint8_t status_configuration_register[2] = { + 0, /* Status Register, ensure the SRWD(bit7) is 0 */ + 0, + }; + op.transfer_buffer = (void *)&status_configuration_register; + result = xspi->api->exec_op(xspi->ctrl, &op, true); + if (result < 0) goto err; + + result = flash_wait_for_write_complete(myctrl, DEFAULT_TIMEOUT); + if (result < 0) goto err; + + /* Verify if the status register is written correctly */ + uint8_t status = flash_read_status_register(myctrl); + if ((status & 0x80) != 0) goto err; + + if (flash_finish_unlock(myctrl) < 0) goto err; + + VERBOSE("Flash HW protection is unlocked\n"); + + return; + +err: + ERROR("Failed to unlock the flash\n"); + panic(); +} + +static int flash_init(qspiflash_mx25l25645g_ctrl_t * myctrl) +{ + if (flash_check_manufacturer_id(myctrl) != 0) return -1; + + const xspi_instance_t * xspi = myctrl->xspi; + + int result = flash_reset(myctrl); + if (result < 0) return result; + + /* Write enable */ + result = flash_write_enable(myctrl); + if (result < 0) return result; + + /* Determine status_register */ + uint8_t status_register = 0; + if (DEFAULT_READ_MODE == READ_MODE_QUAD) { + status_register = 1u << 6; /* QE (Quad Enable) : Enable */ + } + + /* Determine configuration_register */ + uint8_t configuration_register = 0; + if (DEFAULT_READ_MODE == READ_MODE_QUAD) { + switch (DEFAULT_DUMMY_CYCLES) { + case DUMMY_CYCLES_4: + configuration_register = 1u << 6; + break; + case DUMMY_CYCLES_8: + configuration_register = 2u << 6; + break; + case DUMMY_CYCLES_10: + configuration_register = 3u << 6; + break; + case DUMMY_CYCLES_6: + default: + configuration_register = 0u << 6; /* Default: 6 dummy cycles */ + break; + } + } else { + if (DEFAULT_DUMMY_CYCLES != DUMMY_CYCLES_8) { + ERROR("Only dummy cycles 8 is supported for normal read mode\n"); + return -1; /* Only dummy cycles 8 is supported for normal read mode */ + } + + configuration_register = 0u << 6; /* DC[1:0] */ + } + + if (DEFAULT_PBE_ENABLE) { + configuration_register |= 1u << 4; /* PBE (Preamble Bit Enable) */ + } + configuration_register |= DEFAULT_OUTPUT_DRIVER_STRENGTH << 0; /* ODS[1:0] */ + + /* Write configuration register */ + xspi_op_t op = op_write_sr; + uint8_t status_configuration_register[2] = { + status_register, + configuration_register + }; + op.transfer_buffer = (void *)&status_configuration_register; + result = xspi->api->exec_op(xspi->ctrl, &op, true); + if (result < 0) return result; + + result = flash_wait_for_write_complete(myctrl, DEFAULT_TIMEOUT); + if (result < 0) return result; + + /* Verify if the status register is written correctly */ + uint8_t status = flash_read_status_register(myctrl); + if (status != status_register) { + if ((status & 0x80) != 0) { + WARN("Flash is in Hardware Protection Mode\n"); + return -EAGAIN; + } + ERROR("Failed to write status register\n"); + return -1; + } + + /* Verify if the configuration register is written correctly */ + uint8_t configuration = flash_read_configuration_register(myctrl); + if (configuration != configuration_register) { + ERROR("Failed to write configuration register\n"); + return -1; + } + + return result; +} + +static int flash_open(xspidevice_ctrl_t * ctrl, xspidevice_cfg_t const * cfg) +{ + assert(ctrl); + assert(cfg); + int result; + qspiflash_mx25l25645g_ctrl_t * myctrl = (qspiflash_mx25l25645g_ctrl_t *)ctrl; + const xspi_instance_t * xspi = cfg->xspi; + + if (myctrl->opened) return -EBUSY; + + myctrl->xspi = xspi; + result = xspi->api->open(xspi->ctrl, xspi->cfg); + if (result == 0) { + result = xspi->api->set_frequency(xspi->ctrl, spi_frequency); + } + if (result == 0) { + udelay(SPI_POST_RESET_WAIT); + + uint32_t retries = 0; + do { + retries++; + if (retries >= MAX_FLASH_UNLOCK_RETRIES) break; + + result = flash_init(myctrl); + if (result == -EAGAIN) flash_hw_protect_unlock(myctrl); + } while (result == -EAGAIN); + + if (result == 0) { + myctrl->opened = true; + } + else { + xspi->api->close(xspi->ctrl); + } + } + + return result; +} + +static int flash_close(xspidevice_ctrl_t * ctrl) +{ + assert(ctrl); + int result = -1; + qspiflash_mx25l25645g_ctrl_t * myctrl = (qspiflash_mx25l25645g_ctrl_t *)ctrl; + const xspi_instance_t * xspi = myctrl->xspi; + if (myctrl->opened) { + result = xspi->api->close(xspi->ctrl); + myctrl->opened = false; + } + + return result; +} + +static int flash_exec_op(xspidevice_ctrl_t * ctrl, xspi_op_t const * op, bool is_write) +{ + assert(ctrl); + assert(op); + qspiflash_mx25l25645g_ctrl_t * myctrl = (qspiflash_mx25l25645g_ctrl_t *)ctrl; + const xspi_instance_t * xspi = myctrl->xspi; + + return xspi->api->exec_op(xspi->ctrl, op, is_write); +} + +static int flash_enter_xip(xspidevice_ctrl_t * ctrl) +{ + int result = -1; + assert(ctrl); + qspiflash_mx25l25645g_ctrl_t * myctrl = (qspiflash_mx25l25645g_ctrl_t *)ctrl; + const xspi_instance_t * xspi = myctrl->xspi; + + result = flash_write_enable(myctrl); + if (result < 0) return result; + + xspi_op_t op = op_burst_read; + uint8_t wrap_depth = DEFAULT_BURST_READ_WRAP_DEPTH; + op.transfer_buffer = (void *)&wrap_depth; + result = xspi->api->exec_op(xspi->ctrl, &op, true); + + result = flash_wait_for_write_complete(myctrl, DEFAULT_TIMEOUT); + if (result < 0) return result; + + if (DEFAULT_READ_MODE == READ_MODE_QUAD) { + result = xspi->api->configure_xip(xspi->ctrl, &op_quad_io_read, NULL); + } else { + result = xspi->api->configure_xip(xspi->ctrl, &op_fast_read, NULL); + } + + if (result < 0) return result; + + result = flash_wait_for_write_complete(myctrl, DEFAULT_TIMEOUT); + if (result < 0) return result; + + result = xspi->api->set_frequency(xspi->ctrl, spi_frequency); + if (result < 0) return result; + + result = xspi->api->start_xip(xspi->ctrl); + + return result; +} +static int flash_exit_xip(xspidevice_ctrl_t * ctrl) +{ + assert(ctrl); + qspiflash_mx25l25645g_ctrl_t * myctrl = (qspiflash_mx25l25645g_ctrl_t *)ctrl; + + xspi_op_t op = op_burst_read; + uint8_t wrap_depth = BURST_READ_WRAP_DISABLE; + op.transfer_buffer = (void *)&wrap_depth; + const xspi_instance_t * xspi = myctrl->xspi; + int result = xspi->api->exec_op(xspi->ctrl, &op, true); + + result = flash_wait_for_write_complete(myctrl, DEFAULT_TIMEOUT); + if (result < 0) return result; + + return xspi->api->stop_xip(xspi->ctrl); +} +static int flash_get_info(xspidevice_ctrl_t * ctrl, xspidevice_info_t * info) +{ + assert(ctrl); + assert(info); + info->capacity = 0; + info->minimum_erase_size = 0; + + strlcpy(info->device_vendor, "Macronix", sizeof(info->device_vendor)); + strlcpy(info->device_product, "MX25L25645G", sizeof(info->device_product)); + return 0; +} +static int flash_read(xspidevice_ctrl_t * ctrl, void * buffer, size_t address, size_t length) +{ + assert(ctrl); + qspiflash_mx25l25645g_ctrl_t * myctrl = (qspiflash_mx25l25645g_ctrl_t *)ctrl; + const xspi_instance_t * xspi = myctrl->xspi; + + uintptr_t mmap_base = xspi->api->get_mmap_base(xspi->ctrl); + memcpy(buffer, (void*)(mmap_base+address), length); + + return 0; +} + +static int flash_write(xspidevice_ctrl_t * ctrl, void const * buffer, size_t address, size_t length) +{ + /* Not supported */ + return -1; +} + +static int flash_erase(xspidevice_ctrl_t * ctrl, size_t address, size_t length) +{ + /* Not supported */ + return -1; +} + +static enum xspidevice_write_status flash_get_write_status(xspidevice_ctrl_t * ctrl) +{ + assert(ctrl); + qspiflash_mx25l25645g_ctrl_t * myctrl = (qspiflash_mx25l25645g_ctrl_t *)ctrl; + + /* Read Flag Status Register */ + uint8_t result = flash_read_status_register(myctrl); + if ((result & BIT(0)) != 0) return WRITE_STATUS_IN_PROGRESS; + if ((result & BIT(1)) == 0) return WRITE_STATUS_DISABLED; + + return WRITE_STATUS_OK; +} diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/xspidevice/qspiflash_mx25l25645g/qspiflash_mx25l25645g_api.h b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/xspidevice/qspiflash_mx25l25645g/qspiflash_mx25l25645g_api.h new file mode 100644 index 00000000..0d8708b6 --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/xspidevice/qspiflash_mx25l25645g/qspiflash_mx25l25645g_api.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2024, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _QSPIFLASH_MX25L25645G_API_H_ +#define _QSPIFLASH_MX25L25645G_API_H_ +#include +#include + +#include "xspidevice_api.h" + +enum flash_id { + MEMORY_DENSITY_128Mbit = 0x18, + MEMORY_DENSITY_256Mbit = 0x19, + MANUFACTURER_ID = 0xC2, + MEMORY_TYPE = 0x20, + MEMORY_DENSITY = MEMORY_DENSITY_256Mbit, + DEVICE_ID = (MEMORY_DENSITY << 8) | MEMORY_TYPE, +}; + +typedef enum { + BURST_READ_WRAP_8_BYTES = 0x00, + BURST_READ_WRAP_16_BYTES = 0x01, + BURST_READ_WRAP_32_BYTES = 0x02, + BURST_READ_WRAP_64_BYTES = 0x03, + BURST_READ_WRAP_DISABLE = 0x1F, +} e_burst_read_wrap_depth_t; + +typedef enum { + OUTPUT_DRIVER_STRENGTH_30_OHMS = 0x00, + OUTPUT_DRIVER_STRENGTH_45_OHMS = 0x01, + OUTPUT_DRIVER_STRENGTH_90_OHMS = 0x02, + OUTPUT_DRIVER_STRENGTH_15_OHMS = 0x03, +} e_output_driver_strength_t; + +typedef enum { + DUMMY_CYCLES_4 = 4, + DUMMY_CYCLES_6 = 6, + DUMMY_CYCLES_8 = 8, + DUMMY_CYCLES_10 = 10, +} e_dummy_cycles_t; + +typedef enum { + READ_MODE_NORMAL, + READ_MODE_QUAD, +} e_read_mode_t; + +/** xSPI device control structure */ +typedef struct st_qspiflash_mx25l25645g_ctrl +{ + bool opened; + const xspi_instance_t * xspi; +} qspiflash_mx25l25645g_ctrl_t; + +/** xSPI device extended configuration structure */ +typedef struct st_qspiflash_mx25l25645g_ext +{ + /* No additional configurations */ +} qspiflash_mx25l25645g_ext_t; + +extern const xspidevice_api_t qspiflash_mx25l25645g_api; + +#endif /* _QSPIFLASH_MX25L25645G_API_H_ */ diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/xspidevice/qspiflash_mx25l25645g/rz_xspidevice.mk b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/xspidevice/qspiflash_mx25l25645g/rz_xspidevice.mk new file mode 100644 index 00000000..cae4d458 --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/drivers/xspidevice/qspiflash_mx25l25645g/rz_xspidevice.mk @@ -0,0 +1,9 @@ +# +# Copyright (c) 2024, Renesas Electronics Corporation. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# +_XSPI_DEVICE:=qspiflash_mx25l25645g +RZ_XSPI_SOURCES:=$(RZ_XSPI_SOURCES) plat/renesas/rz/common/drivers/xspidevice/$(_XSPI_DEVICE)/$(_XSPI_DEVICE).c +PLAT_INCLUDES+=-Iplat/renesas/rz/common/drivers/xspidevice/$(_XSPI_DEVICE) +RZ_XSPI_HEADERS:=$(RZ_XSPI_HEADERS) $(_XSPI_DEVICE)_api.h diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/include/cpg.h b/drivers/rz/ipl/rza/plat/renesas/rz/common/include/cpg.h new file mode 100644 index 00000000..5b3628ed --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/include/cpg.h @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __CPG_H__ +#define __CPG_H__ +#include "cpg_regs.h" +#include + +typedef enum { + XSPI_CLOCK_SPIM, + XSPI_CLOCK_OCTA, +} xspi_clock; + +typedef enum clock_id_t { + CPG_CLOCK_SPIM = 20, + CPG_CLOCK_OCTA = 61, +} clock_id; + +static inline void cpg_clock_onoff(int clkid, uint32_t mask, uint32_t val) { + val = mask * (val & 1); + mmio_write_32(CPG_CLKON_CA55 + clkid * 4, (mask << 16) + val); + while ((mmio_read_32(CPG_CLKMON_CA55 + clkid * 4) & mask) != val); +} + +static inline void cpg_reset_onoff(int clkid, uint32_t mask, uint32_t val) { + val = mask * (val & 1); + mmio_write_32(CPG_RST_CA55 + clkid * 4, (mask << 16) + (val ^ 0xffff)); + while ((mmio_read_32(CPG_RSTMON_CA55 + clkid * 4) & mask) != val); +} + +#define CPG_CLKRSTONOFF_START(id) switch (id) { +#define CPG_CLKRSTONOFF_END(a) } +#define CPG_CLKON_DEF(id, mask) CPG_CLKONOFF_DEF(id, mask, 1) +#define CPG_CLKOFF_DEF(id, mask) CPG_CLKONOFF_DEF(id, mask, 0) +#define CPG_CLKONOFF_DEF(id, mask, value) \ + case id: \ + cpg_clock_onoff(id, mask, value); \ + break; +#define CPG_RSTON_DEF(id, mask) CPG_RSTONOFF_DEF(id, mask, 1) +#define CPG_RSTOFF_DEF(id, mask) CPG_RSTONOFF_DEF(id, mask, 0) +#define CPG_RSTONOFF_DEF(id, mask, value) \ + case id: \ + cpg_reset_onoff(id, mask, value); \ + break; + +static inline void cpg_clock_on(enum clock_id_t clkid) { + CPG_CLKRSTONOFF_START(clkid); + CPG_CLKON_DEF(CPG_CLOCK_SPIM, 3); + CPG_CLKON_DEF(CPG_CLOCK_OCTA, 3); + CPG_CLKRSTONOFF_END(); +} + +static inline void cpg_clock_off(enum clock_id_t clkid) { + CPG_CLKRSTONOFF_START(clkid); + CPG_CLKOFF_DEF(CPG_CLOCK_SPIM, 3); + CPG_CLKOFF_DEF(CPG_CLOCK_OCTA, 3); + CPG_CLKRSTONOFF_END(); +} + +static inline void cpg_reset_on(enum clock_id_t clkid) { + CPG_CLKRSTONOFF_START(clkid); + CPG_RSTON_DEF(CPG_CLOCK_SPIM, 1); + CPG_RSTON_DEF(CPG_CLOCK_OCTA, 1); + CPG_CLKRSTONOFF_END(); +} + +static inline void cpg_reset_off(enum clock_id_t clkid) { + CPG_CLKRSTONOFF_START(clkid); + CPG_RSTOFF_DEF(CPG_CLOCK_SPIM, 1); + CPG_RSTOFF_DEF(CPG_CLOCK_OCTA, 1); + CPG_CLKRSTONOFF_END(); +} + +void cpg_early_setup(void); +void cpg_setup(void); +void cpg_active_ddr(void (*disable_phy)(void)); +void cpg_reset_ddr_mc(void); +int cpg_set_xspi_clock(xspi_clock spi, int frequency_hz); +int cpg_get_xspi_clock(xspi_clock spi); + +#endif /* __CPG_H__ */ diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/include/cpg_regs.h b/drivers/rz/ipl/rza/plat/renesas/rz/common/include/cpg_regs.h new file mode 100644 index 00000000..2edf95f1 --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/include/cpg_regs.h @@ -0,0 +1,723 @@ +/* + * Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __CPG_REGS_H__ +#define __CPG_REGS_H__ + +#define CPG_BASE (0x11010000) /* CPG base address */ + +#define CPG_PLL1_STBY (CPG_BASE + 0x0000) /* PLL1 (SSCG) standby control register */ +#define CPG_PLL1_CLK1 (CPG_BASE + 0x0004) /* PLL1 (SSCG) output clock setting register 1 */ +#define CPG_PLL1_CLK2 (CPG_BASE + 0x0008) /* PLL1 (SSCG) output clock setting register 2 */ +#define CPG_PLL1_MON (CPG_BASE + 0x000C) /* PLL1 (SSCG) monitor register */ +#define CPG_PLL4_STBY (CPG_BASE + 0x0010) /* PLL4 (SSCG) standby control register */ +#define CPG_PLL4_CLK1 (CPG_BASE + 0x0014) /* PLL4 (SSCG) output clock setting register 1 */ +#define CPG_PLL4_CLK2 (CPG_BASE + 0x0018) /* PLL4 (SSCG) output clock setting register 2 */ +#define CPG_PLL4_MON (CPG_BASE + 0x001C) /* PLL4 (SSCG) monitor register */ +#define CPG_PLL6_STBY (CPG_BASE + 0x0020) /* PLL6 (SSCG) standby control register */ +#define CPG_PLL6_CLK1 (CPG_BASE + 0x0024) /* PLL6 (SSCG) output clock setting register 1 */ +#define CPG_PLL6_CLK2 (CPG_BASE + 0x0028) /* PLL6 (SSCG) output clock setting register 2 */ +#define CPG_PLL6_MON (CPG_BASE + 0x002C) /* PLL6 (SSCG) monitor register */ +#define CPG_PLL1_SETTING (CPG_BASE + 0x0040) /* PLL1_SEL_SETTING */ +#define CPG_OTPPLL0_MON (CPG_BASE + 0x0044) /* OTP_OTPPLL0 monitor register */ +#define CPG_OTPPLL1_MON (CPG_BASE + 0x0048) /* OTP_OTPPLL1 monitor register */ +#define CPG_OTPPLL2_MON (CPG_BASE + 0x004C) /* OTP_OTPPLL2 monitor register */ + +#define CPG_PLL2_STBY (CPG_BASE + 0x0100) /* PLL2 (SSCG) standby control register */ +#define CPG_PLL2_CLK1 (CPG_BASE + 0x0104) /* PLL2 (SSCG) output clock setting register 1 */ +#define CPG_PLL2_CLK2 (CPG_BASE + 0x0108) /* PLL2 (SSCG) output clock setting register 2 */ +#define CPG_PLL2_CLK3 (CPG_BASE + 0x010C) /* PLL2 (SSCG) output clock setting register 3 */ +#define CPG_PLL2_CLK4 (CPG_BASE + 0x0110) /* PLL2 (SSCG) output clock setting register 4 */ +#define CPG_PLL2_CLK5 (CPG_BASE + 0x0114) /* PLL2 (SSCG) output clock setting register 5 */ +#define CPG_PLL2_CLK6 (CPG_BASE + 0x0118) /* PLL2 (SSCG) output clock setting register 6 */ +#define CPG_PLL2_MON (CPG_BASE + 0x011C) /* PLL2 (SSCG) monitor register */ +#define CPG_PLL3_STBY (CPG_BASE + 0x0120) /* PLL3 (SSCG) standby control register */ +#define CPG_PLL3_CLK1 (CPG_BASE + 0x0124) /* PLL3 (SSCG) output clock setting register 1 */ +#define CPG_PLL3_CLK2 (CPG_BASE + 0x0128) /* PLL3 (SSCG) output clock setting register 2 */ +#define CPG_PLL3_CLK3 (CPG_BASE + 0x012C) /* PLL3 (SSCG) output clock setting register 3 */ +#define CPG_PLL3_CLK4 (CPG_BASE + 0x0130) /* PLL3 (SSCG) output clock setting register 4 */ +#define CPG_PLL3_CLK5 (CPG_BASE + 0x0134) /* PLL3 (SSCG) output clock setting register 5 */ +#define CPG_PLL3_MON (CPG_BASE + 0x013C) /* PLL3 (SSCG) monitor register */ +#define CPG_PLL5_STBY (CPG_BASE + 0x0140) /* PLL5 (SSCG) standby control register */ +#define CPG_PLL5_CLK1 (CPG_BASE + 0x0144) /* PLL5 (SSCG) output clock setting register 1 */ +#define CPG_PLL5_CLK2 (CPG_BASE + 0x0148) /* PLL5 (SSCG) output clock setting register 2 */ +#define CPG_PLL5_CLK3 (CPG_BASE + 0x014C) /* PLL5 (SSCG) output clock setting register 3 */ +#define CPG_PLL5_CLK4 (CPG_BASE + 0x0150) /* PLL5 (SSCG) output clock setting register 4 */ +#define CPG_PLL5_CLK5 (CPG_BASE + 0x0154) /* PLL5 (SSCG) output clock setting register 5 */ +#define CPG_PLL5_MON (CPG_BASE + 0x015C) /* PLL5 (SSCG) monitor register */ + +#define CPG_PL1_DDIV (CPG_BASE + 0x0200) /* Division ratio setting register */ +#define CPG_PL2_DDIV (CPG_BASE + 0x0204) /* Division ratio setting register */ +#define CPG_PL3A_DDIV (CPG_BASE + 0x0208) /* Division ratio setting register */ +#define CPG_PL3B_DDIV (CPG_BASE + 0x020C) /* Division ratio setting register */ +#define CPG_PL6_DDIV (CPG_BASE + 0x0210) /* Division ratio setting register */ + +#define CPG_PL2SDHI_DSEL (CPG_BASE + 0x0218) /* Source clock setting register */ +#define CPG_PL4_DSEL (CPG_BASE + 0x021C) /* Source clock setting register */ +#define CPG_CLKSTATUS (CPG_BASE + 0x0280) /* CLK status register */ + +#define CPG_PL1_CA55_SSEL (CPG_BASE + 0x0400) /* Source clock setting register */ +#define CPG_PL2_SSEL (CPG_BASE + 0x0404) /* Source clock setting register */ +#define CPG_PL3_SSEL (CPG_BASE + 0x0408) /* Source clock setting register */ +#define CPG_PL5_SSEL (CPG_BASE + 0x0410) /* Source clock setting register */ +#define CPG_PL6_SSEL (CPG_BASE + 0x0414) /* Source clock setting register */ +#define CPG_PL6_ETH_SSEL (CPG_BASE + 0x0418) /* Source clock setting register */ +#define CPG_PL5_SDIV (CPG_BASE + 0x0420) /* Division ratio setting register */ + +#define CPG_CLKON_CA55 (CPG_BASE + 0x0500) /* Clock ON / OFF register CA55 */ +#define CPG_CLKON_CM33 (CPG_BASE + 0x0504) /* Clock ON / OFF register CM33 */ +#define CPG_CLKON_SRAM_ACPU (CPG_BASE + 0x0508) /* Clock ON / OFF register SRAM_ACPU */ +#define CPG_CLKON_SRAM_MCPU (CPG_BASE + 0x050C) /* Clock ON / OFF register SRAM_MCPU */ +#define CPG_CLKON_ROM (CPG_BASE + 0x0510) /* Clock ON / OFF register ROM */ +#define CPG_CLKON_GIC600 (CPG_BASE + 0x0514) /* Clock ON / OFF register GIC600 */ +#define CPG_CLKON_IA55 (CPG_BASE + 0x0518) /* Clock ON / OFF register IA55 */ +#define CPG_CLKON_IM33 (CPG_BASE + 0x051C) /* Clock ON / OFF register IM33 */ +#define CPG_CLKON_MHU (CPG_BASE + 0x0520) /* Clock ON / OFF register MHU */ +#define CPG_CLKON_CST (CPG_BASE + 0x0524) /* Clock ON / OFF register CST */ +#define CPG_CLKON_SYC (CPG_BASE + 0x0528) /* Clock ON / OFF register SYC */ +#define CPG_CLKON_DAMC_REG (CPG_BASE + 0x052C) /* Clock ON / OFF register DAMC_REG */ +#define CPG_CLKON_SYSC (CPG_BASE + 0x0530) /* Clock ON / OFF register SYSC */ +#define CPG_CLKON_OSTM (CPG_BASE + 0x0534) /* Clock ON / OFF register OSTM */ +#define CPG_CLKON_MTU (CPG_BASE + 0x0538) /* Clock ON / OFF register MTU */ +#define CPG_CLKON_POE3 (CPG_BASE + 0x053C) /* Clock ON / OFF register POE3 */ +#define CPG_CLKON_GPT (CPG_BASE + 0x0540) /* Clock ON / OFF register GPT */ +#define CPG_CLKON_POEG (CPG_BASE + 0x0544) /* Clock ON / OFF register POEG */ +#define CPG_CLKON_WDT (CPG_BASE + 0x0548) /* Clock ON / OFF register WDT */ +#define CPG_CLKON_DDR (CPG_BASE + 0x054C) /* Clock ON / OFF register DDR */ +#define CPG_CLKON_SPI_MULTI (CPG_BASE + 0x0550) /* Clock ON / OFF register SPI_MULTI */ +#define CPG_CLKON_SDHI (CPG_BASE + 0x0554) /* Clock ON / OFF register SDHI */ +#define CPG_CLKON_GPU (CPG_BASE + 0x0558) /* Clock ON / OFF register GPU */ +#define CPG_CLKON_ISU (CPG_BASE + 0x055C) /* Clock ON / OFF register ISU */ +#define CPG_CLKON_H264 (CPG_BASE + 0x0560) /* Clock ON / OFF register H264 */ +#define CPG_CLKON_CRU (CPG_BASE + 0x0564) /* Clock ON / OFF register CRU */ +#define CPG_CLKON_MIPI_DSI (CPG_BASE + 0x0568) /* Clock ON / OFF register MIPI_DSI */ +#define CPG_CLKON_LCDC (CPG_BASE + 0x056C) /* Clock ON / OFF register LCDC */ +#define CPG_CLKON_SSI (CPG_BASE + 0x0570) /* Clock ON / OFF register SSI */ +#define CPG_CLKON_SRC (CPG_BASE + 0x0574) /* Clock ON / OFF register SRC */ +#define CPG_CLKON_USB (CPG_BASE + 0x0578) /* Clock ON / OFF register USB */ +#define CPG_CLKON_ETH (CPG_BASE + 0x057C) /* Clock ON / OFF register ETH */ +#define CPG_CLKON_I2C (CPG_BASE + 0x0580) /* Clock ON / OFF register I2C */ +#define CPG_CLKON_SCIF (CPG_BASE + 0x0584) /* Clock ON / OFF register SCIF */ +#define CPG_CLKON_SCI (CPG_BASE + 0x0588) /* Clock ON / OFF register SCI */ +#define CPG_CLKON_IRDA (CPG_BASE + 0x058C) /* Clock ON / OFF register IRDA */ +#define CPG_CLKON_RSPI (CPG_BASE + 0x0590) /* Clock ON / OFF register RSPI */ +#define CPG_CLKON_CANFD (CPG_BASE + 0x0594) /* Clock ON / OFF register CANFD */ +#define CPG_CLKON_GPIO (CPG_BASE + 0x0598) /* Clock ON / OFF register GPIO */ +#define CPG_CLKON_TSIPG (CPG_BASE + 0x059C) /* Clock ON / OFF register TSIPG */ +#define CPG_CLKON_JAUTH (CPG_BASE + 0x05A0) /* Clock ON / OFF register JAUTH */ +#define CPG_CLKON_OTP (CPG_BASE + 0x05A4) /* Clock ON / OFF register OTP */ +#define CPG_CLKON_ADC (CPG_BASE + 0x05A8) /* Clock ON / OFF register ADC */ +#define CPG_CLKON_TSU (CPG_BASE + 0x05AC) /* Clock ON / OFF register TSU */ +#define CPG_CLKON_BBGU (CPG_BASE + 0x05B0) /* Clock ON / OFF register BBGU */ +#define CPG_CLKON_AXI_ACPU_BUS (CPG_BASE + 0x05B4) /* Clock ON / OFF register AXI_ACPU_BUS */ +#define CPG_CLKON_AXI_MCPU_BUS (CPG_BASE + 0x05B8) /* Clock ON / OFF register AXI_MCPU_BUS */ +#define CPG_CLKON_AXI_COM_BUS (CPG_BASE + 0x05BC) /* Clock ON / OFF register AXI_COM_BUS */ +#define CPG_CLKON_AXI_VIDEO_BUS (CPG_BASE + 0x05C0) /* Clock ON / OFF register AXI_VIDEO_BUS */ +#define CPG_CLKON_PERI_COM (CPG_BASE + 0x05C4) /* Clock ON / OFF register PERI_COM */ +#define CPG_CLKON_REG1_BUS (CPG_BASE + 0x05C8) /* Clock ON / OFF register REG1_BUS */ +#define CPG_CLKON_REG0_BUS (CPG_BASE + 0x05CC) /* Clock ON / OFF register REG0_BUS */ +#define CPG_CLKON_PERI_CPU (CPG_BASE + 0x05D0) /* Clock ON / OFF register PERI_CPU */ +#define CPG_CLKON_PERI_VIDEO (CPG_BASE + 0x05D4) /* Clock ON / OFF register PERI_VIDEO */ +#define CPG_CLKON_PERI_DDR (CPG_BASE + 0x05D8) /* Clock ON / OFF register PERI_DDR */ +#define CPG_CLKON_AXI_TZCDDR (CPG_BASE + 0x05DC) /* Clock ON / OFF register AXI_TZCDDR */ +#define CPG_CLKON_MTGPGS (CPG_BASE + 0x05E0) /* Clock ON / OFF register MTGPGS */ +#define CPG_CLKON_AXI_DEFAULT_SLV (CPG_BASE + 0x05E4) /* Clock ON / OFF register AXI_DEFAULT_SLV */ +#define CPG_CLKON_OCTA (CPG_BASE + 0x05F4) /* Clock ON / OFF register OCTA */ + +#define CPG_CLKMON_CA55 (CPG_BASE + 0x0680) /* Clock monitor register CA55 */ +#define CPG_CLKMON_CM33 (CPG_BASE + 0x0684) /* Clock monitor register CM33 */ +#define CPG_CLKMON_SRAM_ACPU (CPG_BASE + 0x0688) /* Clock monitor register SRAM_ACPU */ +#define CPG_CLKMON_SRAM_MCPU (CPG_BASE + 0x068C) /* Clock monitor register SRAM_MCPU */ +#define CPG_CLKMON_ROM (CPG_BASE + 0x0690) /* Clock monitor register ROM */ +#define CPG_CLKMON_GIC600 (CPG_BASE + 0x0694) /* Clock monitor register GIC600 */ +#define CPG_CLKMON_IA55 (CPG_BASE + 0x0698) /* Clock monitor register IA55 */ +#define CPG_CLKMON_IM33 (CPG_BASE + 0x069C) /* Clock monitor register IM33 */ +#define CPG_CLKMON_MHU (CPG_BASE + 0x06A0) /* Clock monitor register MHU */ +#define CPG_CLKMON_CST (CPG_BASE + 0x06A4) /* Clock monitor register CST */ +#define CPG_CLKMON_SYC (CPG_BASE + 0x06A8) /* Clock monitor register SYC */ +#define CPG_CLKMON_DAMC_REG (CPG_BASE + 0x06AC) /* Clock monitor register DAMC_REG */ +#define CPG_CLKMON_SYSC (CPG_BASE + 0x06B0) /* Clock monitor register SYSC */ +#define CPG_CLKMON_OSTM (CPG_BASE + 0x06B4) /* Clock monitor register OSTM */ +#define CPG_CLKMON_MTU (CPG_BASE + 0x06B8) /* Clock monitor register MTU */ +#define CPG_CLKMON_POE3 (CPG_BASE + 0x06BC) /* Clock monitor register POE3 */ +#define CPG_CLKMON_GPT (CPG_BASE + 0x06C0) /* Clock monitor register GPT */ +#define CPG_CLKMON_POEG (CPG_BASE + 0x06C4) /* Clock monitor register POEG */ +#define CPG_CLKMON_WDT (CPG_BASE + 0x06C8) /* Clock monitor register WDT */ +#define CPG_CLKMON_DDR (CPG_BASE + 0x06CC) /* Clock monitor register DDR */ +#define CPG_CLKMON_SPI_MULTI (CPG_BASE + 0x06D0) /* Clock monitor register SPI_MULTI */ +#define CPG_CLKMON_SDHI (CPG_BASE + 0x06D4) /* Clock monitor register SDHI */ +#define CPG_CLKMON_GPU (CPG_BASE + 0x06D8) /* Clock monitor register GPU */ +#define CPG_CLKMON_ISU (CPG_BASE + 0x06DC) /* Clock monitor register ISU */ +#define CPG_CLKMON_H264 (CPG_BASE + 0x06E0) /* Clock monitor register H264 */ +#define CPG_CLKMON_CRU (CPG_BASE + 0x06E4) /* Clock monitor register CRU */ +#define CPG_CLKMON_MIPI_DSI (CPG_BASE + 0x06E8) /* Clock monitor register MIPI_DSI */ +#define CPG_CLKMON_LCDC (CPG_BASE + 0x06EC) /* Clock monitor register LCDC */ +#define CPG_CLKMON_SSI (CPG_BASE + 0x06F0) /* Clock monitor register SSI */ +#define CPG_CLKMON_SRC (CPG_BASE + 0x06F4) /* Clock monitor register SRC */ +#define CPG_CLKMON_USB (CPG_BASE + 0x06F8) /* Clock monitor register USB */ +#define CPG_CLKMON_ETH (CPG_BASE + 0x06FC) /* Clock monitor register ETH */ +#define CPG_CLKMON_I2C (CPG_BASE + 0x0700) /* Clock monitor register I2C */ +#define CPG_CLKMON_SCIF (CPG_BASE + 0x0704) /* Clock monitor register SCIF */ +#define CPG_CLKMON_SCI (CPG_BASE + 0x0708) /* Clock monitor register SCI */ +#define CPG_CLKMON_IRDA (CPG_BASE + 0x070C) /* Clock monitor register IRDA */ +#define CPG_CLKMON_RSPI (CPG_BASE + 0x0710) /* Clock monitor register RSPI */ +#define CPG_CLKMON_CANFD (CPG_BASE + 0x0714) /* Clock monitor register CANFD */ +#define CPG_CLKMON_GPIO (CPG_BASE + 0x0718) /* Clock monitor register GPIO */ +#define CPG_CLKMON_TSIPG (CPG_BASE + 0x071C) /* Clock monitor register TSIPG */ +#define CPG_CLKMON_JAUTH (CPG_BASE + 0x0720) /* Clock monitor register JAUTH */ +#define CPG_CLKMON_OTP (CPG_BASE + 0x0724) /* Clock monitor register OTP */ +#define CPG_CLKMON_ADC (CPG_BASE + 0x0728) /* Clock monitor register ADC */ +#define CPG_CLKMON_TSU (CPG_BASE + 0x072C) /* Clock monitor register TSU */ +#define CPG_CLKMON_BBGU (CPG_BASE + 0x0730) /* Clock monitor register BBGU */ +#define CPG_CLKMON_AXI_ACPU_BUS (CPG_BASE + 0x0734) /* Clock monitor register AXI_ACPU_BUS */ +#define CPG_CLKMON_AXI_MCPU_BUS (CPG_BASE + 0x0738) /* Clock monitor register AXI_MCPU_BUS */ +#define CPG_CLKMON_AXI_COM_BUS (CPG_BASE + 0x073C) /* Clock monitor register AXI_COM_BUS */ +#define CPG_CLKMON_AXI_VIDEO_BUS (CPG_BASE + 0x0740) /* Clock monitor register AXI_VIDEO_BUS */ +#define CPG_CLKMON_PERI_COM (CPG_BASE + 0x0744) /* Clock monitor register PERI_COM */ +#define CPG_CLKMON_REG1_BUS (CPG_BASE + 0x0748) /* Clock monitor register REG1_BUS */ +#define CPG_CLKMON_REG0_BUS (CPG_BASE + 0x074C) /* Clock monitor register REG0_BUS */ +#define CPG_CLKMON_PERI_CPU (CPG_BASE + 0x0750) /* Clock monitor register PERI_CPU */ +#define CPG_CLKMON_PERI_VIDEO (CPG_BASE + 0x0754) /* Clock monitor register PERI_VIDEO */ +#define CPG_CLKMON_PERI_DDR (CPG_BASE + 0x0758) /* Clock monitor register PERI_DDR */ +#define CPG_CLKMON_AXI_TZCDDR (CPG_BASE + 0x075C) /* Clock monitor register AXI_TZCDDR */ +#define CPG_CLKMON_MTGPGS (CPG_BASE + 0x0760) /* Clock monitor register MTGPGS */ +#define CPG_CLKMON_AXI_DEFAULT_SLV (CPG_BASE + 0x0764) /* Clock monitor register AXI_DEFAULT_SLV */ +#define CPG_CLKMON_OCTA (CPG_BASE + 0x0774) /* Clock monitor register OCTA */ + +#define CPG_RST_CA55 (CPG_BASE + 0x0800) /* Reset ONOFF register CA55 */ +#define CPG_RST_CM33 (CPG_BASE + 0x0804) /* Reset ONOFF register CM33 */ +#define CPG_RST_SRAM_ACPU (CPG_BASE + 0x0808) /* Reset ONOFF register SRAM_ACPU */ +#define CPG_RST_SRAM_MCPU (CPG_BASE + 0x080C) /* Reset ONOFF register SRAM_MCPU */ +#define CPG_RST_ROM (CPG_BASE + 0x0810) /* Reset ONOFF register ROM */ +#define CPG_RST_GIC600 (CPG_BASE + 0x0814) /* Reset ONOFF register GIC600 */ +#define CPG_RST_IA55 (CPG_BASE + 0x0818) /* Reset ONOFF register IA55 */ +#define CPG_RST_IM33 (CPG_BASE + 0x081C) /* Reset ONOFF register IM33 */ +#define CPG_RST_MHU (CPG_BASE + 0x0820) /* Reset ONOFF register MHU */ +#define CPG_RST_CST (CPG_BASE + 0x0824) /* Reset ONOFF register CST */ +#define CPG_RST_SYC (CPG_BASE + 0x0828) /* Reset ONOFF register SYC */ +#define CPG_RST_DMAC (CPG_BASE + 0x082C) /* Reset ONOFF register DMAC */ +#define CPG_RST_SYSC (CPG_BASE + 0x0830) /* Reset ONOFF register SYSC */ +#define CPG_RST_OSTM (CPG_BASE + 0x0834) /* Reset ONOFF register OSTM */ +#define CPG_RST_MTU (CPG_BASE + 0x0838) /* Reset ONOFF register MTU */ +#define CPG_RST_POE3 (CPG_BASE + 0x083C) /* Reset ONOFF register POE3 */ +#define CPG_RST_GPT (CPG_BASE + 0x0840) /* Reset ONOFF register GPT */ +#define CPG_RST_POEG (CPG_BASE + 0x0844) /* Reset ONOFF register POEG */ +#define CPG_RST_WDT (CPG_BASE + 0x0848) /* Reset ONOFF register WDT */ +#define CPG_RST_DDR (CPG_BASE + 0x084C) /* Reset ONOFF register DDR */ +#define CPG_RST_SPI (CPG_BASE + 0x0850) /* Reset ONOFF register SPI */ +#define CPG_RST_SDHI (CPG_BASE + 0x0854) /* Reset ONOFF register SDHI */ +#define CPG_RST_GPU (CPG_BASE + 0x0858) /* Reset ONOFF register GPU */ +#define CPG_RST_ISU (CPG_BASE + 0x085C) /* Reset ONOFF register ISU */ +#define CPG_RST_H264 (CPG_BASE + 0x0860) /* Reset ONOFF register H264 */ +#define CPG_RST_CRU (CPG_BASE + 0x0864) /* Reset ONOFF register CRU */ +#define CPG_RST_MIPI_DSI (CPG_BASE + 0x0868) /* Reset ONOFF register MIPI_DSI */ +#define CPG_RST_LCDC (CPG_BASE + 0x086C) /* Reset ONOFF register LCDC */ +#define CPG_RST_SSIF (CPG_BASE + 0x0870) /* Reset ONOFF register SSIF */ +#define CPG_RST_SRC (CPG_BASE + 0x0874) /* Reset ONOFF register SRC */ +#define CPG_RST_USB (CPG_BASE + 0x0878) /* Reset ONOFF register USB */ +#define CPG_RST_ETH (CPG_BASE + 0x087C) /* Reset ONOFF register ETH */ +#define CPG_RST_I2C (CPG_BASE + 0x0880) /* Reset ONOFF register I2C */ +#define CPG_RST_SCIF (CPG_BASE + 0x0884) /* Reset ONOFF register SCIF */ +#define CPG_RST_SCI (CPG_BASE + 0x0888) /* Reset ONOFF register SCI */ +#define CPG_RST_IRDA (CPG_BASE + 0x088C) /* Reset ONOFF register IRDA */ +#define CPG_RST_RSPI (CPG_BASE + 0x0890) /* Reset ONOFF register RSPI */ +#define CPG_RST_CANFD (CPG_BASE + 0x0894) /* Reset ONOFF register CANFD */ +#define CPG_RST_GPIO (CPG_BASE + 0x0898) /* Reset ONOFF register GPIO */ +#define CPG_RST_TSIPG (CPG_BASE + 0x089C) /* Reset ONOFF register TSIPG */ +#define CPG_RST_JAUTH (CPG_BASE + 0x08A0) /* Reset ONOFF register JAUTH */ +#define CPG_RST_OTP (CPG_BASE + 0x08A4) /* Reset ONOFF register OTP */ +#define CPG_RST_ADC (CPG_BASE + 0x08A8) /* Reset ONOFF register ADC */ +#define CPG_RST_TSU (CPG_BASE + 0x08AC) /* Reset ONOFF register TSU */ +#define CPG_RST_BBGU (CPG_BASE + 0x08B0) /* Reset ONOFF register BBGU */ +#define CPG_RST_AXI_ACPU_BUS (CPG_BASE + 0x08B4) /* Reset ONOFF register AXI_ACPU_BUS */ +#define CPG_RST_AXI_MCPU_BUS (CPG_BASE + 0x08B8) /* Reset ONOFF register AXI_MCPU_BUS */ +#define CPG_RST_AXI_COM_BUS (CPG_BASE + 0x08BC) /* Reset ONOFF register AXI_COM_BUS */ +#define CPG_RST_AXI_VIDEO_BUS (CPG_BASE + 0x08C0) /* Reset ONOFF register AXI_VIDEO_BUS */ +#define CPG_RST_PERI_COM (CPG_BASE + 0x08C4) /* Reset ONOFF register PERI_COM */ +#define CPG_RST_REG1_BUS (CPG_BASE + 0x08C8) /* Reset ONOFF register REG1_BUS */ +#define CPG_RST_REG0_BUS (CPG_BASE + 0x08CC) /* Reset ONOFF register REG0_BUS */ +#define CPG_RST_PERI_CPU (CPG_BASE + 0x08D0) /* Reset ONOFF register PERI_CPU */ +#define CPG_RST_PERI_VIDEO (CPG_BASE + 0x08D4) /* Reset ONOFF register PERI_VIDEO */ +#define CPG_RST_PERI_DDR (CPG_BASE + 0x08D8) /* Reset ONOFF register PERI_DDR */ +#define CPG_RST_AXI_TZCDDR (CPG_BASE + 0x08DC) /* Reset ONOFF register AXI_TZCDDR */ +#define CPG_RST_MTGPGS (CPG_BASE + 0x08E0) /* Reset ONOFF register MTGPGS */ +#define CPG_RST_AXI_DEFAULT_SLV (CPG_BASE + 0x08E4) /* Reset ONOFF register AXI_DEFAULT_SLV */ +#define CPG_RST_OCTA (CPG_BASE + 0x08F4) /* Reset ONOFF register OCTA */ + +#define CPG_RSTMON_CA55 (CPG_BASE + 0x0980) /* Reset monitor register CA55 */ +#define CPG_RSTMON_CM33 (CPG_BASE + 0x0984) /* Reset monitor register CM33 */ +#define CPG_RSTMON_SRAM_ACPU (CPG_BASE + 0x0988) /* Reset monitor register SRAM_ACPU */ +#define CPG_RSTMON_SRAM_MCPU (CPG_BASE + 0x098C) /* Reset monitor register SRAM_MCPU */ +#define CPG_RSTMON_ROM (CPG_BASE + 0x0990) /* Reset monitor register ROM */ +#define CPG_RSTMON_GIC600 (CPG_BASE + 0x0994) /* Reset monitor register GIC600 */ +#define CPG_RSTMON_IA55 (CPG_BASE + 0x0998) /* Reset monitor register IA55 */ +#define CPG_RSTMON_IM33 (CPG_BASE + 0x099C) /* Reset monitor register IM33 */ +#define CPG_RSTMON_MHU (CPG_BASE + 0x09A0) /* Reset monitor register MHU */ +#define CPG_RSTMON_CST (CPG_BASE + 0x09A4) /* Reset monitor register CST */ +#define CPG_RSTMON_SYC (CPG_BASE + 0x09A8) /* Reset monitor register SYC */ +#define CPG_RSTMON_DMAC (CPG_BASE + 0x09AC) /* Reset monitor register DMAC */ +#define CPG_RSTMON_SYSC (CPG_BASE + 0x09B0) /* Reset monitor register SYSC */ +#define CPG_RSTMON_OSTM (CPG_BASE + 0x09B4) /* Reset monitor register OSTM */ +#define CPG_RSTMON_MTU (CPG_BASE + 0x09B8) /* Reset monitor register MTU */ +#define CPG_RSTMON_POE3 (CPG_BASE + 0x09BC) /* Reset monitor register POE3 */ +#define CPG_RSTMON_GPT (CPG_BASE + 0x09C0) /* Reset monitor register GPT */ +#define CPG_RSTMON_POEG (CPG_BASE + 0x09C4) /* Reset monitor register POEG */ +#define CPG_RSTMON_WDT (CPG_BASE + 0x09C8) /* Reset monitor register WDT */ +#define CPG_RSTMON_DDR (CPG_BASE + 0x09CC) /* Reset monitor register DDR */ +#define CPG_RSTMON_SPI (CPG_BASE + 0x09D0) /* Reset monitor register SPI */ +#define CPG_RSTMON_SDHI (CPG_BASE + 0x09D4) /* Reset monitor register SDHI */ +#define CPG_RSTMON_GPU (CPG_BASE + 0x09D8) /* Reset monitor register GPU */ +#define CPG_RSTMON_ISU (CPG_BASE + 0x09DC) /* Reset monitor register ISU */ +#define CPG_RSTMON_H264 (CPG_BASE + 0x09E0) /* Reset monitor register H264 */ +#define CPG_RSTMON_CRU (CPG_BASE + 0x09E4) /* Reset monitor register CRU */ +#define CPG_RSTMON_MIPI_DSI (CPG_BASE + 0x09E8) /* Reset monitor register MIPI_DSI */ +#define CPG_RSTMON_LCDC (CPG_BASE + 0x09EC) /* Reset monitor register LCDC */ +#define CPG_RSTMON_SSIF (CPG_BASE + 0x09F0) /* Reset monitor register SSIF */ +#define CPG_RSTMON_SRC (CPG_BASE + 0x09F4) /* Reset monitor register SRC */ +#define CPG_RSTMON_USB (CPG_BASE + 0x09F8) /* Reset monitor register USB */ +#define CPG_RSTMON_ETH (CPG_BASE + 0x09FC) /* Reset monitor register ETH */ +#define CPG_RSTMON_I2C (CPG_BASE + 0x0A00) /* Reset monitor register I2C */ +#define CPG_RSTMON_SCIF (CPG_BASE + 0x0A04) /* Reset monitor register SCIF */ +#define CPG_RSTMON_SCI (CPG_BASE + 0x0A08) /* Reset monitor register SCI */ +#define CPG_RSTMON_IRDA (CPG_BASE + 0x0A0C) /* Reset monitor register IRDA */ +#define CPG_RSTMON_RSPI (CPG_BASE + 0x0A10) /* Reset monitor register RSPI */ +#define CPG_RSTMON_CANFD (CPG_BASE + 0x0A14) /* Reset monitor register CANFD */ +#define CPG_RSTMON_GPIO (CPG_BASE + 0x0A18) /* Reset monitor register GPIO */ +#define CPG_RSTMON_TSIPG (CPG_BASE + 0x0A1C) /* Reset monitor register TSIPG */ +#define CPG_RSTMON_JAUTH (CPG_BASE + 0x0A20) /* Reset monitor register JAUTH */ +#define CPG_RSTMON_OTP (CPG_BASE + 0x0A24) /* Reset monitor register OTP */ +#define CPG_RSTMON_ADC (CPG_BASE + 0x0A28) /* Reset monitor register ADC */ +#define CPG_RSTMON_TSU (CPG_BASE + 0x0A2C) /* Reset monitor register TSU */ +#define CPG_RSTMON_BBGU (CPG_BASE + 0x0A30) /* Reset monitor register BBGU */ +#define CPG_RSTMON_AXI_ACPU_BUS (CPG_BASE + 0x0A34) /* Reset monitor register AXI_ACPU_BUS */ +#define CPG_RSTMON_AXI_MCPU_BUS (CPG_BASE + 0x0A38) /* Reset monitor register AXI_MCPU_BUS */ +#define CPG_RSTMON_AXI_COM_BUS (CPG_BASE + 0x0A3C) /* Reset monitor register AXI_COM_BUS */ +#define CPG_RSTMON_AXI_VIDEO_BUS (CPG_BASE + 0x0A40) /* Reset monitor register AXI_VIDEO_BUS */ +#define CPG_RSTMON_PERI_COM (CPG_BASE + 0x0A44) /* Reset monitor register PERI_COM */ +#define CPG_RSTMON_REG1_BUS (CPG_BASE + 0x0A48) /* Reset monitor register REG1_BUS */ +#define CPG_RSTMON_REG0_BUS (CPG_BASE + 0x0A4C) /* Reset monitor register REG0_BUS */ +#define CPG_RSTMON_PERI_CPU (CPG_BASE + 0x0A50) /* Reset monitor register PERI_CPU */ +#define CPG_RSTMON_PERI_VIDEO (CPG_BASE + 0x0A54) /* Reset monitor register PERI_VIDEO */ +#define CPG_RSTMON_PERI_DDR (CPG_BASE + 0x0A58) /* Reset monitor register PERI_DDR */ +#define CPG_RSTMON_AXI_TZCDDR (CPG_BASE + 0x0A5C) /* Reset monitor register AXI_TZCDDR */ +#define CPG_RSTMON_MTGPGS (CPG_BASE + 0x0A60) /* Reset monitor register MTGPGS */ +#define CPG_RSTMON_AXI_DEFAULT_SLV (CPG_BASE + 0x0A64) /* Reset monitor register AXI_DEFAULT_SLV */ +#define CPG_RSTMON_OCTA (CPG_BASE + 0x0A74) /* Reset monitor register OCTA */ + +#define CPG_EN_OSTM (CPG_BASE + 0x0B00) /* Enable ONOFF register_OSTM */ +#define CPG_WDTOVF_RST (CPG_BASE + 0x0B10) /* WDT overflow system reset register */ +#define CPG_WDTRST_SEL (CPG_BASE + 0x0B14) /* WDT reset selector register */ +#define CPG_DBGRST (CPG_BASE + 0x0B20) /* Reset ONOFF register DBGRST */ +#define CPG_CLUSTER_PCHMON (CPG_BASE + 0x0B30) /* CA55 Cluster Power Status Monitor Register */ +#define CPG_CLUSTER_PCHCTL (CPG_BASE + 0x0B34) /* CA55 Cluster Power Status Control Register */ +#define CPG_CORE0_PCHMON (CPG_BASE + 0x0B38) /* CA55 Core0 Power Status Monitor Register */ +#define CPG_CORE0_PCHCTL (CPG_BASE + 0x0B3C) /* CA55 Core0 Power Status Control Register */ +#define CPG_CORE1_PCHMON (CPG_BASE + 0x0B40) /* CA55 Core1 Power Status Monitor Register */ +#define CPG_CORE1_PCHCTL (CPG_BASE + 0x0B44) /* CA55 Core1 Power Status Control Register */ +#define CPG_BUS_ACPU_MSTOP (CPG_BASE + 0x0B60) /* MSTOP registerBUS_ACPU */ +#define CPG_BUS_MCPU1_MSTOP (CPG_BASE + 0x0B64) /* MSTOP registerBUS_MCPU1 */ +#define CPG_BUS_MCPU2_MSTOP (CPG_BASE + 0x0B68) /* MSTOP registerBUS_MCPU2 */ +#define CPG_BUS_PERI_COM_MSTOP (CPG_BASE + 0x0B6C) /* MSTOP registerBUS_PERI_COM */ +#define CPG_BUS_PERI_CPU_MSTOP (CPG_BASE + 0x0B70) /* MSTOP registerBUS_PERI_CPU */ +#define CPG_BUS_PERI_DDR_MSTOP (CPG_BASE + 0x0B74) /* MSTOP registerBUS_PERI_DDR */ +#define CPG_BUS_PERI_VIDEO_MSTOP (CPG_BASE + 0x0B78) /* MSTOP registerBUS_PERI_VIDEO */ +#define CPG_BUS_REG0_MSTOP (CPG_BASE + 0x0B7C) /* MSTOP registerBUS_REG0 */ +#define CPG_BUS_REG1_MSTOP (CPG_BASE + 0x0B80) /* MSTOP registerBUS_REG1 */ +#define CPG_BUS_TZCDDR_MSTOP (CPG_BASE + 0x0B84) /* MSTOP registerBUS_TZCDDR */ +#define CPG_MHU_MSTOP (CPG_BASE + 0x0B88) /* MSTOP registerMHU */ +#define CPG_BUS_PERI_STP_MSTOP (CPG_BASE + 0x0B8C) /* MSTOP registerBUS_PERI_STP */ +#define CPG_BUS_MCPU3_MSTOP (CPG_BASE + 0x0B90) /* MSTOP register BUS_MCPU3 */ + +#define CPG_OTHERFUNC1_REG (CPG_BASE + 0x0BE8) /* Other function registers1 */ +#define CPG_OTHERFUNC2_REG (CPG_BASE + 0x0BEC) /* Other function registers2 */ + +#define PLL1_STBY_RESETB (1 << 0) +#define PLL1_STBY_SSC_EN (1 << 2) +#define PLL1_STBY_SSC_MODE0 (1 << 4) +#define PLL1_STBY_SSC_MODE1 (1 << 5) +#define PLL1_STBY_RESETB_WEN (1 << 16) +#define PLL1_STBY_SSC_EN_WEN (1 << 18) +#define PLL1_STBY_SSC_MODE_WEN (1 << 20) +#define PLL1_CLK1_DIV_P_24M (1 << 0) +#define PLL1_CLK1_DIV_P_12M (2 << 0) +#define PLL1_CLK1_DIV_P_8M (3 << 0) +#define PLL1_CLK1_DIV_P_6M (4 << 0) +#define PLL1_CLK2_DIV_S_RATIO1 (0 << 0) +#define PLL1_CLK2_DIV_S_RATIO2 (1 << 0) +#define PLL1_CLK2_DIV_S_RATIO4 (2 << 0) +#define PLL1_CLK2_DIV_S_RATIO8 (3 << 0) +#define PLL1_CLK2_DIV_S_RATIO16 (4 << 0) +#define PLL1_CLK2_DIV_S_RATIO32 (5 << 0) +#define PLL1_CLK2_DIV_S_RATIO64 (6 << 0) +#define PLL1_MON_PLL1_RESETB (1 << 0) +#define PLL1_MON_PLL1_LOCK (1 << 4) +#define PLL4_STBY_RESETB (1 << 0) +#define PLL4_STBY_SSC_EN (1 << 2) +#define PLL4_STBY_SSC_MODE0 (1 << 4) +#define PLL4_STBY_SSC_MODE1 (1 << 5) +#define PLL4_STBY_RESETB_WEN (1 << 16) +#define PLL4_STBY_SSC_EN_WEN (1 << 18) +#define PLL4_STBY_SSC_MODE_WEN (1 << 20) +#define PLL4_CLK1_DIV_P_24M (1 << 0) +#define PLL4_CLK1_DIV_P_12M (2 << 0) +#define PLL4_CLK1_DIV_P_8M (3 << 0) +#define PLL4_CLK1_DIV_P_6M (4 << 0) +#define PLL4_CLK2_DIV_S_RATIO1 (0 << 0) +#define PLL4_CLK2_DIV_S_RATIO2 (1 << 0) +#define PLL4_CLK2_DIV_S_RATIO4 (2 << 0) +#define PLL4_CLK2_DIV_S_RATIO8 (3 << 0) +#define PLL4_CLK2_DIV_S_RATIO16 (4 << 0) +#define PLL4_CLK2_DIV_S_RATIO32 (5 << 0) +#define PLL4_CLK2_DIV_S_RATIO64 (6 << 0) +#define PLL4_MON_PLL4_RESETB (1 << 0) +#define PLL4_MON_PLL4_LOCK (1 << 4) +#define PLL6_STBY_RESETB (1 << 0) +#define PLL6_STBY_SSC_EN (1 << 2) +#define PLL6_STBY_SSC_MODE0 (1 << 4) +#define PLL6_STBY_SSC_MODE1 (1 << 5) +#define PLL6_STBY_RESETB_WEN (1 << 16) +#define PLL6_STBY_SSC_EN_WEN (1 << 18) +#define PLL6_STBY_SSC_MODE_WEN (1 << 20) +#define PLL6_CLK1_DIV_P_24M (1 << 0) +#define PLL6_CLK1_DIV_P_12M (2 << 0) +#define PLL6_CLK1_DIV_P_8M (3 << 0) +#define PLL6_CLK1_DIV_P_6M (4 << 0) +#define PLL6_CLK2_DIV_S_RATIO1 (0 << 0) +#define PLL6_CLK2_DIV_S_RATIO2 (1 << 0) +#define PLL6_CLK2_DIV_S_RATIO4 (2 << 0) +#define PLL6_CLK2_DIV_S_RATIO8 (3 << 0) +#define PLL6_CLK2_DIV_S_RATIO16 (4 << 0) +#define PLL6_CLK2_DIV_S_RATIO32 (5 << 0) +#define PLL6_CLK2_DIV_S_RATIO64 (6 << 0) +#define PLL6_MON_PLL6_RESETB (1 << 0) +#define PLL6_MON_PLL6_LOCK (1 << 4) +#define PLL1_SETTING_SEL_PLL1 (1 << 0) +#define PLL1_SETTING_SEL_PLL1_WEN (1 << 16) +#define PLL_CLK_DIV_M_SET(a, b) (mmio_write_32(a, ((mmio_read_32(a)) | (b << 6)))) +#define PLL_CLK_DIV_K_SET(a, b) (mmio_write_32(a, ((mmio_read_32(a)) | (b << 16)))) +#define PLL_CLK_MRR_SET(a, b) (mmio_write_32(a, ((mmio_read_32(a)) | (b << 8)))) +#define PLL_CLK_MFR_SET(a, b) (mmio_write_32(a, ((mmio_read_32(a)) | (b << 16)))) + +#define PLL2_STBY_RESETB (1 << 0) +#define PLL2_STBY_SSC_EN (1 << 2) +#define PLL2_STBY_DOWNSPREAD (1 << 4) +#define PLL2_STBY_RESETB_WEN (1 << 16) +#define PLL2_STBY_SSC_EN_WEN (1 << 18) +#define PLL2_STBY_DOWNSPREAD_WEN (1 << 20) +#define PLL2_CLK1_POSTDIV1_WEN (1 << 16) +#define PLL2_CLK1_POSTDIV2_WEN (1 << 20) +#define PLL2_CLK1_REFDIV_WEN (1 << 24) +#define PLL2_CLK2_DACPD (1 << 0) +#define PLL2_CLK2_DSMPD (1 << 2) +#define PLL2_CLK2_FOUT4PHASEPD (1 << 4) +#define PLL2_CLK2_FOUTPOSTDIVPD (1 << 6) +#define PLL2_CLK2_FOUTVCOPD (1 << 8) +#define PLL2_CLK2_DACPD_WEN (1 << 16) +#define PLL2_CLK2_DSMPD_WEN (1 << 18) +#define PLL2_CLK2_FOUT4PHASEPD_WEN (1 << 20) +#define PLL2_CLK2_FOUTPOSTDIVPD_WEN (1 << 22) +#define PLL2_CLK2_FOUTVCOPD_WEN (1 << 24) +#define PLL2_CLK6_SEL_EXTWAVE (1 << 0) +#define PLL2_CLK6_SEL_EXTWAVE_WEN (1 << 16) +#define PLL2_MON_PLL2_RESETB (1 << 0) +#define PLL2_MON_PLL2_LOCK (1 << 4) +#define PLL3_STBY_RESETB (1 << 0) +#define PLL3_STBY_SSC_EN (1 << 2) +#define PLL3_STBY_DOWNSPREAD (1 << 4) +#define PLL3_STBY_RESETB_WEN (1 << 16) +#define PLL3_STBY_SSC_EN_WEN (1 << 18) +#define PLL3_STBY_DOWNSPREAD_WEN (1 << 20) +#define PLL3_CLK1_POSTDIV1_WEN (1 << 16) +#define PLL3_CLK1_POSTDIV2_WEN (1 << 20) +#define PLL3_CLK1_REFDIV_WEN (1 << 24) +#define PLL3_CLK2_DACPD (1 << 0) +#define PLL3_CLK2_DSMPD (1 << 2) +#define PLL3_CLK2_FOUT4PHASEPD (1 << 4) +#define PLL3_CLK2_FOUTPOSTDIVPD (1 << 6) +#define PLL3_CLK2_FOUTVCOPD (1 << 8) +#define PLL3_CLK2_DACPD_WEN (1 << 16) +#define PLL3_CLK2_DSMPD_WEN (1 << 18) +#define PLL3_CLK2_FOUT4PHASEPD_WEN (1 << 20) +#define PLL3_CLK2_FOUTPOSTDIVPD_WEN (1 << 22) +#define PLL3_CLK2_FOUTVCOPD_WEN (1 << 24) +#define PLL3_CLK6_SEL_EXTWAVE (1 << 0) +#define PLL3_CLK6_SEL_EXTWAVE_WEN (1 << 16) +#define PLL3_MON_PLL3_RESETB (1 << 0) +#define PLL3_MON_PLL3_LOCK (1 << 4) +#define PLL5_STBY_RESETB (1 << 0) +#define PLL5_STBY_SSC_EN (1 << 2) +#define PLL5_STBY_DOWNSPREAD (1 << 4) +#define PLL5_STBY_RESETB_WEN (1 << 16) +#define PLL5_STBY_SSC_EN_WEN (1 << 18) +#define PLL5_STBY_DOWNSPREAD_WEN (1 << 20) +#define PLL5_CLK1_POSTDIV1_WEN (1 << 16) +#define PLL5_CLK1_POSTDIV2_WEN (1 << 20) +#define PLL5_CLK1_REFDIV_WEN (1 << 24) +#define PLL5_CLK2_DACPD (1 << 0) +#define PLL5_CLK2_DSMPD (1 << 2) +#define PLL5_CLK2_FOUT4PHASEPD (1 << 4) +#define PLL5_CLK2_FOUTPOSTDIVPD (1 << 6) +#define PLL5_CLK2_FOUTVCOPD (1 << 8) +#define PLL5_CLK2_DACPD_WEN (1 << 16) +#define PLL5_CLK2_DSMPD_WEN (1 << 18) +#define PLL5_CLK2_FOUT4PHASEPD_WEN (1 << 20) +#define PLL5_CLK2_FOUTPOSTDIVPD_WEN (1 << 22) +#define PLL5_CLK2_FOUTVCOPD_WEN (1 << 24) +#define PLL5_CLK6_SEL_EXTWAVE (1 << 0) +#define PLL5_CLK6_SEL_EXTWAVE_WEN (1 << 16) +#define PLL5_MON_PLL5_RESETB (1 << 0) +#define PLL5_MON_PLL5_LOCK (1 << 4) + +#define PLL_CLK_POSTDIV1_SET(a, b) (mmio_write_32(a, ((mmio_read_32(a)) | (b << 0)))) +#define PLL_CLK_POSTDIV2_SET(a, b) (mmio_write_32(a, ((mmio_read_32(a)) | (b << 4)))) +#define PLL_CLK_REFDIV_SET(a, b) (mmio_write_32(a, ((mmio_read_32(a)) | (b << 8)))) +#define PLL_CLK_DIVVAL_SET(a, b) (mmio_write_32(a, ((mmio_read_32(a)) | (b << 0)))) +#define PLL_CLK_FRACIN_SET(a, b) (mmio_write_32(a, ((mmio_read_32(a)) | (b << 8)))) +#define PLL_CLK_EXT_MAXADDR_SET(a, b) (mmio_write_32(a, ((mmio_read_32(a)) | (b << 0)))) +#define PLL_CLK_INITIN_SET(a, b) (mmio_write_32(a, ((mmio_read_32(a)) | (b << 16)))) +#define PLL_CLK_SPREAD_SET(a, b) (mmio_write_32(a, ((mmio_read_32(a)) | (b << 0)))) + +#define PL1_DDIV_DIVPL1_SET_1_1 (0 << 0) +#define PL1_DDIV_DIVPL1_SET_1_2 (1 << 0) +#define PL1_DDIV_DIVPL1_SET_1_4 (2 << 0) +#define PL1_DDIV_DIVPL1_SET_1_8 (3 << 0) +#define PL1_DDIV_DIVPL1_SET_WEN (1 << 16) +#define PL2_DDIV_DIVPL2A_SET_1_1 (0 << 0) +#define PL2_DDIV_DIVPL2A_SET_1_2 (1 << 0) +#define PL2_DDIV_DIVPL2A_SET_1_4 (2 << 0) +#define PL2_DDIV_DIVPL2A_SET_1_8 (3 << 0) +#define PL2_DDIV_DIVPL2A_SET_1_32 (4 << 0) +#define PL2_DDIV_DIVPL2B_SET_1_1 (0 << 4) +#define PL2_DDIV_DIVPL2B_SET_1_2 (1 << 4) +#define PL2_DDIV_DIVPL2B_SET_1_4 (2 << 4) +#define PL2_DDIV_DIVPL2B_SET_1_8 (3 << 4) +#define PL2_DDIV_DIVPL2B_SET_1_32 (4 << 4) +#define PL2_DDIV_DIVPL2C_SET_1_1 (0 << 8) +#define PL2_DDIV_DIVPL2C_SET_1_2 (1 << 8) +#define PL2_DDIV_DIVPL2C_SET_1_4 (2 << 8) +#define PL2_DDIV_DIVPL2C_SET_1_8 (3 << 8) +#define PL2_DDIV_DIVPL2C_SET_1_32 (4 << 8) +#define PL2_DDIV_DIVDSILPCLK_SET_1_16 (0 << 12) +#define PL2_DDIV_DIVDSILPCLK_SET_1_32 (1 << 12) +#define PL2_DDIV_DIVDSILPCLK_SET_1_64 (2 << 12) +#define PL2_DDIV_DIVDSILPCLK_SET_1_128 (3 << 12) +#define PL2_DDIV_DIVPL2A_WEN (1 << 16) +#define PL2_DDIV_DIVPL2B_WEN (1 << 20) +#define PL2_DDIV_DIVPL2C_WEN (1 << 24) +#define PL2_DDIV_DIVDSILPCLK_WEN (1 << 28) +#define PL3A_DDIV_DIVPL3A_SET_1_1 (0 << 0) +#define PL3A_DDIV_DIVPL3A_SET_1_2 (1 << 0) +#define PL3A_DDIV_DIVPL3A_SET_1_4 (2 << 0) +#define PL3A_DDIV_DIVPL3A_SET_1_8 (3 << 0) +#define PL3A_DDIV_DIVPL3A_SET_1_32 (4 << 0) +#define PL3A_DDIV_DIVPL3B_SET_1_1 (0 << 0) +#define PL3A_DDIV_DIVPL3B_SET_1_2 (1 << 0) +#define PL3A_DDIV_DIVPL3B_SET_1_4 (2 << 0) +#define PL3A_DDIV_DIVPL3B_SET_1_8 (3 << 0) +#define PL3A_DDIV_DIVPL3B_SET_1_32 (4 << 0) +#define PL3A_DDIV_DIVPL3C_SET_1_1 (0 << 0) +#define PL3A_DDIV_DIVPL3C_SET_1_2 (1 << 0) +#define PL3A_DDIV_DIVPL3C_SET_1_4 (2 << 0) +#define PL3A_DDIV_DIVPL3C_SET_1_8 (3 << 0) +#define PL3A_DDIV_DIVPL3C_SET_1_32 (4 << 0) +#define PL3A_DDIV_DIVPL3F_SET_1_1 (0 << 0) +#define PL3A_DDIV_DIVPL3F_SET_1_2 (1 << 0) +#define PL3A_DDIV_DIVPL3F_SET_1_4 (2 << 0) +#define PL3A_DDIV_DIVPL3F_SET_1_8 (3 << 0) +#define PL3A_DDIV_DIVPL3F_SET_1_32 (4 << 0) +#define PL3A_DDIV_DIVPL3A_WEN (1 << 16) +#define PL3A_DDIV_DIVPL3B_WEN (1 << 20) +#define PL3A_DDIV_DIVPL3C_WEN (1 << 24) +#define PL3A_DDIV_DIVPL3F_WEN (1 << 28) +#define PL3B_DDIV_DIVPL3CLK200FIX_SET_1_1 (0 << 0) +#define PL3B_DDIV_DIVPL3CLK200FIX_SET_1_2 (1 << 0) +#define PL3B_DDIV_DIVPL3CLK200FIX_SET_1_4 (2 << 0) +#define PL3B_DDIV_DIVPL3CLK200FIX_SET_1_8 (3 << 0) +#define PL3B_DDIV_DIVPL3CLK200FIX_SET_1_32 (4 << 0) +#define PL3B_DDIV_DIVPL3CLK200FIX_WEN (1 << 16) +#define PL6_DDIV_DIVGPU_SET_1_1 (0 << 0) +#define PL6_DDIV_DIVGPU_SET_1_2 (1 << 0) +#define PL6_DDIV_DIVGPU_SET_1_4 (2 << 0) +#define PL6_DDIV_DIVGPU_SET_1_8 (3 << 0) +#define PL6_DDIV_DIVGPU_WEN (1 << 16) +#define PL2SDHI_DSEL_SEL_SDHI0_SET_CLK533FIX_C (1 << 0) +#define PL2SDHI_DSEL_SEL_SDHI0_SET_DIV_PLL2_DIV8 (2 << 0) +#define PL2SDHI_DSEL_SEL_SDHI0_SET_DIV_PLL2_DIV12 (3 << 0) +#define PL2SDHI_DSEL_SEL_SDHI1_SET_CLK533FIX_C (1 << 4) +#define PL2SDHI_DSEL_SEL_SDHI1_SET_DIV_PLL2_DIV8 (2 << 4) +#define PL2SDHI_DSEL_SEL_SDHI1_SET_DIV_PLL2_DIV12 (3 << 4) +#define PL2SDHI_DSEL_SEL_SDHI0_WEN (1 << 16) +#define PL2SDHI_DSEL_SEL_SDHI1_WEN (1 << 20) +#define PL4_DSEL_SEL_PLL4_SET (1 << 0) +#define PL4_DSEL_SEL_PLL4_WEN (1 << 16) +#define CLKSTATUS_DIVPL1_STS (1 << 0) +#define CLKSTATUS_DIVPL2A_STS (1 << 4) +#define CLKSTATUS_DIVPL2B_STS (1 << 5) +#define CLKSTATUS_DIVPL2C_STS (1 << 6) +#define CLKSTATUS_DIVDSILPCLK_STS (1 << 7) +#define CLKSTATUS_DIVPL3A_STS (1 << 8) +#define CLKSTATUS_DIVPL3B_STS (1 << 9) +#define CLKSTATUS_DIVPL3C_STS (1 << 10) +#define CLKSTATUS_DIVPL3CLK200FIX_STS (1 << 11) +#define CLKSTATUS_DIVPL3F_STS (1 << 12) +#define CLKSTATUS_DIVGPU_STS (1 << 20) +#define CLKSTATUS_SELSDHI0_STS (1 << 28) +#define CLKSTATUS_SELSDHI1_STS (1 << 29) +#define CLKSTATUS_SELPLL4_STS (1 << 31) +#define PL1_CA55_SSEL_SEL_PLL1_SET (1 << 0) +#define PL1_CA55_SSEL_SEL_PLL1_WEN (1 << 16) +#define PL2_SSEL_SEL_PLL2_1_SET (1 << 0) +#define PL2_SSEL_SEL_PLL2_2_SET (1 << 4) +#define PL2_SSEL_SEL_PLL2_1_WEN (1 << 16) +#define PL2_SSEL_SEL_PLL2_2_WEN (1 << 20) +#define PL3_SSEL_SEL_PLL3_1_SET (1 << 0) +#define PL3_SSEL_SEL_PLL3_2_SET (1 << 4) +#define PL3_SSEL_SEL_PLL3_3_SET (1 << 8) +#define PL3_SSEL_SEL_PLL3_5_SET (1 << 12) +#define PL3_SSEL_SEL_PLL3_1_WEN (1 << 16) +#define PL3_SSEL_SEL_PLL3_2_WEN (1 << 20) +#define PL3_SSEL_SEL_PLL3_3_WEN (1 << 24) +#define PL3_SSEL_SEL_PLL3_5_WEN (1 << 28) +#define PL5_SSEL_SEL_PLL5_1_SET (1 << 0) +#define PL5_SSEL_SEL_PLL5_2_SET (1 << 4) +#define PL5_SSEL_SEL_PLL5_1_WEN (1 << 16) +#define PL5_SSEL_SEL_PLL5_2_WEN (1 << 20) +#define PL6_SSEL_SEL_PLL6_1_SET (1 << 0) +#define PL6_SSEL_SEL_GPU1_1_SET (1 << 4) +#define PL6_SSEL_SEL_GPU1_2_SET (1 << 8) +#define PL6_SSEL_SEL_GPU2_SET (1 << 12) +#define PL6_SSEL_SEL_PLL6_1_WEN (1 << 16) +#define PL6_SSEL_SEL_GPU1_1_WEN (1 << 20) +#define PL6_SSEL_SEL_GPU1_2_WEN (1 << 24) +#define PL6_SSEL_SEL_GPU2_WEN (1 << 28) +#define PL6_ETH_SSEL_SEL_PLL6_2_SET (1 << 0) +#define PL6_ETH_SSEL_SEL_ETH_SET (1 << 4) +#define PL6_ETH_SSEL_SEL_PLL6_2_WEN (1 << 16) +#define PL6_ETH_SSEL_SEL_ETH_WEN (1 << 20) +#define PL5_SDIV_DIVDSIA_SET_1_1 (0 << 0) +#define PL5_SDIV_DIVDSIA_SET_1_2 (1 << 0) +#define PL5_SDIV_DIVDSIA_SET_1_4 (2 << 0) +#define PL5_SDIV_DIVDSIA_SET_1_8 (3 << 0) +#define PL5_SDIV_DIVDSIB_SET_1_1 (0 << 8) +#define PL5_SDIV_DIVDSIB_SET_1_2 (1 << 8) +#define PL5_SDIV_DIVDSIB_SET_1_3 (2 << 8) +#define PL5_SDIV_DIVDSIB_SET_1_4 (3 << 8) +#define PL5_SDIV_DIVDSIB_SET_1_5 (4 << 8) +#define PL5_SDIV_DIVDSIB_SET_1_6 (5 << 8) +#define PL5_SDIV_DIVDSIB_SET_1_7 (6 << 8) +#define PL5_SDIV_DIVDSIB_SET_1_8 (7 << 8) +#define PL5_SDIV_DIVDSIB_SET_1_9 (8 << 8) +#define PL5_SDIV_DIVDSIB_SET_1_10 (9 << 8) +#define PL5_SDIV_DIVDSIB_SET_1_11 (10 << 8) +#define PL5_SDIV_DIVDSIB_SET_1_12 (11 << 8) +#define PL5_SDIV_DIVDSIB_SET_1_13 (12 << 8) +#define PL5_SDIV_DIVDSIB_SET_1_14 (13 << 8) +#define PL5_SDIV_DIVDSIB_SET_1_15 (14 << 8) +#define PL5_SDIV_DIVDSIB_SET_1_16 (15 << 8) +#define PL5_SDIV_DIVDSA_WEN (1 << 16) +#define PL5_SDIV_DIVSDIB_WEN (1 << 24) +#define CLKON_CLK0_ON (1 << 0) +#define CLKON_CLK0_ON_WEN (1 << 16) +#define CLKMON_UNIT0_CLK_MON (1 << 0) +#define RST_UNIT0_RSTB (1 << 0) +#define RST_UNIT0_RST_WEN (1 << 16) +#define RSTMON_UNIT0_RST_MON (1 << 0) +#define EN_OSTM_EN0_ON (1 << 0) +#define EN_OSTM_EN1_ON (1 << 1) +#define EN_OSTM_EN2_ON (1 << 2) +#define EN_OSTM_EN0_WEN (1 << 16) +#define EN_OSTM_EN1_WEN (1 << 17) +#define EN_OSTM_EN2_WEN (1 << 18) +#define WDTOVF_RST_WDTOVF0 (1 << 0) +#define WDTOVF_RST_WDTOVF1 (1 << 1) +#define WDTOVF_RST_WDTOVF2 (1 << 2) +#define WDTOVF_RST_WDTOVF3 (1 << 3) +#define WDTOVF_RST_WDTOVF0_WEN (1 << 16) +#define WDTOVF_RST_WDTOVF1_WEN (1 << 17) +#define WDTOVF_RST_WDTOVF2_WEN (1 << 18) +#define WDTOVF_RST_WDTOVF3_WEN (1 << 19) +#define WDTRST_SEL_WDTRSTSEL0 (1 << 0) +#define WDTRST_SEL_WDTRSTSEL1 (1 << 1) +#define WDTRST_SEL_WDTRSTSEL2 (1 << 2) +#define WDTRST_SEL_WDTRSTSEL3 (1 << 3) +#define WDTRST_SEL_WDTRSTSEL4 (1 << 4) +#define WDTRST_SEL_WDTRSTSEL5 (1 << 5) +#define WDTRST_SEL_WDTRSTSEL6 (1 << 6) +#define WDTRST_SEL_WDTRSTSEL7 (1 << 7) +#define WDTRST_SEL_WDTRSTSEL8 (1 << 8) +#define WDTRST_SEL_WDTRSTSEL9 (1 << 9) +#define WDTRST_SEL_WDTRSTSEL10 (1 << 10) +#define WDTRST_SEL_WDTRSTSEL0_WEN (1 << 16) +#define WDTRST_SEL_WDTRSTSEL1_WEN (1 << 17) +#define WDTRST_SEL_WDTRSTSEL2_WEN (1 << 18) +#define WDTRST_SEL_WDTRSTSEL3_WEN (1 << 19) +#define WDTRST_SEL_WDTRSTSEL4_WEN (1 << 20) +#define WDTRST_SEL_WDTRSTSEL5_WEN (1 << 21) +#define WDTRST_SEL_WDTRSTSEL6_WEN (1 << 22) +#define WDTRST_SEL_WDTRSTSEL7_WEN (1 << 23) +#define WDTRST_SEL_WDTRSTSEL8_WEN (1 << 24) +#define WDTRST_SEL_WDTRSTSEL9_WEN (1 << 25) +#define WDTRST_SEL_WDTRSTSEL10_WEN (1 << 26) +#define DBGRST_UNIT0_RSTB (1 << 0) +#define DBGRST_UNIT0_RST_WEN (1 << 16) +#define CLUSTER_PCHMON_PACCEPT_MON (1 << 0) +#define CLUSTER_PCHMON_PDENY_MON (1 << 1) +#define CLUSTER_PCHCTL_PREQ_SET (1 << 0) +#define CLUSTER_PCHCTL_PSTATE0_SET_ON (0x48 << 16) +#define CLUSTER_PCHCTL_PSTATE0_SET_OFF (0x00 << 16) +#define CORE0_PCHMON_PACCEPT0_MON (1 << 0) +#define CORE0_PCHMON_PDENY0_MON (1 << 1) +#define CORE0_PCHCTL_PREQ0_SET (1 << 0) +#define CORE0_PCHCTL_PSTATE0_SET_ON (0x08 << 16) +#define CORE0_PCHCTL_PSTATE0_SET_OFF_EMULATED (0x01 << 16) +#define CORE0_PCHCTL_PSTATE0_SET_OFF (0x00 << 16) +#define CORE1_PCHMON_PACCEPT1_MON (1 << 0) +#define CORE1_PCHMON_PDENY1_MON (1 << 1) +#define CORE1_PCHCTL_PREQ1_SET (1 << 0) +#define CORE1_PCHCTL_PSTATE1_SET_ON (0x08 << 16) +#define CORE1_PCHCTL_PSTATE1_SET_OFF_EMULATED (0x01 << 16) +#define CORE1_PCHCTL_PSTATE1_SET_OFF (0x00 << 16) +#define BUS_MSTOP_MSTOPMODE_SET (1 << 0) +#define BUS_MSTOP_MSTOPMODE_SET_WEN (1 << 16) +#define OTHERFUNC1_REG_RES0_SET (1 << 0) +#define OTHERFUNC1_REG_RES0_ON_WEN (1 << 16) +#define OTHERFUNC2_REG_RES0_SET (1 << 0) +#define OTHERFUNC2_REG_RES0_ON_WEN (1 << 16) + +#define BIT0_ON (1 << 0) +#define BIT1_ON (1 << 1) +#define BIT2_ON (1 << 2) +#define BIT3_ON (1 << 3) +#define BIT4_ON (1 << 4) +#define BIT5_ON (1 << 5) +#define BIT6_ON (1 << 6) +#define BIT7_ON (1 << 7) +#define BIT8_ON (1 << 8) +#define BIT9_ON (1 << 9) +#define BIT10_ON (1 << 10) +#define BIT11_ON (1 << 11) +#define BIT12_ON (1 << 12) +#define BIT13_ON (1 << 13) +#define BIT14_ON (1 << 14) +#define BIT15_ON (1 << 15) +#define BIT16_ON (1 << 16) +#define BIT17_ON (1 << 17) +#define BIT18_ON (1 << 18) +#define BIT19_ON (1 << 19) +#define BIT20_ON (1 << 20) +#define BIT21_ON (1 << 21) +#define BIT22_ON (1 << 22) +#define BIT23_ON (1 << 23) +#define BIT24_ON (1 << 24) +#define BIT25_ON (1 << 25) +#define BIT26_ON (1 << 26) +#define BIT27_ON (1 << 27) +#define BIT28_ON (1 << 28) +#define BIT29_ON (1 << 29) +#define BIT30_ON (1 << 30) +#define BIT31_ON (1 << 31) + +#endif /* __CPG_REGS_H__ */ diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/include/ddr.h b/drivers/rz/ipl/rza/plat/renesas/rz/common/include/ddr.h new file mode 100644 index 00000000..4a88b947 --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/include/ddr.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __DDR_H__ +#define __DDR_H__ + +void ddr_setup(void); + +#endif /* __DDR_H__ */ diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/include/ddr_internal.h b/drivers/rz/ipl/rza/plat/renesas/rz/common/include/ddr_internal.h new file mode 100644 index 00000000..923ff4a8 --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/include/ddr_internal.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __DDR_INTERNAL_H__ +#define __DDR_INTERNAL_H__ + +#include +#include +#include + +#define MC_PHYSET_NUM (4) +#define SWIZZLE_MC_NUM (9) +#define SIZZLE_PHY_NUM (16) + +static inline uint32_t read_mc_reg(uint32_t offset) +{ + return mmio_read_32(DDR_MC_BASE + offset); +} + +static inline void write_mc_reg(uint32_t offset, uint32_t val) +{ + mmio_write_32(DDR_MC_BASE + offset, val); +} + +static inline void rmw_mc_reg(uint32_t offset, uint32_t mask, uint32_t val) +{ + write_mc_reg(offset, (read_mc_reg(offset) & mask) | val); +} + +static inline uint32_t read_phy_reg(uint32_t offset) +{ + return mmio_read_32(DDR_PHY_BASE + offset); +} + +static inline void write_phy_reg(uint32_t offset, uint32_t val) +{ + mmio_write_32(DDR_PHY_BASE + offset, val); +} + +static inline void rmw_phy_reg(uint32_t offset, uint32_t mask, uint32_t val) +{ + write_phy_reg(offset, (read_phy_reg(offset) & mask) | val); +} + +void ddr_ctrl_reten_en_n(uint8_t val); + + +#endif /* __DDR_INTERNAL_H__ */ diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/include/drivers/auth/auth_common.h b/drivers/rz/ipl/rza/plat/renesas/rz/common/include/drivers/auth/auth_common.h new file mode 100644 index 00000000..43cabab2 --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/include/drivers/auth/auth_common.h @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef AUTH_COMMON_H +#define AUTH_COMMON_H + +/* + * Authentication framework common types + */ + +/* + * Type of parameters that can be extracted from an image and + * used for authentication + */ +typedef enum auth_param_type_enum { + AUTH_PARAM_NONE, + AUTH_PARAM_RAW_DATA, /* Raw image data */ + AUTH_PARAM_SIG, /* The image signature */ + AUTH_PARAM_SIG_ALG, /* The image signature algorithm */ + AUTH_PARAM_HASH, /* A hash (including the algorithm) */ + AUTH_PARAM_PUB_KEY, /* A public key */ + AUTH_PARAM_NV_CTR, /* A non-volatile counter */ +} auth_param_type_t; + +/* + * Defines an authentication parameter. The cookie will be interpreted by the + * image parser module. + */ +typedef struct auth_param_type_desc_s { + auth_param_type_t type; + void *cookie; +} auth_param_type_desc_t; + +/* + * Store a pointer to the authentication parameter and its length + */ +typedef struct auth_param_data_desc_s { + void *ptr; + unsigned int len; +} auth_param_data_desc_t; + +/* + * Authentication parameter descriptor, including type and value + */ +typedef struct auth_param_desc_s { + auth_param_type_desc_t *type_desc; + auth_param_data_desc_t data; +} auth_param_desc_t; + +/* + * The method type defines how an image is authenticated + */ +typedef enum auth_method_type_enum { + AUTH_METHOD_NONE = 0, + AUTH_METHOD_HASH, /* Authenticate by hash matching */ + AUTH_METHOD_SIG, /* Authenticate by PK operation */ + AUTH_METHOD_NV_CTR, /* Authenticate by Non-Volatile Counter */ + AUTH_METHOD_SBLIB, /* Authenticate by Renesas RZ/G2L SBLib */ + AUTH_METHOD_NUM /* Number of methods */ +} auth_method_type_t; + +/* + * Parameters for authentication by hash matching + */ +typedef struct auth_method_param_hash_s { + auth_param_type_desc_t *data; /* Data to hash */ + auth_param_type_desc_t *hash; /* Hash to match with */ +} auth_method_param_hash_t; + +/* + * Parameters for authentication by signature + */ +typedef struct auth_method_param_sig_s { + auth_param_type_desc_t *pk; /* Public key */ + auth_param_type_desc_t *sig; /* Signature to check */ + auth_param_type_desc_t *alg; /* Signature algorithm */ + auth_param_type_desc_t *data; /* Data signed */ +} auth_method_param_sig_t; + +/* + * Parameters for authentication by NV counter + */ +typedef struct auth_method_param_nv_ctr_s { + auth_param_type_desc_t *cert_nv_ctr; /* NV counter in certificate */ + auth_param_type_desc_t *plat_nv_ctr; /* NV counter in platform */ +} auth_method_param_nv_ctr_t; + +typedef struct auth_method_param_sblib_s { + auth_param_type_desc_t *data; + auth_param_type_desc_t *key_cert; + auth_param_type_desc_t *content_cert; +} auth_method_param_sblib_t; + +/* + * Authentication method descriptor + */ +typedef struct auth_method_desc_s { + auth_method_type_t type; + union { + auth_method_param_hash_t hash; + auth_method_param_sig_t sig; + auth_method_param_nv_ctr_t nv_ctr; + auth_method_param_sblib_t sblib; + } param; +} auth_method_desc_t; + +/* + * Helper macro to define an authentication parameter type descriptor + */ +#define AUTH_PARAM_TYPE_DESC(_type, _cookie) \ + { \ + .type = _type, \ + .cookie = (void *)_cookie \ + } + +/* + * Helper macro to define an authentication parameter data descriptor + */ +#define AUTH_PARAM_DATA_DESC(_ptr, _len) \ + { \ + .ptr = (void *)_ptr, \ + .len = (unsigned int)_len \ + } + +#endif /* AUTH_COMMON_H */ diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/include/drivers/auth/sblib/crypto_sblib.h b/drivers/rz/ipl/rza/plat/renesas/rz/common/include/drivers/auth/sblib/crypto_sblib.h new file mode 100644 index 00000000..c441afd2 --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/include/drivers/auth/sblib/crypto_sblib.h @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CRYPTO_SBLIB_H +#define CRYPTO_SBLIB_H + +void crypto_sblib_init(void); + +int crypto_sblib_auth(void *data_ptr, size_t len, + const void *key_cert, unsigned int key_cert_len, + const void *content_cert, unsigned int content_cert_len); + +#endif /* CRYPTO_SBLIB_H */ + diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/include/drivers/spi_multi/AT25QL128A/spi_multi_reg_values.h b/drivers/rz/ipl/rza/plat/renesas/rz/common/include/drivers/spi_multi/AT25QL128A/spi_multi_reg_values.h new file mode 100644 index 00000000..fc919ef9 --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/include/drivers/spi_multi/AT25QL128A/spi_multi_reg_values.h @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +/* Dialog AT25QL128A */ +#ifndef _SPI_MULTI_REG_VALUES_H_ +#define _SPI_MULTI_REG_VALUES_H_ +/* + * Selectable definitions + */ +/* In the case of addr width 24bit */ +#define SET_DRENR_ADE_VALUE DRENR_ADE_ADD23_OUT +#define SET_DREAR_EAC_VALUE DREAR_EAC_EXADDR24 + +/* In the case of bit width 1-1-1 and addr width 24bit */ +/* #define SET_DRCMR_CMD_VALUE DRCMR_CMD_FAST_READ_3B */ +/* #define SET_DRENR_ADB_VALUE DRENR_ADB_1BIT */ +/* #define SET_DRENR_DRDB_VALUE DRENR_DRDB_1BIT */ +/* #define SET_DRDMCR_VALUE SPI_MULTI_DUMMY_8CYCLE */ +/* #define SET_DRENR_SET_VALUE (DRENR_CDB_1BIT | DRENR_OCDB_1BIT | SET_DRENR_ADB_VALUE | \ */ +/* DRENR_OPDB_1BIT | SET_DRENR_DRDB_VALUE | DRENR_CDE | DRENR_DME | \ */ +/* SET_DRENR_ADE_VALUE) */ + +/* In the case of bit width 1-1-4 and addr width 24bit */ +/* #define SET_DRCMR_CMD_VALUE DRCMR_CMD_QUAD_OUTPUT_FAST_READ_3B */ +/* #define SET_DRENR_ADB_VALUE DRENR_ADB_1BIT */ +/* #define SET_DRENR_DRDB_VALUE DRENR_DRDB_4BIT */ +/* #define SET_DRDMCR_VALUE SPI_MULTI_DUMMY_8CYCLE */ +/* #define SET_DRENR_SET_VALUE (DRENR_CDB_1BIT | DRENR_OCDB_1BIT | SET_DRENR_ADB_VALUE | \ */ +/* DRENR_OPDB_1BIT | SET_DRENR_DRDB_VALUE | DRENR_CDE | DRENR_DME | \ */ +/* SET_DRENR_ADE_VALUE) */ + +/* In the case of bit width 1-4-4 and addr width 24bi */ +#define SET_DRCMR_CMD_VALUE DRCMR_CMD_QUAD_INPUT_OUTPUT_FAST_READ_3B +#define SET_DRENR_ADB_VALUE DRENR_ADB_4BIT +#define SET_DRENR_DRDB_VALUE DRENR_DRDB_4BIT +#define SET_DRDMCR_VALUE SPI_MULTI_DUMMY_4CYCLE +#define SET_DRENR_SET_VALUE (DRENR_CDB_1BIT | DRENR_OCDB_1BIT | SET_DRENR_ADB_VALUE | \ + DRENR_OPDB_1BIT | SET_DRENR_DRDB_VALUE | DRENR_CDE | DRENR_DME | \ + SET_DRENR_ADE_VALUE | DRENR_OPDB_4BIT | DRENR_OPDE_OPD3_OUT) + +/* SDR mode serial flash settings */ +#define SPIM_PHYCNT_SET_VALUE (PHYCNT_DEF_DATA | PHYCNT_PHYMEM_SDR_MODE | \ + PHYCNT_WBUF_NOT_USED | PHYCNT_WBUF2_NOT_USED | \ + PHYCNT_CKSEL_SLOW | PHYCNT_HS_OTHER_MODE | \ + PHYCNT_OCT_OTHER_MODE | PHYCNT_EXDS_NOT_USED | \ + PHYCNT_OCTA_HYPER_FLASH | PHYCNT_ALT_ALIGN_NOT_SUPPORTED | \ + PHYCNT_CAL_NOT_PERFOMED) +#define SPIM_PHYCNT_SDR_TIM_ADJ_SET_VALUE (SPIM_PHYCNT_SET_VALUE | PHYCNT_CKSEL_FAST) +/* Read timing setting */ +#define SPIM_PHYOFFSET1_SET_VALUE (PHYOFFSET1_DEF_DATA | PHYOFFSET1_DDRTMG_SPIDRE_0) +#define SPIM_PHYOFFSET2_SET_VALUE (PHYOFFSET2_DEF_DATA | PHYOFFSET2_OCTTMG_HYPER_FLASH) + +/* Set the QSPIn_SSL setting value */ +#define SPIM_CMNCR_EXTREAD_SET_VALUE (CMNCR_IO0FV_OUT_PREV | CMNCR_IO2FV_OUT_PREV | \ + CMNCR_IO3FV_OUT_PREV | CMNCR_MOIIO0_OUT1 | \ + CMNCR_MOIIO1_OUT1 | CMNCR_MOIIO2_OUT1 | \ + CMNCR_MOIIO3_OUT1 | CMNCR_DEF_DATA | \ + CMNCR_MD_EXT_READ) + +#define SPIM_CMNCR_MANUAL_SET_VALUE (CMNCR_IO0FV_OUT_PREV | CMNCR_IO2FV_OUT_PREV | \ + CMNCR_IO3FV_OUT_PREV | CMNCR_MOIIO0_OUT1 | \ + CMNCR_MOIIO1_OUT1 | CMNCR_MOIIO2_OUT1 | \ + CMNCR_MOIIO3_OUT1 | CMNCR_DEF_DATA | \ + CMNCR_MD_MANUAL) + +/* Set SSL delay setting value */ +#define SPIM_SSLDR_SET_VALUE (SSLDR_SCKDL_4_5 | SSLDR_SLNDL_4QSPIn | SSLDR_SPNDL_4QSPIn) + +/* Set the RBE bit and RCF bit and RBURST */ +#define SPIM_DRCR_SET_VALUE (DRCR_RBE | DRCR_RCF | DRCR_RBURST_32_DATALEN) + +/* Set the data read command */ +#define SPIM_DRCMR_SET_VALUE (SET_DRCMR_CMD_VALUE) + +/* Extended external address setting */ +#define SPIM_DREAR_SET_VALUE (SET_DREAR_EAC_VALUE) + +/* Set the bit width of command and address output to 1 bit and */ +/* the address size to 4 byte */ +#define SPIM_DRENR_SET_VALUE (SET_DRENR_SET_VALUE) +/* Dummy cycle setting */ +#define SPIM_DRDMCR_SET_VALUE (SET_DRDMCR_VALUE) + +/* Change to SPI flash mode */ +#define SPIM_DRDRENR_SET_VALUE (DRDRENR_DRDRE_SDR | DRDRENR_OPDRE_SDR | \ + DRDRENR_ADDRE_SDR | DRDRENR_HYPE_SPI) +/* Set the SDR transfer & SPI flash mode */ +#define SPIM_SMDRENR_SET_VALUE (SMDRENR_HYPE_SPI_FLASH) + +/* Set the option data */ +#define SPIM_DROPR_SET_VALUE (0) + +/* Manual Command */ +#define SMCMR_CMD_WRITE_ENABLE (0x06) +#define SMCMR_CMD_WRITE_STATUS_REGISTER_2 (0x31) +#define SMCMR_CMD_READ_STATUS_REGISTER_1 (0x05) +#define SMCMR_CMD_READ_STATUS_REGISTER_2 (0x35) +#define SMCMR_CMD_BIT_SHIFT (16) +#define SMWDR0_1BYTE_DATA_BIT_SHIFT (24) + +/* Manual Command Configure Length */ +#define SPI_MANUAL_COMMAND_SIZE_0 SMENR_SPIDE_NO_SEND +#define SPI_MANUAL_COMMAND_SIZE_8_BIT SMENR_SPIDE_8BIT_SEND +#define SPI_MANUAL_COMMAND_SIZE_16_BIT SMENR_SPIDE_16BIT_SEND +#define SPI_MANUAL_COMMAND_SIZE_32_BIT SMENR_SPIDE_32BIT_SEND +/* Read Status Register-1(05h) */ +#define STATUS_1_BUSY_BIT (1<<0) +#define STATUS_1_WEL_BIT (1<<1) +#define STATUS_1_BUSY (1<<0) +#define STATUS_1_WEL (1<<1) +/* Read Status Register-1(BUSY flag) read delay time(micro sec) */ +#define STATUS_BUSY_READ_DELAY_TIME (100) +/* Read Status Register-2(35h) */ +/* Write Status Register-2(31h) */ +#define STATUS_2_QE (1<<1) + +#endif /* _SPI_MULTI_REG_VALUES_H_ */ diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/include/drivers/spi_multi/MT25QU512ABB/spi_multi_reg_values.h b/drivers/rz/ipl/rza/plat/renesas/rz/common/include/drivers/spi_multi/MT25QU512ABB/spi_multi_reg_values.h new file mode 100644 index 00000000..cb99ae04 --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/include/drivers/spi_multi/MT25QU512ABB/spi_multi_reg_values.h @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +/* MICRON MT25QU512ABB */ +#ifndef _SPI_MULTI_REG_VALUES_H_ +#define _SPI_MULTI_REG_VALUES_H_ +/* + * Selectable definitions + */ +/* In the case of addr width 24bit */ +#define SET_DRENR_ADE_VALUE DRENR_ADE_ADD23_OUT +#define SET_DREAR_EAC_VALUE DREAR_EAC_EXADDR24 +/* In the case of addr width 32bit */ +/* #define SET_DRENR_ADE_VALUE DRENR_ADE_ADD31_OUT */ +/* #define SET_DREAR_EAC_VALUE DREAR_EAC_EXADDR25 */ + +/* In the case of bit width 1-1-1 and addr width 24bit */ +/* #define SET_DRCMR_CMD_VALUE DRCMR_CMD_FAST_READ_3B */ +/* #define SET_DRENR_ADB_VALUE DRENR_ADB_1BIT */ +/* #define SET_DRENR_DRDB_VALUE DRENR_DRDB_1BIT */ +/* In the case of bit width 1-1-4 and addr width 24bit */ +/* #define SET_DRCMR_CMD_VALUE DRCMR_CMD_QUAD_OUTPUT_FAST_READ_3B */ +/* #define SET_DRENR_ADB_VALUE DRENR_ADB_1BIT */ +/* #define SET_DRENR_DRDB_VALUE DRENR_DRDB_4BIT */ +/* In the case of bit width 1-4-4 and addr width 24bit */ +#define SET_DRCMR_CMD_VALUE DRCMR_CMD_QUAD_INPUT_OUTPUT_FAST_READ_3B +#define SET_DRENR_ADB_VALUE DRENR_ADB_4BIT +#define SET_DRENR_DRDB_VALUE DRENR_DRDB_4BIT + +/* In the case of bit width 1-1-1 and addr width 32bit */ +/* #define SET_DRCMR_CMD_VALUE DRCMR_CMD_FAST_READ_4B */ +/* #define SET_DRENR_ADB_VALUE DRENR_ADB_1BIT */ +/* #define SET_DRENR_DRDB_VALUE DRENR_DRDB_1BIT */ +/* In the case of bit width 1-1-4 and addr width 32bit */ +/* #define SET_DRCMR_CMD_VALUE DRCMR_CMD_QUAD_OUTPUT_FAST_READ_4B */ +/* #define SET_DRENR_ADB_VALUE DRENR_ADB_1BIT */ +/* #define SET_DRENR_DRDB_VALUE DRENR_DRDB_4BIT */ +/* In the case of bit width 1-4-4 and addr width 32bit */ +/* #define SET_DRCMR_CMD_VALUE DRCMR_CMD_QUAD_INPUT_OUTPUT_FAST_READ_4B*/ +/* #define SET_DRENR_ADB_VALUE DRENR_ADB_4BIT */ +/* #define SET_DRENR_DRDB_VALUE DRENR_DRDB_4BIT */ + +/* dummy cycle SPI_MULTI_DUMMY_1CYCLE - SPI_MULTI_DUMMY_20CYCLE */ +#define SET_DRDMCR_VALUE SPI_MULTI_DUMMY_10CYCLE + +/* SDR mode serial flash settings */ +#define SPIM_PHYCNT_SET_VALUE (PHYCNT_DEF_DATA | PHYCNT_PHYMEM_SDR_MODE | \ + PHYCNT_WBUF_NOT_USED | PHYCNT_WBUF2_NOT_USED | \ + PHYCNT_CKSEL_SLOW | PHYCNT_HS_OTHER_MODE | \ + PHYCNT_OCT_OTHER_MODE | PHYCNT_EXDS_NOT_USED | \ + PHYCNT_OCTA_HYPER_FLASH | PHYCNT_ALT_ALIGN_NOT_SUPPORTED | \ + PHYCNT_CAL_NOT_PERFOMED) +#define SPIM_PHYCNT_SDR_TIM_ADJ_SET_VALUE (SPIM_PHYCNT_SET_VALUE | PHYCNT_CKSEL_FAST) + +/* Read timing setting */ +#define SPIM_PHYOFFSET1_SET_VALUE (PHYOFFSET1_DEF_DATA | PHYOFFSET1_DDRTMG_SPIDRE_0) +#define SPIM_PHYOFFSET2_SET_VALUE (PHYOFFSET2_DEF_DATA | PHYOFFSET2_OCTTMG_HYPER_FLASH) + +/* Set the QSPIn_SSL setting value */ +#define SPIM_CMNCR_EXTREAD_SET_VALUE (CMNCR_IO0FV_OUT_PREV | CMNCR_IO2FV_OUT_PREV | \ + CMNCR_IO3FV_OUT_PREV | CMNCR_MOIIO0_OUT1 | \ + CMNCR_MOIIO1_OUT1 | CMNCR_MOIIO2_OUT1 | \ + CMNCR_MOIIO3_OUT1 | CMNCR_DEF_DATA | \ + CMNCR_MD_EXT_READ) + +#define SPIM_CMNCR_MANUAL_SET_VALUE (CMNCR_IO0FV_OUT_PREV | CMNCR_IO2FV_OUT_PREV | \ + CMNCR_IO3FV_OUT_PREV | CMNCR_MOIIO0_OUT1 | \ + CMNCR_MOIIO1_OUT1 | CMNCR_MOIIO2_OUT1 | \ + CMNCR_MOIIO3_OUT1 | CMNCR_DEF_DATA | \ + CMNCR_MD_MANUAL) +/* Set SSL delay setting value */ +#define SPIM_SSLDR_SET_VALUE (SSLDR_SCKDL_4_5 | SSLDR_SLNDL_4QSPIn | SSLDR_SPNDL_4QSPIn) + +/* Set the RBE bit and RCF bit and RBURST */ +#define SPIM_DRCR_SET_VALUE (DRCR_RBE | DRCR_RCF | DRCR_RBURST_32_DATALEN) + +/* Set the data read command */ +#define SPIM_DRCMR_SET_VALUE (SET_DRCMR_CMD_VALUE) + +/* Extended external address setting */ +#define SPIM_DREAR_SET_VALUE (SET_DREAR_EAC_VALUE) + +/* Set the bit width of command and address output to 1 bit and */ +/* the address size to 4 byte */ +#define SPIM_DRENR_SET_VALUE (DRENR_CDB_1BIT | DRENR_OCDB_1BIT | SET_DRENR_ADB_VALUE | \ + DRENR_OPDB_1BIT | SET_DRENR_DRDB_VALUE | DRENR_CDE | DRENR_DME | \ + SET_DRENR_ADE_VALUE | DRENR_OPDE_NO_OUT) +/* Dummy cycle setting */ +#define SPIM_DRDMCR_SET_VALUE (SET_DRDMCR_VALUE) + +/* Change to SPI flash mode */ +#define SPIM_DRDRENR_SET_VALUE (DRDRENR_DRDRE_SDR | DRDRENR_OPDRE_SDR | \ + DRDRENR_ADDRE_SDR | DRDRENR_HYPE_SPI) +/* Set the SDR transfer & SPI flash mode */ +#define SPIM_SMDRENR_SET_VALUE (SMDRENR_HYPE_SPI_FLASH) +/* Manual Command */ +#define SMCMR_CMD_READ_STATUS_REGISTER (0x05) +#define SMCMR_CMD_BIT_SHIFT (16) +#define SMWDR0_1BYTE_DATA_BIT_SHIFT (24) + +/* Manual Command Configure Length */ +#define SPI_MANUAL_COMMAND_SIZE_0 SMENR_SPIDE_NO_SEND +#define SPI_MANUAL_COMMAND_SIZE_8_BIT SMENR_SPIDE_8BIT_SEND +#define SPI_MANUAL_COMMAND_SIZE_16_BIT SMENR_SPIDE_16BIT_SEND +#define SPI_MANUAL_COMMAND_SIZE_32_BIT SMENR_SPIDE_32BIT_SEND + +#endif /* _SPI_MULTI_REG_VALUES_H_ */ diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/include/drivers/spi_multi/spi_multi.h b/drivers/rz/ipl/rza/plat/renesas/rz/common/include/drivers/spi_multi/spi_multi.h new file mode 100644 index 00000000..1433e908 --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/include/drivers/spi_multi/spi_multi.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _SPI_MULTI_H_ +#define _SPI_MULTI_H_ + +#define SPI_MULTI_ADDR_WIDES_24 (0) +#define SPI_MULTI_ADDR_WIDES_32 (1) + +#define SPI_MULTI_DQ_WIDES_1_1_1 (0) +#define SPI_MULTI_DQ_WIDES_1_1_4 (1) +#define SPI_MULTI_DQ_WIDES_1_4_4 (2) + +#define SPI_MULTI_DUMMY_2CYCLE (1) +#define SPI_MULTI_DUMMY_3CYCLE (2) +#define SPI_MULTI_DUMMY_4CYCLE (3) +#define SPI_MULTI_DUMMY_5CYCLE (4) +#define SPI_MULTI_DUMMY_6CYCLE (5) +#define SPI_MULTI_DUMMY_7CYCLE (6) +#define SPI_MULTI_DUMMY_8CYCLE (7) +#define SPI_MULTI_DUMMY_9CYCLE (8) +#define SPI_MULTI_DUMMY_10CYCLE (9) +#define SPI_MULTI_DUMMY_11CYCLE (10) +#define SPI_MULTI_DUMMY_12CYCLE (11) +#define SPI_MULTI_DUMMY_13CYCLE (12) +#define SPI_MULTI_DUMMY_14CYCLE (13) +#define SPI_MULTI_DUMMY_15CYCLE (14) +#define SPI_MULTI_DUMMY_16CYCLE (15) +#define SPI_MULTI_DUMMY_17CYCLE (16) +#define SPI_MULTI_DUMMY_18CYCLE (17) +#define SPI_MULTI_DUMMY_19CYCLE (18) +#define SPI_MULTI_DUMMY_20CYCLE (19) + +#define SPI_MULTI_SUCCESS (0) +#define SPI_MULTI_ERROR (-1) + +int spi_multi_setup(void); +void spi_multi_setup_device(void); +void spi_multi_timing_set(void); +uint8_t spi_multi_cmd_read(uint8_t command); +void spi_multi_cmd_write(uint8_t command,uint8_t size,uint32_t data); + +#endif /* _SPI_MULTI_H_ */ diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/include/drivers/spi_multi/spi_multi_regs.h b/drivers/rz/ipl/rza/plat/renesas/rz/common/include/drivers/spi_multi/spi_multi_regs.h new file mode 100644 index 00000000..e795b418 --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/include/drivers/spi_multi/spi_multi_regs.h @@ -0,0 +1,256 @@ +/* + * Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _SPI_MULTI_REG_H_ +#define _SPI_MULTI_REG_H_ + +#define SPI_MULTI_BASE (0x10060000) +#define SPI_MULTI_BUF (0x10070000) + +#define SPIM_CMNCR (SPI_MULTI_BASE + 0x00000000) /* Common control register */ +#define SPIM_SSLDR (SPI_MULTI_BASE + 0x00000004) /* SSL delay register */ +#define SPIM_DRCR (SPI_MULTI_BASE + 0x0000000C) /* Data read control register */ +#define SPIM_DRCMR (SPI_MULTI_BASE + 0x00000010) /* Data read command setting register */ +#define SPIM_DREAR (SPI_MULTI_BASE + 0x00000014) /* Data read extended address setting register */ +#define SPIM_DROPR (SPI_MULTI_BASE + 0x00000018) /* Data read option setting register */ +#define SPIM_DRENR (SPI_MULTI_BASE + 0x0000001C) /* Data read enable setting register */ +#define SPIM_SMCR (SPI_MULTI_BASE + 0x00000020) /* Manual mode control register */ +#define SPIM_SMCMR (SPI_MULTI_BASE + 0x00000024) /* Manual mode command setting register */ +#define SPIM_SMADR (SPI_MULTI_BASE + 0x00000028) /* Manual mode address setting register */ +#define SPIM_SMOPR (SPI_MULTI_BASE + 0x0000002C) /* Manual mode option setting register */ +#define SPIM_SMENR (SPI_MULTI_BASE + 0x00000030) /* Manual mode enable setting register */ +#define SPIM_SMRDR0 (SPI_MULTI_BASE + 0x00000038) /* Manual mode read data register 0 */ +#define SPIM_SMRDR1 (SPI_MULTI_BASE + 0x0000003C) /* Manual mode read data register 1 */ +#define SPIM_SMWDR0 (SPI_MULTI_BASE + 0x00000040) /* Manual mode write data register 0 */ +#define SPIM_SMWDR1 (SPI_MULTI_BASE + 0x00000044) /* Manual mode write data register 1 */ +#define SPIM_CMNSR (SPI_MULTI_BASE + 0x00000048) /* Common status register */ +#define SPIM_DRDMCR (SPI_MULTI_BASE + 0x00000058) /* Data read dummy cycle setting register */ +#define SPIM_DRDRENR (SPI_MULTI_BASE + 0x0000005C) /* Data read DDR enable register */ +#define SPIM_SMDMCR (SPI_MULTI_BASE + 0x00000060) /* Manual mode dummy cycle setting register */ +#define SPIM_SMDRENR (SPI_MULTI_BASE + 0x00000064) /* Manual mode DDR enable register */ +#define SPIM_PHYCNT (SPI_MULTI_BASE + 0x0000007C) /* PHY control register */ +#define SPIM_PHYOFFSET1 (SPI_MULTI_BASE + 0x00000080) /* PHY offset register 1 */ +#define SPIM_PHYOFFSET2 (SPI_MULTI_BASE + 0x00000084) /* PHY offset register 2 */ +#define SPIM_PHYINT (SPI_MULTI_BASE + 0x00000088) /* PHY interrupt register */ +#define SPIM_PHYADJ1 (SPI_MULTI_BASE + 0x00000070) /* PHY adjustment register 1 */ +#define SPIM_PHYADJ2 (SPI_MULTI_BASE + 0x00000074) /* PHY adjustment register 2 */ + +#define CMNCR_BSZ_FLASH_NUM_1 (0 << 0) +#define CMNCR_BSZ_FLASH_NUM_2 (1 << 0) +#define CMNCR_IO0FV_OUT0 (0 << 8) +#define CMNCR_IO0FV_OUT1 (1 << 8) +#define CMNCR_IO0FV_OUT_PREV (2 << 8) +#define CMNCR_IO0FV_HIZ (3 << 8) +#define CMNCR_IO2FV_OUT0 (0 << 12) +#define CMNCR_IO2FV_OUT1 (1 << 12) +#define CMNCR_IO2FV_OUT_PREV (2 << 12) +#define CMNCR_IO2FV_HIZ (3 << 12) +#define CMNCR_IO3FV_OUT0 (0 << 14) +#define CMNCR_IO3FV_OUT1 (1 << 14) +#define CMNCR_IO3FV_OUT_PREV (2 << 14) +#define CMNCR_IO3FV_HIZ (3 << 14) +#define CMNCR_DEF_DATA (1 << 24) +#define CMNCR_MOIIO0_OUT0 (0 << 16) +#define CMNCR_MOIIO0_OUT1 (1 << 16) +#define CMNCR_MOIIO0_OUT_PREV (2 << 16) +#define CMNCR_MOIIO0_HIZ (3 << 16) +#define CMNCR_MOIIO1_OUT0 (0 << 18) +#define CMNCR_MOIIO1_OUT1 (1 << 18) +#define CMNCR_MOIIO1_OUT_PREV (2 << 18) +#define CMNCR_MOIIO1_HIZ (3 << 18) +#define CMNCR_MOIIO2_OUT0 (0 << 20) +#define CMNCR_MOIIO2_OUT1 (1 << 20) +#define CMNCR_MOIIO2_OUT_PREV (2 << 20) +#define CMNCR_MOIIO2_HIZ (3 << 20) +#define CMNCR_MOIIO3_OUT0 (0 << 22) +#define CMNCR_MOIIO3_OUT1 (1 << 22) +#define CMNCR_MOIIO3_OUT_PREV (2 << 22) +#define CMNCR_MOIIO3_HIZ (3 << 22) +#define CMNCR_MD_MANUAL (U(1) << 31) +#define CMNCR_MD_EXT_READ (0 << 31) +#define SSLDR_SCKDL_1_5 (0 << 0) +#define SSLDR_SCKDL_2_5 (1 << 0) +#define SSLDR_SCKDL_3_5 (2 << 0) +#define SSLDR_SCKDL_4_5 (3 << 0) +#define SSLDR_SCKDL_5_5 (4 << 0) +#define SSLDR_SCKDL_6_5 (5 << 0) +#define SSLDR_SCKDL_7_5 (6 << 0) +#define SSLDR_SCKDL_8_5 (7 << 0) +#define SSLDR_SLNDL_1QSPIn (0 << 8) +#define SSLDR_SLNDL_2QSPIn (1 << 8) +#define SSLDR_SLNDL_3QSPIn (2 << 8) +#define SSLDR_SLNDL_4QSPIn (3 << 8) +#define SSLDR_SLNDL_5QSPIn (4 << 8) +#define SSLDR_SLNDL_6QSPIn (5 << 8) +#define SSLDR_SLNDL_7QSPIn (6 << 8) +#define SSLDR_SLNDL_8QSPIn (7 << 8) +#define SSLDR_SPNDL_1QSPIn (0 << 16) +#define SSLDR_SPNDL_2QSPIn (1 << 16) +#define SSLDR_SPNDL_3QSPIn (2 << 16) +#define SSLDR_SPNDL_4QSPIn (3 << 16) +#define SSLDR_SPNDL_5QSPIn (4 << 16) +#define SSLDR_SPNDL_6QSPIn (5 << 16) +#define SSLDR_SPNDL_7QSPIn (6 << 16) +#define SSLDR_SPNDL_8QSPIn (7 << 16) +#define DRCR_SSLE (1 << 0) +#define DRCR_RBE (1 << 8) +#define DRCR_RCF (1 << 9) +#define DRCR_RBURST_1_DATALEN (0 << 16) +#define DRCR_RBURST_2_DATALEN (1 << 16) +#define DRCR_RBURST_3_DATALEN (2 << 16) +#define DRCR_RBURST_4_DATALEN (3 << 16) +#define DRCR_RBURST_5_DATALEN (4 << 16) +#define DRCR_RBURST_6_DATALEN (5 << 16) +#define DRCR_RBURST_7_DATALEN (6 << 16) +#define DRCR_RBURST_8_DATALEN (7 << 16) +#define DRCR_RBURST_9_DATALEN (8 << 16) +#define DRCR_RBURST_10_DATALEN (9 << 16) +#define DRCR_RBURST_11_DATALEN (10 << 16) +#define DRCR_RBURST_12_DATALEN (11 << 16) +#define DRCR_RBURST_13_DATALEN (12 << 16) +#define DRCR_RBURST_14_DATALEN (13 << 16) +#define DRCR_RBURST_15_DATALEN (14 << 16) +#define DRCR_RBURST_16_DATALEN (15 << 16) +#define DRCR_RBURST_17_DATALEN (16 << 16) +#define DRCR_RBURST_18_DATALEN (17 << 16) +#define DRCR_RBURST_19_DATALEN (18 << 16) +#define DRCR_RBURST_20_DATALEN (19 << 16) +#define DRCR_RBURST_21_DATALEN (20 << 16) +#define DRCR_RBURST_22_DATALEN (21 << 16) +#define DRCR_RBURST_23_DATALEN (22 << 16) +#define DRCR_RBURST_24_DATALEN (23 << 16) +#define DRCR_RBURST_25_DATALEN (24 << 16) +#define DRCR_RBURST_26_DATALEN (25 << 16) +#define DRCR_RBURST_27_DATALEN (26 << 16) +#define DRCR_RBURST_28_DATALEN (27 << 16) +#define DRCR_RBURST_29_DATALEN (28 << 16) +#define DRCR_RBURST_30_DATALEN (29 << 16) +#define DRCR_RBURST_31_DATALEN (30 << 16) +#define DRCR_RBURST_32_DATALEN (31 << 16) +#define DRCR_SSLN (1 << 24) +#define DREAR_EAC_EXADDR24 (0 << 0) +#define DREAR_EAC_EXADDR25 (1 << 0) +#define DREAR_EAC_EXADDR26 (2 << 0) +#define DREAR_EAC_EXADDR27 (3 << 0) +#define DRENR_OPDE_NO_OUT (0 << 4) +#define DRENR_OPDE_OPD3_OUT (8 << 4) +#define DRENR_OPDE_OPD32_OUT (12 << 4) +#define DRENR_OPDE_OPD321_OUT (14 << 4) +#define DRENR_OPDE_OPD3210_OUT (15 << 4) +#define DRENR_ADE_NO_OUT (0 << 8) +#define DRENR_ADE_ADD23_OUT (7 << 8) +#define DRENR_ADE_ADD31_OUT (15 << 8) +#define DRENR_ADE_OCTA_FLASH (12 << 8) +#define DRENR_ADE_HYPER_FLASH (4 << 8) +#define DRENR_OCDE (1 << 12) +#define DRENR_CDE (1 << 14) +#define DRENR_DME (1 << 15) +#define DRENR_DRDB_1BIT (0 << 16) +#define DRENR_DRDB_4BIT (2 << 16) +#define DRENR_OPDB_1BIT (0 << 20) +#define DRENR_OPDB_4BIT (2 << 20) +#define DRENR_ADB_1BIT (0 << 24) +#define DRENR_ADB_4BIT (2 << 24) +#define DRENR_OCDB_1BIT (0 << 28) +#define DRENR_OCDB_4BIT (2 << 28) +#define DRENR_CDB_1BIT (0 << 30) +/* #define DRENR_CDB_4BIT (2 << 30) */ +#define DRENR_CDB_4BIT (0x80000000) +#define SMCR_SPIE (1 << 0) +#define SMCR_SPIWE (1 << 1) +#define SMCR_SPIRE (1 << 2) +#define SMCR_SSLKP (1 << 8) +#define SMENR_SPIDE_NO_SEND (0 << 0) +#define SMENR_SPIDE_8BIT_SEND (8 << 0) +#define SMENR_SPIDE_16BIT_SEND (12 << 0) +#define SMENR_SPIDE_32BIT_SEND (15 << 0) +#define SMENR_OPDE_NO_OUT (0 << 4) +#define SMENR_OPDE_OPD3_OUT (8 << 4) +#define SMENR_OPDE_OPD32_OUT (12 << 4) +#define SMENR_OPDE_OPD321_OUT (14 << 4) +#define SMENR_OPDE_OPD3210_OUT (15 << 4) +#define SMENR_ADE_NO_OUT (0 << 8) +#define SMENR_ADE_ADR23_16_OUT (4 << 8) +#define SMENR_ADE_ADR23_8_OUT (6 << 8) +#define SMENR_ADE_ADR23_0_OUT (7 << 8) +#define SMENR_ADE_ADR31_0_OUT (15 << 8) +#define SMENR_OCDE (1 << 12) +#define SMENR_CDE (1 << 14) +#define SMENR_DME (1 << 15) +#define SMENR_SPIDB_1BIT (0 << 16) +#define SMENR_SPIDB_4BIT (2 << 16) +#define SMENR_OPDB_1BIT (0 << 20) +#define SMENR_OPDB_4BIT (2 << 20) +#define SMENR_ADB_1BIT (0 << 24) +#define SMENR_ADB_4BIT (2 << 24) +#define SMENR_OCDB_1BIT (0 << 28) +#define SMENR_OCDB_4BIT (2 << 28) +#define SMENR_CDB_1BIT (0 << 30) +#define SMENR_CDB_4BIT (U(2) << 30) +#define CMNSR_TEND (1 << 0) +#define CMNSR_SSLF (1 << 1) +#define DRDRENR_DRDRE_DDR (1 << 0) +#define DRDRENR_DRDRE_SDR (0 << 0) +#define DRDRENR_OPDRE_DDR (1 << 4) +#define DRDRENR_OPDRE_SDR (0 << 4) +#define DRDRENR_ADDRE_DDR (1 << 8) +#define DRDRENR_ADDRE_SDR (0 << 8) +#define DRDRENR_HYPE_HYPER (5 << 12) +#define DRDRENR_HYPE_OCTA (4 << 12) +#define DRDRENR_HYPE_SPI (0 << 12) +#define SMDRENR_SPIDRE (1 << 0) +#define SMDRENR_OPDRE (1 << 4) +#define SMDRENR_ADDRE (1 << 8) +#define SMDRENR_HYPE_HYPER_FLASH (5 << 12) +#define SMDRENR_HYPE_OCTA_FLASH (4 << 12) +#define SMDRENR_HYPE_SPI_FLASH (0 << 12) +#define PHYCNT_PHYMEM_SDR_MODE (0 << 0) +#define PHYCNT_PHYMEM_DDR_MODE (1 << 0) +#define PHYCNT_PHYMEM_HYPER_FLASH (3 << 0) +#define PHYCNT_WBUF_USED (1 << 2) +#define PHYCNT_WBUF_NOT_USED (0 << 2) +#define PHYCNT_WBUF2_USED (1 << 4) +#define PHYCNT_WBUF2_NOT_USED (0 << 4) +#define PHYCNT_CKSEL_SLOW (0 << 16) +#define PHYCNT_CKSEL_FAST (3 << 16) +#define PHYCNT_HS_MODE (1 << 18) +#define PHYCNT_HS_OTHER_MODE (0 << 18) +#define PHYCNT_OCT_MODE (1 << 20) +#define PHYCNT_OCT_OTHER_MODE (0 << 20) +#define PHYCNT_EXDS_USED (1 << 21) +#define PHYCNT_EXDS_NOT_USED (0 << 21) +#define PHYCNT_OCTA_HYPER_FLASH (0 << 22) +#define PHYCNT_OCTA_ALTE (1 << 22) +#define PHYCNT_OCTA_ORDER (2 << 22) +#define PHYCNT_ALT_ALIGN_SUPPORTED (1 << 30) +#define PHYCNT_ALT_ALIGN_NOT_SUPPORTED (0 << 30) +#define PHYCNT_CAL_PERFOMED (U(1) << 31) +#define PHYCNT_CAL_NOT_PERFOMED (0 << 31) +#define PHYCNT_DEF_DATA (0x00000260) +#define PHYOFFSET1_DDRTMG_SPIDRE_1 (2 << 28) +#define PHYOFFSET1_DDRTMG_SPIDRE_0 (3 << 28) +#define PHYOFFSET1_DEF_DATA (0x01511144) +#define PHYOFFSET2_OCTTMG_HYPER_FLASH (4 << 8) +#define PHYOFFSET2_OCTTMG_OCTA_FLASH (3 << 8) +#define PHYOFFSET2_DEF_DATA (0x00000031) +#define PHYINT_INT (1 << 0) +#define PHYINT_WPVAL (1 << 1) +#define PHYINT_RSTVAL (1 << 2) +#define PHYINT_INTEN (1 << 24) +#define PHYINT_WPEN (1 << 25) +#define PHYINT_RSTEN (1 << 26) + +#define DREAR_EAV_ADDRE_DATA (2 << 16) + +#define DRCMR_CMD_FAST_READ_3B (0x0B << 16) +#define DRCMR_CMD_QUAD_OUTPUT_FAST_READ_3B (0x6B << 16) +#define DRCMR_CMD_QUAD_INPUT_OUTPUT_FAST_READ_3B (0xEB << 16) +#define DRCMR_CMD_FAST_READ_4B (0x0C << 16) +#define DRCMR_CMD_QUAD_OUTPUT_FAST_READ_4B (0x6C << 16) +#define DRCMR_CMD_QUAD_INPUT_OUTPUT_FAST_READ_4B (0xEC << 16) + +#endif /* _SPI_MULTI_REG_H_ */ + diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/include/octa.h b/drivers/rz/ipl/rza/plat/renesas/rz/common/include/octa.h new file mode 100644 index 00000000..ed0e4afe --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/include/octa.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _OCTA_API_H_ +#define _OCTA_API_H_ +#include +#include + +#include "xspi_api.h" + +/** xSPI device control structure */ +typedef struct st_octa_ctrl +{ + bool opened; + uint8_t device_type; + uintptr_t reg_base; + uintptr_t mmap_base; + uint32_t calibration_base; + size_t mmap_size; + uint8_t channel; +} octa_ctrl_t; + +/** xSPI device extended configuration structure */ +typedef struct st_octa_ext +{ + uint32_t device_size; + uint32_t calibration_base; +} octa_ext_t; + +extern const xspi_api_t octa_api; + +#endif /* _OCTA_API_H_ */ + diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/include/octa_regs.h b/drivers/rz/ipl/rza/plat/renesas/rz/common/include/octa_regs.h new file mode 100644 index 00000000..4d128fdc --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/include/octa_regs.h @@ -0,0 +1,279 @@ +/* + * Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _OCTA_REG_H_ +#define _OCTA_REG_H_ + +#define OCTA_DCR 0x0000 /* Device command register */ +#define OCTA_DAR 0x0004 /* Device address register */ +#define OCTA_DCSR 0x0008 /* Device command setting register */ +#define OCTA_DSR0 0x000C /* Device size register 0 */ +#define OCTA_DSR1 0x0010 /* Device size register 1 */ +#define OCTA_MDTR 0x0014 /* Memory delay trim register */ +#define OCTA_ACTR 0x0018 /* Auto-calibration timer register */ +#define OCTA_ACAR0 0x001C /* Auto-calibration address register 0 */ +#define OCTA_ACAR1 0x0020 /* Auto-calibration address register 1 */ +#define OCTA_DRCSTR 0x0034 /* Device memory map read chip select timing setting register */ +#define OCTA_DWCSTR 0x0038 /* Device memory map write chip select timing setting register */ +#define OCTA_DCSTR 0x003C /* Device chip select timing setting register */ +#define OCTA_CDSR 0x0040 /* Controller and device setting register */ +#define OCTA_MDLR 0x0044 /* Memory map dummy length register */ +#define OCTA_MRWCR0 0x0048 /* Memory map read/write command register 0 */ +#define OCTA_MRWCR1 0x004C /* Memory map read/write command register 1 */ +#define OCTA_MRWCSR 0x0050 /* Memory map read/write setting register */ +#define OCTA_ESR 0x0054 /* Error status register */ +#define OCTA_CWNDR 0x0058 /* Configure write without data register */ +#define OCTA_CWDR 0x005C /* Configure write data register */ +#define OCTA_CRR 0x0060 /* Configure read register */ +#define OCTA_RSTCNT 0x0080 /* Device reset register */ +#define OCTA_AER 0x0084 /* Address extend register */ + +/* DCR field */ +#define OCTA_DCR_DVCMD1_POS (8UL) +#define OCTA_DCR_DVCMD1 (0xFFUL << OCTA_DCR_DVCMD1_POS) +#define OCTA_DCR_DVCMD0_POS (0UL) +#define OCTA_DCR_DVCMD0 (0xFFUL << OCTA_DCR_DVCMD0_POS) + +/* DAR field */ +#define OCTA_DAR_DVAD3_POS (24UL) +#define OCTA_DAR_DVAD3 (0xFFUL << OCTA_DAR_DVAD3_POS) +#define OCTA_DAR_DVAD2_POS (16UL) +#define OCTA_DAR_DVAD2 (0xFFUL << OCTA_DAR_DVAD2_POS) +#define OCTA_DAR_DVAD1_POS (8UL) +#define OCTA_DAR_DVAD1 (0xFFUL << OCTA_DAR_DVAD1_POS) +#define OCTA_DAR_DVAD0_POS (0UL) +#define OCTA_DAR_DVAD0 (0xFFUL << OCTA_DAR_DVAD0_POS) + +/* DCSR field */ +#define OCTA_DCSR_ACDA_POS (28UL) +#define OCTA_DCSR_ACDA (0x1UL << OCTA_DCSR_ACDA_POS) +#define OCTA_DCSR_DOPI_POS (27UL) +#define OCTA_DCSR_DOPI (0x1UL << OCTA_DCSR_DOPI_POS) +#define OCTA_DCSR_ADLEN_POS (24UL) +#define OCTA_DCSR_ADLEN (0x7UL << OCTA_DCSR_ADLEN_POS) +#define OCTA_DCSR_DAOR_POS (23UL) +#define OCTA_DCSR_DAOR (0x1UL << OCTA_DCSR_DAOR_POS) +#define OCTA_DCSR_CMDLEN_POS (20UL) +#define OCTA_DCSR_CMDLEN (0x7UL << OCTA_DCSR_CMDLEN_POS) +#define OCTA_DCSR_ACDV_POS (19UL) +#define OCTA_DCSR_ACDV (0x1UL << OCTA_DCSR_ACDV_POS) +#define OCTA_DCSR_DMLEN_POS (8UL) +#define OCTA_DCSR_DMLEN (0xFFUL << OCTA_DCSR_DMLEN_POS) +#define OCTA_DCSR_DALEN_POS (0UL) +#define OCTA_DCSR_DALEN (0xFFUL << OCTA_DCSR_DALEN_POS) + +/* DSR0 field */ +#define OCTA_DSR0_DV0TYP_POS (30UL) +#define OCTA_DSR0_DV0TYP (0x3UL << OCTA_DSR0_DV0TYP_POS) +#define OCTA_DSR0_DV0SZ_POS (0UL) +#define OCTA_DSR0_DV0SZ (0x3FFFFFFFUL << OCTA_DSR0_DV0SZ_POS) +#define OCTA_DSR_TYP_FLASH 0u +#define OCTA_DSR_TYP_RAM 1u +#define OCTA_DSR_TYP_NONE 2u + +/* DSR1 field */ +#define OCTA_DSR1_DV1TYP_POS (30UL) +#define OCTA_DSR1_DV1TYP (0x3UL << OCTA_DSR1_DV1TYP_POS) +#define OCTA_DSR1_DV1SZ_POS (0UL) +#define OCTA_DSR1_DV1SZ (0x3FFFFFFFUL << OCTA_DSR1_DV1SZ_POS) + +/* MDTR field */ +#define OCTA_MDTR_DQSEDOPI_POS (24UL) +#define OCTA_MDTR_DQSEDOPI (0xFUL << OCTA_MDTR_DQSEDOPI_POS) +#define OCTA_MDTR_DV1DEL_POS (16UL) +#define OCTA_MDTR_DV1DEL (0xFFUL << OCTA_MDTR_DV1DEL_POS) +#define OCTA_MDTR_DQSESOPI_POS (12UL) +#define OCTA_MDTR_DQSESOPI (0xFUL << OCTA_MDTR_DQSESOPI_POS) +#define OCTA_MDTR_DQSERAM_POS (8UL) +#define OCTA_MDTR_DQSERAM (0xFUL << OCTA_MDTR_DQSERAM_POS) +#define OCTA_MDTR_DV0DEL_POS (0UL) +#define OCTA_MDTR_DV0DEL (0xFFUL << OCTA_MDTR_DV0DEL_POS) + +/* ACTR field */ +#define OCTA_ACTR_CTP_POS (0UL) +#define OCTA_ACTR_CTP (0xFFFFFFFFUL << OCTA_ACTR_CTP_POS) + +/* ACAR0 field */ +#define OCTA_ACAR0_CAD0_POS (0UL) +#define OCTA_ACAR0_CAD0 (0xFFFFFFFFUL << OCTA_ACAR0_CAD0_POS) + +/* ACAR1 field */ +#define OCTA_ACAR1_CAD1_POS (0UL) +#define OCTA_ACAR1_CAD1 (0xFFFFFFFFUL << OCTA_ACAR1_CAD1_POS) + +/* DRCSTR field */ +#define OCTA_DRCSTR_DVRDLO1_POS (30UL) +#define OCTA_DRCSTR_DVRDLO1 (0x3UL << OCTA_DRCSTR_DVRDLO1_POS) +#define OCTA_DRCSTR_DVRDHI1_POS (27UL) +#define OCTA_DRCSTR_DVRDHI1 (0x7UL << OCTA_DRCSTR_DVRDHI1_POS) +#define OCTA_DRCSTR_DVRDCMD1_POS (24UL) +#define OCTA_DRCSTR_DVRDCMD1 (0x7UL << OCTA_DRCSTR_DVRDCMD1_POS) +/* CTR1 and CTRW1 are not available in RZ */ +#define OCTA_DRCSTR_CTR1_POS (23UL) +#define OCTA_DRCSTR_CTR1 (0x1UL << OCTA_DRCSTR_CTR1_POS) +#define OCTA_DRCSTR_CTRW1_POS (16UL) +#define OCTA_DRCSTR_CTRW1 (0x7FUL << OCTA_DRCSTR_CTRW1_POS) +#define OCTA_DRCSTR_DVRDLO0_POS (14UL) +#define OCTA_DRCSTR_DVRDLO0 (0x3UL << OCTA_DRCSTR_DVRDLO0_POS) +#define OCTA_DRCSTR_DVRDHI0_POS (11UL) +#define OCTA_DRCSTR_DVRDHI0 (0x7UL << OCTA_DRCSTR_DVRDHI0_POS) +#define OCTA_DRCSTR_DVRDCMD0_POS (8UL) +#define OCTA_DRCSTR_DVRDCMD0 (0x7UL << OCTA_DRCSTR_DVRDCMD0_POS) +#define OCTA_DRCSTR_CTR0_POS (7UL) +#define OCTA_DRCSTR_CTR0 (0x1UL << OCTA_DRCSTR_CTR0_POS) +#define OCTA_DRCSTR_CTRW0_POS (0UL) +#define OCTA_DRCSTR_CTRW0 (0x7FUL << OCTA_DRCSTR_CTRW0_POS) + +/* DWCSTR field */ +#define OCTA_DWCSTR_DVWLO1_POS (30UL) +#define OCTA_DWCSTR_DVWLO1 (0x3UL << OCTA_DWCSTR_DVWLO1_POS) +#define OCTA_DWCSTR_DVWHI1_POS (27UL) +#define OCTA_DWCSTR_DVWHI1 (0x7UL << OCTA_DWCSTR_DVWHI1_POS) +#define OCTA_DWCSTR_DVWCMD1_POS (24UL) +#define OCTA_DWCSTR_DVWCMD1 (0x7UL << OCTA_DWCSTR_DVWCMD1_POS) +/* CTW1 and CTWW1 are not available in RZ */ +#define OCTA_DWCSTR_CTW1_POS (23UL) +#define OCTA_DWCSTR_CTW1 (0x1UL << OCTA_DWCSTR_CTW1_POS) +#define OCTA_DWCSTR_CTWW1_POS (16UL) +#define OCTA_DWCSTR_CTWW1 (0x7FUL << OCTA_DWCSTR_CTWW1_POS) +#define OCTA_DWCSTR_DVWLO0_POS (14UL) +#define OCTA_DWCSTR_DVWLO0 (0x3UL << OCTA_DWCSTR_DVWLO0_POS) +#define OCTA_DWCSTR_DVWHI0_POS (11UL) +#define OCTA_DWCSTR_DVWHI0 (0x7UL << OCTA_DWCSTR_DVWHI0_POS) +#define OCTA_DWCSTR_DVWCMD0_POS (8UL) +#define OCTA_DWCSTR_DVWCMD0 (0x7UL << OCTA_DWCSTR_DVWCMD0_POS) +/* CTW0 and CTWW0 are not available in RZ */ +#define OCTA_DWCSTR_CTW0_POS (7UL) +#define OCTA_DWCSTR_CTW0 (0x1UL << OCTA_DWCSTR_CTW0_POS) +#define OCTA_DWCSTR_CTWW0_POS (0UL) +#define OCTA_DWCSTR_CTWW0 (0x7FUL << OCTA_DWCSTR_CTWW0_POS) + +/* DCSTR field */ +#define OCTA_DCSTR_DVSELLO_POS (14UL) +#define OCTA_DCSTR_DVSELLO (0x3UL << OCTA_DCSTR_DVSELLO_POS) +#define OCTA_DCSTR_DVSELHI_POS (11UL) +#define OCTA_DCSTR_DVSELHI (0x7UL << OCTA_DCSTR_DVSELHI_POS) +#define OCTA_DCSTR_DVSELCMD_POS (8UL) +#define OCTA_DCSTR_DVSELCMD (0x7UL << OCTA_DCSTR_DVSELCMD_POS) + +/* CDSR field */ +#define OCTA_CDSR_DLFT_POS (31UL) +#define OCTA_CDSR_DLFT (0x1UL << OCTA_CDSR_DLFT_POS) +#define OCTA_CDSR_ACMODE_POS (12UL) +#define OCTA_CDSR_ACMODE (0x3UL << OCTA_CDSR_ACMODE_POS) +#define OCTA_CDSR_ACMODE_DISABLE 0u +#define OCTA_CDSR_ACMODE_ENABLE 1u +#define OCTA_CDSR_ACMEME1_POS (11UL) +#define OCTA_CDSR_ACMEME1 (0x1UL << OCTA_CDSR_ACMEME1_POS) +#define OCTA_CDSR_ACMEME0_POS (10UL) +#define OCTA_CDSR_ACMEME0 (0x1UL << OCTA_CDSR_ACMEME0_POS) +#define OCTA_CDSR_DV1PC_POS (5UL) +#define OCTA_CDSR_DV1PC (0x1UL << OCTA_CDSR_DV1PC_POS) +#define OCTA_CDSR_DV0PC_POS (4UL) +#define OCTA_CDSR_DV0PC (0x1UL << OCTA_CDSR_DV0PC_POS) +#define OCTA_CDSR_DV1TTYP_POS (2UL) +#define OCTA_CDSR_DV1TTYP (0x3UL << OCTA_CDSR_DV1TTYP_POS) +#define OCTA_CDSR_DV0TTYP_POS (0UL) +#define OCTA_CDSR_DV0TTYP (0x3UL << OCTA_CDSR_DV0TTYP_POS) +#define OCTA_CDSR_DVTTYP_SPI 0u +#define OCTA_CDSR_DVTTYP_SOPI 1u +#define OCTA_CDSR_DVTTYP_DOPI 2u + +/* MDLR field */ +#define OCTA_MDLR_DV1WDL_POS (24UL) +#define OCTA_MDLR_DV1WDL (0xFFUL << OCTA_MDLR_DV1WDL_POS) +#define OCTA_MDLR_DV1RDL_POS (16UL) +#define OCTA_MDLR_DV1RDL (0xFFUL << OCTA_MDLR_DV1RDL_POS) +#define OCTA_MDLR_DV0WDL_POS (8UL) +#define OCTA_MDLR_DV0WDL (0xFFUL << OCTA_MDLR_DV0WDL_POS) +#define OCTA_MDLR_DV0RDL_POS (0UL) +#define OCTA_MDLR_DV0RDL (0xFFUL << OCTA_MDLR_DV0RDL_POS) + +/* MRWCR0 field */ +#define OCTA_MRWCR0_D0MWCMD1_POS (24UL) +#define OCTA_MRWCR0_D0MWCMD1 (0xFFUL << OCTA_MRWCR0_D0MWCMD1_POS) +#define OCTA_MRWCR0_D0MWCMD0_POS (16UL) +#define OCTA_MRWCR0_D0MWCMD0 (0xFFUL << OCTA_MRWCR0_D0MWCMD0_POS) +#define OCTA_MRWCR0_D0MRCMD1_POS (8UL) +#define OCTA_MRWCR0_D0MRCMD1 (0xFFUL << OCTA_MRWCR0_D0MRCMD1_POS) +#define OCTA_MRWCR0_D0MRCMD0_POS (0UL) +#define OCTA_MRWCR0_D0MRCMD0 (0xFFUL << OCTA_MRWCR0_D0MRCMD0_POS) + +/* MRWCR1 field */ +#define OCTA_MRWCR1_D1MWCMD1_POS (24UL) +#define OCTA_MRWCR1_D1MWCMD1 (0xFFUL << OCTA_MRWCR1_D1MWCMD1_POS) +#define OCTA_MRWCR1_D1MWCMD0_POS (16UL) +#define OCTA_MRWCR1_D1MWCMD0 (0xFFUL << OCTA_MRWCR1_D1MWCMD0_POS) +#define OCTA_MRWCR1_D1MRCMD1_POS (8UL) +#define OCTA_MRWCR1_D1MRCMD1 (0xFFUL << OCTA_MRWCR1_D1MRCMD1_POS) +#define OCTA_MRWCR1_D1MRCMD0_POS (0UL) +#define OCTA_MRWCR1_D1MRCMD0 (0xFFUL << OCTA_MRWCR1_D1MRCMD0_POS) + +/* MRWCSR field */ +#define OCTA_MRWCSR_MWO1_POS (30UL) +#define OCTA_MRWCSR_MWO1 (0x1UL << OCTA_MRWCSR_MWO1_POS) +#define OCTA_MRWCSR_MWCL1_POS (27UL) +#define OCTA_MRWCSR_MWCL1 (0x7UL << OCTA_MRWCSR_MWCL1_POS) +#define OCTA_MRWCSR_MWAL1_POS (24UL) +#define OCTA_MRWCSR_MWAL1 (0x7UL << OCTA_MRWCSR_MWAL1_POS) +#define OCTA_MRWCSR_MRO1_POS (22UL) +#define OCTA_MRWCSR_MRO1 (0x1UL << OCTA_MRWCSR_MRO1_POS) +#define OCTA_MRWCSR_MRCL1_POS (19UL) +#define OCTA_MRWCSR_MRCL1 (0x7UL << OCTA_MRWCSR_MRCL1_POS) +#define OCTA_MRWCSR_MRAL1_POS (16UL) +#define OCTA_MRWCSR_MRAL1 (0x7UL << OCTA_MRWCSR_MRAL1_POS) +#define OCTA_MRWCSR_MWO0_POS (14UL) +#define OCTA_MRWCSR_MWO0 (0x1UL << OCTA_MRWCSR_MWO0_POS) +#define OCTA_MRWCSR_MWCL0_POS (11UL) +#define OCTA_MRWCSR_MWCL0 (0x7UL << OCTA_MRWCSR_MWCL0_POS) +#define OCTA_MRWCSR_MWAL0_POS (8UL) +#define OCTA_MRWCSR_MWAL0 (0x7UL << OCTA_MRWCSR_MWAL0_POS) +#define OCTA_MRWCSR_MRO0_POS (6UL) +#define OCTA_MRWCSR_MRO0 (0x1UL << OCTA_MRWCSR_MRO0_POS) +#define OCTA_MRWCSR_MRCL0_POS (3UL) +#define OCTA_MRWCSR_MRCL0 (0x7UL << OCTA_MRWCSR_MRCL0_POS) +#define OCTA_MRWCSR_MRAL0_POS (0UL) +#define OCTA_MRWCSR_MRAL0 (0x7UL << OCTA_MRWCSR_MRAL0_POS) + +/* ESR field */ +#define OCTA_ESR_MWESR_POS (8UL) +#define OCTA_ESR_MWESR (0xFFUL << OCTA_ESR_MWESR_POS) +#define OCTA_ESR_MRESR_POS (0UL) +#define OCTA_ESR_MRESR (0xFFUL << OCTA_ESR_MRESR_POS) + +/* CWDR field */ +#define OCTA_CWDR_WD3_POS (24UL) +#define OCTA_CWDR_WD3 (0xFFUL << OCTA_CWDR_WD3_POS) +#define OCTA_CWDR_WD2_POS (16UL) +#define OCTA_CWDR_WD2 (0xFFUL << OCTA_CWDR_WD2_POS) +#define OCTA_CWDR_WD1_POS (8UL) +#define OCTA_CWDR_WD1 (0xFFUL << OCTA_CWDR_WD1_POS) +#define OCTA_CWDR_WD0_POS (0UL) +#define OCTA_CWDR_WD0 (0xFFUL << OCTA_CWDR_WD0_POS) + +/* CRR field */ +#define OCTA_CRR_RD3_POS (24UL) +#define OCTA_CRR_RD3 (0xFFUL << OCTA_CRR_RD3_POS) +#define OCTA_CRR_RD2_POS (16UL) +#define OCTA_CRR_RD2 (0xFFUL << OCTA_CRR_RD2_POS) +#define OCTA_CRR_RD1_POS (8UL) +#define OCTA_CRR_RD1 (0xFFUL << OCTA_CRR_RD1_POS) +#define OCTA_CRR_RD0_POS (0UL) +#define OCTA_CRR_RD0 (0xFFUL << OCTA_CRR_RD0_POS) + +/* RSTCN field */ +#define OCTA_RSTCNT_RSTVAL_POS (0UL) +#define OCTA_RSTCNT_RSTVAL (0x1UL << OCTA_RSTCNT_RSTVAL_POS) + +/* AER field */ +#define OCTA_AER_POS (0UL) +#define OCTA_AER_LE64MB (0x0UL << OCTA_AER_POS) +#define OCTA_AER_128MB (0x1UL << OCTA_AER_POS) +#define OCTA_AER_256MB (0x3UL << OCTA_AER_POS) +#define OCTA_AER_512MB (0x7UL << OCTA_AER_POS) + +#endif /* _OCTA_REG_H_ */ + diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/include/pfc.h b/drivers/rz/ipl/rza/plat/renesas/rz/common/include/pfc.h new file mode 100644 index 00000000..499e347e --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/include/pfc.h @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __PFC_H__ +#define __PFC_H__ + +void pfc_setup(void); + + +#endif /* __PFC_H__ */ diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/include/pfc_regs.h b/drivers/rz/ipl/rza/plat/renesas/rz/common/include/pfc_regs.h new file mode 100644 index 00000000..cbed8d18 --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/include/pfc_regs.h @@ -0,0 +1,746 @@ +/* + * Copyright (c) 2020-2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __PFC_REGS_H__ +#define __PFC_REGS_H__ + +#define PFC_BASE (0x11030000) /* PFC base address */ + +#define PFC_P05 (PFC_BASE + 0x0005) /* Port register */ +#define PFC_P10 (PFC_BASE + 0x0010) /* Port register */ +#define PFC_P11 (PFC_BASE + 0x0011) /* Port register */ +#define PFC_P12 (PFC_BASE + 0x0012) /* Port register */ +#define PFC_P13 (PFC_BASE + 0x0013) /* Port register */ +#define PFC_P14 (PFC_BASE + 0x0014) /* Port register */ +#define PFC_P15 (PFC_BASE + 0x0015) /* Port register */ +#define PFC_P16 (PFC_BASE + 0x0016) /* Port register */ +#define PFC_P17 (PFC_BASE + 0x0017) /* Port register */ +#define PFC_P18 (PFC_BASE + 0x0018) /* Port register */ +#define PFC_P19 (PFC_BASE + 0x0019) /* Port register */ +#define PFC_P1A (PFC_BASE + 0x001A) /* Port register */ +#define PFC_P1B (PFC_BASE + 0x001B) /* Port register */ +#define PFC_P1C (PFC_BASE + 0x001C) /* Port register */ +#define PFC_P1D (PFC_BASE + 0x001D) /* Port register */ +#define PFC_P1E (PFC_BASE + 0x001E) /* Port register */ +#define PFC_P1F (PFC_BASE + 0x001F) /* Port register */ +#define PFC_P20 (PFC_BASE + 0x0020) /* Port register */ +#define PFC_P21 (PFC_BASE + 0x0021) /* Port register */ +#define PFC_P22 (PFC_BASE + 0x0022) /* Port register */ +#define PFC_P23 (PFC_BASE + 0x0023) /* Port register */ +#define PFC_P24 (PFC_BASE + 0x0024) /* Port register */ +#define PFC_P25 (PFC_BASE + 0x0025) /* Port register */ +#define PFC_P26 (PFC_BASE + 0x0026) /* Port register */ +#define PFC_P27 (PFC_BASE + 0x0027) /* Port register */ +#define PFC_P28 (PFC_BASE + 0x0028) /* Port register */ +#define PFC_P29 (PFC_BASE + 0x0029) /* Port register */ +#define PFC_P2A (PFC_BASE + 0x002A) /* Port register */ +#define PFC_P2B (PFC_BASE + 0x002B) /* Port register */ +#define PFC_P2C (PFC_BASE + 0x002C) /* Port register */ +#define PFC_P2D (PFC_BASE + 0x002D) /* Port register */ +#define PFC_P2E (PFC_BASE + 0x002E) /* Port register */ +#define PFC_P2F (PFC_BASE + 0x002F) /* Port register */ +#define PFC_P30 (PFC_BASE + 0x0030) /* Port register */ +#define PFC_P31 (PFC_BASE + 0x0031) /* Port register */ +#define PFC_P32 (PFC_BASE + 0x0032) /* Port register */ +#define PFC_P33 (PFC_BASE + 0x0033) /* Port register */ +#define PFC_P34 (PFC_BASE + 0x0034) /* Port register */ +#define PFC_P35 (PFC_BASE + 0x0035) /* Port register */ +#define PFC_P36 (PFC_BASE + 0x0036) /* Port register */ +#define PFC_P37 (PFC_BASE + 0x0037) /* Port register */ +#define PFC_P38 (PFC_BASE + 0x0038) /* Port register */ +#define PFC_P39 (PFC_BASE + 0x0039) /* Port register */ +#define PFC_P3A (PFC_BASE + 0x003A) /* Port register */ +#define PFC_P3B (PFC_BASE + 0x003B) /* Port register */ +#define PFC_P3C (PFC_BASE + 0x003C) /* Port register */ +#define PFC_P3D (PFC_BASE + 0x003D) /* Port register */ +#define PFC_P3E (PFC_BASE + 0x003E) /* Port register */ +#define PFC_P3F (PFC_BASE + 0x003F) /* Port register */ +#define PFC_P40 (PFC_BASE + 0x0040) /* Port register */ +#define PFC_PM10 (PFC_BASE + 0x0120) /* Port mode register */ +#define PFC_PM11 (PFC_BASE + 0x0122) /* Port mode register */ +#define PFC_PM12 (PFC_BASE + 0x0124) /* Port mode register */ +#define PFC_PM13 (PFC_BASE + 0x0126) /* Port mode register */ +#define PFC_PM14 (PFC_BASE + 0x0128) /* Port mode register */ +#define PFC_PM15 (PFC_BASE + 0x012A) /* Port mode register */ +#define PFC_PM16 (PFC_BASE + 0x012C) /* Port mode register */ +#define PFC_PM17 (PFC_BASE + 0x012E) /* Port mode register */ +#define PFC_PM18 (PFC_BASE + 0x0130) /* Port mode register */ +#define PFC_PM19 (PFC_BASE + 0x0132) /* Port mode register */ +#define PFC_PM1A (PFC_BASE + 0x0134) /* Port mode register */ +#define PFC_PM1B (PFC_BASE + 0x0136) /* Port mode register */ +#define PFC_PM1C (PFC_BASE + 0x0138) /* Port mode register */ +#define PFC_PM1D (PFC_BASE + 0x013A) /* Port mode register */ +#define PFC_PM1E (PFC_BASE + 0x013C) /* Port mode register */ +#define PFC_PM1F (PFC_BASE + 0x013E) /* Port mode register */ +#define PFC_PM20 (PFC_BASE + 0x0140) /* Port mode register */ +#define PFC_PM21 (PFC_BASE + 0x0142) /* Port mode register */ +#define PFC_PM22 (PFC_BASE + 0x0144) /* Port mode register */ +#define PFC_PM23 (PFC_BASE + 0x0146) /* Port mode register */ +#define PFC_PM24 (PFC_BASE + 0x0148) /* Port mode register */ +#define PFC_PM25 (PFC_BASE + 0x014A) /* Port mode register */ +#define PFC_PM26 (PFC_BASE + 0x014C) /* Port mode register */ +#define PFC_PM27 (PFC_BASE + 0x014E) /* Port mode register */ +#define PFC_PM28 (PFC_BASE + 0x0150) /* Port mode register */ +#define PFC_PM29 (PFC_BASE + 0x0152) /* Port mode register */ +#define PFC_PM2A (PFC_BASE + 0x0154) /* Port mode register */ +#define PFC_PM2B (PFC_BASE + 0x0156) /* Port mode register */ +#define PFC_PM2C (PFC_BASE + 0x0158) /* Port mode register */ +#define PFC_PM2D (PFC_BASE + 0x015A) /* Port mode register */ +#define PFC_PM2E (PFC_BASE + 0x015C) /* Port mode register */ +#define PFC_PM2F (PFC_BASE + 0x015E) /* Port mode register */ +#define PFC_PM30 (PFC_BASE + 0x0160) /* Port mode register */ +#define PFC_PM31 (PFC_BASE + 0x0162) /* Port mode register */ +#define PFC_PM32 (PFC_BASE + 0x0164) /* Port mode register */ +#define PFC_PM33 (PFC_BASE + 0x0166) /* Port mode register */ +#define PFC_PM34 (PFC_BASE + 0x0168) /* Port mode register */ +#define PFC_PM35 (PFC_BASE + 0x016A) /* Port mode register */ +#define PFC_PM36 (PFC_BASE + 0x016C) /* Port mode register */ +#define PFC_PM37 (PFC_BASE + 0x016E) /* Port mode register */ +#define PFC_PM38 (PFC_BASE + 0x0170) /* Port mode register */ +#define PFC_PM39 (PFC_BASE + 0x0172) /* Port mode register */ +#define PFC_PM3A (PFC_BASE + 0x0174) /* Port mode register */ +#define PFC_PM3B (PFC_BASE + 0x0176) /* Port mode register */ +#define PFC_PM3C (PFC_BASE + 0x0178) /* Port mode register */ +#define PFC_PM3D (PFC_BASE + 0x017A) /* Port mode register */ +#define PFC_PM3E (PFC_BASE + 0x017C) /* Port mode register */ +#define PFC_PM3F (PFC_BASE + 0x017E) /* Port mode register */ +#define PFC_PM40 (PFC_BASE + 0x0180) /* Port mode register */ +#define PFC_PMC04 (PFC_BASE + 0x0204) /* Port mode control register */ +#define PFC_PMC05 (PFC_BASE + 0x0205) /* Port mode control register */ +#define PFC_PMC10 (PFC_BASE + 0x0210) /* Port mode control register */ +#define PFC_PMC11 (PFC_BASE + 0x0211) /* Port mode control register */ +#define PFC_PMC12 (PFC_BASE + 0x0212) /* Port mode control register */ +#define PFC_PMC13 (PFC_BASE + 0x0213) /* Port mode control register */ +#define PFC_PMC14 (PFC_BASE + 0x0214) /* Port mode control register */ +#define PFC_PMC15 (PFC_BASE + 0x0215) /* Port mode control register */ +#define PFC_PMC16 (PFC_BASE + 0x0216) /* Port mode control register */ +#define PFC_PMC17 (PFC_BASE + 0x0217) /* Port mode control register */ +#define PFC_PMC18 (PFC_BASE + 0x0218) /* Port mode control register */ +#define PFC_PMC19 (PFC_BASE + 0x0219) /* Port mode control register */ +#define PFC_PMC1A (PFC_BASE + 0x021A) /* Port mode control register */ +#define PFC_PMC1B (PFC_BASE + 0x021B) /* Port mode control register */ +#define PFC_PMC1C (PFC_BASE + 0x021C) /* Port mode control register */ +#define PFC_PMC1D (PFC_BASE + 0x021D) /* Port mode control register */ +#define PFC_PMC1E (PFC_BASE + 0x021E) /* Port mode control register */ +#define PFC_PMC1F (PFC_BASE + 0x021F) /* Port mode control register */ +#define PFC_PMC20 (PFC_BASE + 0x0220) /* Port mode control register */ +#define PFC_PMC21 (PFC_BASE + 0x0221) /* Port mode control register */ +#define PFC_PMC22 (PFC_BASE + 0x0222) /* Port mode control register */ +#define PFC_PMC23 (PFC_BASE + 0x0223) /* Port mode control register */ +#define PFC_PMC24 (PFC_BASE + 0x0224) /* Port mode control register */ +#define PFC_PMC25 (PFC_BASE + 0x0225) /* Port mode control register */ +#define PFC_PMC26 (PFC_BASE + 0x0226) /* Port mode control register */ +#define PFC_PMC27 (PFC_BASE + 0x0227) /* Port mode control register */ +#define PFC_PMC28 (PFC_BASE + 0x0228) /* Port mode control register */ +#define PFC_PMC29 (PFC_BASE + 0x0229) /* Port mode control register */ +#define PFC_PMC2A (PFC_BASE + 0x022A) /* Port mode control register */ +#define PFC_PMC2B (PFC_BASE + 0x022B) /* Port mode control register */ +#define PFC_PMC2C (PFC_BASE + 0x022C) /* Port mode control register */ +#define PFC_PMC2D (PFC_BASE + 0x022D) /* Port mode control register */ +#define PFC_PMC2E (PFC_BASE + 0x022E) /* Port mode control register */ +#define PFC_PMC2F (PFC_BASE + 0x022F) /* Port mode control register */ +#define PFC_PMC30 (PFC_BASE + 0x0230) /* Port mode control register */ +#define PFC_PMC31 (PFC_BASE + 0x0231) /* Port mode control register */ +#define PFC_PMC32 (PFC_BASE + 0x0232) /* Port mode control register */ +#define PFC_PMC33 (PFC_BASE + 0x0233) /* Port mode control register */ +#define PFC_PMC34 (PFC_BASE + 0x0234) /* Port mode control register */ +#define PFC_PMC35 (PFC_BASE + 0x0235) /* Port mode control register */ +#define PFC_PMC36 (PFC_BASE + 0x0236) /* Port mode control register */ +#define PFC_PMC37 (PFC_BASE + 0x0237) /* Port mode control register */ +#define PFC_PMC38 (PFC_BASE + 0x0238) /* Port mode control register */ +#define PFC_PMC39 (PFC_BASE + 0x0239) /* Port mode control register */ +#define PFC_PMC3A (PFC_BASE + 0x023A) /* Port mode control register */ +#define PFC_PMC3B (PFC_BASE + 0x023B) /* Port mode control register */ +#define PFC_PMC3C (PFC_BASE + 0x023C) /* Port mode control register */ +#define PFC_PMC3D (PFC_BASE + 0x023D) /* Port mode control register */ +#define PFC_PMC3E (PFC_BASE + 0x023E) /* Port mode control register */ +#define PFC_PMC3F (PFC_BASE + 0x023F) /* Port mode control register */ +#define PFC_PMC40 (PFC_BASE + 0x0240) /* Port mode control register */ +#define PFC_PFC04 (PFC_BASE + 0x0410) /* Port function control register */ +#define PFC_PFC05 (PFC_BASE + 0x0414) /* Port function control register */ +#define PFC_PFC10 (PFC_BASE + 0x0440) /* Port function control register */ +#define PFC_PFC11 (PFC_BASE + 0x0444) /* Port function control register */ +#define PFC_PFC12 (PFC_BASE + 0x0448) /* Port function control register */ +#define PFC_PFC13 (PFC_BASE + 0x044C) /* Port function control register */ +#define PFC_PFC14 (PFC_BASE + 0x0450) /* Port function control register */ +#define PFC_PFC15 (PFC_BASE + 0x0454) /* Port function control register */ +#define PFC_PFC16 (PFC_BASE + 0x0458) /* Port function control register */ +#define PFC_PFC17 (PFC_BASE + 0x045C) /* Port function control register */ +#define PFC_PFC18 (PFC_BASE + 0x0460) /* Port function control register */ +#define PFC_PFC19 (PFC_BASE + 0x0464) /* Port function control register */ +#define PFC_PFC1A (PFC_BASE + 0x0468) /* Port function control register */ +#define PFC_PFC1B (PFC_BASE + 0x046C) /* Port function control register */ +#define PFC_PFC1C (PFC_BASE + 0x0470) /* Port function control register */ +#define PFC_PFC1D (PFC_BASE + 0x0474) /* Port function control register */ +#define PFC_PFC1E (PFC_BASE + 0x0478) /* Port function control register */ +#define PFC_PFC1F (PFC_BASE + 0x047C) /* Port function control register */ +#define PFC_PFC20 (PFC_BASE + 0x0480) /* Port function control register */ +#define PFC_PFC21 (PFC_BASE + 0x0484) /* Port function control register */ +#define PFC_PFC22 (PFC_BASE + 0x0488) /* Port function control register */ +#define PFC_PFC23 (PFC_BASE + 0x048C) /* Port function control register */ +#define PFC_PFC24 (PFC_BASE + 0x0490) /* Port function control register */ +#define PFC_PFC25 (PFC_BASE + 0x0494) /* Port function control register */ +#define PFC_PFC26 (PFC_BASE + 0x0498) /* Port function control register */ +#define PFC_PFC27 (PFC_BASE + 0x049C) /* Port function control register */ +#define PFC_PFC28 (PFC_BASE + 0x04A0) /* Port function control register */ +#define PFC_PFC29 (PFC_BASE + 0x04A4) /* Port function control register */ +#define PFC_PFC2A (PFC_BASE + 0x04A8) /* Port function control register */ +#define PFC_PFC2B (PFC_BASE + 0x04AC) /* Port function control register */ +#define PFC_PFC2C (PFC_BASE + 0x04B0) /* Port function control register */ +#define PFC_PFC2D (PFC_BASE + 0x04B4) /* Port function control register */ +#define PFC_PFC2E (PFC_BASE + 0x04B8) /* Port function control register */ +#define PFC_PFC2F (PFC_BASE + 0x04BC) /* Port function control register */ +#define PFC_PFC30 (PFC_BASE + 0x04C0) /* Port function control register */ +#define PFC_PFC31 (PFC_BASE + 0x04C4) /* Port function control register */ +#define PFC_PFC32 (PFC_BASE + 0x04C8) /* Port function control register */ +#define PFC_PFC33 (PFC_BASE + 0x04CC) /* Port function control register */ +#define PFC_PFC34 (PFC_BASE + 0x04D0) /* Port function control register */ +#define PFC_PFC35 (PFC_BASE + 0x04D4) /* Port function control register */ +#define PFC_PFC36 (PFC_BASE + 0x04D8) /* Port function control register */ +#define PFC_PFC37 (PFC_BASE + 0x04DC) /* Port function control register */ +#define PFC_PFC38 (PFC_BASE + 0x04E0) /* Port function control register */ +#define PFC_PFC39 (PFC_BASE + 0x04E4) /* Port function control register */ +#define PFC_PFC3A (PFC_BASE + 0x04E8) /* Port function control register */ +#define PFC_PFC3B (PFC_BASE + 0x04EC) /* Port function control register */ +#define PFC_PFC3C (PFC_BASE + 0x04F0) /* Port function control register */ +#define PFC_PFC3D (PFC_BASE + 0x04F4) /* Port function control register */ +#define PFC_PFC3E (PFC_BASE + 0x04F8) /* Port function control register */ +#define PFC_PFC3F (PFC_BASE + 0x04FC) /* Port function control register */ +#define PFC_PFC40 (PFC_BASE + 0x0500) /* Port function control register */ +#define PFC_IOLH02 (PFC_BASE + 0x1010) /* IOLH switch register */ +#define PFC_IOLH03 (PFC_BASE + 0x1018) /* IOLH switch register */ +#define PFC_IOLH04 (PFC_BASE + 0x1020) /* IOLH switch register */ +#define PFC_IOLH05 (PFC_BASE + 0x1028) /* IOLH switch register */ +#define PFC_IOLH06 (PFC_BASE + 0x1030) /* IOLH switch register */ +#define PFC_IOLH07 (PFC_BASE + 0x1038) /* IOLH switch register */ +#define PFC_IOLH08 (PFC_BASE + 0x1040) /* IOLH switch register */ +#define PFC_IOLH09 (PFC_BASE + 0x1048) /* IOLH switch register */ +#define PFC_IOLH0A (PFC_BASE + 0x1050) /* IOLH switch register */ +#define PFC_IOLH0B (PFC_BASE + 0x1058) /* IOLH switch register */ +#define PFC_IOLH0C (PFC_BASE + 0x1060) /* IOLH switch register */ +#define PFC_IOLH0D (PFC_BASE + 0x1068) /* IOLH switch register */ +#define PFC_IOLH10 (PFC_BASE + 0x1080) /* IOLH switch register */ +#define PFC_IOLH11 (PFC_BASE + 0x1088) /* IOLH switch register */ +#define PFC_IOLH12 (PFC_BASE + 0x1090) /* IOLH switch register */ +#define PFC_IOLH13 (PFC_BASE + 0x1098) /* IOLH switch register */ +#define PFC_IOLH14 (PFC_BASE + 0x10A0) /* IOLH switch register */ +#define PFC_IOLH15 (PFC_BASE + 0x10A8) /* IOLH switch register */ +#define PFC_IOLH16 (PFC_BASE + 0x10B0) /* IOLH switch register */ +#define PFC_IOLH17 (PFC_BASE + 0x10B8) /* IOLH switch register */ +#define PFC_IOLH18 (PFC_BASE + 0x10C0) /* IOLH switch register */ +#define PFC_IOLH19 (PFC_BASE + 0x10C8) /* IOLH switch register */ +#define PFC_IOLH1A (PFC_BASE + 0x10D0) /* IOLH switch register */ +#define PFC_IOLH1B (PFC_BASE + 0x10D8) /* IOLH switch register */ +#define PFC_IOLH1C (PFC_BASE + 0x10E0) /* IOLH switch register */ +#define PFC_IOLH1D (PFC_BASE + 0x10E8) /* IOLH switch register */ +#define PFC_IOLH1E (PFC_BASE + 0x10F0) /* IOLH switch register */ +#define PFC_IOLH1F (PFC_BASE + 0x10F8) /* IOLH switch register */ +#define PFC_IOLH20 (PFC_BASE + 0x1100) /* IOLH switch register */ +#define PFC_IOLH21 (PFC_BASE + 0x1108) /* IOLH switch register */ +#define PFC_IOLH22 (PFC_BASE + 0x1120) /* IOLH switch register */ +#define PFC_IOLH23 (PFC_BASE + 0x1128) /* IOLH switch register */ +#define PFC_IOLH36 (PFC_BASE + 0x11B0) /* IOLH switch register */ +#define PFC_IOLH37 (PFC_BASE + 0x11B8) /* IOLH switch register */ +#define PFC_IOLH38 (PFC_BASE + 0x11C0) /* IOLH switch register */ +#define PFC_IOLH39 (PFC_BASE + 0x11C8) /* IOLH switch register */ +#define PFC_IOLH3A (PFC_BASE + 0x11D0) /* IOLH switch register */ +#define PFC_IOLH3B (PFC_BASE + 0x11D8) /* IOLH switch register */ +#define PFC_IOLH3C (PFC_BASE + 0x11E0) /* IOLH switch register */ +#define PFC_IOLH3D (PFC_BASE + 0x11E8) /* IOLH switch register */ +#define PFC_IOLH3E (PFC_BASE + 0x11F0) /* IOLH switch register */ +#define PFC_IOLH3F (PFC_BASE + 0x11F8) /* IOLH switch register */ +#define PFC_IOLH40 (PFC_BASE + 0x1200) /* IOLH switch register */ +#define PFC_SR04 (PFC_BASE + 0x1420) /* Slew-Rate switch register */ +#define PFC_SR05 (PFC_BASE + 0x1428) /* Slew-Rate switch register */ +#define PFC_SR06 (PFC_BASE + 0x1430) /* Slew-Rate switch register */ +#define PFC_SR07 (PFC_BASE + 0x1438) /* Slew-Rate switch register */ +#define PFC_SR08 (PFC_BASE + 0x1440) /* Slew-Rate switch register */ +#define PFC_SR09 (PFC_BASE + 0x1448) /* Slew-Rate switch register */ +#define PFC_SR0A (PFC_BASE + 0x1450) /* Slew-Rate switch register */ +#define PFC_SR0B (PFC_BASE + 0x1458) /* Slew-Rate switch register */ +#define PFC_SR0C (PFC_BASE + 0x1460) /* Slew-Rate switch register */ +#define PFC_SR10 (PFC_BASE + 0x1480) /* Slew-Rate switch register */ +#define PFC_SR15 (PFC_BASE + 0x14A8) /* Slew-Rate switch register */ +#define PFC_SR16 (PFC_BASE + 0x14B0) /* Slew-Rate switch register */ +#define PFC_SR1A (PFC_BASE + 0x14D0) /* Slew-Rate switch register */ +#define PFC_SR1B (PFC_BASE + 0x14D8) /* Slew-Rate switch register */ +#define PFC_SR1C (PFC_BASE + 0x14E0) /* Slew-Rate switch register */ +#define PFC_SR1D (PFC_BASE + 0x14E8) /* Slew-Rate switch register */ +#define PFC_SR1E (PFC_BASE + 0x14F0) /* Slew-Rate switch register */ +#define PFC_SR1F (PFC_BASE + 0x14F8) /* Slew-Rate switch register */ +#define PFC_SR20 (PFC_BASE + 0x1500) /* Slew-Rate switch register */ +#define PFC_SR21 (PFC_BASE + 0x1508) /* Slew-Rate switch register */ +#define PFC_SR22 (PFC_BASE + 0x1510) /* Slew-Rate switch register */ +#define PFC_SR23 (PFC_BASE + 0x1518) /* Slew-Rate switch register */ +#define PFC_SR36 (PFC_BASE + 0x15B0) /* Slew-Rate switch register */ +#define PFC_SR37 (PFC_BASE + 0x15B8) /* Slew-Rate switch register */ +#define PFC_IEN06 (PFC_BASE + 0x1830) /* IEN switch register */ +#define PFC_IEN07 (PFC_BASE + 0x1838) /* IEN switch register */ +#define PFC_IEN08 (PFC_BASE + 0x1840) /* IEN switch register */ +#define PFC_IEN09 (PFC_BASE + 0x1848) /* IEN switch register */ +#define PFC_PUPD04 (PFC_BASE + 0x1C20) /* PU/PD switch register */ +#define PFC_PUPD05 (PFC_BASE + 0x1C28) /* PU/PD switch register */ +#define PFC_PUPD06 (PFC_BASE + 0x1C30) /* PU/PD switch register */ +#define PFC_PUPD07 (PFC_BASE + 0x1C38) /* PU/PD switch register */ +#define PFC_PUPD08 (PFC_BASE + 0x1C40) /* PU/PD switch register */ +#define PFC_PUPD09 (PFC_BASE + 0x1C48) /* PU/PD switch register */ +#define PFC_PUPD0A (PFC_BASE + 0x1C50) /* PU/PD switch register */ +#define PFC_PUPD0B (PFC_BASE + 0x1C58) /* PU/PD switch register */ +#define PFC_PUPD0C (PFC_BASE + 0x1C60) /* PU/PD switch register */ +#define PFC_PUPD10 (PFC_BASE + 0x1C80) /* PU/PD switch register */ +#define PFC_PUPD15 (PFC_BASE + 0x1CA8) /* PU/PD switch register */ +#define PFC_PUPD16 (PFC_BASE + 0x1CB0) /* PU/PD switch register */ +#define PFC_PUPD1A (PFC_BASE + 0x1CD0) /* PU/PD switch register */ +#define PFC_PUPD1B (PFC_BASE + 0x1CD8) /* PU/PD switch register */ +#define PFC_PUPD1C (PFC_BASE + 0x1CE0) /* PU/PD switch register */ +#define PFC_PUPD1D (PFC_BASE + 0x1CE8) /* PU/PD switch register */ +#define PFC_PUPD1E (PFC_BASE + 0x1CF0) /* PU/PD switch register */ +#define PFC_PUPD1F (PFC_BASE + 0x1CF8) /* PU/PD switch register */ +#define PFC_PUPD20 (PFC_BASE + 0x1D00) /* PU/PD switch register */ +#define PFC_PUPD21 (PFC_BASE + 0x1D08) /* PU/PD switch register */ +#define PFC_PUPD22 (PFC_BASE + 0x1D10) /* PU/PD switch register */ +#define PFC_PUPD23 (PFC_BASE + 0x1D18) /* PU/PD switch register */ +#define PFC_PUPD36 (PFC_BASE + 0x1DB0) /* PU/PD switch register */ +#define PFC_PUPD37 (PFC_BASE + 0x1DB8) /* PU/PD switch register */ +#define PFC_SD_ch0 (PFC_BASE + 0x3000) /* SD ch0 IO voltage control register */ +#define PFC_SD_ch1 (PFC_BASE + 0x3004) /* SD ch1 IO voltage control register */ +#define PFC_QSPI (PFC_BASE + 0x3008) /* QSPI IO voltage control register */ +#define PFC_ETH_ch0 (PFC_BASE + 0x300C) /* ETH ch0 voltage control register */ +#define PFC_ETH_ch1 (PFC_BASE + 0x3010) /* ETH ch1 voltage control register */ +#define PFC_PWPR (PFC_BASE + 0x3014) /* Write protect */ +#define PFC_FILONOFF01 (PFC_BASE + 0x2008) /* Digital noise filter (FILONOFF) register */ +#define PFC_FILONOFF10 (PFC_BASE + 0x2080) /* Digital noise filter (FILONOFF) register */ +#define PFC_FILONOFF11 (PFC_BASE + 0x2088) /* Digital noise filter (FILONOFF) register */ +#define PFC_FILONOFF12 (PFC_BASE + 0x2090) /* Digital noise filter (FILONOFF) register */ +#define PFC_FILONOFF13 (PFC_BASE + 0x2098) /* Digital noise filter (FILONOFF) register */ +#define PFC_FILONOFF14 (PFC_BASE + 0x20A0) /* Digital noise filter (FILONOFF) register */ +#define PFC_FILONOFF15 (PFC_BASE + 0x20A8) /* Digital noise filter (FILONOFF) register */ +#define PFC_FILONOFF16 (PFC_BASE + 0x20B0) /* Digital noise filter (FILONOFF) register */ +#define PFC_FILONOFF17 (PFC_BASE + 0x20B8) /* Digital noise filter (FILONOFF) register */ +#define PFC_FILONOFF18 (PFC_BASE + 0x20C0) /* Digital noise filter (FILONOFF) register */ +#define PFC_FILONOFF19 (PFC_BASE + 0x20C8) /* Digital noise filter (FILONOFF) register */ +#define PFC_FILONOFF1A (PFC_BASE + 0x20D0) /* Digital noise filter (FILONOFF) register */ +#define PFC_FILONOFF1B (PFC_BASE + 0x20D8) /* Digital noise filter (FILONOFF) register */ +#define PFC_FILONOFF1C (PFC_BASE + 0x20E0) /* Digital noise filter (FILONOFF) register */ +#define PFC_FILONOFF1D (PFC_BASE + 0x20E8) /* Digital noise filter (FILONOFF) register */ +#define PFC_FILONOFF1E (PFC_BASE + 0x20F0) /* Digital noise filter (FILONOFF) register */ +#define PFC_FILONOFF1F (PFC_BASE + 0x20F8) /* Digital noise filter (FILONOFF) register */ +#define PFC_FILONOFF20 (PFC_BASE + 0x2100) /* Digital noise filter (FILONOFF) register */ +#define PFC_FILONOFF21 (PFC_BASE + 0x2108) /* Digital noise filter (FILONOFF) register */ +#define PFC_FILONOFF22 (PFC_BASE + 0x2110) /* Digital noise filter (FILONOFF) register */ +#define PFC_FILONOFF23 (PFC_BASE + 0x2118) /* Digital noise filter (FILONOFF) register */ +#define PFC_FILONOFF24 (PFC_BASE + 0x2120) /* Digital noise filter (FILONOFF) register */ +#define PFC_FILONOFF25 (PFC_BASE + 0x2128) /* Digital noise filter (FILONOFF) register */ +#define PFC_FILONOFF26 (PFC_BASE + 0x2130) /* Digital noise filter (FILONOFF) register */ +#define PFC_FILONOFF27 (PFC_BASE + 0x2138) /* Digital noise filter (FILONOFF) register */ +#define PFC_FILONOFF28 (PFC_BASE + 0x2140) /* Digital noise filter (FILONOFF) register */ +#define PFC_FILONOFF29 (PFC_BASE + 0x2148) /* Digital noise filter (FILONOFF) register */ +#define PFC_FILONOFF2A (PFC_BASE + 0x2150) /* Digital noise filter (FILONOFF) register */ +#define PFC_FILONOFF2B (PFC_BASE + 0x2158) /* Digital noise filter (FILONOFF) register */ +#define PFC_FILONOFF2C (PFC_BASE + 0x2160) /* Digital noise filter (FILONOFF) register */ +#define PFC_FILONOFF2D (PFC_BASE + 0x2168) /* Digital noise filter (FILONOFF) register */ +#define PFC_FILONOFF2E (PFC_BASE + 0x2170) /* Digital noise filter (FILONOFF) register */ +#define PFC_FILONOFF2F (PFC_BASE + 0x2178) /* Digital noise filter (FILONOFF) register */ +#define PFC_FILONOFF30 (PFC_BASE + 0x2180) /* Digital noise filter (FILONOFF) register */ +#define PFC_FILONOFF31 (PFC_BASE + 0x2188) /* Digital noise filter (FILONOFF) register */ +#define PFC_FILONOFF32 (PFC_BASE + 0x2190) /* Digital noise filter (FILONOFF) register */ +#define PFC_FILONOFF33 (PFC_BASE + 0x2198) /* Digital noise filter (FILONOFF) register */ +#define PFC_FILONOFF34 (PFC_BASE + 0x21A0) /* Digital noise filter (FILONOFF) register */ +#define PFC_FILONOFF35 (PFC_BASE + 0x21A8) /* Digital noise filter (FILONOFF) register */ +#define PFC_FILONOFF36 (PFC_BASE + 0x21B0) /* Digital noise filter (FILONOFF) register */ +#define PFC_FILONOFF37 (PFC_BASE + 0x21B8) /* Digital noise filter (FILONOFF) register */ +#define PFC_FILONOFF38 (PFC_BASE + 0x21C0) /* Digital noise filter (FILONOFF) register */ +#define PFC_FILONOFF39 (PFC_BASE + 0x21C8) /* Digital noise filter (FILONOFF) register */ +#define PFC_FILONOFF3A (PFC_BASE + 0x21D0) /* Digital noise filter (FILONOFF) register */ +#define PFC_FILONOFF3B (PFC_BASE + 0x21D8) /* Digital noise filter (FILONOFF) register */ +#define PFC_FILONOFF3C (PFC_BASE + 0x21E0) /* Digital noise filter (FILONOFF) register */ +#define PFC_FILONOFF3D (PFC_BASE + 0x21E8) /* Digital noise filter (FILONOFF) register */ +#define PFC_FILONOFF3E (PFC_BASE + 0x21F0) /* Digital noise filter (FILONOFF) register */ +#define PFC_FILONOFF3F (PFC_BASE + 0x21F8) /* Digital noise filter (FILONOFF) register */ +#define PFC_FILONOFF40 (PFC_BASE + 0x2200) /* Digital noise filter (FILONOFF) register */ +#define PFC_FILNUM01 (PFC_BASE + 0x2408) /* Digital noise filter (FILNUM) register */ +#define PFC_FILNUM10 (PFC_BASE + 0x2480) /* Digital noise filter (FILNUM) register */ +#define PFC_FILNUM11 (PFC_BASE + 0x2488) /* Digital noise filter (FILNUM) register */ +#define PFC_FILNUM12 (PFC_BASE + 0x2490) /* Digital noise filter (FILNUM) register */ +#define PFC_FILNUM13 (PFC_BASE + 0x2498) /* Digital noise filter (FILNUM) register */ +#define PFC_FILNUM14 (PFC_BASE + 0x24A0) /* Digital noise filter (FILNUM) register */ +#define PFC_FILNUM15 (PFC_BASE + 0x24A8) /* Digital noise filter (FILNUM) register */ +#define PFC_FILNUM16 (PFC_BASE + 0x24B0) /* Digital noise filter (FILNUM) register */ +#define PFC_FILNUM17 (PFC_BASE + 0x24B8) /* Digital noise filter (FILNUM) register */ +#define PFC_FILNUM18 (PFC_BASE + 0x24C0) /* Digital noise filter (FILNUM) register */ +#define PFC_FILNUM19 (PFC_BASE + 0x24C8) /* Digital noise filter (FILNUM) register */ +#define PFC_FILNUM1A (PFC_BASE + 0x24D0) /* Digital noise filter (FILNUM) register */ +#define PFC_FILNUM1B (PFC_BASE + 0x24D8) /* Digital noise filter (FILNUM) register */ +#define PFC_FILNUM1C (PFC_BASE + 0x24E0) /* Digital noise filter (FILNUM) register */ +#define PFC_FILNUM1D (PFC_BASE + 0x24E8) /* Digital noise filter (FILNUM) register */ +#define PFC_FILNUM1E (PFC_BASE + 0x24F0) /* Digital noise filter (FILNUM) register */ +#define PFC_FILNUM1F (PFC_BASE + 0x24F8) /* Digital noise filter (FILNUM) register */ +#define PFC_FILNUM20 (PFC_BASE + 0x2500) /* Digital noise filter (FILNUM) register */ +#define PFC_FILNUM21 (PFC_BASE + 0x2508) /* Digital noise filter (FILNUM) register */ +#define PFC_FILNUM22 (PFC_BASE + 0x2510) /* Digital noise filter (FILNUM) register */ +#define PFC_FILNUM23 (PFC_BASE + 0x2518) /* Digital noise filter (FILNUM) register */ +#define PFC_FILNUM24 (PFC_BASE + 0x2520) /* Digital noise filter (FILNUM) register */ +#define PFC_FILNUM25 (PFC_BASE + 0x2528) /* Digital noise filter (FILNUM) register */ +#define PFC_FILNUM26 (PFC_BASE + 0x2530) /* Digital noise filter (FILNUM) register */ +#define PFC_FILNUM27 (PFC_BASE + 0x2538) /* Digital noise filter (FILNUM) register */ +#define PFC_FILNUM28 (PFC_BASE + 0x2540) /* Digital noise filter (FILNUM) register */ +#define PFC_FILNUM29 (PFC_BASE + 0x2548) /* Digital noise filter (FILNUM) register */ +#define PFC_FILNUM2A (PFC_BASE + 0x2550) /* Digital noise filter (FILNUM) register */ +#define PFC_FILNUM2B (PFC_BASE + 0x2558) /* Digital noise filter (FILNUM) register */ +#define PFC_FILNUM2C (PFC_BASE + 0x2560) /* Digital noise filter (FILNUM) register */ +#define PFC_FILNUM2D (PFC_BASE + 0x2568) /* Digital noise filter (FILNUM) register */ +#define PFC_FILNUM2E (PFC_BASE + 0x2570) /* Digital noise filter (FILNUM) register */ +#define PFC_FILNUM2F (PFC_BASE + 0x2578) /* Digital noise filter (FILNUM) register */ +#define PFC_FILNUM30 (PFC_BASE + 0x2580) /* Digital noise filter (FILNUM) register */ +#define PFC_FILNUM31 (PFC_BASE + 0x2588) /* Digital noise filter (FILNUM) register */ +#define PFC_FILNUM32 (PFC_BASE + 0x2590) /* Digital noise filter (FILNUM) register */ +#define PFC_FILNUM33 (PFC_BASE + 0x2598) /* Digital noise filter (FILNUM) register */ +#define PFC_FILNUM34 (PFC_BASE + 0x25A0) /* Digital noise filter (FILNUM) register */ +#define PFC_FILNUM35 (PFC_BASE + 0x25A8) /* Digital noise filter (FILNUM) register */ +#define PFC_FILNUM36 (PFC_BASE + 0x25B0) /* Digital noise filter (FILNUM) register */ +#define PFC_FILNUM37 (PFC_BASE + 0x25B8) /* Digital noise filter (FILNUM) register */ +#define PFC_FILNUM38 (PFC_BASE + 0x25C0) /* Digital noise filter (FILNUM) register */ +#define PFC_FILNUM39 (PFC_BASE + 0x25C8) /* Digital noise filter (FILNUM) register */ +#define PFC_FILNUM3A (PFC_BASE + 0x25D0) /* Digital noise filter (FILNUM) register */ +#define PFC_FILNUM3B (PFC_BASE + 0x25D8) /* Digital noise filter (FILNUM) register */ +#define PFC_FILNUM3C (PFC_BASE + 0x25E0) /* Digital noise filter (FILNUM) register */ +#define PFC_FILNUM3D (PFC_BASE + 0x25E8) /* Digital noise filter (FILNUM) register */ +#define PFC_FILNUM3E (PFC_BASE + 0x25F0) /* Digital noise filter (FILNUM) register */ +#define PFC_FILNUM3F (PFC_BASE + 0x25F8) /* Digital noise filter (FILNUM) register */ +#define PFC_FILNUM40 (PFC_BASE + 0x2600) /* Digital noise filter (FILNUM) register */ +#define PFC_FILCLKSEL01 (PFC_BASE + 0x2808) /* Digital noise filter (FILCLKSEL) register */ +#define PFC_FILCLKSEL10 (PFC_BASE + 0x2880) /* Digital noise filter (FILCLKSEL) register */ +#define PFC_FILCLKSEL11 (PFC_BASE + 0x2888) /* Digital noise filter (FILCLKSEL) register */ +#define PFC_FILCLKSEL12 (PFC_BASE + 0x2890) /* Digital noise filter (FILCLKSEL) register */ +#define PFC_FILCLKSEL13 (PFC_BASE + 0x2898) /* Digital noise filter (FILCLKSEL) register */ +#define PFC_FILCLKSEL14 (PFC_BASE + 0x28A0) /* Digital noise filter (FILCLKSEL) register */ +#define PFC_FILCLKSEL15 (PFC_BASE + 0x28A8) /* Digital noise filter (FILCLKSEL) register */ +#define PFC_FILCLKSEL16 (PFC_BASE + 0x28B0) /* Digital noise filter (FILCLKSEL) register */ +#define PFC_FILCLKSEL17 (PFC_BASE + 0x28B8) /* Digital noise filter (FILCLKSEL) register */ +#define PFC_FILCLKSEL18 (PFC_BASE + 0x28C0) /* Digital noise filter (FILCLKSEL) register */ +#define PFC_FILCLKSEL19 (PFC_BASE + 0x28C8) /* Digital noise filter (FILCLKSEL) register */ +#define PFC_FILCLKSEL1A (PFC_BASE + 0x28D0) /* Digital noise filter (FILCLKSEL) register */ +#define PFC_FILCLKSEL1B (PFC_BASE + 0x28D8) /* Digital noise filter (FILCLKSEL) register */ +#define PFC_FILCLKSEL1C (PFC_BASE + 0x28E0) /* Digital noise filter (FILCLKSEL) register */ +#define PFC_FILCLKSEL1D (PFC_BASE + 0x28E8) /* Digital noise filter (FILCLKSEL) register */ +#define PFC_FILCLKSEL1E (PFC_BASE + 0x28F0) /* Digital noise filter (FILCLKSEL) register */ +#define PFC_FILCLKSEL1F (PFC_BASE + 0x28F8) /* Digital noise filter (FILCLKSEL) register */ +#define PFC_FILCLKSEL20 (PFC_BASE + 0x2900) /* Digital noise filter (FILCLKSEL) register */ +#define PFC_FILCLKSEL21 (PFC_BASE + 0x2908) /* Digital noise filter (FILCLKSEL) register */ +#define PFC_FILCLKSEL22 (PFC_BASE + 0x2910) /* Digital noise filter (FILCLKSEL) register */ +#define PFC_FILCLKSEL23 (PFC_BASE + 0x2918) /* Digital noise filter (FILCLKSEL) register */ +#define PFC_FILCLKSEL24 (PFC_BASE + 0x2920) /* Digital noise filter (FILCLKSEL) register */ +#define PFC_FILCLKSEL25 (PFC_BASE + 0x2928) /* Digital noise filter (FILCLKSEL) register */ +#define PFC_FILCLKSEL26 (PFC_BASE + 0x2930) /* Digital noise filter (FILCLKSEL) register */ +#define PFC_FILCLKSEL27 (PFC_BASE + 0x2938) /* Digital noise filter (FILCLKSEL) register */ +#define PFC_FILCLKSEL28 (PFC_BASE + 0x2940) /* Digital noise filter (FILCLKSEL) register */ +#define PFC_FILCLKSEL29 (PFC_BASE + 0x2948) /* Digital noise filter (FILCLKSEL) register */ +#define PFC_FILCLKSEL2A (PFC_BASE + 0x2950) /* Digital noise filter (FILCLKSEL) register */ +#define PFC_FILCLKSEL2B (PFC_BASE + 0x2958) /* Digital noise filter (FILCLKSEL) register */ +#define PFC_FILCLKSEL2C (PFC_BASE + 0x2960) /* Digital noise filter (FILCLKSEL) register */ +#define PFC_FILCLKSEL2D (PFC_BASE + 0x2968) /* Digital noise filter (FILCLKSEL) register */ +#define PFC_FILCLKSEL2E (PFC_BASE + 0x2970) /* Digital noise filter (FILCLKSEL) register */ +#define PFC_FILCLKSEL2F (PFC_BASE + 0x2978) /* Digital noise filter (FILCLKSEL) register */ +#define PFC_FILCLKSEL30 (PFC_BASE + 0x2980) /* Digital noise filter (FILCLKSEL) register */ +#define PFC_FILCLKSEL31 (PFC_BASE + 0x2988) /* Digital noise filter (FILCLKSEL) register */ +#define PFC_FILCLKSEL32 (PFC_BASE + 0x2990) /* Digital noise filter (FILCLKSEL) register */ +#define PFC_FILCLKSEL33 (PFC_BASE + 0x2998) /* Digital noise filter (FILCLKSEL) register */ +#define PFC_FILCLKSEL34 (PFC_BASE + 0x29A0) /* Digital noise filter (FILCLKSEL) register */ +#define PFC_FILCLKSEL35 (PFC_BASE + 0x29A8) /* Digital noise filter (FILCLKSEL) register */ +#define PFC_FILCLKSEL36 (PFC_BASE + 0x29B0) /* Digital noise filter (FILCLKSEL) register */ +#define PFC_FILCLKSEL37 (PFC_BASE + 0x29B8) /* Digital noise filter (FILCLKSEL) register */ +#define PFC_FILCLKSEL38 (PFC_BASE + 0x29C0) /* Digital noise filter (FILCLKSEL) register */ +#define PFC_FILCLKSEL39 (PFC_BASE + 0x29C8) /* Digital noise filter (FILCLKSEL) register */ +#define PFC_FILCLKSEL3A (PFC_BASE + 0x29D0) /* Digital noise filter (FILCLKSEL) register */ +#define PFC_FILCLKSEL3B (PFC_BASE + 0x29D8) /* Digital noise filter (FILCLKSEL) register */ +#define PFC_FILCLKSEL3C (PFC_BASE + 0x29E0) /* Digital noise filter (FILCLKSEL) register */ +#define PFC_FILCLKSEL3D (PFC_BASE + 0x29E8) /* Digital noise filter (FILCLKSEL) register */ +#define PFC_FILCLKSEL3E (PFC_BASE + 0x29F0) /* Digital noise filter (FILCLKSEL) register */ +#define PFC_FILCLKSEL3F (PFC_BASE + 0x29F8) /* Digital noise filter (FILCLKSEL) register */ +#define PFC_FILCLKSEL40 (PFC_BASE + 0x2A00) /* Digital noise filter (FILCLKSEL) register */ +#define PFC_ETH_MII (PFC_BASE + 0x3018) /* Register for setting the mode of ETH MII / RGMII */ + +/* Combined terminal setting */ +/* Definition for port register */ +#define P_P0 (1 << 0) +#define P_P1 (1 << 1) +#define P_P2 (1 << 2) +#define P_P3 (1 << 3) +#define P_P4 (1 << 4) +#define P_P5 (1 << 5) +#define P_P6 (1 << 6) +#define P_P7 (1 << 7) +/* Definition for port mode register */ +#define PM0_HIZ (0 << 0) +#define PM0_IN (1 << 0) +#define PM0_OUT_DIS (2 << 0) +#define PM0_OUT_EN (3 << 0) +#define PM1_HIZ (0 << 2) +#define PM1_IN (1 << 2) +#define PM1_OUT_DIS (2 << 2) +#define PM1_OUT_EN (3 << 2) +#define PM2_HIZ (0 << 4) +#define PM2_IN (1 << 4) +#define PM2_OUT_DIS (2 << 4) +#define PM2_OUT_EN (3 << 4) +#define PM3_HIZ (0 << 6) +#define PM3_IN (1 << 6) +#define PM3_OUT_DIS (2 << 6) +#define PM3_OUT_EN (3 << 6) +#define PM4_HIZ (0 << 8) +#define PM4_IN (1 << 8) +#define PM4_OUT_DIS (2 << 8) +#define PM4_OUT_EN (3 << 8) +/* Definition for port mode control register */ +#define PMC_PMC0 (1 << 0) +#define PMC_PMC1 (1 << 1) +#define PMC_PMC2 (1 << 2) +#define PMC_PMC3 (1 << 3) +#define PMC_PMC4 (1 << 4) +#define PMC_PMC5 (1 << 5) +#define PMC_PMC6 (1 << 6) +#define PMC_PMC7 (1 << 7) +/* Definition for port function control register */ +#define PFC0_MODE0 (0 << 0) +#define PFC0_MODE1 (1 << 0) +#define PFC0_MODE2 (2 << 0) +#define PFC0_MODE3 (3 << 0) +#define PFC0_MODE4 (4 << 0) +#define PFC0_MODE5 (5 << 0) +#define PFC1_MODE0 (0 << 4) +#define PFC1_MODE1 (1 << 4) +#define PFC1_MODE2 (2 << 4) +#define PFC1_MODE3 (3 << 4) +#define PFC1_MODE4 (4 << 4) +#define PFC1_MODE5 (5 << 4) +#define PFC2_MODE0 (0 << 8) +#define PFC2_MODE1 (1 << 8) +#define PFC2_MODE2 (2 << 8) +#define PFC2_MODE3 (3 << 8) +#define PFC2_MODE4 (4 << 8) +#define PFC2_MODE5 (5 << 8) +#define PFC3_MODE0 (0 << 12) +#define PFC3_MODE1 (1 << 12) +#define PFC3_MODE2 (2 << 12) +#define PFC3_MODE3 (3 << 12) +#define PFC3_MODE4 (4 << 12) +#define PFC3_MODE5 (5 << 12) +#define PFC4_MODE0 (0 << 16) +#define PFC4_MODE1 (1 << 16) +#define PFC4_MODE2 (2 << 16) +#define PFC4_MODE3 (3 << 16) +#define PFC4_MODE4 (4 << 16) +#define PFC4_MODE5 (5 << 16) +/* Definition for IOLH switch register */ +#define IOLH0_2MA (0 << 0) +#define IOLH0_4MA (1 << 0) +#define IOLH0_8MA (2 << 0) +#define IOLH0_12MA (3 << 0) +#define IOLH1_2MA (0 << 8) +#define IOLH1_4MA (1 << 8) +#define IOLH1_8MA (2 << 8) +#define IOLH1_12MA (3 << 8) +#define IOLH2_2MA (0 << 16) +#define IOLH2_4MA (1 << 16) +#define IOLH2_8MA (2 << 16) +#define IOLH2_12MA (3 << 16) +#define IOLH3_2MA (0 << 24) +#define IOLH3_4MA (1 << 24) +#define IOLH3_8MA (2 << 24) +#define IOLH3_12MA (3 << 24) +#define IOLH4_2MA (0 << 32) +#define IOLH4_4MA (1 << 32) +#define IOLH4_8MA (2 << 32) +#define IOLH4_12MA (3 << 32) +#define IOLH5_2MA (0 << 40) +#define IOLH5_4MA (1 << 40) +#define IOLH5_8MA (2 << 40) +#define IOLH5_12MA (3 << 40) +#define IOLH6_2MA (0 << 48) +#define IOLH6_4MA (1 << 48) +#define IOLH6_8MA (2 << 48) +#define IOLH6_12MA (3 << 48) +#define IOLH7_2MA (0 << 56) +#define IOLH7_4MA (1 << 56) +#define IOLH7_8MA (2 << 56) +#define IOLH7_12MA (3 << 56) +/* Definition for Slew-Rate switch register */ +#define SR0_FAST (1 << 0) +#define SR1_FAST (1 << 8) +#define SR2_FAST (1 << 16) +#define SR3_FAST (1 << 24) +#define SR4_FAST (1 << 32) +#define SR5_FAST (1 << 40) +#define SR6_FAST (1 << 48) +#define SR7_FAST (1 << 56) +/* Definition for IEN switching register */ +#define IEN0_ENABLE (1 << 0) +#define IEN1_ENABLE (1 << 8) +#define IEN2_ENABLE (1 << 16) +#define IEN3_ENABLE (1 << 24) +#define IEN4_ENABLE (1 << 32) +#define IEN5_ENABLE (1 << 40) +#define IEN6_ENABLE (1 << 48) +#define IEN7_ENABLE (1 << 56) +/* Definition for PUPD switching register */ +#define PUPD0_NO (0 << 0) +#define PUPD0_UP (1 << 0) +#define PUPD0_DOWN (2 << 0) +#define PUPD1_NO (0 << 8) +#define PUPD1_UP (1 << 8) +#define PUPD1_DOWN (2 << 8) +#define PUPD2_NO (0 << 16) +#define PUPD2_UP (1 << 16) +#define PUPD2_DOWN (2 << 16) +#define PUPD3_NO (0 << 24) +#define PUPD3_UP (1 << 24) +#define PUPD3_DOWN (2 << 24) +#define PUPD4_NO (0 << 32) +#define PUPD4_UP (1 << 32) +#define PUPD4_DOWN (2 << 32) +#define PUPD5_NO (0 << 40) +#define PUPD5_UP (1 << 40) +#define PUPD5_DOWN (2 << 40) +#define PUPD6_NO (0 << 48) +#define PUPD6_UP (1 << 48) +#define PUPD6_DOWN (2 << 48) +#define PUPD7_NO (0 << 56) +#define PUPD7_UP (1 << 56) +#define PUPD7_DOWN (2 << 56) +/* SD ch0 IO Definition for voltage control register */ +#define SD0_PVDD (1 << 0) +/* SD ch1 IO Definition for voltage control register */ +#define SD1_PVDD (1 << 0) +/* Definition for QSPI IO voltage control register */ +#define QSPI_PVDD (1 << 0) +/* ETH ch0 voltage control register */ +#define ETH_ch0_3_3 (0 << 0) +#define ETH_ch0_1_8 (1 << 0) +#define ETH_ch0_2_5 (2 << 0) +/* ETH ch1 voltage control register */ +#define ETH_ch1_3_3 (0 << 0) +#define ETH_ch1_1_8 (1 << 0) +#define ETH_ch1_2_5 (2 << 0) +/* Write protection definition */ +#define PWPR_B0Wl (1 << 7) +#define PWPR_PFCWE (1 << 6) +/* Digital noise filter (FILONOFF) register */ +#define FILONOFF_FILON0 (1 << 0) +#define FILONOFF_FILON1 (1 << 8) +#define FILONOFF_FILON2 (1 << 16) +#define FILONOFF_FILON3 (1 << 24) +#define FILONOFF_FILON4 (1 << 32) +#define FILONOFF_FILON5 (1 << 40) +#define FILONOFF_FILON6 (1 << 48) +#define FILONOFF_FILON7 (1 << 56) +/* Digital noise filter (FILNUM) register */ +#define FILNUM_FILNUM0_4 (0 << 0) +#define FILNUM_FILNUM0_8 (1 << 0) +#define FILNUM_FILNUM0_12 (2 << 0) +#define FILNUM_FILNUM0_16 (3 << 0) +#define FILNUM_FILNUM1_4 (0 << 8) +#define FILNUM_FILNUM1_8 (1 << 8) +#define FILNUM_FILNUM1_12 (2 << 8) +#define FILNUM_FILNUM1_16 (3 << 8) +#define FILNUM_FILNUM2_4 (0 << 16) +#define FILNUM_FILNUM2_8 (1 << 16) +#define FILNUM_FILNUM2_12 (2 << 16) +#define FILNUM_FILNUM2_16 (3 << 16) +#define FILNUM_FILNUM3_4 (0 << 24) +#define FILNUM_FILNUM3_8 (1 << 24) +#define FILNUM_FILNUM3_12 (2 << 24) +#define FILNUM_FILNUM3_16 (3 << 24) +#define FILNUM_FILNUM4_4 (0 << 32) +#define FILNUM_FILNUM4_8 (1 << 32) +#define FILNUM_FILNUM4_12 (2 << 32) +#define FILNUM_FILNUM4_16 (3 << 32) +#define FILNUM_FILNUM5_4 (0 << 40) +#define FILNUM_FILNUM5_8 (1 << 40) +#define FILNUM_FILNUM5_12 (2 << 40) +#define FILNUM_FILNUM5_16 (3 << 40) +#define FILNUM_FILNUM6_4 (0 << 48) +#define FILNUM_FILNUM6_8 (1 << 48) +#define FILNUM_FILNUM6_12 (2 << 48) +#define FILNUM_FILNUM6_16 (3 << 48) +#define FILNUM_FILNUM7_4 (0 << 56) +#define FILNUM_FILNUM7_8 (1 << 56) +#define FILNUM_FILNUM7_12 (2 << 56) +#define FILNUM_FILNUM7_16 (3 << 56) +/* Digital noise filter (FILCLKSEL) register */ +#define FILCLKSEL_FILCLK0_0 (0 << 0) +#define FILCLKSEL_FILCLK0_1 (1 << 0) +#define FILCLKSEL_FILCLK0_2 (2 << 0) +#define FILCLKSEL_FILCLK0_3 (3 << 0) +#define FILCLKSEL_FILCLK1_0 (0 << 8) +#define FILCLKSEL_FILCLK1_1 (1 << 8) +#define FILCLKSEL_FILCLK1_2 (2 << 8) +#define FILCLKSEL_FILCLK1_3 (3 << 8) +#define FILCLKSEL_FILCLK2_0 (0 << 16) +#define FILCLKSEL_FILCLK2_1 (1 << 16) +#define FILCLKSEL_FILCLK2_2 (2 << 16) +#define FILCLKSEL_FILCLK2_3 (3 << 16) +#define FILCLKSEL_FILCLK3_0 (0 << 24) +#define FILCLKSEL_FILCLK3_1 (1 << 24) +#define FILCLKSEL_FILCLK3_2 (2 << 24) +#define FILCLKSEL_FILCLK3_3 (3 << 24) +#define FILCLKSEL_FILCLK4_0 (0 << 32) +#define FILCLKSEL_FILCLK4_1 (1 << 32) +#define FILCLKSEL_FILCLK4_2 (2 << 32) +#define FILCLKSEL_FILCLK4_3 (3 << 32) +#define FILCLKSEL_FILCLK5_0 (0 << 40) +#define FILCLKSEL_FILCLK5_1 (1 << 40) +#define FILCLKSEL_FILCLK5_2 (2 << 40) +#define FILCLKSEL_FILCLK5_3 (3 << 40) +#define FILCLKSEL_FILCLK6_0 (0 << 48) +#define FILCLKSEL_FILCLK6_1 (1 << 48) +#define FILCLKSEL_FILCLK6_2 (2 << 48) +#define FILCLKSEL_FILCLK6_3 (3 << 48) +#define FILCLKSEL_FILCLK7_0 (0 << 56) +#define FILCLKSEL_FILCLK7_1 (1 << 56) +#define FILCLKSEL_FILCLK7_2 (2 << 56) +#define FILCLKSEL_FILCLK7_3 (3 << 56) +/* Register for setting the mode of ETH MII / RGMII */ +#define ETH_MII_0_MII (1 << 0) +#define ETH_MII_1_MII (1 << 1) + +#define PFC_SET_TBL_NUM (11) +#define PFC_OFF (0) +#define PFC_ON (1) + +#define PFC_MUX_TBL_NUM (4) +#define PFC_QSPI_TBL_NUM (3) +#define PFC_SD_TBL_NUM (4) + +typedef struct { + int flg; + uintptr_t reg; + uint8_t val; +} PFC_REG_UINT8; + +typedef struct { + int flg; + uintptr_t reg; + uint32_t val; +} PFC_REG_UINT32; + +typedef struct { + int flg; + uintptr_t reg; + uint64_t val; +} PFC_REG_UINT64; + + +typedef struct { + PFC_REG_UINT8 pmc; + PFC_REG_UINT32 pfc; + PFC_REG_UINT64 iolh; + PFC_REG_UINT64 pupd; + PFC_REG_UINT64 sr; + PFC_REG_UINT64 ien; +} PFC_REGS; + + +#endif /* __PFC_REGS_H__ */ diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/include/plat_macros.S b/drivers/rz/ipl/rza/plat/renesas/rz/common/include/plat_macros.S new file mode 100644 index 00000000..16d9e1ec --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/include/plat_macros.S @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __PLAT_MACROS_S__ +#define __PLAT_MACROS_S__ + + .macro plat_crash_print_regs + .endm + +#endif /* __PLAT_MACROS_S__ */ diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/include/plat_tzc_def.h b/drivers/rz/ipl/rza/plat/renesas/rz/common/include/plat_tzc_def.h new file mode 100644 index 00000000..ec199931 --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/include/plat_tzc_def.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_TZC_DEF_H +#define PLAT_TZC_DEF_H + +/* Platform specific TrsutZone setup constants */ + +#define PLAT_TZC_REGION_ACCESS_ID_MASK U(0x3) +#define PLAT_TZC_REGION_ACCESS_RDWR(nsaid) \ + (TZC_REGION_ACCESS_RDWR(nsaid & PLAT_TZC_REGION_ACCESS_ID_MASK)) + +#define PLAT_TZC_REGION_ACCESS_S_PRIV \ + (PLAT_TZC_REGION_ACCESS_RDWR(0x1)) +#define PLAT_TZC_REGION_ACCESS_S_UNPRIV \ + (PLAT_TZC_REGION_ACCESS_RDWR(0x0) | PLAT_TZC_REGION_ACCESS_S_PRIV) +#define PLAT_TZC_REGION_ACCESS_NS_PRIV \ + (PLAT_TZC_REGION_ACCESS_RDWR(0x3) | PLAT_TZC_REGION_ACCESS_S_UNPRIV) +#define PLAT_TZC_REGION_ACCESS_NS_UNPRIV \ + (PLAT_TZC_REGION_ACCESS_RDWR(0x2) | PLAT_TZC_REGION_ACCESS_NS_PRIV) + +/* AP shared secure SRAM1 0x00010000 - 0x0001FFFF */ +#define PLAT_AP_TZC_PROT_SRAM1_BASE (0x00010000) +#define PLAT_AP_TZC_PROT_SRAM1_SIZE (0x00010000) +#define PLAT_AP_TZC_PROT_SRAM1_END \ + (PLAT_AP_TZC_PROT_SRAM1_BASE + PLAT_AP_TZC_PROT_SRAM1_SIZE - 1) + +/* AP shared secure SRAM2 0x00020000 - 0x0002FFFF */ +#define PLAT_AP_TZC_PROT_SRAM2_BASE (0x00020000) +#define PLAT_AP_TZC_PROT_SRAM2_SIZE (0x00010000) +#define PLAT_AP_TZC_PROT_SRAM2_END \ + (PLAT_AP_TZC_PROT_SRAM2_BASE + PLAT_AP_TZC_PROT_SRAM2_SIZE - 1) + +/* Trusted Firmware(BL31) secure DRAM 0x43F00000 - 0x440FFFFF */ +#define PLAT_FW_TZC_PROT_DRAM1_BASE (0x43F00000) +#define PLAT_FW_TZC_PROT_DRAM1_SIZE (0x00200000) +#define PLAT_FW_TZC_PROT_DRAM1_END \ + (PLAT_FW_TZC_PROT_DRAM1_BASE + PLAT_FW_TZC_PROT_DRAM1_SIZE - 1) + +/* OP-TEE secure DRAM 0x44100000 - 0x47DFFFFF */ +#define PLAT_TEE_TZC_PROT_DRAM1_BASE (0x44100000) +#define PLAT_TEE_TZC_PROT_DRAM1_SIZE (0x03D00000) +#define PLAT_TEE_TZC_PROT_DRAM1_END \ + (PLAT_TEE_TZC_PROT_DRAM1_BASE + PLAT_TEE_TZC_PROT_DRAM1_SIZE - 1) + +void plat_security_setup(void); + +#endif /* PLAT_TZC_DEF_H */ diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/include/platform_def.h b/drivers/rz/ipl/rza/plat/renesas/rz/common/include/platform_def.h new file mode 100644 index 00000000..0ff0766a --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/include/platform_def.h @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#ifndef __ASSEMBLER__ +#include +#endif + +#include + +/******************************************************************************* + * Platform binary types for linking + ******************************************************************************/ +#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64" +#define PLATFORM_LINKER_ARCH aarch64 + +/******************************************************************************* + * Generic platform constants + ******************************************************************************/ +#define PLATFORM_STACK_SIZE U(0x1000) + +#define PLATFORM_SYSTEM_COUNT U(1) +#define PLATFORM_CLUSTER_COUNT U(1) +#define PLATFORM_CORE_COUNT U(2) + +#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL2 +#define PLAT_NUM_PWR_DOMAINS (PLATFORM_CORE_COUNT + \ + PLATFORM_CLUSTER_COUNT + \ + PLATFORM_SYSTEM_COUNT) + +#define PLAT_MAX_RET_STATE U(1) +#define PLAT_MAX_OFF_STATE U(2) +#define PLAT_MAX_PWR_LVL_STATES U(2) + +#define MAX_IO_DEVICES U(2) +#define MAX_IO_HANDLES U(2) +#define MAX_IO_BLOCK_DEVICES U(1) + +/******************************************************************************* + * BL2 specific defines. + ******************************************************************************/ +#if !TRUSTED_BOARD_BOOT +#define BL2_BASE (0x00012000) +#define BL2_LIMIT (0x0002F000) +#else +#define BL2_BASE (0x00013000) +#define BL2_LIMIT (0x0002F000) +#endif + +/******************************************************************************* + * BL31 specific defines. + ******************************************************************************/ +#define BL31_BASE (0x44000000) +#define BL31_LIMIT (0x44040000) + +/******************************************************************************* + * BL32 specific defines. + ******************************************************************************/ +#ifndef SPD_none +#define BL32_BASE (0x44100000) +#define BL32_LIMIT (BL32_BASE + 0x100000) +#endif + +/******************************************************************************* + * BL33 + ******************************************************************************/ +#define BL33_BASE (0x50000000) +#define BL33_LIMIT (BL33_BASE + 0x08000000) + +/******************************************************************************* + * BSP + ******************************************************************************/ +#define BSP_BASE (0x50000000) +#define BSP_LIMIT (BSP_BASE + 0x08000000) + +/******************************************************************************* + * Platform specific page table and MMU setup constants + ******************************************************************************/ +#if IMAGE_BL2 +#if RZA3 +#define MAX_XLAT_TABLES U(4) +#else +#define MAX_XLAT_TABLES U(6) +#endif +#define MAX_MMAP_REGIONS U(9) +#elif IMAGE_BL31 +#define MAX_XLAT_TABLES U(6) +#define MAX_MMAP_REGIONS U(9) +#endif + +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32) +#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32) + +/******************************************************************************* + * Determining the use of FIP format + ******************************************************************************/ +#define RZ_NOFIP (0) +#define RZ_FIP (1) + +#define ARMv8A (1) + +#define RZ_APP_PAYLOAD_OFFSET (0x200) + +/******************************************************************************* + * Declarations and constants to access the mailboxes safely. Each mailbox is + * aligned on the biggest cache line size in the platform. This is known only + * to the platform as it might have a combination of integrated and external + * caches. Such alignment ensures that two maiboxes do not sit on the same cache + * line at any cache level. They could belong to different cpus/clusters & + * get written while being protected by different locks causing corruption of + * a valid mailbox address. + ******************************************************************************/ +#define CACHE_WRITEBACK_SHIFT U(6) +#define CACHE_WRITEBACK_GRANULE (U(1) << CACHE_WRITEBACK_SHIFT) + +#endif /* PLATFORM_DEF_H */ diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/include/rz_private.h b/drivers/rz/ipl/rza/plat/renesas/rz/common/include/rz_private.h new file mode 100644 index 00000000..d20e8d66 --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/include/rz_private.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __RZ_PRIVATE_H__ +#define __RZ_PRIVATE_H__ + +#include + +/* plat_gic.c */ +void plat_gic_driver_init(void); +void plat_gic_init(void); +void plat_gic_cpuif_enable(void); +void plat_gic_cpuif_disable(void); +void plat_gic_pcpu_init(void); + +/* plat_security.c */ +void plat_tzc400_setup(uintptr_t tzc_base); + +/* plat_storage.c */ +void rz_io_setup(void); + +/* plat_image_load.c */ +#if (APPLOAD == RZ_NOFIP) +void rza_load_fsp(void); +#endif /* (APPLOAD == RZ_NOFIP) */ +void rza_print_descs(void); + +#if RZ_TEST +void rz_run_tests(void); +#define RZ_RUN_TESTS() rz_run_tests() +#else +#define RZ_RUN_TESTS() /* dummy */ +#endif /* RZ_FLASH_TEST */ + +typedef struct bl2_to_bl31_params_mem { + entry_point_info_t bl32_ep_info; + entry_point_info_t bl33_ep_info; +} bl2_to_bl31_params_mem_t; + +#endif /* __RZ_PRIVATE_H__ */ diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/include/rz_sip_svc.h b/drivers/rz/ipl/rza/plat/renesas/rz/common/include/rz_sip_svc.h new file mode 100644 index 00000000..62ed2b3f --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/include/rz_sip_svc.h @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2020-2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __RZ_SIP_SVC_H__ +#define __RZ_SIP_SVC_H__ + +/* Function ID to get Device ID */ +#define RZ_SIP_SVC_GET_DEVID U(0x82000010) + +/* Function ID to get Chip ID */ +#define RZ_SIP_SVC_GET_CHIPID U(0x82000011) + +#endif /* __RZ_SIP_SVC_H__ */ diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/include/rza3ul_def.h b/drivers/rz/ipl/rza/plat/renesas/rz/common/include/rza3ul_def.h new file mode 100644 index 00000000..c3f51396 --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/include/rza3ul_def.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2022, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __RZA3_DEF_H__ +#define __RZA3_DEF_H__ + +#define RZA3_INTERNAL_MEMORY_BASE (0x00000000) +#define RZA3_DEVICE_BASE (0x10000000) +/* move to platform.mk */ +/*#define RZA3_XSPI_MEMORY_BASE (0x20000000) */ +#define RZA3_DDR_MEMORY_BASE0 (0x40000000) +#define RZA3_DDR_MEMORY_BASE1 (0x50000000) +#define RZA3_DDR_MEMORY_BASE2 (0x60000000) +#define RZA3_DDR_MEMORY_BASE3 (0x70000000) + +#define RZA3_INTERNAL_MEMORY_MMU_SIZE (0x00200000) +#define RZA3_DEVICE_MMU_SIZE (0x10000000) +#define RZA3_XSPI_MEMORY_MMU_SIZE (0x10000000) +#define RZA3_DDR_MEMORY_MMU_SIZE (0x10000000) + +#endif /* __RZA3_DEF_H__ */ diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/include/rza_ipl_version.h b/drivers/rz/ipl/rza/plat/renesas/rz/common/include/rza_ipl_version.h new file mode 100644 index 00000000..538e9562 --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/include/rza_ipl_version.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2022, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _RZA_IPL_VERSION_H_ +#define _RZA_IPL_VERSION_H_ + +#define RZA_IPL_VERSION_STRING "v2.1.0" + +#endif /* _RZA_IPL_VERSION_H_ */ diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/include/rza_mmu.h b/drivers/rz/ipl/rza/plat/renesas/rz/common/include/rza_mmu.h new file mode 100644 index 00000000..db214d30 --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/include/rza_mmu.h @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2022, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _RZA_MMU_H_ +#define _RZA_MMU_H_ + +#include "platform_def.h" + +/*********************************************************************************************************************** + * Includes + **********************************************************************************************************************/ + +/* Common macro for FSP header files. There is also a corresponding FSP_FOOTER macro at the end of this file. */ + +/*********************************************************************************************************************** + * Macro definitions + **********************************************************************************************************************/ + +/* descripter bits define */ +#define RZA_MMU_DESC_XN (1 << 54) +#define RZA_MMU_DESC_PXN (1 << 53) +#define RZA_MMU_DESC_AF (1 << 10) +#define RZA_MMU_DESC_SH_NS (0 << 8) +#define RZA_MMU_DESC_SH_OS (2 << 8) +#define RZA_MMU_DESC_SH_IS (3 << 8) +#define RZA_MMU_DESC_AP_RW_NONE (0 << 6) +#define RZA_MMU_DESC_AP_RW_RW (1 << 6) +#define RZA_MMU_DESC_AP_RO_NONE (2 << 6) +#define RZA_MMU_DESC_AP_RO_RO (3 << 6) +#define RZA_MMU_DESC_NS (1 << 5) + +/* descripter index for MAIR register */ +#define RZA_MMU_DESC_MAIR_INDEX_0 (0 << 2) +#define RZA_MMU_DESC_MAIR_INDEX_1 (1 << 2) +#define RZA_MMU_DESC_MAIR_INDEX_2 (2 << 2) +#define RZA_MMU_DESC_MAIR_INDEX_3 (3 << 2) +#define RZA_MMU_DESC_MAIR_INDEX_4 (4 << 2) +#define RZA_MMU_DESC_MAIR_INDEX_5 (5 << 2) +#define RZA_MMU_DESC_MAIR_INDEX_6 (6 << 2) +#define RZA_MMU_DESC_MAIR_INDEX_7 (7 << 2) + +/* index number each memory type */ +/* 0: normal memory, cacheable + 1: device + 2: normal memory, non-cacheable */ +#define RZA_MMU_ATTR_NON_CACHEABLE_INDEX (2) +#define RZA_MMU_ATTR_DEVICE_INDEX (1) +#define RZA_MMU_ATTR_IWBWA_OWBWA_NTR_INDEX (0) + +/* Normal Memory, Outer/Inner Non-cacheable */ +#define RZA_MMU_ATTR_NON_CACHEABLE MAKE_MAIR_NORMAL_MEMORY(MAIR_NORM_NC, MAIR_NORM_NC) +/* Device */ +#define RZA_MMU_ATTR_DEVICE MAIR_DEV_nGnRE +/* Normal Memory, Outer/Inner Write-Back */ +#define RZA_MMU_ATTR_IWBWA_OWBWA_NTR MAKE_MAIR_NORMAL_MEMORY(MAIR_NORM_WB_NTR_RWA, MAIR_NORM_WB_NTR_RWA) + +#define RZA_MMU_ATTR_FIELD_WIDTH (8) +#define RZA_MMU_MAIR_ATTR_SET(attr, index) ((attr) << ((index) * RZA_MMU_ATTR_FIELD_WIDTH)) + +#define RZA_MMU_ATTR_NEXT_TBL (0x03) + +/* descripter entry type */ +#define RZA_MMU_DESC_TABLE_DESC (3 << 0) +#define RZA_MMU_DESC_BLOCK_ENTRY_L12 (1 << 0) +#define RZA_MMU_DESC_BLOCK_ENTRY_L3 (3 << 0) + +/* max address */ +#define RZA_MMU_PHY_ADDR_MAX (PLAT_PHY_ADDR_SPACE_SIZE - 1) +#define RZA_MMU_VIRT_ADDR_MAX (PLAT_VIRT_ADDR_SPACE_SIZE - 1) +#define RZA_MMU_PHY_SIZE_MAX (PLAT_PHY_ADDR_SPACE_SIZE) +#define RZA_MMU_VIRT_SIZE_MAX (PLAT_VIRT_ADDR_SPACE_SIZE) + +/* exception evel */ +#define RZA_MMU_CURRENT_EL0 (0x00) +#define RZA_MMU_CURRENT_EL1 (0x04) +#define RZA_MMU_CURRENT_EL2 (0x08) +#define RZA_MMU_CURRENT_EL3 (0x0C) + +/* Virtual space size per entry each level */ +#define RZA_MMU_L1_ENTRY_SIZE (0x40000000) /* 1GB */ +#define RZA_MMU_L2_ENTRY_SIZE (0x00200000) /* 2MB */ +#define RZA_MMU_L3_ENTRY_SIZE (0x00001000) /* 4KB */ + +/* descripter size (byte) */ +#define RZA_MMU_TABLE_DESC_SIZE (8) + +/* start virtual address each blocks */ +#define RZA_MMU_N1_TABLE_START_VADDR (0x00000000) +#define RZA_MMU_N2_TABLE_START_VADDR (0x40000000) +#define RZA_MMU_N3_TABLE_START_VADDR (0x80000000) +#define RZA_MMU_N4_TABLE_START_VADDR (0xC0000000) + +/* width of virtual space each blocks */ +#define RZA_MMU_TTB_BLOCK_WIDTH (0x40000000) + +#define RZA_MMU_LEVEL2_TABLE_INDEX_MAX (4) +#define RZA_MMU_TABLE_ENTRY (512) + +/* MMU attribute setting (user setting) */ +#define RZA_MMU_ATTRIBUTE_NORMAL_CACHEABLE (RZA_MMU_DESC_AF | RZA_MMU_DESC_SH_IS | RZA_MMU_DESC_AP_RW_RW | \ + RZA_MMU_DESC_MAIR_INDEX_0) +#define RZA_MMU_ATTRIBUTE_NORMAL_UNCACHE (RZA_MMU_DESC_AF | RZA_MMU_DESC_SH_IS | RZA_MMU_DESC_AP_RW_RW | \ + RZA_MMU_DESC_MAIR_INDEX_2) +#define RZA_MMU_ATTRIBUTE_DEVICE (RZA_MMU_DESC_AF | RZA_MMU_DESC_SH_IS | RZA_MMU_DESC_AP_RW_RW | \ + RZA_MMU_DESC_MAIR_INDEX_1) +#define RZA_MMU_ATTRIBUTE_ACCESS_FAULT (0x00000000) +#define RZA_MMU_ATTRIBUTE_CONFIG_END (0xFFFFFFFF) + +/* xSPI device extended configuration structure */ +typedef struct mmu_pagetable_config +{ + uint64_t vaddress; + uint64_t paddress; + uint64_t size; + uint64_t attribute; +} rza_mmu_pgtbl_cfg_t; + +/* external functions */ +int plat_mmu_init(const rza_mmu_pgtbl_cfg_t *config_table); +void plat_mmu_enable(void); + +#endif /* _RZA_MMU_H_ */ diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/include/rza_printf.h b/drivers/rz/ipl/rza/plat/renesas/rz/common/include/rza_printf.h new file mode 100644 index 00000000..13dd84a1 --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/include/rza_printf.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2022, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _RZA_PRINTF_H_ +#define _RZA_PRINTF_H_ + +#include + +/* This header file defines printf that outputs logs with RZ/A3UL. */ + +#define RZ_UNUSED_PARAM(param) (void)(param) +#define STRING(str) #str + +#if (RZA3 == 1) +#if (DEBUG == 1) +#define RZA_PRINTF_VERBOSE(...) printf(__VA_ARGS__) +#else +#define RZA_PRINTF_VERBOSE(...) +#endif /* DEBUG == 1 */ + +#define RZA_PRINTF(...) printf(__VA_ARGS__) +#define RZA_PRINTF_NOTICE(...) RZA_PRINTF_VERBOSE(__VA_ARGS__) +#define RZA_PRINTF_ERROR(...) RZA_PRINTF_VERBOSE(__VA_ARGS__) +#define RZA_PRINTF_WARN(...) RZA_PRINTF_VERBOSE(__VA_ARGS__) +#define RZA_PRINTF_INFO(...) RZA_PRINTF_VERBOSE(__VA_ARGS__) +#else + +#define RZA_PRINTF_VERBOSE(...) +#define RZA_PRINTF(...) +#define RZA_PRINTF_NOTICE(...) NOTICE(__VA_ARGS__) +#define RZA_PRINTF_ERROR(...) ERROR(__VA_ARGS__) +#define RZA_PRINTF_WARN(...) WARN(__VA_ARGS__) +#define RZA_PRINTF_INFO(...) INFO(__VA_ARGS__) + +#endif /* RZA3 == 1 */ + +#endif /* _RZA_PRINTF_H_ */ diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/include/rzg2l_def.h b/drivers/rz/ipl/rza/plat/renesas/rz/common/include/rzg2l_def.h new file mode 100644 index 00000000..3c03b2df --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/include/rzg2l_def.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __RZG2L_DEF_H__ +#define __RZG2L_DEF_H__ + +#define RZG2L_BOOT_ROM_BASE (0x00000000) +#define RZG2L_MSRAM_BASE (0x00010000) +#define RZG2L_ASRAM_BASE (0x00020000) +#define RZG2L_DEVICE_BASE (0x10000000) +#define RZG2L_SCIF0_BASE (0x1004B800) +#define RZG2L_SPIMULT_BASE (0x10060000) +#define RZG2L_SPIMULT_WBUF_BASE (0x10070000) +#define RZG2L_SYC_BASE (0x11000000) +#define RZG2L_CPG_BASE (0x11010000) +#define RZG2L_SYSC_BASE (0x11020000) +#define RZG2L_GPIO_BASE (0x11030000) +#define RZG2L_TZC_ASRAM_BASE (0x11040000) +#define RZG2L_TZC_MSRAM_BASE (0x11050000) +#define RZG2L_TZC_SPI_BASE (0x11060000) +#define RZG2L_TZC_DDR_BASE (0x11070000) +#define RZG2L_DDR_PHY_BASE (0x11400000) +#define RZG2L_DDR_MEMC_BASE (0x11410000) +#define RZG2L_OTP_BASE (0x11860000) +#define RZG2L_GIC_BASE (0x11900000) +#define RZG2L_SD0_BASE (0x11C00000) +#define RZG2L_SPIROM_BASE (0x20000000) +#define RZG2L_DDR1_BASE (0x40000000) +#define RZG2L_DDR2_BASE (0x80000000) +#define RZG2L_DDR3_BASE (0x100000000) + +#define RZG2L_GICD_BASE (RZG2L_GIC_BASE) +#define RZG2L_GICR_BASE (RZG2L_GIC_BASE + 0x00040000) + +#define RZG2L_SRAM_BASE (RZG2L_MSRAM_BASE) + +#define RZG2L_BOOT_ROM_SIZE (0x00010000 - RZG2L_BOOT_ROM_BASE) +#define RZG2L_MSRAM_SIZE (0x00020000 - RZG2L_MSRAM_BASE) +#define RZG2L_ASRAM_SIZE (0x00030000 - RZG2L_ASRAM_BASE) +#define RZG2L_SRAM_SIZE (RZG2L_MSRAM_SIZE + RZG2L_ASRAM_SIZE) +#define RZG2L_DEVICE_SIZE (0x15000000 - RZG2L_DEVICE_BASE) +#define RZG2L_SPIROM_SIZE (0x30000000 - RZG2L_SPIROM_BASE) +#define RZG2L_DDR1_SIZE (RZG2L_DDR2_BASE - RZG2L_DDR1_BASE) +#define RZG2L_DDR2_SIZE (RZG2L_DDR3_BASE - RZG2L_DDR2_BASE) + +#define RZG2L_SPIROM_FIP_BASE (RZG2L_SPIROM_BASE + 0x0001D200) +#define RZG2L_SPIROM_FIP_SIZE (0x30000000 - RZG2L_SPIROM_FIP_BASE) + +#define RZG2L_OTP_DEVICE_INFO (RZG2L_OTP_BASE + 0x1178) + +#define RZG2L_EMMC_FIP_BASE (0x00020000) +#define RZG2L_EMMC_FIP_SIZE (0x001DFFFF) + +#define RZG2L_SYC_INCK_HZ (24000000) +#define RZG2L_UART_INCK_HZ (100000000) +#define RZG2L_UART_BARDRATE (115200) + +/* Boot Info base address */ +#define RZG2L_BOOTINFO_BASE (RZG2L_SRAM_BASE) + +/* Base address where parameters to BL31 are stored */ +#define PARAMS_BASE (RZG2L_SRAM_BASE + 0x0001F000) +#define PARAMS_SIZE (0x1000) + +#endif /* __RZG2L_DEF_H__ */ diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/include/scifa.h b/drivers/rz/ipl/rza/plat/renesas/rz/common/include/scifa.h new file mode 100644 index 00000000..e78c5f32 --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/include/scifa.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __SCIFA_H__ +#define __SCIFA_H__ + +#ifndef __ASSEMBLER__ + +#include +#include + +int console_rzg2l_register(uintptr_t baseaddr, uint32_t clock, + uint32_t baud, console_t *console); + +#endif /* __ASSEMBLER__ */ + +#endif /* __SCIFA_H__ */ diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/include/spim.h b/drivers/rz/ipl/rza/plat/renesas/rz/common/include/spim.h new file mode 100644 index 00000000..4e035793 --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/include/spim.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _SPIM_API_H_ +#define _SPIM_API_H_ +#include +#include + +#include "xspi_api.h" + +/** xSPI device control structure */ +typedef struct st_spim_ctrl +{ + bool opened; + uintptr_t reg_base; + uintptr_t mmap_base; + size_t mmap_size; + uint8_t channel; +} spim_ctrl_t; + +/** xSPI device extended configuration structure */ +typedef struct st_spim_ext +{ + bool voltage_is_3300mv; +} spim_ext_t; + +extern const xspi_api_t spim_api; + +#endif /* _SPIM_API_H_ */ + diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/include/spim_regs.h b/drivers/rz/ipl/rza/plat/renesas/rz/common/include/spim_regs.h new file mode 100644 index 00000000..d3eb5609 --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/include/spim_regs.h @@ -0,0 +1,295 @@ +/* + * Copyright (c) 2022, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _SPIM_REG_H_ +#define _SPIM_REG_H_ + +#define SPIM_CMNCR 0x0000 +#define SPIM_SSLDR 0x0004 +#define SPIM_DRCR 0x000c +#define SPIM_DRCMR 0x0010 +#define SPIM_DREAR 0x0014 +#define SPIM_DROPR 0x0018 +#define SPIM_DRENR 0x001c +#define SPIM_SMCR 0x0020 +#define SPIM_SMCMR 0x0024 +#define SPIM_SMADR 0x0028 +#define SPIM_SMOPR 0x002c +#define SPIM_SMENR 0x0030 +#define SPIM_SMRDR0 0x0038 +#define SPIM_SMRDR1 0x003c +#define SPIM_SMWDR0 0x0040 +#define SPIM_SMWDR1 0x0044 +#define SPIM_CMNSR 0x0048 +#define SPIM_DRDMCR 0x0058 +#define SPIM_DRDRENR 0x005c +#define SPIM_SMDMCR 0x0060 +#define SPIM_SMDRENR 0x0064 +#define SPIM_PHYADJ1 0x0070 +#define SPIM_PHYADJ2 0x0074 +#define SPIM_PHYCNT 0x007c +#define SPIM_PHYOFFSET1 0x0080 +#define SPIM_PHYOFFSET2 0x0084 +#define SPIM_PHYINT 0x0088 +#define SPIM_BUFFER 0x10000 + +/* CMNCR field */ +#define SPIM_CMNCR_MD_POS 31 +#define SPIM_CMNCR_MD (1u << SPIM_CMNCR_MD_POS) +#define SPIM_CMNCR_MOIIO3_POS 22 +#define SPIM_CMNCR_MOIIO3 (3u << SPIM_CMNCR_MOIIO3_POS) +#define SPIM_CMNCR_MOIIO2_POS 20 +#define SPIM_CMNCR_MOIIO2 (3u << SPIM_CMNCR_MOIIO2_POS) +#define SPIM_CMNCR_MOIIO1_POS 18 +#define SPIM_CMNCR_MOIIO1 (3u << SPIM_CMNCR_MOIIO1_POS) +#define SPIM_CMNCR_MOIIO0_POS 16 +#define SPIM_CMNCR_MOIIO0 (3u << SPIM_CMNCR_MOIIO0_POS) +#define SPIM_CMNCR_IO3FV_POS 14 +#define SPIM_CMNCR_IO3FV (3u << SPIM_CMNCR_IO3FV_POS) +#define SPIM_CMNCR_IO2FV_POS 12 +#define SPIM_CMNCR_IO2FV (3u << SPIM_CMNCR_IO2FV_POS) +#define SPIM_CMNCR_IO0FV_POS 8 +#define SPIM_CMNCR_IO0FV (3u << SPIM_CMNCR_IO0FV_POS) +#define SPIM_CMNCR_IO_LOW 0u +#define SPIM_CMNCR_IO_HIGH 1u +#define SPIM_CMNCR_IO_KEEP 2u +#define SPIM_CMNCR_IO_HIZ 3u +#define SPIM_CMNCR_BSZ_POS 0 +#define SPIM_CMNCR_BSZ (3u << SPIM_CMNCR_BSZ_POS) +#define SPIM_CMNCR_BSZ_SINGLE 0u +#define SPIM_CMNCR_BSZ_DUAL 1u +#define SPIM_CMNCR_BSZ_OCTA 1u +#define SPIM_CMNCR_BSZ_HYPER 1u + +/* SSLDR field */ +#define SPIM_SSLDR_SPNDL_POS 16 +#define SPIM_SSLDR_SPNDL (7u << SPIM_SSLDR_SPNDL_POS) +#define SPIM_SSLDR_SLNDL_POS 8 +#define SPIM_SSLDR_SLNDL (7u << SPIM_SSLDR_SLNDL_POS) +#define SPIM_SSLDR_SCKDL_POS 0 +#define SPIM_SSLDR_SCKDL (7u << SPIM_SSLDR_SCKDL_POS) + +/* DRCR field */ +#define SPIM_DRCR_SSLN_POS 24 +#define SPIM_DRCR_SSLN (1u << SPIM_DRCR_SSLN_POS) +#define SPIM_DRCR_RBURST_POS 16 +#define SPIM_DRCR_RBURST (31u << SPIM_DRCR_RBURST_POS) +#define SPIM_DRCR_RCF_POS 9 +#define SPIM_DRCR_RCF (1u << SPIM_DRCR_RCF_POS) +#define SPIM_DRCR_RBE_POS 8 +#define SPIM_DRCR_RBE (1u << SPIM_DRCR_RBE_POS) +#define SPIM_DRCR_SSLE_POS 0 +#define SPIM_DRCR_SSLE (1u << SPIM_DRCR_SSLE_POS) + +/* DREAR field */ +#define SPIM_DREAR_EAV_POS 16 +#define SPIM_DREAR_EAV (255u << SPIM_DREAR_EAV_POS) +#define SPIM_DREAR_EAC_POS 0 +#define SPIM_DREAR_EAC (7u << SPIM_DREAR_EAC_POS) + +/* DRCMR field */ +#define SPIM_DRCMR_CMD_POS 16 +#define SPIM_DRCMR_CMD (255u << SPIM_DRCMR_CMD_POS) +#define SPIM_DRCMR_OCMD_POS 0 +#define SPIM_DRCMR_OCMD (255u << SPIM_DRCMR_OCMD_POS) + +/* DROPR field */ +#define SPIM_DROPR_OPD3_POS 24 +#define SPIM_DROPR_OPD3 (255u << SPIM_DROPR_OPD3_POS) +#define SPIM_DROPR_OPD2_POS 16 +#define SPIM_DROPR_OPD2 (255u << SPIM_DROPR_OPD2_POS) +#define SPIM_DROPR_OPD1_POS 8 +#define SPIM_DROPR_OPD1 (255u << SPIM_DROPR_OPD1_POS) +#define SPIM_DROPR_OPD0_POS 0 +#define SPIM_DROPR_OPD0 (255u << SPIM_DROPR_OPD0_POS) + +/* CMNSR field */ +#define SPIM_CMNSR_SSLF_POS 1 +#define SPIM_CMNSR_SSLF (1u << SPIM_CMNSR_SSLF_POS) +#define SPIM_CMNSR_TEND_POS 0 +#define SPIM_CMNSR_TEND (1u << SPIM_CMNSR_TEND_POS) + +/* DRDMCR field */ +#define SPIM_DRDMCR_DMCYC_POS 0 +#define SPIM_DRDMCR_DMCYC (31u << SPIM_DRDMCR_DMCYC_POS) + +/* DRENR field */ +#define SPIM_DRENR_CDB_POS 30 +#define SPIM_DRENR_CDB (3u << SPIM_DRENR_CDB_POS) +#define SPIM_DRENR_OCDB_POS 28 +#define SPIM_DRENR_OCDB (3u << SPIM_DRENR_OCDB_POS) +#define SPIM_DRENR_ADB_POS 24 +#define SPIM_DRENR_ADB (3u << SPIM_DRENR_ADB_POS) +#define SPIM_DRENR_OPDB_POS 20 +#define SPIM_DRENR_OPDB (3u << SPIM_DRENR_OPDB_POS) +#define SPIM_DRENR_DRDB_POS 16 +#define SPIM_DRENR_DRDB (3u << SPIM_DRENR_DRDB_POS) +#define SPIM_DRENR_DB_4BIT 2u +#define SPIM_DRENR_DB_1BIT 0u +#define SPIM_DRENR_DME_POS 15 +#define SPIM_DRENR_DME (1u << SPIM_DRENR_DME_POS) +#define SPIM_DRENR_CDE_POS 14 +#define SPIM_DRENR_CDE (1u << SPIM_DRENR_CDE_POS) +#define SPIM_DRENR_OCDE_POS 12 +#define SPIM_DRENR_OCDE (1u << SPIM_DRENR_OCDE_POS) +#define SPIM_DRENR_ADE_POS 8 +#define SPIM_DRENR_ADE (15u << SPIM_DRENR_ADE_POS) +#define SPIM_DRENR_ADE_3BYTE 7u +#define SPIM_DRENR_ADE_4BYTE 15u +#define SPIM_DRENR_ADE_OPI 12u +#define SPIM_DRENR_ADE_HYPER 4u +#define SPIM_DRENR_ADE_NONE 0u +#define SPIM_DRENR_OPDE_POS 4 +#define SPIM_DRENR_OPDE (15u << SPIM_DRENR_OPDE_POS) +#define SPIM_DRENR_OPDE_NONE 0u +#define SPIM_DRENR_OPDE_1BYTE 8u +#define SPIM_DRENR_OPDE_2BYTE 12u +#define SPIM_DRENR_OPDE_3BYTE 14u +#define SPIM_DRENR_OPDE_4BYTE 15u + +/* SMCR field */ +#define SPIM_SMCR_SSLKP_POS 8 +#define SPIM_SMCR_SSLKP (1u << SPIM_SMCR_SSLKP_POS) +#define SPIM_SMCR_SPIRE_POS 2 +#define SPIM_SMCR_SPIRE (1u << SPIM_SMCR_SPIRE_POS) +#define SPIM_SMCR_SPIWE_POS 1 +#define SPIM_SMCR_SPIWE (1u << SPIM_SMCR_SPIWE_POS) +#define SPIM_SMCR_SPIE_POS 0 +#define SPIM_SMCR_SPIE (1u << SPIM_SMCR_SPIE_POS) + +/* SMCMR field */ +#define SPIM_SMCMR_CMD_POS 16 +#define SPIM_SMCMR_CMD (255u << SPIM_SMCMR_CMD_POS) +#define SPIM_SMCMR_OCMD_POS 0 +#define SPIM_SMCMR_OCMD (255u << SPIM_SMCMR_OCMD_POS) + +/* SMOPR field */ +#define SPIM_SMOPR_OPD3_POS 24 +#define SPIM_SMOPR_OPD3 (255u << SPIM_SMOPR_OPD3_POS) +#define SPIM_SMOPR_OPD2_POS 16 +#define SPIM_SMOPR_OPD2 (255u << SPIM_SMOPR_OPD2_POS) +#define SPIM_SMOPR_OPD1_POS 8 +#define SPIM_SMOPR_OPD1 (255u << SPIM_SMOPR_OPD1_POS) +#define SPIM_SMOPR_OPD0_POS 0 +#define SPIM_SMOPR_OPD0 (255u << SPIM_SMOPR_OPD0_POS) + +/* SMENR field */ +#define SPIM_SMENR_CDB_POS 30 +#define SPIM_SMENR_CDB (3u << SPIM_SMENR_CDB_POS) +#define SPIM_SMENR_OCDB_POS 28 +#define SPIM_SMENR_OCDB (3u << SPIM_SMENR_OCDB_POS) +#define SPIM_SMENR_ADB_POS 24 +#define SPIM_SMENR_ADB (3u << SPIM_SMENR_ADB_POS) +#define SPIM_SMENR_OPDB_POS 20 +#define SPIM_SMENR_OPDB (3u << SPIM_SMENR_OPDB_POS) +#define SPIM_SMENR_SPIDB_POS 16 +#define SPIM_SMENR_SPIDB (3u << SPIM_SMENR_SPIDB_POS) +#define SPIM_SMENR_DB_4BIT 2u +#define SPIM_SMENR_DB_1BIT 0u +#define SPIM_SMENR_DME_POS 15 +#define SPIM_SMENR_DME (1u << SPIM_SMENR_DME_POS) +#define SPIM_SMENR_CDE_POS 14 +#define SPIM_SMENR_CDE (1u << SPIM_SMENR_CDE_POS) +#define SPIM_SMENR_OCDE_POS 12 +#define SPIM_SMENR_OCDE (1u << SPIM_SMENR_OCDE_POS) +#define SPIM_SMENR_ADE_POS 8 +#define SPIM_SMENR_ADE (15u << SPIM_SMENR_ADE_POS) +#define SPIM_SMENR_ADE_3BYTE 7u +#define SPIM_SMENR_ADE_4BYTE 15u +#define SPIM_SMENR_ADE_OPI 12u +#define SPIM_SMENR_ADE_HYPER 4u +#define SPIM_SMENR_ADE_NONE 0u +#define SPIM_SMENR_OPDE_POS 4 +#define SPIM_SMENR_OPDE (15u << SPIM_SMENR_OPDE_POS) +#define SPIM_SMENR_OPDE_NONE 0u +#define SPIM_SMENR_OPDE_1BYTE 8u +#define SPIM_SMENR_OPDE_2BYTE 12u +#define SPIM_SMENR_OPDE_3BYTE 14u +#define SPIM_SMENR_OPDE_4BYTE 15u +#define SPIM_SMENR_SPIDE_POS 0 +#define SPIM_SMENR_SPIDE (15u << SPIM_SMENR_SPIDE_POS) +#define SPIM_SMENR_SPIDE_NONE 0u +#define SPIM_SMENR_SPIDE_BYTE 8u +#define SPIM_SMENR_SPIDE_WORD 12u +#define SPIM_SMENR_SPIDE_LONG 15u + +/* DRDRENR field */ +#define SPIM_DRDRENR_HYPE_POS 12 +#define SPIM_DRDRENR_HYPE (7u << SPIM_DRDRENR_HYPE_POS) +#define SPIM_DRDRENR_SPI 0u +#define SPIM_DRDRENR_DDR 5u +#define SPIM_DRDRENR_OCTADDR 4u +#define SPIM_DRDRENR_ADDRE_POS 8 +#define SPIM_DRDRENR_ADDRE (1u << SPIM_DRDRENR_ADDRE_POS) +#define SPIM_DRDRENR_OPDRE_POS 4 +#define SPIM_DRDRENR_OPDRE (1u << SPIM_DRDRENR_OPDRE_POS) +#define SPIM_DRDRENR_DRDRE_POS 0 +#define SPIM_DRDRENR_DRDRE (1u << SPIM_DRDRENR_DRDRE_POS) + +/* SMDMCR field */ +#define SPIM_SMDMCR_DMCYC_POS 0 +#define SPIM_SMDMCR_DMCYC (31u << SPIM_SMDMCR_DMCYC_POS) + +/* SMDRENR field */ +#define SPIM_SMDRENR_HYPE_POS 12 +#define SPIM_SMDRENR_HYPE (7u << SPIM_SMDRENR_HYPE_POS) +#define SPIM_SMDRENR_SPI 0u +#define SPIM_SMDRENR_DDR 5u +#define SPIM_SMDRENR_OCTADDR 4u +#define SPIM_SMDRENR_ADDRE_POS 8 +#define SPIM_SMDRENR_ADDRE (1u << SPIM_SMDRENR_ADDRE_POS) +#define SPIM_SMDRENR_OPDRE_POS 4 +#define SPIM_SMDRENR_OPDRE (1u << SPIM_SMDRENR_OPDRE_POS) +#define SPIM_SMDRENR_DRDRE_POS 0 +#define SPIM_SMDRENR_DRDRE (1u << SPIM_SMDRENR_DRDRE_POS) + +/* PHYCNT field */ +#define SPIM_PHYCNT_CAL_POS 31 +#define SPIM_PHYCNT_CAL (1u << SPIM_PHYCNT_CAL_POS) +#define SPIM_PHYCNT_ALT_ALIGN_POS 30 +#define SPIM_PHYCNT_ALT_ALIGN (1u << SPIM_PHYCNT_ALT_ALIGN_POS) +#define SPIM_PHYCNT_OCTA_POS 22 +#define SPIM_PHYCNT_OCTA (3u << SPIM_PHYCNT_OCTA_POS) +#define SPIM_PHYCNT_OCTA_DDR_ALT 1u +#define SPIM_PHYCNT_OCTA_DDR_SEQ 2u +#define SPIM_PHYCNT_EXDS_POS 21 +#define SPIM_PHYCNT_EXDS (1u << SPIM_PHYCNT_EXDS_POS) +#define SPIM_PHYCNT_OCT_POS 20 +#define SPIM_PHYCNT_OCT (1u << SPIM_PHYCNT_OCT_POS) +#define SPIM_PHYCNT_HS_POS 18 +#define SPIM_PHYCNT_HS (1u << SPIM_PHYCNT_HS_POS) +#define SPIM_PHYCNT_CKSEL_POS 16 +#define SPIM_PHYCNT_CKSEL (3u << SPIM_PHYCNT_CKSEL_POS) +#define SPIM_PHYCNT_WBUF2_POS 4 +#define SPIM_PHYCNT_WBUF2 (1u << SPIM_PHYCNT_WBUF2_POS) +#define SPIM_PHYCNT_WBUF_POS 2 +#define SPIM_PHYCNT_WBUF (1u << SPIM_PHYCNT_WBUF_POS) +#define SPIM_PHYCNT_PHYMEM_POS 0 +#define SPIM_PHYCNT_PHYMEM (3u << SPIM_PHYCNT_PHYMEM_POS) +#define SPIM_PHYCNT_SDR 0u +#define SPIM_PHYCNT_DDR 1u +#define SPIM_PHYCNT_HYPER 3u + +/* PHYOFFSET1 field */ +#define SPIM_PHYOFFSET1_DDRTMG_POS 28 +#define SPIM_PHYOFFSET1_DDRTMG (7u << SPIM_PHYOFFSET1_DDRTMG_POS) +#define SPIM_PHYOFFSET1_DDR 2u +#define SPIM_PHYOFFSET1_SDR 3u + +/* PHYOFFSET2 field */ +#define SPIM_PHYOFFSET2_OCTTMG_POS 8 +#define SPIM_PHYOFFSET2_OCTTMG (7u << SPIM_PHYOFFSET2_OCTTMG_POS) +#define SPIM_PHYOFFSET2_SPI 4u +#define SPIM_PHYOFFSET2_HYPER 4u +#define SPIM_PHYOFFSET2_SPI_WBUF 0u +#define SPIM_PHYOFFSET2_OPI 3u + + + + +#endif /* _SPIM_REG_H_ */ + + diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/include/syc.h b/drivers/rz/ipl/rza/plat/renesas/rz/common/include/syc.h new file mode 100644 index 00000000..089c3373 --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/include/syc.h @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __SYC_H__ +#define __SYC_H__ + +void syc_init(unsigned int freq); +unsigned int syc_get_freq(void); + +#endif /* __SYC_H__ */ diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/include/sys.h b/drivers/rz/ipl/rza/plat/renesas/rz/common/include/sys.h new file mode 100644 index 00000000..ea8119e9 --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/include/sys.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __SYS_H__ +#define __SYS_H__ + +#define MASK_BOOTM_DEVICE (0x0F) +#define MASK_BOOTM_SECURE (0x10) + +#define BOOT_MODE_ESD (0) +#define BOOT_MODE_EMMC_1_8 (1) +#define BOOT_MODE_EMMC_3_3 (2) +#define BOOT_MODE_SPI_1_8 (3) +#define BOOT_MODE_SPI_3_3 (4) +#define BOOT_MODE_SCIF (5) +#define BOOT_MODE_NAND_SPI_1_8 (6) +#define BOOT_MODE_NAND_SPI_3_3 (7) + +#endif /* __SYS_H__ */ diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/include/sys_regs.h b/drivers/rz/ipl/rza/plat/renesas/rz/common/include/sys_regs.h new file mode 100644 index 00000000..0394002f --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/include/sys_regs.h @@ -0,0 +1,859 @@ +/* + * Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __SYS_REGS_H__ +#define __SYS_REGS_H__ + +#define SYS_BASE (0x11020000) + +#define SYS_MSTACCCTL0 (SYS_BASE + 0x00000000) +#define SYS_MSTACCCTL1 (SYS_BASE + 0x00000004) +#define SYS_MSTACCCTL2 (SYS_BASE + 0x00000008) +#define SYS_MSTACCCTL3 (SYS_BASE + 0x0000000C) +#define SYS_MSTACCCTL4 (SYS_BASE + 0x00000010) +#define SYS_MSTACCCTL5 (SYS_BASE + 0x00000014) +#define SYS_SLVACCCTL0 (SYS_BASE + 0x00000100) +#define SYS_SLVACCCTL1 (SYS_BASE + 0x00000104) +#define SYS_SLVACCCTL2 (SYS_BASE + 0x00000108) +#define SYS_SLVACCCTL3 (SYS_BASE + 0x0000010C) +#define SYS_SLVACCCTL4 (SYS_BASE + 0x00000110) +#define SYS_SLVACCCTL5 (SYS_BASE + 0x00000114) +#define SYS_SLVACCCTL6 (SYS_BASE + 0x00000118) +#define SYS_SLVACCCTL7 (SYS_BASE + 0x0000011C) +#define SYS_SLVACCCTL8 (SYS_BASE + 0x00000120) +#define SYS_SLVACCCTL9 (SYS_BASE + 0x00000124) +#define SYS_SLVACCCTL10 (SYS_BASE + 0x00000128) +#define SYS_SLVACCCTL11 (SYS_BASE + 0x0000012C) +#define SYS_SLVACCCTL12 (SYS_BASE + 0x00000130) +#define SYS_SLVACCCTL13 (SYS_BASE + 0x00000134) +#define SYS_SLVACCCTL14 (SYS_BASE + 0x00000138) +#define SYS_SLVACCCTL15 (SYS_BASE + 0x0000013C) +#define SYS_RAM0_ECC (SYS_BASE + 0x00000200) +#define SYS_RAM0_EN (SYS_BASE + 0x00000204) +#define SYS_RAM0_TEST (SYS_BASE + 0x00000208) +#define SYS_RAM0_MON (SYS_BASE + 0x0000020C) +#define SYS_RAM1_ECC (SYS_BASE + 0x00000210) +#define SYS_RAM1_EN (SYS_BASE + 0x00000214) +#define SYS_RAM1_TEST (SYS_BASE + 0x00000218) +#define SYS_RAM1_MON (SYS_BASE + 0x0000021C) +#define SYS_WDT0_CTRL (SYS_BASE + 0x00000220) +#define SYS_WDT1_CTRL (SYS_BASE + 0x00000230) +#define SYS_WDT2_CTRL (SYS_BASE + 0x00000240) +#define SYS_WDT3_CTRL (SYS_BASE + 0x00000250) +#define SYS_GPU_COHE (SYS_BASE + 0x00000300) +#define SYS_GPU_STRP (SYS_BASE + 0x00000304) +#define SYS_GPU_TEXT (SYS_BASE + 0x00000308) +#define SYS_H264_CFG0 (SYS_BASE + 0x00000310) +#define SYS_H264_CFG1 (SYS_BASE + 0x00000314) +#define SYS_H264_CFG2 (SYS_BASE + 0x00000318) +#define SYS_H264_MON (SYS_BASE + 0x0000031C) +#define SYS_H264_BSTOP (SYS_BASE + 0x00000320) +#define SYS_GETH0_CFG (SYS_BASE + 0x00000330) +#define SYS_GETH1_CFG (SYS_BASE + 0x00000340) +#define SYS_I2C0_CFG (SYS_BASE + 0x00000400) +#define SYS_I2C1_CFG (SYS_BASE + 0x00000410) +#define SYS_I2C2_CFG (SYS_BASE + 0x00000420) +#define SYS_I2C3_CFG (SYS_BASE + 0x00000430) +#define SYS_CANFD_CFG (SYS_BASE + 0x00000440) +#define SYS_SCIF0_CFG (SYS_BASE + 0x00000450) +#define SYS_SCIF1_CFG (SYS_BASE + 0x00000460) +#define SYS_SCIF2_CFG (SYS_BASE + 0x00000470) +#define SYS_SCIF3_CFG (SYS_BASE + 0x00000480) +#define SYS_SCIF4_CFG (SYS_BASE + 0x00000490) +#define SYS_SCI0_CFG (SYS_BASE + 0x000004A0) +#define SYS_SCI1_CFG (SYS_BASE + 0x000004B0) +#define SYS_CM33_STAT (SYS_BASE + 0x00000800) +#define SYS_CM33_CFG0 (SYS_BASE + 0x00000804) +#define SYS_CM33_CFG1 (SYS_BASE + 0x00000808) +#define SYS_CM33_CFG2 (SYS_BASE + 0x0000080C) +#define SYS_CM33_CFG3 (SYS_BASE + 0x00000810) +#define SYS_CM33_LOCK (SYS_BASE + 0x00000814) +#define SYS_CM33_CTL (SYS_BASE + 0x00000818) +#define SYS_CA55_CFG_AArch0 (SYS_BASE + 0x00000840) +#define SYS_CA55_CFG_AArch1 (SYS_BASE + 0x00000844) +#define SYS_CA55_CFG_Endian0 (SYS_BASE + 0x00000848) +#define SYS_CA55_CFG_Endian1 (SYS_BASE + 0x0000084C) +#define SYS_CA55_CFG_Thumb0 (SYS_BASE + 0x00000850) +#define SYS_CA55_CFG_Thumb1 (SYS_BASE + 0x00000854) +#define SYS_CA55_CFG_RVAL0 (SYS_BASE + 0x00000858) +#define SYS_CA55_CFG_RVAH0 (SYS_BASE + 0x0000085C) +#define SYS_CA55_CFG_RVAL1 (SYS_BASE + 0x00000860) +#define SYS_CA55_CFG_RVAH1 (SYS_BASE + 0x00000864) +#define SYS_CA55_CFG_VA0 (SYS_BASE + 0x00000868) +#define SYS_CA55_CFG_VA1 (SYS_BASE + 0x0000086C) +#define SYS_BBG_CTRL_ENABLE (SYS_BASE + 0x00000900) +#define SYS_BBG_CTRL (SYS_BASE + 0x00000904) +#define SYS_BBG_CTRL_MON (SYS_BASE + 0x00000908) +#define SYS_BBG_OFFSET0 (SYS_BASE + 0x0000090C) +#define SYS_BBG_OFFSET1 (SYS_BASE + 0x00000910) +#define SYS_BBG_OFFSET2 (SYS_BASE + 0x00000914) +#define SYS_BBG_OFFSET3 (SYS_BASE + 0x00000918) +#define SYS_BBG_OFFSET4 (SYS_BASE + 0x0000091C) +#define SYS_BBG_OFFSET5 (SYS_BASE + 0x00000920) +#define SYS_BBG_OFFSET6 (SYS_BASE + 0x00000924) +#define SYS_BBG_OFFSET7 (SYS_BASE + 0x00000928) +#define SYS_BBG_OFFSET_CTRL (SYS_BASE + 0x00000930) +#define SYS_BBG_PFREQ_MON (SYS_BASE + 0x00000934) +#define SYS_BBG_NFREQ_MON (SYS_BASE + 0x00000938) +#define SYS_BBG_TEMP_MON (SYS_BASE + 0x0000093C) +#define SYS_BBG_VOLT_MON (SYS_BASE + 0x00000940) +#define SYS_LSI_MODE (SYS_BASE + 0x00000A00) +#define SYS_LSI_DEVID (SYS_BASE + 0x00000A04) +#define SYS_LSI_PRR (SYS_BASE + 0x00000A08) +#define SYS_LSI_OTPSECEN (SYS_BASE + 0x00000A0C) +#define SYS_LSI_OTPSECMODE (SYS_BASE + 0x00000A10) +#define SYS_LSI_OTPJAM (SYS_BASE + 0x00000A14) +#define SYS_LSI_OTPCORE (SYS_BASE + 0x00000A18) +#define SYS_LSI_OTPPOC (SYS_BASE + 0x00000A20) +#define SYS_JAUTH_JUDGE (SYS_BASE + 0x00000B00) +#define SYS_AOF0 (SYS_BASE + 0x00000C00) +#define SYS_AOF1 (SYS_BASE + 0x00000C04) +#define SYS_AOF2 (SYS_BASE + 0x00000C08) +#define SYS_AOF3 (SYS_BASE + 0x00000C0C) +#define SYS_AOF4 (SYS_BASE + 0x00000C10) +#define SYS_AOF5 (SYS_BASE + 0x00000C14) +#define SYS_AOF6 (SYS_BASE + 0x00000C18) +#define SYS_AOF7 (SYS_BASE + 0x00000C1C) +#define SYS_AOF8 (SYS_BASE + 0x00000C20) +#define SYS_LP_CTL0 (SYS_BASE + 0x00000D00) +#define SYS_LP_CTL1 (SYS_BASE + 0x00000D04) +#define SYS_LP_CTL2 (SYS_BASE + 0x00000D08) +#define SYS_LP_CTL3 (SYS_BASE + 0x00000D0C) +#define SYS_LP_CTL4 (SYS_BASE + 0x00000D10) +#define SYS_LP_CTL5 (SYS_BASE + 0x00000D14) +#define SYS_LP_CTL6 (SYS_BASE + 0x00000D18) +#define SYS_LP_CTL7 (SYS_BASE + 0x00000D1C) +#define SYS_LP_CTL8 (SYS_BASE + 0x00000D20) +#define SYS_LP_CM33CTL0 (SYS_BASE + 0x00000D24) +#define SYS_LP_CM33CTL1 (SYS_BASE + 0x00000D28) +#define SYS_LP_CM33CTL2 (SYS_BASE + 0x00000D2C) +#define SYS_LP_CM33CPG (SYS_BASE + 0x00000D30) +#define SYS_LP_CA55_CTL0 (SYS_BASE + 0x00000D34) +#define SYS_LP_CA55CK_CTL1 (SYS_BASE + 0x00000D38) +#define SYS_LP_CA55CK_CTL2 (SYS_BASE + 0x00000D3C) +#define SYS_LP_CA55CK_CTL3 (SYS_BASE + 0x00000D40) +#define SYS_LP_CA55CPGC0 (SYS_BASE + 0x00000D44) +#define SYS_LP_CA55CPGC1 (SYS_BASE + 0x00000D48) +#define SYS_LP_GPU_CTL (SYS_BASE + 0x00000D50) +#define SYS_GPREG_0 (SYS_BASE + 0x00000E00) +#define SYS_GPREG_1 (SYS_BASE + 0x00000E04) +#define SYS_GPREG_2 (SYS_BASE + 0x00000E08) +#define SYS_GPREG_3 (SYS_BASE + 0x00000E0C) +#define SYS_RESREG_0 (SYS_BASE + 0x00000E10) +#define SYS_RESREG_1 (SYS_BASE + 0x00000E14) +#define SYS_RESREG_2 (SYS_BASE + 0x00000E18) +#define SYS_RESREG_3 (SYS_BASE + 0x00000E1C) +#define SYS_IPCONT (SYS_BASE + 0x00000E20) + +#define MSTACCCTL0_DMAC0_AWPU (1 << 0) +#define MSTACCCTL0_DMAC0_AWNS (1 << 1) +#define MSTACCCTL0_DMAC0_AWSEL (1 << 3) +#define MSTACCCTL0_DMAC0_ARRU (1 << 4) +#define MSTACCCTL0_DMAC0_ARNS (1 << 5) +#define MSTACCCTL0_DMAC0_ARSEL (1 << 7) +#define MSTACCCTL0_DMAC1_AWPU (1 << 8) +#define MSTACCCTL0_DMAC1_AWNS (1 << 9) +#define MSTACCCTL0_DMAC1_AWSEL (1 << 11) +#define MSTACCCTL0_DMAC1_ARRU (1 << 12) +#define MSTACCCTL0_DMAC1_ARNS (1 << 13) +#define MSTACCCTL0_DMAC1_ARSEL (1 << 15) +#define MSTACCCTL0_GPU_AWPU (1 << 16) +#define MSTACCCTL0_GPU_AWNS (1 << 17) +#define MSTACCCTL0_GPU_AWSEL (1 << 19) +#define MSTACCCTL0_GPU_ARRU (1 << 20) +#define MSTACCCTL0_GPU_ARNS (1 << 21) +#define MSTACCCTL0_GPU_ARSEL (1 << 23) +#define MSTACCCTL1_SDHI0_AWPU (1 << 0) +#define MSTACCCTL1_SDHI0_AWNS (1 << 1) +#define MSTACCCTL1_SDHI0_AWSEL (1 << 3) +#define MSTACCCTL1_SDHI0_ARRU (1 << 4) +#define MSTACCCTL1_SDHI0_ARNS (1 << 5) +#define MSTACCCTL1_SDHI0_ARSEL (1 << 7) +#define MSTACCCTL1_SDHI1_AWPU (1 << 8) +#define MSTACCCTL1_SDHI1_AWNS (1 << 9) +#define MSTACCCTL1_SDHI1_AWSEL (1 << 11) +#define MSTACCCTL1_SDHI1_ARRU (1 << 12) +#define MSTACCCTL1_SDHI1_ARNS (1 << 13) +#define MSTACCCTL1_SDHI1_ARSEL (1 << 15) +#define MSTACCCTL1_GEther0_AWPU (1 << 16) +#define MSTACCCTL1_GEther0_AWNS (1 << 17) +#define MSTACCCTL1_GEther0_AWSEL (1 << 19) +#define MSTACCCTL1_GEther0_ARRU (1 << 20) +#define MSTACCCTL1_GEther0_ARNS (1 << 21) +#define MSTACCCTL1_GEther0_ARSEL (1 << 23) +#define MSTACCCTL1_GEther1_AWPU (1 << 24) +#define MSTACCCTL1_GEther1_AWNS (1 << 25) +#define MSTACCCTL1_GEther1_AWSEL (1 << 27) +#define MSTACCCTL1_GEther1_ARRU (1 << 28) +#define MSTACCCTL1_GEther1_ARNS (1 << 29) +#define MSTACCCTL1_GEther1_ARSEL (1 << 31) +#define MSTACCCTL2_USB2_0H_AWPU (1 << 0) +#define MSTACCCTL2_USB2_0H_AWNS (1 << 1) +#define MSTACCCTL2_USB2_0H_AWSEL (1 << 3) +#define MSTACCCTL2_USB2_0H_ARRU (1 << 4) +#define MSTACCCTL2_USB2_0H_ARNS (1 << 5) +#define MSTACCCTL2_USB2_0H_ARSEL (1 << 7) +#define MSTACCCTL2_USB2_1H_AWPU (1 << 8) +#define MSTACCCTL2_USB2_1H_AWNS (1 << 9) +#define MSTACCCTL2_USB2_1H_AWSEL (1 << 11) +#define MSTACCCTL2_USB2_1H_ARRU (1 << 12) +#define MSTACCCTL2_USB2_1H_ARNS (1 << 13) +#define MSTACCCTL2_USB2_1H_ARSEL (1 << 15) +#define MSTACCCTL2_USB2_0D_AWPU (1 << 16) +#define MSTACCCTL2_USB2_0D_AWNS (1 << 17) +#define MSTACCCTL2_USB2_0D_AWSEL (1 << 19) +#define MSTACCCTL2_USB2_0D_ARRU (1 << 20) +#define MSTACCCTL2_USB2_0D_ARNS (1 << 21) +#define MSTACCCTL2_USB2_0D_ARSEL (1 << 23) +#define MSTACCCTL3_H264_AWPU (1 << 0) +#define MSTACCCTL3_H264_AWNS (1 << 1) +#define MSTACCCTL3_H264_AWSEL (1 << 3) +#define MSTACCCTL3_H264_ARRU (1 << 4) +#define MSTACCCTL3_H264_ARNS (1 << 5) +#define MSTACCCTL3_H264_ARSEL (1 << 7) +#define MSTACCCTL3_LCDC_AWPU (1 << 8) +#define MSTACCCTL3_LCDC_AWNS (1 << 9) +#define MSTACCCTL3_LCDC_AWSEL (1 << 11) +#define MSTACCCTL3_LCDC_ARRU (1 << 12) +#define MSTACCCTL3_LCDC_ARNS (1 << 13) +#define MSTACCCTL3_LCDC_ARSEL (1 << 15) +#define MSTACCCTL3_DSI_AWPU (1 << 16) +#define MSTACCCTL3_DSI_AWNS (1 << 17) +#define MSTACCCTL3_DSI_AWSEL (1 << 19) +#define MSTACCCTL3_DSI_ARRU (1 << 20) +#define MSTACCCTL3_DSI_ARNS (1 << 21) +#define MSTACCCTL3_DSI_ARSEL (1 << 23) +#define MSTACCCTL4_ISU_AWPU (1 << 0) +#define MSTACCCTL4_ISU_AWNS (1 << 1) +#define MSTACCCTL4_ISU_AWSEL (1 << 3) +#define MSTACCCTL4_ISU_ARRU (1 << 4) +#define MSTACCCTL4_ISU_ARNS (1 << 5) +#define MSTACCCTL4_ISU_ARSEL (1 << 7) +#define MSTACCCTL4_CRU_VD_AWPU (1 << 16) +#define MSTACCCTL4_CRU_VD_AWNS (1 << 17) +#define MSTACCCTL4_CRU_VD_AWSEL (1 << 19) +#define MSTACCCTL4_CRU_VD_ARRU (1 << 20) +#define MSTACCCTL4_CRU_VD_ARNS (1 << 21) +#define MSTACCCTL4_CRU_VD_ARSEL (1 << 23) +#define MSTACCCTL4_CRU_ST_AWPU (1 << 24) +#define MSTACCCTL4_CRU_ST_AWNS (1 << 25) +#define MSTACCCTL4_CRU_ST_AWSEL (1 << 27) +#define MSTACCCTL4_CRU_ST_ARRU (1 << 28) +#define MSTACCCTL4_CRU_ST_ARNS (1 << 29) +#define MSTACCCTL4_CRU_ST_ARSEL (1 << 31) +#define MSTACCCTL5_DRP0_AWPU (1 << 0) +#define MSTACCCTL5_DRP0_AWNS (1 << 1) +#define MSTACCCTL5_DRP0_AWSEL (1 << 3) +#define MSTACCCTL5_DRP0_ARRU (1 << 4) +#define MSTACCCTL5_DRP0_ARNS (1 << 5) +#define MSTACCCTL5_DRP0_ARSEL (1 << 7) +#define MSTACCCTL5_DRP1_AWPU (1 << 8) +#define MSTACCCTL5_DRP1_AWNS (1 << 9) +#define MSTACCCTL5_DRP1_AWSEL (1 << 11) +#define MSTACCCTL5_DRP1_ARRU (1 << 12) +#define MSTACCCTL5_DRP1_ARNS (1 << 13) +#define MSTACCCTL5_DRP1_ARSEL (1 << 15) +#define MSTACCCTL5_DRP2_AWPU (1 << 16) +#define MSTACCCTL5_DRP2_AWNS (1 << 17) +#define MSTACCCTL5_DRP2_AWSEL (1 << 19) +#define MSTACCCTL5_DRP2_ARRU (1 << 20) +#define MSTACCCTL5_DRP2_ARNS (1 << 21) +#define MSTACCCTL5_DRP2_ARSEL (1 << 23) +#define MSTACCCTL5_DRP3_AWPU (1 << 24) +#define MSTACCCTL5_DRP3_AWNS (1 << 25) +#define MSTACCCTL5_DRP3_AWSEL (1 << 27) +#define MSTACCCTL5_DRP3_ARRU (1 << 28) +#define MSTACCCTL5_DRP3_ARNS (1 << 29) +#define MSTACCCTL5_DRP3_ARSEL (1 << 31) +#define SLVACCCTL0_SRAM0_SL_00 (0 << 0) +#define SLVACCCTL0_SRAM0_SL_01 (1 << 0) +#define SLVACCCTL0_SRAM0_SL_10 (2 << 0) +#define SLVACCCTL0_SRAM0_SL_11 (3 << 0) +#define SLVACCCTL0_SRAM1_SL_00 (0 << 2) +#define SLVACCCTL0_SRAM1_SL_01 (1 << 2) +#define SLVACCCTL0_SRAM1_SL_10 (2 << 2) +#define SLVACCCTL0_SRAM1_SL_11 (3 << 2) +#define SLVACCCTL0_GPV_ACPU_SL_10 (2 << 4) +#define SLVACCCTL0_GPV_ACPU_SL_11 (3 << 4) +#define SLVACCCTL0_GPV_MCPU_SL_10 (2 << 6) +#define SLVACCCTL0_GPV_MCPU_SL_11 (3 << 6) +#define SLVACCCTL0_GPV_REG0_SL_10 (2 << 8) +#define SLVACCCTL0_GPV_REG0_SL_11 (3 << 8) +#define SLVACCCTL0_GPV_REG1_SL_10 (2 << 10) +#define SLVACCCTL0_GPV_REG1_SL_11 (3 << 10) +#define SLVACCCTL0_GPV_PERIVIDEO_SL_10 (2 << 12) +#define SLVACCCTL0_GPV_PERIVIDEO_SL_11 (3 << 12) +#define SLVACCCTL0_GPV_PERICPU_SL_10 (2 << 14) +#define SLVACCCTL0_GPV_PERICPU_SL_11 (3 << 14) +#define SLVACCCTL0_GPV_PERIDDR_SL_10 (2 << 16) +#define SLVACCCTL0_GPV_PERIDDR_SL_11 (3 << 16) +#define SLVACCCTL0_GPV_PERICOM_SL_10 (2 << 18) +#define SLVACCCTL0_GPV_PERICOM_SL_11 (3 << 18) +#define SLVACCCTL0_GPV_MXCOM_SL_10 (2 << 20) +#define SLVACCCTL0_GPV_MXCOM_SL_11 (3 << 20) +#define SLVACCCTL0_GPV_MXVIDEO_SL_10 (2 << 22) +#define SLVACCCTL0_GPV_MXVIDEO_SL_11 (3 << 22) +#define SLVACCCTL0_GPV_MXDRP_SL_10 (2 << 24) +#define SLVACCCTL0_GPV_MXDRP_SL_11 (3 << 24) +#define SLVACCCTL0_GPV_PERISTP_SL_10 (2 << 26) +#define SLVACCCTL0_GPV_PERISTP_SL_11 (3 << 26) +#define SLVACCCTL1_TZC0_SL_10 (2 << 0) +#define SLVACCCTL1_TZC0_SL_11 (3 << 0) +#define SLVACCCTL1_TZC1_SL_10 (2 << 2) +#define SLVACCCTL1_TZC1_SL_11 (3 << 2) +#define SLVACCCTL1_TZC2_SL_10 (2 << 4) +#define SLVACCCTL1_TZC2_SL_11 (3 << 4) +#define SLVACCCTL1_TZC3_SL_10 (2 << 6) +#define SLVACCCTL1_TZC3_SL_11 (3 << 6) +#define SLVACCCTL1_CST_SL_00 (0 << 10) +#define SLVACCCTL1_CST_SL_01 (1 << 10) +#define SLVACCCTL1_CST_SL_10 (2 << 10) +#define SLVACCCTL1_CST_SL_11 (3 << 10) +#define SLVACCCTL1_CPG_SL_00 (0 << 12) +#define SLVACCCTL1_CPG_SL_01 (1 << 12) +#define SLVACCCTL1_CPG_SL_10 (2 << 12) +#define SLVACCCTL1_CPG_SL_11 (3 << 12) +#define SLVACCCTL1_SYSC_SL_00 (0 << 14) +#define SLVACCCTL1_SYSC_SL_01 (1 << 14) +#define SLVACCCTL1_SYSC_SL_10 (2 << 14) +#define SLVACCCTL1_SYSC_SL_11 (3 << 14) +#define SLVACCCTL1_SYC_SL_00 (0 << 16) +#define SLVACCCTL1_SYC_SL_01 (1 << 16) +#define SLVACCCTL1_SYC_SL_10 (2 << 16) +#define SLVACCCTL1_SYC_SL_11 (3 << 16) +#define SLVACCCTL1_GIC_SL_00 (0 << 18) +#define SLVACCCTL1_GIC_SL_01 (1 << 18) +#define SLVACCCTL1_GIC_SL_10 (2 << 18) +#define SLVACCCTL1_GIC_SL_11 (3 << 18) +#define SLVACCCTL1_IA55_IM33_SL_00 (0 << 20) +#define SLVACCCTL1_IA55_IM33_SL_01 (1 << 20) +#define SLVACCCTL1_IA55_IM33_SL_10 (2 << 20) +#define SLVACCCTL1_IA55_IM33_SL_11 (3 << 20) +#define SLVACCCTL1_GPIO_SL_00 (0 << 22) +#define SLVACCCTL1_GPIO_SL_01 (1 << 22) +#define SLVACCCTL1_GPIO_SL_10 (2 << 22) +#define SLVACCCTL1_GPIO_SL_11 (3 << 22) +#define SLVACCCTL1_MHU_SL_00 (0 << 24) +#define SLVACCCTL1_MHU_SL_01 (1 << 24) +#define SLVACCCTL1_MHU_SL_10 (2 << 24) +#define SLVACCCTL1_MHU_SL_11 (3 << 24) +#define SLVACCCTL1_DMAC0_SL_00 (0 << 26) +#define SLVACCCTL1_DMAC0_SL_01 (1 << 26) +#define SLVACCCTL1_DMAC0_SL_10 (2 << 26) +#define SLVACCCTL1_DMAC0_SL_11 (3 << 26) +#define SLVACCCTL1_DMAC1_SL_00 (0 << 28) +#define SLVACCCTL1_DMAC1_SL_01 (1 << 28) +#define SLVACCCTL1_DMAC1_SL_10 (2 << 28) +#define SLVACCCTL1_DMAC1_SL_11 (3 << 28) +#define SLVACCCTL2_OSTM0_SL_00 (0 << 0) +#define SLVACCCTL2_OSTM0_SL_01 (1 << 0) +#define SLVACCCTL2_OSTM0_SL_10 (2 << 0) +#define SLVACCCTL2_OSTM0_SL_11 (3 << 0) +#define SLVACCCTL2_OSTM1_SL_00 (0 << 2) +#define SLVACCCTL2_OSTM1_SL_01 (1 << 2) +#define SLVACCCTL2_OSTM1_SL_10 (2 << 2) +#define SLVACCCTL2_OSTM1_SL_11 (3 << 2) +#define SLVACCCTL2_OSTM2_SL_00 (0 << 4) +#define SLVACCCTL2_OSTM2_SL_01 (1 << 4) +#define SLVACCCTL2_OSTM2_SL_10 (2 << 4) +#define SLVACCCTL2_OSTM2_SL_11 (3 << 4) +#define SLVACCCTL2_WDT0_SL_00 (0 << 6) +#define SLVACCCTL2_WDT0_SL_01 (1 << 6) +#define SLVACCCTL2_WDT0_SL_10 (2 << 6) +#define SLVACCCTL2_WDT0_SL_11 (3 << 6) +#define SLVACCCTL2_WDT1_SL_00 (0 << 8) +#define SLVACCCTL2_WDT1_SL_01 (1 << 8) +#define SLVACCCTL2_WDT1_SL_10 (2 << 8) +#define SLVACCCTL2_WDT1_SL_11 (3 << 8) +#define SLVACCCTL2_WDT2_SL_00 (0 << 10) +#define SLVACCCTL2_WDT2_SL_01 (1 << 10) +#define SLVACCCTL2_WDT2_SL_10 (2 << 10) +#define SLVACCCTL2_WDT2_SL_11 (3 << 10) +#define SLVACCCTL2_WDT3_SL_00 (0 << 12) +#define SLVACCCTL2_WDT3_SL_01 (1 << 12) +#define SLVACCCTL2_WDT3_SL_10 (2 << 12) +#define SLVACCCTL2_WDT3_SL_11 (3 << 12) +#define SLVACCCTL2_MTU3A_SL_00 (0 << 14) +#define SLVACCCTL2_MTU3A_SL_01 (1 << 14) +#define SLVACCCTL2_MTU3A_SL_10 (2 << 14) +#define SLVACCCTL2_MTU3A_SL_11 (3 << 14) +#define SLVACCCTL2_POE3_SL_00 (0 << 16) +#define SLVACCCTL2_POE3_SL_01 (1 << 16) +#define SLVACCCTL2_POE3_SL_10 (2 << 16) +#define SLVACCCTL2_POE3_SL_11 (3 << 16) +#define SLVACCCTL2_GPT_SL_00 (0 << 18) +#define SLVACCCTL2_GPT_SL_01 (1 << 18) +#define SLVACCCTL2_GPT_SL_10 (2 << 18) +#define SLVACCCTL2_GPT_SL_11 (3 << 18) +#define SLVACCCTL2_POEG_SL_00 (0 << 20) +#define SLVACCCTL2_POEG_SL_01 (1 << 20) +#define SLVACCCTL2_POEG_SL_10 (2 << 20) +#define SLVACCCTL2_POEG_SL_11 (3 << 20) +#define SLVACCCTL2_DDR_SL_00 (0 << 22) +#define SLVACCCTL2_DDR_SL_01 (1 << 22) +#define SLVACCCTL2_DDR_SL_10 (2 << 22) +#define SLVACCCTL2_DDR_SL_11 (3 << 22) +#define SLVACCCTL3_GPU_SL_00 (0 << 0) +#define SLVACCCTL3_GPU_SL_01 (1 << 0) +#define SLVACCCTL3_GPU_SL_10 (2 << 0) +#define SLVACCCTL3_GPU_SL_11 (3 << 0) +#define SLVACCCTL3_H264_SL_00 (0 << 2) +#define SLVACCCTL3_H264_SL_01 (1 << 2) +#define SLVACCCTL3_H264_SL_10 (2 << 2) +#define SLVACCCTL3_H264_SL_11 (3 << 2) +#define SLVACCCTL3_CRU_SL_00 (0 << 4) +#define SLVACCCTL3_CRU_SL_01 (1 << 4) +#define SLVACCCTL3_CRU_SL_10 (2 << 4) +#define SLVACCCTL3_CRU_SL_11 (3 << 4) +#define SLVACCCTL3_ISU_SL_00 (0 << 6) +#define SLVACCCTL3_ISU_SL_01 (1 << 6) +#define SLVACCCTL3_ISU_SL_10 (2 << 6) +#define SLVACCCTL3_ISU_SL_11 (3 << 6) +#define SLVACCCTL3_DSIPHY_SL_00 (0 << 8) +#define SLVACCCTL3_DSIPHY_SL_01 (1 << 8) +#define SLVACCCTL3_DSIPHY_SL_10 (2 << 8) +#define SLVACCCTL3_DSIPHY_SL_11 (3 << 8) +#define SLVACCCTL3_DSILINK_SL_00 (0 << 10) +#define SLVACCCTL3_DSILINK_SL_01 (1 << 10) +#define SLVACCCTL3_DSILINK_SL_10 (2 << 10) +#define SLVACCCTL3_DSILINK_SL_11 (3 << 10) +#define SLVACCCTL3_LCDC_SL_00 (0 << 12) +#define SLVACCCTL3_LCDC_SL_01 (1 << 12) +#define SLVACCCTL3_LCDC_SL_10 (2 << 12) +#define SLVACCCTL3_LCDC_SL_11 (3 << 12) +#define SLVACCCTL3_DRP_SL_00 (0 << 14) +#define SLVACCCTL3_DRP_SL_01 (1 << 14) +#define SLVACCCTL3_DRP_SL_10 (2 << 14) +#define SLVACCCTL3_DRP_SL_11 (3 << 14) +#define SLVACCCTL3_USBT_SL_00 (0 << 16) +#define SLVACCCTL3_USBT_SL_01 (1 << 16) +#define SLVACCCTL3_USBT_SL_10 (2 << 16) +#define SLVACCCTL3_USBT_SL_11 (3 << 16) +#define SLVACCCTL3_USB20_SL_00 (0 << 18) +#define SLVACCCTL3_USB20_SL_01 (1 << 18) +#define SLVACCCTL3_USB20_SL_10 (2 << 18) +#define SLVACCCTL3_USB20_SL_11 (3 << 18) +#define SLVACCCTL3_USB21_SL_00 (0 << 20) +#define SLVACCCTL3_USB21_SL_01 (1 << 20) +#define SLVACCCTL3_USB21_SL_10 (2 << 20) +#define SLVACCCTL3_USB21_SL_11 (3 << 20) +#define SLVACCCTL3_SDHI0_SL_00 (0 << 22) +#define SLVACCCTL3_SDHI0_SL_01 (1 << 22) +#define SLVACCCTL3_SDHI0_SL_10 (2 << 22) +#define SLVACCCTL3_SDHI0_SL_11 (3 << 22) +#define SLVACCCTL3_SDHI1_SL_00 (0 << 24) +#define SLVACCCTL3_SDHI1_SL_01 (1 << 24) +#define SLVACCCTL3_SDHI1_SL_10 (2 << 24) +#define SLVACCCTL3_SDHI1_SL_11 (3 << 24) +#define SLVACCCTL3_ETH0_SL_00 (0 << 26) +#define SLVACCCTL3_ETH0_SL_01 (1 << 26) +#define SLVACCCTL3_ETH0_SL_10 (2 << 26) +#define SLVACCCTL3_ETH0_SL_11 (3 << 26) +#define SLVACCCTL3_ETH1_SL_00 (0 << 28) +#define SLVACCCTL3_ETH1_SL_01 (1 << 28) +#define SLVACCCTL3_ETH1_SL_10 (2 << 28) +#define SLVACCCTL3_ETH1_SL_11 (3 << 28) +#define SLVACCCTL4_I2C0_SL_00 (0 << 0) +#define SLVACCCTL4_I2C0_SL_01 (1 << 0) +#define SLVACCCTL4_I2C0_SL_10 (2 << 0) +#define SLVACCCTL4_I2C0_SL_11 (3 << 0) +#define SLVACCCTL4_I2C1_SL_00 (0 << 2) +#define SLVACCCTL4_I2C1_SL_01 (1 << 2) +#define SLVACCCTL4_I2C1_SL_10 (2 << 2) +#define SLVACCCTL4_I2C1_SL_11 (3 << 2) +#define SLVACCCTL4_I2C2_SL_00 (0 << 4) +#define SLVACCCTL4_I2C2_SL_01 (1 << 4) +#define SLVACCCTL4_I2C2_SL_10 (2 << 4) +#define SLVACCCTL4_I2C2_SL_11 (3 << 4) +#define SLVACCCTL4_I2C3_SL_00 (0 << 6) +#define SLVACCCTL4_I2C3_SL_01 (1 << 6) +#define SLVACCCTL4_I2C3_SL_10 (2 << 6) +#define SLVACCCTL4_I2C3_SL_11 (3 << 6) +#define SLVACCCTL4_CANFD_SL_00 (0 << 8) +#define SLVACCCTL4_CANFD_SL_01 (1 << 8) +#define SLVACCCTL4_CANFD_SL_10 (2 << 8) +#define SLVACCCTL4_CANFD_SL_11 (3 << 8) +#define SLVACCCTL4_RSPI_SL_00 (0 << 10) +#define SLVACCCTL4_RSPI_SL_01 (1 << 10) +#define SLVACCCTL4_RSPI_SL_10 (2 << 10) +#define SLVACCCTL4_RSPI_SL_11 (3 << 10) +#define SLVACCCTL4_SCIF0_SL_00 (0 << 16) +#define SLVACCCTL4_SCIF0_SL_01 (1 << 16) +#define SLVACCCTL4_SCIF0_SL_10 (2 << 16) +#define SLVACCCTL4_SCIF0_SL_11 (3 << 16) +#define SLVACCCTL4_SCIF1_SL_00 (0 << 18) +#define SLVACCCTL4_SCIF1_SL_01 (1 << 18) +#define SLVACCCTL4_SCIF1_SL_10 (2 << 18) +#define SLVACCCTL4_SCIF1_SL_11 (3 << 18) +#define SLVACCCTL4_SCIF2_SL_00 (0 << 20) +#define SLVACCCTL4_SCIF2_SL_01 (1 << 20) +#define SLVACCCTL4_SCIF2_SL_10 (2 << 20) +#define SLVACCCTL4_SCIF2_SL_11 (3 << 20) +#define SLVACCCTL4_SCIF3_SL_00 (0 << 22) +#define SLVACCCTL4_SCIF3_SL_01 (1 << 22) +#define SLVACCCTL4_SCIF3_SL_10 (2 << 22) +#define SLVACCCTL4_SCIF3_SL_11 (3 << 22) +#define SLVACCCTL4_SCIF4_SL_00 (0 << 24) +#define SLVACCCTL4_SCIF4_SL_01 (1 << 24) +#define SLVACCCTL4_SCIF4_SL_10 (2 << 24) +#define SLVACCCTL4_SCIF4_SL_11 (3 << 24) +#define SLVACCCTL4_SCI0_SL_00 (0 << 26) +#define SLVACCCTL4_SCI0_SL_01 (1 << 26) +#define SLVACCCTL4_SCI0_SL_10 (2 << 26) +#define SLVACCCTL4_SCI0_SL_11 (3 << 26) +#define SLVACCCTL4_SCI1_SL_00 (0 << 28) +#define SLVACCCTL4_SCI1_SL_01 (1 << 28) +#define SLVACCCTL4_SCI1_SL_10 (2 << 28) +#define SLVACCCTL4_SCI1_SL_11 (3 << 28) +#define SLVACCCTL4_IRDA_SL_00 (0 << 30) +#define SLVACCCTL4_IRDA_SL_01 (1 << 30) +#define SLVACCCTL4_IRDA_SL_10 (2 << 30) +#define SLVACCCTL4_IRDA_SL_11 (3 << 30) +#define SLVACCCTL5_SSIF_SL_00 (0 << 0) +#define SLVACCCTL5_SSIF_SL_01 (1 << 0) +#define SLVACCCTL5_SSIF_SL_10 (2 << 0) +#define SLVACCCTL5_SSIF_SL_11 (3 << 0) +#define SLVACCCTL5_SRC_SL_00 (0 << 4) +#define SLVACCCTL5_SRC_SL_01 (1 << 4) +#define SLVACCCTL5_SRC_SL_10 (2 << 4) +#define SLVACCCTL5_SRC_SL_11 (3 << 4) +#define SLVACCCTL6_ADC_SL_00 (0 << 0) +#define SLVACCCTL6_ADC_SL_01 (1 << 0) +#define SLVACCCTL6_ADC_SL_10 (2 << 0) +#define SLVACCCTL6_ADC_SL_11 (3 << 0) +#define SLVACCCTL6_TSU_SL_00 (0 << 2) +#define SLVACCCTL6_TSU_SL_01 (1 << 2) +#define SLVACCCTL6_TSU_SL_10 (2 << 2) +#define SLVACCCTL6_TSU_SL_11 (3 << 2) +#define SLVACCCTL7_TSIP_SL_00 (0 << 0) +#define SLVACCCTL7_TSIP_SL_01 (1 << 0) +#define SLVACCCTL7_TSIP_SL_10 (2 << 0) +#define SLVACCCTL7_TSIP_SL_11 (3 << 0) +#define SLVACCCTL7_OTP_SL_00 (0 << 2) +#define SLVACCCTL7_OTP_SL_01 (1 << 2) +#define SLVACCCTL7_OTP_SL_10 (2 << 2) +#define SLVACCCTL7_OTP_SL_11 (3 << 2) +#define SLVACCCTL8_CM33_SL_00 (0 << 0) +#define SLVACCCTL8_CM33_SL_01 (1 << 0) +#define SLVACCCTL8_CM33_SL_10 (2 << 0) +#define SLVACCCTL8_CM33_SL_11 (3 << 0) +#define SLVACCCTL8_CA55_SL_00 (0 << 2) +#define SLVACCCTL8_CA55_SL_01 (1 << 2) +#define SLVACCCTL8_CA55_SL_10 (2 << 2) +#define SLVACCCTL8_CA55_SL_11 (3 << 2) +#define SLVACCCTL9_BBG_SL_00 (0 << 0) +#define SLVACCCTL9_BBG_SL_01 (1 << 0) +#define SLVACCCTL9_BBG_SL_10 (2 << 0) +#define SLVACCCTL9_BBG_SL_11 (3 << 0) +#define SLVACCCTL10_LSI_S_00 (0 << 0) +#define SLVACCCTL10_LSI_S_01 (1 << 0) +#define SLVACCCTL10_LSI_S_10 (2 << 0) +#define SLVACCCTL10_LSI_S_11 (3 << 0) +#define SLVACCCTL11_JAUTH_SL_00 (0 << 0) +#define SLVACCCTL11_JAUTH_SL_01 (1 << 0) +#define SLVACCCTL11_JAUTH_SL_10 (2 << 0) +#define SLVACCCTL11_JAUTH_SL_11 (3 << 0) +#define SLVACCCTL12_AOF_SL_00 (0 << 0) +#define SLVACCCTL12_AOF_SL_01 (1 << 0) +#define SLVACCCTL12_AOF_SL_10 (2 << 0) +#define SLVACCCTL12_AOF_SL_11 (3 << 0) +#define SLVACCCTL13LP_SL_00 (0 << 0) +#define SLVACCCTL13LP_SL_01 (1 << 0) +#define SLVACCCTL13LP_SL_10 (2 << 0) +#define SLVACCCTL13LP_SL_11 (3 << 0) +#define SLVACCCTL14_GPREG_SL_00 (0 << 0) +#define SLVACCCTL14_GPREG_SL_01 (1 << 0) +#define SLVACCCTL14_GPREG_SL_10 (2 << 0) +#define SLVACCCTL14_GPREG_SL_11 (3 << 0) +#define SLVACCCTL15_RESREG_SL_00 (0 << 0) +#define SLVACCCTL15_RESREG_SL_01 (1 << 0) +#define SLVACCCTL15_RESREG_SL_10 (2 << 0) +#define SLVACCCTL15_RESREG_SL_11 (3 << 0) +#define RAM0_ECC_VECCEN (1 << 0) +#define RAM0_ECC_EC7TERVE (1 << 1) +#define RAM0_EN_VCEN (1 << 0) +#define RAM0_EN_VLWEN (1 << 1) +#define RAM0_TEST_READTEST (1 << 0) +#define RAM0_MON_RAMON_O (1 << 0) +#define RAM1_ECC_VECCEN (1 << 0) +#define RAM1_ECC_EC7TERVE (1 << 1) +#define RAM1_EN_VCEN (1 << 0) +#define RAM1_EN_VLWEN (1 << 1) +#define RAM1_TEST_READTEST (1 << 0) +#define RAM1_MON_RAMON_O (1 << 0) +#define WDT0_CTRL_WDTSTOP (1 << 0) +#define WDT0_CTRL_WDTSTOPMASK (1 << 16) +#define WDT1_CTRL_WDTSTOP (1 << 0) +#define WDT1_CTRL_WDTSTOPMASK (1 << 16) +#define WDT2_CTRL_WDTSTOP (1 << 0) +#define WDT2_CTRL_WDTSTOPMASK (1 << 16) +#define WDT3_CTRL_WDTSTOP (1 << 0) +#define WDT3_CTRL_WDTSTOPMASK (1 << 16) +#define GPU_COHE_COHERENCY (1 << 0) +#define GPU_TEXT_TEXFMTENABLE (1 << 0) +#define H264_CFG0_SYNC_AB_RAW_VCPLF_00 (0 << 24) +#define H264_CFG0_SYNC_AB_RAW_VCPLF_01 (1 << 24) +#define H264_CFG0_SYNC_AB_RAW_VCPLF_10 (2 << 24) +#define H264_CFG0_SYNC_AB_RAW_VCPLF_11 (3 << 24) +#define H264_CFG1_VPI_CAXI2_ENABLE_N (1 << 0) +#define H264_CFG2_VPI_CAXI_DPIC_STALL (1 << 0) +#define H264_MON_VPO_CAXI_DPIC_VALID (1 << 0) +#define H264_MON_VPO_CAXI_DPIC_MBL_START (1 << 8) +#define H264_MON_VPO_CAXI_DPIC_2D_START (1 << 16) +#define H264_BSTOP_FCI_CL_ISREQ_P (1 << 0) +#define H264_BSTOP_FCO_CL_ISACK_P (1 << 16) +#define GETH0_CFG_AVB_MIIMG_PIMODE (1 << 0) +#define GETH0_CFG_FEC_MIIMG_PIMODE (1 << 16) +#define GETH0_CFG_FEC_GIGA_ENABLE (1 << 24) +#define GETH1_CFG_AVB_MIIMG_PIMODE (1 << 0) +#define GETH1_CFG_FEC_MIIMG_PIMODE (1 << 16) +#define GETH1_CFG_FEC_GIGA_ENABLE (1 << 24) +#define I2C0_CFG_af_bypass (1 << 0) +#define I2C0_CFG_c2dloop (1 << 8) +#define I2C0_CFG_d2cloop (1 << 9) +#define I2C1_CFG_af_bypass (1 << 0) +#define I2C1_CFG_c2dloop (1 << 8) +#define I2C1_CFG_d2cloop (1 << 9) +#define I2C2_CFG_af_bypass (1 << 0) +#define I2C2_CFG_c2dloop (1 << 8) +#define I2C2_CFG_d2cloop (1 << 9) +#define I2C3_CFG_af_bypass (1 << 0) +#define I2C3_CFG_c2dloop (1 << 8) +#define I2C3_CFG_d2cloop (1 << 9) +#define CANFD_CFG_RS_CANFD_MODE (1 << 0) +#define CANFD_CFG_RS_CANFD_NON_ISO_SEL (1 << 1) +#define CANFD_CFG_RS_CANFD_NON_ISO_EN (1 << 2) +#define SCIF0_CFG_e1_iotestmd (1 << 0) +#define SCIF1_CFG_e1_iotestmd (1 << 0) +#define SCIF2_CFG_e1_iotestmd (1 << 0) +#define SCIF3_CFG_e1_iotestmd (1 << 0) +#define SCIF4_CFG_e1_iotestmd (1 << 0) +#define SCI0_CFG_SY_TM32 (1 << 0) +#define SCI1_CFG__SY_TM32 (1 << 0) +#define CM33_STAT_CORECLKEN (1 << 0) +#define CM33_LOCK_LOCKSVTAIRCR (1 << 0) +#define CM33_LOCK_LOCKNSVTOR (1 << 1) +#define CM33_LOCK_LOCKSMPU (1 << 2) +#define CM33_LOCK_LOCKNSMPU (1 << 3) +#define CM33_LOCK_LOCKSAU (1 << 4) +#define CM33_CTL_CPUWAIT (1 << 0) +#define CA55_CFG_AArch0_AA64nAA32_0 (1 << 0) +#define CA55_CFG_AArch1_AA64nAA32_1 (1 << 1) +#define CA55_CFG_Endian0_CFGEND0 (1 << 0) +#define CA55_CFG_Endian1_CFGEND1 (1 << 1) +#define CA55_CFG_Thumb0_CFGTE0 (1 << 0) +#define CA55_CFG_Thumb1_CFGTE1 (1 << 1) +#define CA55_CFG_VA0_VINITHI0 (1 << 0) +#define CA55_CFG_VA1_VINITHI1 (1 << 1) +#define BBG_CTRL_ENABLE_REG_EN (1 << 0) +#define BBG_CTRL_REG_EN_CP (1 << 15) +#define BBG_CTRL_REG_EN_VBBP (1 << 13) +#define BBG_CTRL_REG_EN_VBBN (1 << 14) +#define BBG_CTRL_MON_EN_CP_STATE (1 << 15) +#define BBG_CTRL_MON_EN_VBBP_STATE (1 << 13) +#define BBG_CTRL_MON_EN_VBBN_STATE (1 << 14) +#define BBG_OFFSET_CTRL_EN_OFFSET (1 << 15) +#define BBG_OFFSET_INDEX_SEL_00 (0 << 0) +#define BBG_OFFSET_INDEX_SEL_01 (1 << 0) +#define BBG_OFFSET_INDEX_SEL_10 (2 << 0) +#define BBG_OFFSET_INDEX_SEL_11 (3 << 0) +#define BBG_OFFSET_P_TYPE_SEL_00 (0 << 2) +#define BBG_OFFSET_P_TYPE_SEL_01 (1 << 2) +#define BBG_OFFSET_P_TYPE_SEL_10 (2 << 2) +#define BBG_OFFSET_P_TYPE_SEL_11 (3 << 2) +#define BBG_OFFSET_N_TYPE_SEL_00 (0 << 4) +#define BBG_OFFSET_N_TYPE_SEL_01 (1 << 4) +#define BBG_OFFSET_N_TYPE_SEL_10 (2 << 4) +#define BBG_OFFSET_N_TYPE_SEL_11 (3 << 4) +#define BBG_OFFSET_R0_VALID_INV (1 << 6) +#define BBG_OFFSET_R1_VALID_INV (1 << 7) +#define BBG_OFFSET_R2_VALID_INV (1 << 8) +#define BBG_OFFSET_R0_VALID_NAND (1 << 9) +#define BBG_OFFSET_R1_VALID_NAND (1 << 10) +#define BBG_OFFSET_R2_VALID_NAND (1 << 11) +#define BBG_OFFSET_R0_VALID_NOR (1 << 12) +#define BBG_OFFSET_R1_VALID_NOR (1 << 13) +#define BBG_OFFSET_R2_VALID_NOR (1 << 14) +#define BBG_PFREQ_MON_P_FREQ_VALID (1 << 15) +#define BBG_NFREQ_MON_N_FREQ_VALID (1 << 15) +#define BBG_TEMP_MON_TEMP_VALID (1 << 15) +#define BBG_VOLT_MON_VOLT_VALID (1 << 15) +#define LSI_MODE_STAT_CPUHOLD (1 << 8) +#define LSI_MODE_STAT_DEBUGEN (1 << 9) +#define LSI_MODE_STAT_MD_CLKS (1 << 12) +#define LSI_MODE_STAT_MD_OSCDRV_00 (0 << 14) +#define LSI_MODE_STAT_MD_OSCDRV_01 (1 << 14) +#define LSI_MODE_STAT_MD_OSCDRV_10 (2 << 14) +#define LSI_MODE_STAT_MD_OSCDRV_11 (3 << 14) +#define LSI_MODE_STAT_STAT_SEC_EN (1 << 16) +#define LSI_PRR_CA55_1CPU (1 << 0) +#define LSI_PRR_CM33_DIS (1 << 4) +#define LSI_PRR_GPU_DIS (1 << 8) +#define LSI_OTPSECEN_SECEN (1 << 0) +#define LSI_OTPSECMODE_SECBT_SD (1 << 0) +#define LSI_OTPSECMODE_SECBT_EMMC18 (1 << 1) +#define LSI_OTPSECMODE_SECBT_EMMC33 (1 << 2) +#define LSI_OTPSECMODE_SECBT_SPI18 (1 << 3) +#define LSI_OTPSECMODE_SECBT_SPI33 (1 << 4) +#define LSI_OTPJAM_JAM_00 (0 << 0) +#define LSI_OTPJAM_JAM_01 (1 << 0) +#define LSI_OTPJAM_JAM_10 (2 << 0) +#define LSI_OTPJAM_JAM_11 (3 << 0) +#define LSI_OTPCORE_CA55_FREQ_00 (0 << 0) +#define LSI_OTPCORE_CA55_FREQ_01 (1 << 0) +#define LSI_OTPCORE_CA55_FREQ_10 (2 << 0) +#define LSI_OTPCORE_CA55_FREQ_11 (3 << 0) +#define LSI_OTPPOC_SD_E_00 (0 << 0) +#define LSI_OTPPOC_SD_E_01 (1 << 0) +#define LSI_OTPPOC_SD_E_10 (2 << 0) +#define LSI_OTPPOC_SD_E_11 (3 << 0) +#define LSI_OTPPOC_EMMC18_E_00 (0 << 2) +#define LSI_OTPPOC_EMMC18_E_01 (1 << 2) +#define LSI_OTPPOC_EMMC18_E_10 (2 << 2) +#define LSI_OTPPOC_EMMC18_E_11 (3 << 2) +#define LSI_OTPPOC_EMMC33_E_00 (0 << 4) +#define LSI_OTPPOC_EMMC33_E_01 (1 << 4) +#define LSI_OTPPOC_EMMC33_E_10 (2 << 4) +#define LSI_OTPPOC_EMMC33_E_11 (3 << 4) +#define LSI_OTPPOC_SPI18_E_00 (0 << 6) +#define LSI_OTPPOC_SPI18_E_01 (1 << 6) +#define LSI_OTPPOC_SPI18_E_10 (2 << 6) +#define LSI_OTPPOC_SPI18_E_11 (3 << 6) +#define LSI_OTPPOC_SPI33_E_00 (0 << 8) +#define LSI_OTPPOC_SPI33_E_01 (1 << 8) +#define LSI_OTPPOC_SPI33_E_10 (2 << 8) +#define LSI_OTPPOC_SPI33_E_11 (3 << 8) +#define LSI_OTPPOC_SCIF_E_00 (0 << 10) +#define LSI_OTPPOC_SCIF_E_01 (1 << 10) +#define LSI_OTPPOC_SCIF_E_10 (2 << 10) +#define LSI_OTPPOC_SCIF_E_11 (3 << 10) +#define LP_CTL0_MAIN_CPU (1 << 0) +#define LP_CTL1_STBY (1 << 0) +#define LP_CTL1_CA55SLEEP_REQ_00 (0 << 8) +#define LP_CTL1_CA55SLEEP_REQ_01 (1 << 8) +#define LP_CTL1_CA55SLEEP_REQ_10 (2 << 8) +#define LP_CTL1_CA55SLEEP_REQ_11 (3 << 8) +#define LP_CTL1_CM33SLEEP_REQ (1 << 12) +#define LP_CTL1_STBY_CA55ST (1 << 16) +#define LP_CTL1_STBY_CM33ST (1 << 17) +#define LP_CTL1_CA55SLEEP_ACK_00 (0 << 24) +#define LP_CTL1_CA55SLEEP_ACK_01 (1 << 24) +#define LP_CTL1_CA55SLEEP_ACK_10 (2 << 24) +#define LP_CTL1_CA55SLEEP_ACK_11 (3 << 24) +#define LP_CTL1_CM33SLEEP_ACK (1 << 28) +#define LP_CTL2_CA55_STBYCTL (1 << 0) +#define LP_CTL3_U0DP_F (1 << 0) +#define LP_CTL3_U0DM_F (1 << 1) +#define LP_CTL3_U0VBUSIN_F (1 << 2) +#define LP_CTL3_U0OVRCLR_F (1 << 3) +#define LP_CTL3_U1DP_F (1 << 8) +#define LP_CTL3_U1DM_F (1 << 9) +#define LP_CTL3_U1OVRCLR_F (1 << 11) +#define LP_CTL3_NMI_F (1 << 24) +#define LP_CTL4_U0DP_E (1 << 0) +#define LP_CTL4_U0DM_E (1 << 1) +#define LP_CTL4_U0VBUSIN_E (1 << 2) +#define LP_CTL4_U0OVRCLR_E (1 << 3) +#define LP_CTL4_U1DP_E (1 << 8) +#define LP_CTL4_U1DM_E (1 << 9) +#define LP_CTL4_U1OVRCLR_E (1 << 11) +#define LP_CTL4_IRQ_E0 (1 << 16) +#define LP_CTL4_IRQ_E1 (1 << 17) +#define LP_CTL4_IRQ_E2 (1 << 18) +#define LP_CTL4_IRQ_E3 (1 << 19) +#define LP_CTL4_IRQ_E4 (1 << 20) +#define LP_CTL4_IRQ_E5 (1 << 21) +#define LP_CTL4_IRQ_E6 (1 << 22) +#define LP_CTL4_IRQ_E7 (1 << 23) +#define LP_CTL4_NMI_E (1 << 24) +#define LP_CTL5_Q4_DENY_F (1 << 0) +#define LP_CTL5_Q9_DENY_F (1 << 1) +#define LP_CTL5_Q10_DENY_F (1 << 2) +#define LP_CTL5_STBY_F (1 << 4) +#define LP_CTL5_CA55SLEEP0_F (1 << 8) +#define LP_CTL5_CA55SLEEP1_F (1 << 9) +#define LP_CTL5_CM33SLEEP_F (1 << 10) +#define LP_CTL5_CA55STBYDONE_F (1 << 16) +#define LP_CTL5_CM33STBYR_F (1 << 20) +#define LP_CTL6_Q4_DENY_E (1 << 0) +#define LP_CTL6_Q9_DENY_E (1 << 1) +#define LP_CTL6_Q10_DENY_E (1 << 2) +#define LP_CTL6_STBY_E (1 << 4) +#define LP_CTL6_CA55STBYDONE_E (1 << 5) +#define LP_CTL6_CM33STBYR_E (1 << 6) +#define LP_CTL6_CA55SLEEP0_E (1 << 8) +#define LP_CTL6_CA55SLEEP1_E (1 << 9) +#define LP_CTL6_CM33SLEEP_E (1 << 10) +#define LP_CTL7_IM33_MASK (1 << 0) +#define LP_CTL8_SUBCPU_RTRIG (1 << 0) +#define LP_CM33CTL0_SLEEPING (1 << 0) +#define LP_CM33CTL0_SLEEPDEEP (1 << 4) +#define LP_CM33CTL0_WAKEUP (1 << 8) +#define LP_CM33CTL0_SYSRESETREQ (1 << 9) +#define LP_CM33CTL0_SLEEPHOLDREQn (1 << 16) +#define LP_CM33CTL0_SLEEPHOLDACKn (1 << 17) +#define LP_CM33CTL0_WICENREQ (1 << 24) +#define LP_CM33CTL0_WICENACK (1 << 25) +#define LP_CM33CTL1_COREQACTIVE (1 << 0) +#define LP_CM33CTL1_DBGQACTIVE (1 << 4) +#define LP_CM33CTL1_COREQREQn (1 << 8) +#define LP_CM33CTL1_DBGQREQn (1 << 12) +#define LP_CM33CTL1_COREQACCEPTn (1 << 16) +#define LP_CM33CTL1_QDBGACCEPTn (1 << 20) +#define LP_CM33CTL1_COREQDENY (1 << 24) +#define LP_CM33CTL1_DBGQDENY (1 << 28) +#define LP_CA55CK_CTL1_QACTIVE_Q_CLK_SLV (1 << 1) +#define LP_CA55CK_CTL1_QACTIVE_Q_CLK_MST (1 << 2) +#define LP_CA55CK_CTL1_PCLKQACTIVE (1 << 8) +#define LP_CA55CK_CTL1_ATCLKQACTIVE (1 << 9) +#define LP_CA55CK_CTL1_GICCLKQACTIVE (1 << 10) +#define LP_CA55CK_CTL1_PDBGCLKQACTIVE (1 << 11) +#define LP_CA55CK_CTL2_QREQn_Q_CLK_SLV (1 << 1) +#define LP_CA55CK_CTL2_QREQn_Q_CLK_MST (1 << 2) +#define LP_CA55CK_CTL2_PCLKQREQn (1 << 8) +#define LP_CA55CK_CTL2_ATCLKQREQn (1 << 9) +#define LP_CA55CK_CTL2_GICCLKQREQn (1 << 10) +#define LP_CA55CK_CTL2_PDBGCLKQREQn (1 << 11) +#define LP_CA55CK_CTL3_SCLKQACCEPTn (1 << 0) +#define LP_CA55CK_CTL3_QACCEPTn_Q_CLK_SLV (1 << 1) +#define LP_CA55CK_CTL3_QACCEPTn_Q_CLK_MST (1 << 2) +#define LP_CA55CK_CTL3_PCLKQACCEPTn (1 << 8) +#define LP_CA55CK_CTL3_ATCLKQACCEPTn (1 << 9) +#define LP_CA55CK_CTL3_GICCLKQACCEPTn (1 << 10) +#define LP_CA55CK_CTL3_PDBGCLKQACCEPTn (1 << 11) +#define LP_CA55CK_CTL3_SCLKQDENY (1 << 16) +#define LP_CA55CK_CTL3_QDENY_Q_CLK_SLV (1 << 17) +#define LP_CA55CK_CTL3_QDENY_Q_CLK_MST (1 << 18) +#define LP_CA55CK_CTL3_PCLKQDENY (1 << 24) +#define LP_CA55CK_CTL3_ATCLKQDENY (1 << 25) +#define LP_CA55CK_CTL3_GICCLKQDENY (1 << 26) +#define LP_CA55CK_CTL3_PDBGCLKQDENY (1 << 27) +#define LP_GPU_CTL_QACTIVE_GPU (1 << 0) +#define LP_GPU_CTL_QACTIVE_AXI_SLV (1 << 1) +#define LP_GPU_CTL_QACTIVE_AXI_MST (1 << 2) +#define LP_GPU_CTL_QACTIVE_ACE_SLV (1 << 3) +#define LP_GPU_CTL_QACTIVE_ACE_MST (1 << 4) +#define LP_GPU_CTL_QREQn_GPU (1 << 8) +#define LP_GPU_CTL_QREQn_AXI_SLV (1 << 9) +#define LP_GPU_CTL_QREQn_AXI_MST (1 << 10) +#define LP_GPU_CTL_QREQn_ACE_SLV (1 << 11) +#define LP_GPU_CTL_QREQn_ACE_MST (1 << 12) +#define LP_GPU_CTL_QACCEPTn_GPU (1 << 16) +#define LP_GPU_CTL_QACCEPTn_AXI_SLV (1 << 17) +#define LP_GPU_CTL_QACCEPTn_AXI_MST (1 << 18) +#define LP_GPU_CTL_QACCEPTn_ACE_SLV (1 << 19) +#define LP_GPU_CTL_QACCEPTn_ACE_MST (1 << 20) +#define LP_GPU_CTL_QDENY_GPU (1 << 24) +#define LP_GPU_CTL_QDENY_AXI_SLV (1 << 25) +#define LP_GPU_CTL_QDENY_AXI_MST (1 << 26) +#define LP_GPU_CTL_QDENY_ACE_SLV (1 << 27) +#define LP_GPU_CTL_QDENY_ACE_MST (1 << 28) +#define IPCONT_SEL_SPI_OCTA_POS 0 +#define IPCONT_SEL_SPI_OCTA (1u << IPCONT_SEL_SPI_OCTA_POS) +#define IPCONT_SEL_SPI_OCTA_SPI 0u +#define IPCONT_SEL_SPI_OCTA_OCTA 1u + +#endif /* __SYS_REGS_H__ */ diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/include/xspi_api.h b/drivers/rz/ipl/rza/plat/renesas/rz/common/include/xspi_api.h new file mode 100644 index 00000000..d96b002a --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/include/xspi_api.h @@ -0,0 +1,213 @@ +/* + * Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _XSPI_API_H_ +#define _XSPI_API_H_ + +#include +#include +#include + +/** xSPI feature flags */ +#define XSPI_FEATURE_FORM112 (1u << 0) /* Form 1-1-2 supported */ +#define XSPI_FEATURE_FORM122 (1u << 1) /* Form 1-2-2 supported */ +#define XSPI_FEATURE_FORM222 (1u << 2) /* Form 2-2-2 supported */ +#define XSPI_FEATURE_DUAL (XSPI_FEATURE_FORM112|XSPI_FEATURE_FORM122|XSPI_FEATURE_FORM222) +#define XSPI_FEATURE_FORM114 (1u << 3) /* Form 1-1-4 supported */ +#define XSPI_FEATURE_FORM144 (1u << 4) /* Form 1-4-4 supported */ +#define XSPI_FEATURE_FORM444 (1u << 5) /* Form 4-4-4 supported */ +#define XSPI_FEATURE_QUAD (XSPI_FEATURE_FORM114|XSPI_FEATURE_FORM144|XSPI_FEATURE_FORM444) +#define XSPI_FEATURE_FORM118 (1u << 6) /* Form 1-1-8 supported */ +#define XSPI_FEATURE_FORM188 (1u << 7) /* Form 1-8-8 supported */ +#define XSPI_FEATURE_FORM888 (1u << 8) /* Form 8-8-8 supported */ +#define XSPI_FEATURE_OCTAL (XSPI_FEATURE_FORM118|XSPI_FEATURE_FORM188|XSPI_FEATURE_FORM888) +#define XSPI_FEATURE_XIP_READ (1u << 12) /* XIP Read operation support */ +#define XSPI_FEATURE_XIP_WRITE (1u << 13) /* XIP Write operation support */ +#define XSPI_FEATURE_DDROP (1u << 14) /* DDR support for OP */ +#define XSPI_FEATURE_DDR (1u << 15) /* DDR support for Address/Data */ +#define XSPI_FEATURE_OCTARAM (1u << 16) /* OctaRAM addressing (RAS/CAS) supported */ + +/** xSPI transfer additional flags */ +#define XSPI_FLAGS_SEQUENTIAL_DDR (1u << 0) /* Enable inverted order for DDR transfer */ +#define XSPI_FLAGS_FORCE_STROBE (1u << 1) /* Force to use of data strobe signal for timing reference */ +#define XSPI_FLAGS_DATA_ACCESS (1u << 2) /* Force to use data access method for exec_op */ + +/** xSPI Transfer form */ +typedef enum e_xspi_transfer_form +{ + SPI_FORM_1_1_1, /* Command executes at 1-1-1 form */ + SPI_FORM_1_1_2, /* Command executes at 1-1-2 form */ + SPI_FORM_1_2_2, /* Command executes at 1-2-2 form */ + SPI_FORM_2_2_2, /* Command executes at 2-2-2 form */ + SPI_FORM_1_1_4, /* Command executes at 1-1-4 form */ + SPI_FORM_1_4_4, /* Command executes at 1-4-4 form */ + SPI_FORM_4_4_4, /* Command executes at 4-4-4 form */ + SPI_FORM_1_1_8, /* Command executes at 1-1-8 form */ + SPI_FORM_1_8_8, /* Command executes at 1-8-8 form */ + SPI_FORM_8_8_8, /* Command executes at 8-8-8 form */ +} xspi_transfer_form_t; + +/** xSPI interface configuration */ +typedef struct st_xspi_cfg +{ + uint8_t channel; /* Channel number to be used */ + uintptr_t base; /* Regisgter base address */ + void const * extend; /* Implementation specific extended configuration */ +} xspi_cfg_t; + +/** xSPI control block. Allocate an implementation specific control block to pass into the xSPI API calls. */ +typedef void xspi_ctrl_t; + +/** xSPI operation table + */ +typedef struct st_xspi_op +{ + xspi_transfer_form_t form; ///< Transfer form + uint16_t op; ///< Operation code (for 2 byte op, highside used as 1st byte) + uint8_t op_size; ///< Operation code size (0 to 2) + bool op_is_ddr; ///< Operation code phase is DDR + uint32_t address; ///< Address (ignored for configuring in-place access) + uint8_t address_size; ///< Address size (0 to 4) + bool address_is_ddr; ///< Address phase is DDR + uint8_t additional_size; ///< Additional data size + uint32_t additional_value; ///< Additional data value + uint8_t dummy_cycles; ///< Dummy cycle count (as clocks) + size_t transfer_size; ///< Transfer size by bytes (ignored for configuring in-place access) + void * transfer_buffer; ///< Transfer buffer pointer (ignored for configuring in-place access) + bool transfer_is_ddr; ///< Transfer phase is DDR + uint8_t transfer_flag; ///< Additional transfer flags + uint8_t force_idle_level_mask; ///< Whether or not to force each IO level during the idle state + uint8_t force_idle_level_value; ///< IO level during the idle state + uint8_t slch_value; + uint8_t clsh_value; + uint8_t shsl_value; +} xspi_op_t; + +/** Shared Interface definition for xSPI */ +typedef struct st_xspi_api +{ + /** Prepare a channel for xSPI operation. + * + * @param[in, out] ctrl Pointer to user-provided storage for the control block. + * @param[in] cfg Pointer to xSPI configuration structure. + */ + int (* open)(xspi_ctrl_t * ctrl, xspi_cfg_t const * const cfg); + + /** Clean up the xSPI control block. + * + * @param[in] ctrl Pointer to the opened control block. + */ + int (* close)(xspi_ctrl_t * const ctrl); + + /** Post initialization routine + * + * @param[in] ctrl Pointer to the opened control block. + */ + int (* post_init)(xspi_ctrl_t * const ctrl); + + /** Execute operation. + * + * @param[in, out] ctrl Pointer to the control block. + * @param[in] op Operation structure + * @param[in] is_write Transaction phase direction is write + */ + int (* exec_op)(xspi_ctrl_t * const ctrl, xspi_op_t const * const op, bool is_write); + + /** Configure for in-place access. + * For enabling in-place access, start_xip must be called. + * + * @param[in, out] ctrl Pointer to the control block. + * @param[in] rop Operation structure for read operation. + * @param[in] wop Operation structure for write operation. + * @note + * For the flash, wop must be nullptr. + * @note + * For the OctaRAM, wop must be specified. + */ + int (* configure_xip)(xspi_ctrl_t * const ctrl, xspi_op_t const * const rop, xspi_op_t const * const wop); + + /** Starting in-place access. + * For configuring in-place access, configure_xip must be called. + * + * @param[in, out] ctrl Pointer to the control block. + */ + int (* start_xip)(xspi_ctrl_t * const ctrl); + + /** Stopping in-place access. + * + * @param[in, out] ctrl Pointer to the control block. + */ + int (* stop_xip)(xspi_ctrl_t * const ctrl); + + /** Do manual calibration. + * + * @param[in, out] ctrl Pointer to the control block. + */ + int (* run_manual_calibration)(xspi_ctrl_t * const ctrl); + + /** Enabling auto calibration. + * + * @param[in, out] ctrl Pointer to the control block. + */ + int (* enable_auto_calibration)(xspi_ctrl_t * const ctrl); + + /** Disabling auto calibration. + * + * @param[in, out] ctrl Pointer to the control block. + */ + int (* disable_auto_calibration)(xspi_ctrl_t * const ctrl); + + /** Setting SPI frequency. + * + * @param[in, out] ctrl Pointer to the control block. + * @param[in] frequency_hz Pointer to the control block. + */ + int (* set_frequency)(xspi_ctrl_t * const ctrl, int frequency_hz); + + /** Invalidate cache for entire MMAP + * + * @param[in] ctrl Pointer to the control block. + */ + int (* inv_mmap)(xspi_ctrl_t * const ctrl); + + /** Clean cache for entire MMAP + * + * @param[in] ctrl Pointer to the control block. + */ + int (* clean_mmap)(xspi_ctrl_t * const ctrl); + + /** Get MMAP base + * + * @param[in] ctrl Pointer to the control block. + */ + uintptr_t (* get_mmap_base)(xspi_ctrl_t * const ctrl); + + /** Get MMAP size + * + * @param[in] ctrl Pointer to the control block. + */ + size_t (* get_mmap_size)(xspi_ctrl_t * const ctrl); + + /** Get features flag + * + * @param[in] ctrl Pointer to the control block. + */ + uint32_t (* get_features)(xspi_ctrl_t * const ctrl); +} xspi_api_t; + +/** This structure encompasses everything that is needed to use an instance of this interface. */ +typedef struct st_xspi_instance +{ + xspi_ctrl_t * ctrl; ///< Pointer to the control structure for this instance + xspi_cfg_t const * cfg; ///< Pointer to the configuration structure for this instance + xspi_api_t const * api; ///< Pointer to the API structure for this instance +} xspi_instance_t; + +/* external functions */ +extern void xspi_setup(void); + +int rz_xspi_read(void* buf, uint64_t from, size_t length); +#endif /* _XSPI_API_H_ */ diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/include/xspidevice_api.h b/drivers/rz/ipl/rza/plat/renesas/rz/common/include/xspidevice_api.h new file mode 100644 index 00000000..2ae80aec --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/include/xspidevice_api.h @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _XSPIDEVICE_API_H_ +#define _XSPIDEVICE_API_H_ +#include +#include + +#include "xspi_api.h" + +/** xSPI device information */ +typedef struct st_xspidevice_info +{ + uint32_t capacity; /* Amount of memory */ + uint32_t minimum_erase_size; /* Minimum erase size (bytes) */ + char device_vendor[32]; /* Device vendor name */ + char device_product[32]; /* Device product name */ +} xspidevice_info_t; + +/** xSPI device configuration */ +typedef struct st_xspidevice_cfg +{ + const xspi_instance_t * xspi; /* Associated xSPI instance */ + void const * extend; /* Implementation configuration */ +} xspidevice_cfg_t; + +/** xSPI device control block. Allocate an implementation specific control block to pass into the xSPI API calls. */ +typedef void xspidevice_ctrl_t; + +/** xSPI device write status. */ +typedef enum xspidevice_write_status +{ + WRITE_STATUS_OK, + WRITE_STATUS_IN_PROGRESS, + WRITE_STATUS_PROTECTED, + WRITE_STATUS_FAIL, + WRITE_STATUS_SUSPENDED, + WRITE_STATUS_DISABLED, +} xspidevice_write_status_t; + +/** Shared Interface definition for xSPI */ +typedef struct st_xspidevice_api +{ + /** Prepare for communicate with SPI device + * + * @param[in, out] ctrl Control block allocated by user. + * @param[in] cfg Instance configuration parameter. + */ + int (* open)(xspidevice_ctrl_t * ctrl, xspidevice_cfg_t const * cfg); + + /** Clean up the xSPI control block. + * + * @param[in] ctrl Opened control block. + */ + int (* close)(xspidevice_ctrl_t * ctrl); + + /** Execute operation. + * + * @param[in, out] ctrl Opened control block. + * @param[in] op Operation structure + * @param[in] is_write Transaction phase direction is write + */ + int (* exec_op)(xspidevice_ctrl_t * ctrl, xspi_op_t const * op, bool is_write); + + /** Entering in-place access mode. + * + * @param[in, out] ctrl Opened control block. + */ + int (* enter_xip)(xspidevice_ctrl_t * ctrl); + + /** Exiting in-place access mode. + * + * @param[in, out] ctrl Opened control block. + */ + int (* exit_xip)(xspidevice_ctrl_t * ctrl); + + /** Get device information. + * + * @param[in, out] ctrl Opened control block. + * @param[out] info Pointer to user-provided storage for the device information + */ + int (* get_info)(xspidevice_ctrl_t * ctrl, xspidevice_info_t * info); + + /** Read memory + * + * @param[in, out] ctrl Opened control block. + * @param[out] buffer Pointer to user-provided storage for the read data + * @param[in] address Start address to read + * @param[in] length Bytes to read + */ + int (* read)(xspidevice_ctrl_t * ctrl, void * buffer, size_t address, size_t length); + + /** Write memory + * + * @param[in, out] ctrl Opened control block. + * @param[in] buffer Pointer to user-provided storage for the write data + * @param[in] address Start address to write + * @param[in] length Bytes to write + */ + int (* write)(xspidevice_ctrl_t * ctrl, void const * buffer, size_t address, size_t length); + + /** Erase memory + * + * @param[in, out] ctrl Opened control block. + * @param[in] address Start address to write + * @param[in] length Bytes to write + */ + int (* erase)(xspidevice_ctrl_t * ctrl, size_t address, size_t length); + + /** Get write status + * + * @param[in, out] ctrl Opened control block. + */ + enum xspidevice_write_status (* get_write_status)(xspidevice_ctrl_t * ctrl); + +} xspidevice_api_t; + +/** This structure encompasses everything that is needed to use an instance of this interface. */ +typedef struct st_xspidevice_instance +{ + xspidevice_ctrl_t * ctrl; /* control structure */ + xspidevice_cfg_t const * cfg; /* configuration structure */ + xspidevice_api_t const * api; /* API structure */ +} xspidevice_instance_t; + +extern const int xspidevices_count; +extern const xspidevice_instance_t * xspidevices[]; + +#endif /* _XSPIDEVICE_API_H_ */ diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/plat_gic.c b/drivers/rz/ipl/rza/plat/renesas/rz/common/plat_gic.c new file mode 100644 index 00000000..bf3760e6 --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/plat_gic.c @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include + +#include +#include + +uintptr_t plat_rdistif_base_addrs[PLATFORM_CORE_COUNT]; + +static unsigned int plat_mpidr_to_core_pos(u_register_t mpidr) +{ + mpidr |= (read_mpidr_el1() & MPIDR_MT_MASK); + return (unsigned int)plat_core_pos_by_mpidr(mpidr); +} + +const gicv3_driver_data_t rzg2l_gic_data = { + .gicd_base = RZG2L_GICD_BASE, + .gicr_base = RZG2L_GICR_BASE, + .rdistif_num = PLATFORM_CORE_COUNT, + .rdistif_base_addrs = plat_rdistif_base_addrs, + .mpidr_to_core_pos = plat_mpidr_to_core_pos, +}; + +void plat_gic_driver_init(void) +{ + gicv3_driver_init(&rzg2l_gic_data); +} + +void plat_gic_init(void) +{ + gicv3_distif_init(); + gicv3_rdistif_init(plat_my_core_pos()); + gicv3_cpuif_enable(plat_my_core_pos()); +} + +void plat_gic_cpuif_enable(void) +{ + gicv3_cpuif_enable(plat_my_core_pos()); +} + +void plat_gic_cpuif_disable(void) +{ + gicv3_cpuif_disable(plat_my_core_pos()); +} + +void plat_gic_pcpu_init(void) +{ + gicv3_rdistif_init(plat_my_core_pos()); +} diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/plat_image_load.c b/drivers/rz/ipl/rza/plat/renesas/rz/common/plat_image_load.c new file mode 100644 index 00000000..19dc20d5 --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/plat_image_load.c @@ -0,0 +1,184 @@ +/* + * Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#if (APPLOAD == RZ_NOFIP) +#define FSP_FROM_XSPI_BASE (FSP_BASE - RZA3_XSPI_MEMORY_BASE) +typedef struct fsp_app_header { + uint64_t entry_addr; + uint64_t entry_addr_inv; + uint64_t dest_addr; + uint64_t dest_addr_inv; + uint64_t payload_size; + uint64_t payload_size_inv; + uint8_t padding[432]; + uint8_t signature[32]; + uint8_t app_payload_start; +} fsp_app_header_t; +#endif /* (APPLOAD == RZ_NOFIP) */ + +bl_load_info_t *plat_get_bl_image_load_info(void) +{ + return get_bl_load_info_from_mem_params_desc(); +} + +bl_params_t *plat_get_next_bl_params(void) +{ + return get_next_bl_params_from_mem_params_desc(); +} + + +void plat_flush_next_bl_params(void) +{ +} + +#if (APPLOAD == RZ_NOFIP) +int rz_check_fsp_header(fsp_app_header_t *header) +{ + int ret = 0; + + RZA_PRINTF_VERBOSE("Check Application Header...\n"); + if (~(header->entry_addr) != header->entry_addr_inv) { + ret = -1; + ERROR("The value of the entry point address does not match its inverted value\n"); + } + + if (0 == ret) { + if (~(header->dest_addr) != header->dest_addr_inv) { + ret = -1; + ERROR("The address to copy application image does not match its inverted value\n"); + } + } + + if (0 == ret) { + if (~(header->payload_size) != header->payload_size_inv) + { + ret = -1; + ERROR("The size of application image does not match its inverted value\n"); + } + } + + if ((FSP_BASE + RZ_APP_PAYLOAD_OFFSET) != header->dest_addr) { + if (0 == ret) { + if ((header->dest_addr < RZG2L_SRAM_BASE) || + ((header->dest_addr + header->payload_size)> (RZG2L_SRAM_BASE + RZG2L_SRAM_SIZE))) { + if ((header->dest_addr < RZG2L_SPIROM_BASE) || + ((header->dest_addr + header->payload_size)> (RZG2L_SPIROM_BASE + RZG2L_SPIROM_SIZE))) { + if ((header->dest_addr < RZG2L_DDR1_BASE) || + ((header->dest_addr + header->payload_size) > (RZG2L_DDR1_BASE + RZG2L_DDR1_SIZE + RZG2L_DDR2_SIZE))) { + ret = -1; + ERROR("The application image to copy does not fit in memory\n"); + } + } + } + } + } + + if (0 == ret) { + RZA_PRINTF_VERBOSE("Success!\n"); + } + + return ret; +} + + +void rz_update_descs(fsp_app_header_t *header) +{ + bl_params_t *bl2_params; + + bl2_params = plat_get_next_bl_params(); + + bl2_params->head->image_info->image_base = (uintptr_t)header->dest_addr; + bl2_params->head->image_info->image_max_size = header->payload_size; + bl2_params->head->image_info->h.attr |= IMAGE_ATTRIB_SKIP_LOADING; + bl2_params->head->ep_info->pc = (uintptr_t)header->entry_addr; + flush_bl_params_desc(); + + return; +} + +static fsp_app_header_t header_impl; +void rza_load_fsp(void) +{ + int ret = 0; + fsp_app_header_t *header; + + header = &header_impl; + + rz_xspi_read(header, FSP_FROM_XSPI_BASE, sizeof(*header)); + + ret = rz_check_fsp_header(header); + + if (0 == ret) { + if ((FSP_BASE + RZ_APP_PAYLOAD_OFFSET) != header->dest_addr) { + rz_xspi_read((void*)header->dest_addr, RZ_APP_PAYLOAD_OFFSET + FSP_FROM_XSPI_BASE, (size_t)header->payload_size); + flush_dcache_range((uintptr_t)(header->dest_addr), header->payload_size); + } + rz_update_descs(header); + } else { + panic(); + } + + return; +} +#endif /* (APPLOAD == RZ_NOFIP) */ + +void rza_print_descs(void) +{ + bl_params_t *bl2_params; + + bl2_params = plat_get_next_bl_params(); + + /* In the case of release build, bl2_params isn't used */ + RZ_UNUSED_PARAM(bl2_params); + RZA_PRINTF_VERBOSE("Address to copy the application: 0x%08llx\n", (uint64_t)bl2_params->head->image_info->image_base); + RZA_PRINTF_VERBOSE("Entry Point Address: 0x%08llx\n", (uint64_t)bl2_params->head->ep_info->pc); + RZA_PRINTF_VERBOSE("Copy Data Size: %dbyte\n", bl2_params->head->image_info->image_max_size); + RZA_PRINTF_VERBOSE("SPSR_EL3 settings:\n"); + if (MODE_RW_64 == GET_RW(bl2_params->head->ep_info->spsr)) { + RZA_PRINTF_VERBOSE("AArch64 execution state\n"); + } else { + RZA_PRINTF_VERBOSE("AArch32 execution state\n"); + } + + if (0 != ((bl2_params->head->ep_info->spsr >> SPSR_DAIF_SHIFT) & DAIF_DBG_BIT)) { + RZA_PRINTF_VERBOSE("Debug exception enable\n"); + } + + if (0 != ((bl2_params->head->ep_info->spsr >> SPSR_DAIF_SHIFT) & DAIF_ABT_BIT)) { + RZA_PRINTF_VERBOSE("SError interrupt enable\n"); + } + + if (0 != ((bl2_params->head->ep_info->spsr >> SPSR_DAIF_SHIFT) & DAIF_IRQ_BIT)) { + RZA_PRINTF_VERBOSE("IRQ interrupt enable\n"); + } + + if (0 != ((bl2_params->head->ep_info->spsr >> SPSR_DAIF_SHIFT) & DAIF_FIQ_BIT)) { + RZA_PRINTF_VERBOSE("FIQ interrupt enable\n"); + } + + RZA_PRINTF_VERBOSE("EL and stack pointer: "); + RZA_PRINTF_VERBOSE("EL%d", GET_EL(bl2_params->head->ep_info->spsr)); + if (MODE_SP_EL0 == GET_SP(bl2_params->head->ep_info->spsr)) { + RZA_PRINTF_VERBOSE("t\n"); + } else { + RZA_PRINTF_VERBOSE("h\n"); + } + + RZA_PRINTF("Jump to Application\n"); + + return; +} diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/plat_pm.c b/drivers/rz/ipl/rza/plat/renesas/rz/common/plat_pm.c new file mode 100644 index 00000000..7bba7840 --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/plat_pm.c @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +#include +#include +#include + +uintptr_t gp_warm_ep; + +static int rzg2l_pwr_domain_on(u_register_t mpidr) +{ + const uint32_t rval[2][2] = { + { SYS_CA55_CFG_RVAL0, SYS_CA55_CFG_RVAH0 }, + { SYS_CA55_CFG_RVAL1, SYS_CA55_CFG_RVAH1 } + }; + const uint32_t pch[2][2] = { + { CPG_CORE0_PCHCTL, CPG_CORE0_PCHMON }, + { CPG_CORE1_PCHCTL, CPG_CORE1_PCHMON } + }; + uint8_t coreid = MPIDR_AFFLVL1_VAL(mpidr); + + if (coreid > 1) + return PSCI_E_INVALID_PARAMS; + + mmio_write_32(rval[coreid][0], (uint32_t)(gp_warm_ep & 0xFFFFFFFC)); + mmio_write_32(rval[coreid][1], (uint32_t)((gp_warm_ep >> 32) & 0xFF)); + + /* Assert PORESET */ + mmio_write_32(CPG_RST_CA55, (0x00010000 << coreid)); + while ((mmio_read_32(CPG_RSTMON_CA55) & (0x1 << coreid)) == 0x0) + ; + + /* Deassert PORESET */ + mmio_write_32(CPG_RST_CA55, (0x00050005 << coreid)); + while ((mmio_read_32(CPG_RSTMON_CA55) & (0x1 << coreid)) != 0x0) + ; + + mmio_write_32(pch[coreid][0], 0x00080001); + while ((mmio_read_32(pch[coreid][1]) & 0x1) != 0x1) + ; + mmio_write_32(pch[coreid][0], 0x00080000); + while ((mmio_read_32(pch[coreid][1]) & 0x1) != 0x0) + ; + + return PSCI_E_SUCCESS; +} + +static void rzg2l_pwr_domain_on_finish(const psci_power_state_t *target_state) +{ +#if !DEBUG_RZG2L_FPGA + plat_gic_pcpu_init(); + plat_gic_cpuif_enable(); +#endif +} + +const plat_psci_ops_t rzg2l_plat_psci_ops = { + .pwr_domain_on = rzg2l_pwr_domain_on, + .pwr_domain_on_finish = rzg2l_pwr_domain_on_finish, +}; + +int plat_setup_psci_ops(uintptr_t sec_entrypoint, + const plat_psci_ops_t **psci_ops) +{ + gp_warm_ep = sec_entrypoint; + *psci_ops = &rzg2l_plat_psci_ops; + + return 0; +} diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/plat_rz_common.c b/drivers/rz/ipl/rza/plat/renesas/rz/common/plat_rz_common.c new file mode 100644 index 00000000..ec4fbf3e --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/plat_rz_common.c @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +unsigned int plat_get_syscnt_freq2(void) +{ + return syc_get_freq(); +} diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/plat_security.c b/drivers/rz/ipl/rza/plat/renesas/rz/common/plat_security.c new file mode 100644 index 00000000..a58d8fc1 --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/plat_security.c @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2020-2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include "rzg2l_def.h" +#include "sys_regs.h" +#include "plat_tzc_def.h" +#include "rza_printf.h" + +typedef struct arm_tzc_regions_info { + unsigned long long base; + unsigned long long end; + unsigned int sec_attr; + unsigned int nsaid_permissions; +} arm_tzc_regions_info_t; + + +static const struct { + uint32_t reg; + uint32_t msk; + uint32_t val; +} sys_acctl[] = { + /* Master Access Control Register */ + {SYS_MSTACCCTL0, 0x00BB00BBU, 0x00AAAA88U}, + {SYS_MSTACCCTL1, 0xBBBBBBBBU, 0xAAAAAAAAU}, + {SYS_MSTACCCTL2, 0x00BBBBBBU, 0x00AAAAAAU}, + {SYS_MSTACCCTL3, 0x00BBBBBBU, 0x00AAAAAAU}, + {SYS_MSTACCCTL4, 0x0B0B00BBU, 0x0A0A00AAU}, + {SYS_MSTACCCTL5, 0x00000000U, 0x00000000U}, + /* Slave Access Control Register */ + {SYS_SLVACCCTL0, 0x0000000FU, 0x00000008U}, + {SYS_SLVACCCTL1, 0x3FFF3CFFU, 0x0800C0AAU}, + {SYS_SLVACCCTL2, 0x00FFCFFFU, 0x00000002U}, + {SYS_SLVACCCTL3, 0x3FFF3FFFU, 0x00000000U}, + {SYS_SLVACCCTL4, 0xFFFF0FFFU, 0x00000000U}, + {SYS_SLVACCCTL5, 0x00000033U, 0x00000000U}, + {SYS_SLVACCCTL6, 0x0000000FU, 0x00000000U}, + {SYS_SLVACCCTL7, 0x0000000CU, 0x00000008U}, + {SYS_SLVACCCTL8, 0x0000000FU, 0x00000000U}, + {SYS_SLVACCCTL9, 0x00000000U, 0x00000000U}, + {SYS_SLVACCCTL10, 0x00000003U, 0x00000000U}, + {SYS_SLVACCCTL11, 0x00000000U, 0x00000000U}, + {SYS_SLVACCCTL12, 0x00000003U, 0x00000000U}, + {SYS_SLVACCCTL13, 0x00000003U, 0x00000000U}, + {SYS_SLVACCCTL14, 0x00000003U, 0x00000000U}, + {SYS_SLVACCCTL15, 0x00000000U, 0x00000000U}, +}; + +void plat_access_control_setup(void) +{ + uint32_t i; + + for (i = 0; i < ARRAY_SIZE(sys_acctl); i++) + { + uint32_t val = mmio_read_32(sys_acctl[i].reg) & (~sys_acctl[i].msk); + val |= (sys_acctl[i].val & sys_acctl[i].msk); + mmio_write_32(sys_acctl[i].reg, val); + } +} + +uint8_t tzc400_get_num_filters(uintptr_t tzc_base) +{ + uint32_t tzc400_build; + + tzc400_build = mmio_read_32(tzc_base + BUILD_CONFIG_OFF); + + return (uint8_t)((tzc400_build >> BUILD_CONFIG_NF_SHIFT) & BUILD_CONFIG_NF_MASK) + 1U; +} + +void plat_tzc400_setup(uintptr_t tzc_base, const arm_tzc_regions_info_t *tzc_regions) +{ + uint8_t num_filters; + unsigned int region_index = 1U; + const arm_tzc_regions_info_t *p; + const arm_tzc_regions_info_t init_tzc_regions[] = { + {0} + }; + + INFO("Configuring TrustZone Controller\n"); + + tzc400_init(tzc_base); + + tzc400_disable_filters(); + + tzc400_configure_region0(TZC_REGION_S_RDWR, PLAT_TZC_REGION_ACCESS_NS_UNPRIV); + + if (tzc_regions == NULL) + p = init_tzc_regions; + else + p = tzc_regions; + + num_filters = tzc400_get_num_filters(tzc_base); + + for (; p->base != 0UL; p++) { + tzc400_configure_region((1 << num_filters) - 1, region_index, + p->base, p->end, p->sec_attr, p->nsaid_permissions); + region_index++; + } + + INFO("Total %u regions set.\n", region_index); + + tzc400_set_action(TZC_ACTION_ERR); + + tzc400_enable_filters(); +} + +#if IMAGE_BL2 +static void bl2_security_setup(void) +{ + const arm_tzc_regions_info_t ddr_tzc_regions[] = { +#ifndef RZA3 +#if TRUSTED_BOARD_BOOT + /* security for BL31 and OP-TEE */ + {PLAT_FW_TZC_PROT_DRAM1_BASE, PLAT_FW_TZC_PROT_DRAM1_END, + TZC_REGION_S_RDWR, PLAT_TZC_REGION_ACCESS_S_UNPRIV}, + {PLAT_TEE_TZC_PROT_DRAM1_BASE, PLAT_TEE_TZC_PROT_DRAM1_END, + TZC_REGION_S_RDWR, PLAT_TZC_REGION_ACCESS_S_UNPRIV}, +#endif /* TRUSTED_BOARD_BOOT */ + {} +#else + {0} +#endif + }; + + /* initialize TZC-400 */ + plat_tzc400_setup(RZG2L_TZC_DDR_BASE, &ddr_tzc_regions[0]); + plat_tzc400_setup(RZG2L_TZC_SPI_BASE, NULL); + + /* setup Master/Slave Access Control */ + plat_access_control_setup(); +} +#endif + +#if IMAGE_BL31 +static void bl31_security_setup(void) +{ + const arm_tzc_regions_info_t msram_tzc_regions[] = { +#if TRUSTED_BOARD_BOOT + { PLAT_AP_TZC_PROT_SRAM1_BASE, PLAT_AP_TZC_PROT_SRAM1_END, + TZC_REGION_S_RDWR, PLAT_TZC_REGION_ACCESS_S_UNPRIV }, +#endif /* TRUSTED_BOARD_BOOT */ + {} + }; + + const arm_tzc_regions_info_t asram_tzc_regions[] = { +#if TRUSTED_BOARD_BOOT + { PLAT_AP_TZC_PROT_SRAM2_BASE, PLAT_AP_TZC_PROT_SRAM2_END, + TZC_REGION_S_RDWR, PLAT_TZC_REGION_ACCESS_S_UNPRIV }, +#endif /* TRUSTED_BOARD_BOOT */ + {} + }; + + /* Additional settings for TZC-400 SRAM */ + plat_tzc400_setup(RZG2L_TZC_MSRAM_BASE, &msram_tzc_regions[0]); + plat_tzc400_setup(RZG2L_TZC_ASRAM_BASE, &asram_tzc_regions[0]); +} +#endif + +void plat_security_setup(void) +{ +#if IMAGE_BL2 + bl2_security_setup(); +#endif + +#if IMAGE_BL31 + bl31_security_setup(); +#endif +} diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/plat_storage.c b/drivers/rz/ipl/rza/plat/renesas/rz/common/plat_storage.c new file mode 100644 index 00000000..f7249f4e --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/plat_storage.c @@ -0,0 +1,277 @@ +/* + * Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +static uintptr_t memdrv_dev_handle; +static uintptr_t fip_dev_handle; +static uintptr_t emmcdrv_dev_handle; + +static uintptr_t boot_io_drv_id; + +static const io_block_spec_t spirom_block_spec = { + .offset = RZG2L_SPIROM_FIP_BASE, + .length = RZG2L_SPIROM_FIP_SIZE, +}; + +static const io_drv_spec_t emmc_block_spec = { + .offset = RZG2L_EMMC_FIP_BASE, + .length = RZG2L_EMMC_FIP_SIZE, +}; + +static const io_uuid_spec_t bl31_file_spec = { + .uuid = UUID_EL3_RUNTIME_FIRMWARE_BL31, +}; + +static const io_uuid_spec_t bl32_file_spec = { + .uuid = UUID_SECURE_PAYLOAD_BL32, +}; + +static const io_uuid_spec_t bl33_file_spec = { + .uuid = UUID_NON_TRUSTED_FIRMWARE_BL33, +}; + +#if TRUSTED_BOARD_BOOT +static const io_uuid_spec_t soc_fw_key_cert_file_spec = { + .uuid = UUID_SOC_FW_KEY_CERT, +}; + +static const io_uuid_spec_t soc_fw_content_cert_file_spec = { + .uuid = UUID_SOC_FW_CONTENT_CERT, +}; + +static const io_uuid_spec_t tos_fw_key_cert_file_spec = { + .uuid = UUID_TRUSTED_OS_FW_KEY_CERT, +}; + +static const io_uuid_spec_t tos_fw_content_cert_file_spec = { + .uuid = UUID_TRUSTED_OS_FW_CONTENT_CERT, +}; + +static const io_uuid_spec_t nt_fw_key_cert_file_spec = { + .uuid = UUID_NON_TRUSTED_FW_KEY_CERT, +}; + +static const io_uuid_spec_t nt_fw_content_cert_file_spec = { + .uuid = UUID_NON_TRUSTED_FW_CONTENT_CERT, +}; +#endif + +static int32_t open_emmcdrv(const uintptr_t spec); +static int32_t open_memmap(const uintptr_t spec); +static int32_t open_fipdrv(const uintptr_t spec); + +struct plat_io_policy { + uintptr_t *dev_handle; + uintptr_t image_spec; + int32_t (*check)(const uintptr_t spec); +}; + +static const struct plat_io_policy* policies; + +static const struct plat_io_policy spirom_policies[] = { + [FIP_IMAGE_ID] = { + &memdrv_dev_handle, + (uintptr_t) &spirom_block_spec, + &open_memmap}, + [BL31_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t) &bl31_file_spec, + &open_fipdrv}, + [BL32_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t) &bl32_file_spec, + &open_fipdrv}, + [BL33_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t) &bl33_file_spec, + &open_fipdrv}, +#if TRUSTED_BOARD_BOOT + [SOC_FW_KEY_CERT_ID] = { + &fip_dev_handle, + (uintptr_t) &soc_fw_key_cert_file_spec, + &open_fipdrv}, + [SOC_FW_CONTENT_CERT_ID] = { + &fip_dev_handle, + (uintptr_t) &soc_fw_content_cert_file_spec, + &open_fipdrv}, + [TRUSTED_OS_FW_KEY_CERT_ID] = { + &fip_dev_handle, + (uintptr_t) &tos_fw_key_cert_file_spec, + &open_fipdrv}, + [TRUSTED_OS_FW_CONTENT_CERT_ID] = { + &fip_dev_handle, + (uintptr_t) &tos_fw_content_cert_file_spec, + &open_fipdrv}, + [NON_TRUSTED_FW_KEY_CERT_ID] = { + &fip_dev_handle, + (uintptr_t) &nt_fw_key_cert_file_spec, + &open_fipdrv}, + [NON_TRUSTED_FW_CONTENT_CERT_ID] = { + &fip_dev_handle, + (uintptr_t) &nt_fw_content_cert_file_spec, + &open_fipdrv}, +#endif + { 0, 0, 0} +}; + +static const struct plat_io_policy emmc_policies[] = { + [FIP_IMAGE_ID] = { + &emmcdrv_dev_handle, + (uintptr_t) &emmc_block_spec, + &open_emmcdrv}, + [BL31_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t) &bl31_file_spec, + &open_fipdrv}, + [BL32_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t) &bl32_file_spec, + &open_fipdrv}, + [BL33_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t) &bl33_file_spec, + &open_fipdrv}, +#if TRUSTED_BOARD_BOOT + [SOC_FW_KEY_CERT_ID] = { + &fip_dev_handle, + (uintptr_t) &soc_fw_key_cert_file_spec, + &open_fipdrv}, + [SOC_FW_CONTENT_CERT_ID] = { + &fip_dev_handle, + (uintptr_t) &soc_fw_content_cert_file_spec, + &open_fipdrv}, + [TRUSTED_OS_FW_KEY_CERT_ID] = { + &fip_dev_handle, + (uintptr_t) &tos_fw_key_cert_file_spec, + &open_fipdrv}, + [TRUSTED_OS_FW_CONTENT_CERT_ID] = { + &fip_dev_handle, + (uintptr_t) &tos_fw_content_cert_file_spec, + &open_fipdrv}, + [NON_TRUSTED_FW_KEY_CERT_ID] = { + &fip_dev_handle, + (uintptr_t) &nt_fw_key_cert_file_spec, + &open_fipdrv}, + [NON_TRUSTED_FW_CONTENT_CERT_ID] = { + &fip_dev_handle, + (uintptr_t) &nt_fw_content_cert_file_spec, + &open_fipdrv}, +#endif + { 0, 0, 0} +}; + +static int32_t open_fipdrv(const uintptr_t spec) +{ + int32_t result; + + result = io_dev_init(fip_dev_handle, boot_io_drv_id); + if (result != 0) + return result; + + return result; +} + +static int32_t open_memmap(const uintptr_t spec) +{ + uintptr_t handle; + int32_t result; + + result = io_dev_init(memdrv_dev_handle, 0); + if (result != 0) + return result; + + result = io_open(memdrv_dev_handle, spec, &handle); + if (result == 0) + io_close(handle); + + return result; +} + +static int32_t open_emmcdrv(const uintptr_t spec) +{ + return io_dev_init(emmcdrv_dev_handle, 0); +} + +void rz_io_setup(void) +{ + const io_dev_connector_t *memmap; + const io_dev_connector_t *emmc; + const io_dev_connector_t *rzg2l; + uint16_t boot_dev; + + boot_dev = *((uint16_t *)RZG2L_BOOTINFO_BASE) & MASK_BOOTM_DEVICE; + + boot_io_drv_id = FIP_IMAGE_ID; + + xspi_setup(); + + register_io_dev_fip(&rzg2l); + + io_dev_open(rzg2l, 0, &fip_dev_handle); + + if ((boot_dev == BOOT_MODE_SPI_1_8) || + (boot_dev == BOOT_MODE_SPI_3_3) || + (boot_dev == BOOT_MODE_NAND_SPI_1_8) || + (boot_dev == BOOT_MODE_NAND_SPI_3_3)) { + register_io_dev_memmap(&memmap); + io_dev_open(memmap, 0, &memdrv_dev_handle); + + policies = &spirom_policies[0]; + } + else if (USE_EMMC && (boot_dev == BOOT_MODE_EMMC_1_8 || + boot_dev == BOOT_MODE_EMMC_3_3)) { + if (emmc_init() != EMMC_SUCCESS) { + NOTICE("BL2: Failed to eMMC driver initialize.\n"); + panic(); + } + emmc_memcard_power(EMMC_POWER_ON); + if (emmc_mount() != EMMC_SUCCESS) { + NOTICE("BL2: Failed to eMMC mount operation.\n"); + panic(); + } + + register_io_dev_emmcdrv(&emmc); + io_dev_open(emmc, 0, &emmcdrv_dev_handle); + + policies = &emmc_policies[0]; + } else { + panic(); + } +} + +int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle, + uintptr_t *image_spec) +{ + const struct plat_io_policy *policy; + int result; + + policy = &policies[image_id]; + + result = policy->check(policy->image_spec); + if (result != 0) + return result; + + *image_spec = policy->image_spec; + *dev_handle = *(policy->dev_handle); + + return 0; +} + diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/plat_topology.c b/drivers/rz/ipl/rza/plat/renesas/rz/common/plat_topology.c new file mode 100644 index 00000000..14fe6694 --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/plat_topology.c @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +static const unsigned char rzg2l_power_domain_tree_desc[] = { + PLATFORM_SYSTEM_COUNT, + PLATFORM_CLUSTER_COUNT, + PLATFORM_CORE_COUNT +}; + +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + return rzg2l_power_domain_tree_desc; +} + +int plat_core_pos_by_mpidr(u_register_t mpidr) +{ + unsigned int cluster_id, cpu_id; + + cluster_id = MPIDR_AFFLVL2_VAL(mpidr); + cpu_id = MPIDR_AFFLVL1_VAL(mpidr); + + if ((cluster_id >= PLATFORM_CLUSTER_COUNT) || (cpu_id >= PLATFORM_CORE_COUNT)) + return -1; + + return cpu_id; +} diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/rz_bl2_xspi_config.sh b/drivers/rz/ipl/rza/plat/renesas/rz/common/rz_bl2_xspi_config.sh new file mode 100644 index 00000000..cd30e7e0 --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/rz_bl2_xspi_config.sh @@ -0,0 +1,159 @@ +#!/bin/sh +# Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause + +envfile=$1 +outfile=$2 +_devices= +_index=0 + +usage() +{ + echo "" + echo "Please specify environment definition file and output file" + exit 1 +} + +error() +{ + local message=$1 + shift + echo "" + echo "Error: $message" + exit 1 +} + +add_device() +{ + local basename=$1 + shift + + # indirect dereference + eval _if_name=\$RZ_${basename}_IF + eval _if_config=\$RZ_${basename}_IF_CONFIG + eval _device=\$${basename}_DEVICE + eval _option=\$${basename}_OPTION + eval _if_option=\$${basename}_IF_OPTION + + # add if defined + if [ -n "$_device" ]; then + # IF + cat << EOT >> "${outfile}" +${_if_name}_ctrl_t xspi${_index}_ctrl; + +EOT + if [ -n "$_if_option" ]; then + cat << EOT >> "${outfile}" +const ${_if_name}_ext_t xspi${_index}_ext = { + ${_if_option} +}; + +const xspi_cfg_t xspi${_index}_cfg = { + ${_if_config}, + .extend=&xspi${_index}_ext +}; +EOT + else + cat << EOT >> "${outfile}" +const xspi_cfg_t xspi${_index}_cfg = { + ${_if_config}, + .extend=NULL +}; +EOT + fi + cat << EOT >> "${outfile}" + +const xspi_instance_t xspi${_index} = { + .ctrl=&xspi${_index}_ctrl, + .cfg=&xspi${_index}_cfg, + .api=&${_if_name}_api +}; + +EOT + + # DEVICE + cat << EOT >> "${outfile}" +${_device}_ctrl_t xspidevice${_index}_ctrl; + +EOT + if [ -n "$_option" ]; then + cat << EOT >> "${outfile}" +const ${_device}_ext_t xspidevice${_index}_ext = { + ${_option} +}; + +const xspidevice_cfg_t xspidevice${_index}_cfg = { + .xspi=&xspi${_index}, + .extend=&xspidevice${_index}_ext +}; +EOT + else + cat << EOT >> "${outfile}" +const xspidevice_cfg_t xspidevice${_index}_cfg = { + .xspi=&xspi${_index}, + .extend=NULL +}; +EOT + fi + cat << EOT >> "${outfile}" + +const xspidevice_instance_t xspidevice${_index} = { + .ctrl=&xspidevice${_index}_ctrl, + .cfg=&xspidevice${_index}_cfg, + .api=&${_device}_api +}; + +EOT + + # append device + _devices="${_devices} xspidevice${_index}" + + _index=`expr ${_index} + 1` + fi +} + +# Script begin +if [ -z "$envfile" ]; then + usage +fi + +if [ -z "$outfile" ]; then + usage +fi + +# Create outfile and test if failed +echo "/* Generated by ${0} */" > "$outfile" +if ! [ $? ]; then + error "Aborted." +fi + +# Import environment +if [ -f "$envfile" ]; then + . "$envfile" +fi + +# Append includes +for header in $RZ_XSPI_HEADERS +do + echo "#include \"$header\"" >> "${outfile}" +done +echo "" >> "${outfile}" + +# Append definitions +for device in $RZ_XSPI_CONFIGS +do + add_device $device +done + +# List device instances +if [ -n "$_devices" ]; then + echo "const int xspidevices_count = ${_index};" >> "${outfile}" + echo "const xspidevice_instance_t * xspidevices[${_index}] = {" >> "${outfile}" + for instance in $_devices + do + echo " &${instance}," >> "${outfile}" + done + echo "};" >> "${outfile}" +fi + diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/rz_common.mk b/drivers/rz/ipl/rza/plat/renesas/rz/common/rz_common.mk new file mode 100644 index 00000000..0b330830 --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/rz_common.mk @@ -0,0 +1,134 @@ +# +# Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +BL2_AT_EL3 := 1 +COLD_BOOT_SINGLE_CPU := 1 +PROGRAMMABLE_RESET_ADDRESS := 1 +WARMBOOT_ENABLE_DCACHE_EARLY := 1 +GICV3_SUPPORT_GIC600 := 1 +HW_ASSISTED_COHERENCY := 1 +USE_COHERENT_MEM := 0 +TRUSTED_BOARD_BOOT := 0 +PROTECTED_CHIPID := 1 +DEBUG_RZG2L_FPGA := 0 +$(eval $(call add_define,PROTECTED_CHIPID)) +$(eval $(call add_define,DEBUG_RZG2L_FPGA)) + +WA_RZG2L_GIC64BIT := 1 +$(eval $(call add_define,WA_RZG2L_GIC64BIT)) + +ifeq (${DEBUG_RZG2L_FPGA}, 0) + USE_SDRAM ?= 1 +else + USE_SDRAM ?= 0 +endif +$(eval $(call add_define,USE_SDRAM)) + +USE_EMMC?=0 +$(eval $(call add_define,USE_EMMC)) + +# Enable workarounds for selected Cortex-A55 erratas. +ERRATA_A55_1530923 := 1 + +ifeq (${APPLOAD},RZ_NOFIP) +FSP_BASE ?= 0x20020000 +$(eval $(call add_define,FSP_BASE)) +endif + +PLAT_INCLUDES := -Iplat/renesas/rz/common/include \ + -Iplat/renesas/rz/common/drivers/emmc \ + -Iplat/renesas/rz/common/drivers/io \ + -Idrivers/renesas/common/io + +RZ_TIMER_SOURCES := drivers/delay_timer/generic_delay_timer.c \ + drivers/delay_timer/delay_timer.c + +ifneq (${USE_SDRAM}, 0) +DDR_SOURCES := plat/renesas/rz/common/drivers/ddr/ddr.c +endif + +ifneq (${ARCH_TYPE}, 0) +MMU_SOURCE := plat/renesas/rz/common/drivers/rza_mmu/ARMv8A/rza_mmu.c +endif + +BL2_SOURCES += lib/cpus/aarch64/cortex_a55.S \ + ${RZ_TIMER_SOURCES} \ + ${DYN_CFG_SOURCES} \ + common/desc_image_load.c \ + drivers/io/io_storage.c \ + drivers/io/io_memmap.c \ + drivers/io/io_fip.c \ + drivers/arm/tzc/tzc400.c \ + plat/renesas/rz/common/drivers/io/io_emmcdrv.c \ + plat/renesas/rz/common/drivers/emmc/emmc_interrupt.c\ + plat/renesas/rz/common/drivers/emmc/emmc_utility.c \ + plat/renesas/rz/common/drivers/emmc/emmc_mount.c \ + plat/renesas/rz/common/drivers/emmc/emmc_init.c \ + plat/renesas/rz/common/drivers/emmc/emmc_read.c \ + plat/renesas/rz/common/drivers/emmc/emmc_cmd.c \ + plat/renesas/rz/common/bl2_plat_setup.c \ + plat/renesas/rz/common/bl2_plat_mem_params_desc.c \ + plat/renesas/rz/common/plat_image_load.c \ + plat/renesas/rz/common/plat_storage.c \ + plat/renesas/rz/common/plat_security.c \ + plat/renesas/rz/common/aarch64/plat_helpers.S \ + plat/renesas/rz/common/drivers/syc.c \ + plat/renesas/rz/common/drivers/pfc.c \ + plat/renesas/rz/common/drivers/cpg.c \ + ${DDR_SOURCES} \ + ${XSPI_SOURCES} \ + ${MMU_SOURCE} + +# Include GICv3 driver files +GICV3_IMPL := GIC600 +include drivers/arm/gic/v3/gicv3.mk + +# BL2 only for RZ/A3UL +ifneq (${PLAT},a3ul) +ifneq (${PLAT},a3m) +BL31_SOURCES += lib/cpus/aarch64/cortex_a55.S \ + ${GICV3_SOURCES} \ + drivers/arm/tzc/tzc400.c \ + plat/common/plat_gicv3.c \ + plat/common/plat_psci_common.c \ + plat/renesas/rz/common/bl31_plat_setup.c \ + plat/renesas/rz/common/plat_pm.c \ + plat/renesas/rz/common/plat_topology.c \ + plat/renesas/rz/common/plat_gic.c \ + plat/renesas/rz/common/plat_security.c \ + plat/renesas/rz/common/rz_plat_sip_handler.c \ + plat/renesas/rz/common/rz_sip_svc.c \ + plat/renesas/rz/common/aarch64/plat_helpers.S \ + plat/renesas/rz/common/drivers/syc.c +endif +endif + +include lib/xlat_tables_v2/xlat_tables.mk +PLAT_BL_COMMON_SOURCES += ${XLAT_TABLES_LIB_SRCS} \ + plat/renesas/rz/common/plat_rz_common.c \ + plat/renesas/rz/common/drivers/scifa.S + +ifneq (${TRUSTED_BOARD_BOOT},0) + + # Include common TBB sources + AUTH_SOURCES := drivers/auth/img_parser_mod.c + + # Include the selected chain of trust sources. + ifeq (${COT},tbbr) + AUTH_SOURCES += plat/renesas/rz/common/drivers/auth/tbbr/tbbr_cot.c + else + $(error Unknown chain of trust ${COT}) + endif + + # Include RZ TBB sources + AUTH_SOURCES += plat/renesas/rz/common/drivers/auth/auth_mod.c \ + plat/renesas/rz/common/drivers/auth/sblib/crypto_sblib.c \ + plat/renesas/rz/common/drivers/auth/sblib/sblib_parser.c + + + BL2_SOURCES += ${AUTH_SOURCES} + +endif diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/rz_image.pl b/drivers/rz/ipl/rza/plat/renesas/rz/common/rz_image.pl new file mode 100644 index 00000000..73a2e355 --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/rz_image.pl @@ -0,0 +1,74 @@ +#!/usr/bin/perl -w +# Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause + +use strict; +use bigint; +my $size_limit = 0x1D000; + +die("Not enough parameter\n") if ($#ARGV < 0); + +# Open input file +my $name = shift(@ARGV); +my $outname; +if ($#ARGV < 0) { + $outname = "rz_" . $name; +} +else { + $outname = shift(@ARGV); +} +open(my $origin, '<', $name) or die("Can not open input file"); +binmode $origin; + +# Obtaining size ($st[7]) +my @st = stat($origin); + +# Check appended size +my $size = ($st[7] + 3) & "0xfffffffffffffffc"; +my $msg; +if ($size != $st[7]) {$msg = "Appended size";} else {$msg="Size";} +die("$msg too big ($size > $size_limit)") if ($size > $size_limit); + +# Create temporary file +open(my $out, '>', $outname) or die("Can not open output file"); +binmode $out; + +# Write header +$out->print(pack('L', $size)); +for(my $i = 1; $i < 112; $i++) { + $out->print(pack('L', 0xffffffff)); +} +$out->print(pack('L', 0xffff0000)); +$out->print(pack('L', 0x000800ff)); +$out->print(pack('L', 0x00fff700)); +$out->print(pack('L', 0xf700f708)); +$out->print(pack('L', 0xffffffff)); +$out->print(pack('L', 0xffffffff)); +$out->print(pack('L', 0xffffffff)); +$out->print(pack('L', 0xffffffff)); +$out->print(pack('L', 0xffffffff)); +$out->print(pack('L', 0xffffffff)); +$out->print(pack('L', 0xffffffff)); +$out->print(pack('L', 0xffffffff)); +$out->print(pack('L', 0xffffffff)); +$out->print(pack('L', 0xffffffff)); +$out->print(pack('L', 0xffffffff)); +$out->print(pack('L', 0xaa55ffff)); + +# Append original data to temporary file +my $buf; +read($origin, $buf, $st[7]); +$out->print($buf); +if($st[7] < $size) { + warn "Not aligned. Append " . ($size-$st[7]) . " zero(s)"; + # Append zero + for(;$st[7] < $size; $size--) { + $out->print(pack('C', 0)); + } +} +$out->flush; + +# close +close $out; +close $origin; diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/rz_plat_sip_handler.c b/drivers/rz/ipl/rza/plat/renesas/rz/common/rz_plat_sip_handler.c new file mode 100644 index 00000000..2753aa66 --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/rz_plat_sip_handler.c @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define RZ_OTP_BASE_DEVID (RZG2L_OTP_BASE + 0x1178) +#define RZ_OTP_BASE_CHIPID (RZG2L_OTP_BASE + 0x1140) + +static uintptr_t rz_otp_handler_devid(void *handle, u_register_t x1) +{ + uint32_t devid = mmio_read_32(RZ_OTP_BASE_DEVID); + SMC_RET1(handle, devid); +} + +static uintptr_t rz_otp_handler_chipid(void *handle, u_register_t x1, u_register_t flags) +{ + uint32_t chipid[4]; + +#if (PROTECTED_CHIPID == 1) + uint32_t ns = is_caller_non_secure(flags); + if (ns) { + WARN("%s: Unauthorized service call from non-secure\n", __func__); + SMC_RET1(handle, SMC_UNK); + } +#endif + + chipid[0] = mmio_read_32(RZ_OTP_BASE_CHIPID + 0x0); + chipid[1] = mmio_read_32(RZ_OTP_BASE_CHIPID + 0x4); + chipid[2] = mmio_read_32(RZ_OTP_BASE_CHIPID + 0x8); + chipid[3] = mmio_read_32(RZ_OTP_BASE_CHIPID + 0xC); + + SMC_RET4(handle, chipid[0], chipid[1], chipid[2], chipid[3]); +} + +uintptr_t rz_plat_sip_handler(uint32_t smc_fid, + u_register_t x1, + u_register_t x2, + u_register_t x3, + u_register_t x4, + void *cookie, + void *handle, + u_register_t flags) +{ + switch (smc_fid) { + + case RZ_SIP_SVC_GET_DEVID: + return rz_otp_handler_devid(handle, x1); + case RZ_SIP_SVC_GET_CHIPID: + return rz_otp_handler_chipid(handle, x1, flags); + default: + WARN("%s: Unimplemented RZ SiP Service Call: 0x%x \n", __func__, smc_fid); + SMC_RET1(handle, SMC_UNK); + } +} diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/rz_sip_svc.c b/drivers/rz/ipl/rza/plat/renesas/rz/common/rz_sip_svc.c new file mode 100644 index 00000000..d78fb5d2 --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/rz_sip_svc.c @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include + +#pragma weak rz_plat_sip_handler + +uintptr_t rz_plat_sip_handler(uint32_t smc_fid, + u_register_t x1, + u_register_t x2, + u_register_t x3, + u_register_t x4, + void *cookie, + void *handle, + u_register_t flags) +{ + WARN("%s: Unimplemented RZ SiP Service Call: 0x%x \n", __func__, smc_fid); + SMC_RET1(handle, SMC_UNK); +} + +/* + * This function handles RZ defined SiP Calls + */ +static uintptr_t rz_sip_handler(unsigned int smc_fid, + u_register_t x1, + u_register_t x2, + u_register_t x3, + u_register_t x4, + void *cookie, + void *handle, + u_register_t flags) +{ + return rz_plat_sip_handler(smc_fid, x1, x2, x3, x4, cookie, handle, flags); +} + + +/* Define a runtime service descriptor for fast SMC calls */ +DECLARE_RT_SVC( + rz_sip_svc, + OEN_SIP_START, + OEN_SIP_END, + SMC_TYPE_FAST, + NULL, + rz_sip_handler +); diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/common/rz_xspi_common.mk b/drivers/rz/ipl/rza/plat/renesas/rz/common/rz_xspi_common.mk new file mode 100644 index 00000000..de348c82 --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/common/rz_xspi_common.mk @@ -0,0 +1,67 @@ +# +# Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +RZ_BUILD_PLAT_TMP:=$(BUILD_PLAT) +RZ_XSPI_DEF:=$(RZ_BUILD_PLAT_TMP)/rz_bl2_xspi_def.c +RZ_XSPI_ENV:=$(RZ_BUILD_PLAT_TMP)/rz_bl2_xspi.env +RZ_XSPI_HEADERS:=xspi_api.h xspidevice_api.h $(RZ_XSPI_HEADERS) +RZ_USE_XSPI:=0 + +RZ_XSPIFLASH_DISABLE_WRITE:=1 +RZ_XSPI_FORCE_VOLTAGE_SETTING:=0 +$(eval $(call add_define,RZ_XSPIFLASH_DISABLE_WRITE)) +$(eval $(call add_define,RZ_XSPI_FORCE_VOLTAGE_SETTING)) + +rz_uniq = $(if $1,$(firstword $1) $(call rz_uniq,$(filter-out $(firstword $1),$1))) + +define RZ_XSPI_ADD_IFDRIVER + $(eval RZ_XSPI_SOURCES:=$(RZ_XSPI_SOURCES) $(RZ_XSPI_DRIVER_PATH)/$(1).c) + $(eval RZ_XSPI_HEADERS:=$(RZ_XSPI_HEADERS) $(1).h) +endef + +define RZ_XSPI_INCLUDE_MAKEFILE + $(if $(filter-out __,_$(strip $($(1)_DEVICE))_),$(call RZ_XSPI_ADD_IFDRIVER,$(RZ_$(1)_IF))) + $(if $(filter-out __,_$(strip $($(1)_DEVICE))_),$(eval include plat/renesas/rz/common/drivers/xspidevice/$($(1)_DEVICE)/rz_xspidevice.mk)) + $(if $(filter-out __,_$(strip $($(1)_DEVICE))_),$(eval RZ_USE_XSPI:=1)) +endef + +# export environment to shell +define RZ_ADD_ENV + @echo $(1)=\"$(strip $($(1)))\" >> $@ + +endef + +define RZ_XSPI_ADD_ENV + $(call RZ_ADD_ENV,RZ_$(1)_IF) + $(call RZ_ADD_ENV,RZ_$(1)_IF_CONFIG) + $(call RZ_ADD_ENV,$(1)_DEVICE) + $(call RZ_ADD_ENV,$(1)_OPTION) + $(call RZ_ADD_ENV,$(1)_IF_OPTION) +endef + +# include makefile for xspidevice driver +$(foreach element,$(RZ_XSPI_CONFIGS),$(call RZ_XSPI_INCLUDE_MAKEFILE,$(element))) + +# eliminate duplicated entries in sources and headers +RZ_XSPI_SOURCES:=$(call rz_uniq,$(RZ_XSPI_SOURCES)) +RZ_XSPI_HEADERS:=$(call rz_uniq,$(RZ_XSPI_HEADERS)) + +# add sources +ifneq ($(RZ_USE_XSPI),0) + XSPI_SOURCES+=$(RZ_XSPI_SOURCES) + XSPI_SOURCES+=$(RZ_XSPI_DEF) +# Outs env file +$(RZ_XSPI_ENV): $(RZ_BUILD_PLAT_TMP) + @echo -n "" > $@ + $(foreach element,$(RZ_XSPI_CONFIGS),$(call RZ_XSPI_ADD_ENV,$(element))) + $(call RZ_ADD_ENV,RZ_XSPI_CONFIGS) + $(call RZ_ADD_ENV,RZ_XSPI_HEADERS) + $(call RZ_ADD_ENV,PLAT) + $(call RZ_ADD_ENV,BOARD) + +$(RZ_XSPI_DEF): $(RZ_XSPI_ENV) + $(Q)$(SHELL) plat/renesas/rz/common/rz_bl2_xspi_config.sh "$(RZ_XSPI_ENV)" "$(RZ_XSPI_DEF)" +endif diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/soc/a3m/drivers/ddr/ddr_a3m.c b/drivers/rz/ipl/rza/plat/renesas/rz/soc/a3m/drivers/ddr/ddr_a3m.c new file mode 100644 index 00000000..3c656cfb --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/soc/a3m/drivers/ddr/ddr_a3m.c @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +void ddr_ctrl_reten_en_n(uint8_t val) +{ + val &= 1; + write_phy_reg(DDRPHY_R79, (val << 1)); +} + diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/soc/a3m/drivers/ddr/param_mc_C-011_D3-01-1.c b/drivers/rz/ipl/rza/plat/renesas/rz/soc/a3m/drivers/ddr/param_mc_C-011_D3-01-1.c new file mode 100644 index 00000000..d1a1bc32 --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/soc/a3m/drivers/ddr/param_mc_C-011_D3-01-1.c @@ -0,0 +1,449 @@ +/* + * Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +const char ddr_an_version[] = "v0.0.41"; + +const uint32_t mc_init_tbl[][2] = { + { DENALI_CTL_00, 0x00000600 }, + { DENALI_CTL_01, 0x00000000 }, + { DENALI_CTL_02, 0x00000000 }, + { DENALI_CTL_03, 0x00000000 }, + { DENALI_CTL_04, 0x00000000 }, + { DENALI_CTL_05, 0x00000000 }, + { DENALI_CTL_06, 0x00000000 }, + { DENALI_CTL_07, 0x00000000 }, + { DENALI_CTL_08, 0x00000000 }, + { DENALI_CTL_09, 0x00000000 }, + { DENALI_CTL_10, 0x01000008 }, + { DENALI_CTL_11, 0x00100100 }, + { DENALI_CTL_12, 0x00027100 }, + { DENALI_CTL_13, 0x00061A80 }, + { DENALI_CTL_14, 0x08160200 }, + { DENALI_CTL_15, 0x00000000 }, + { DENALI_CTL_16, 0x06000404 }, + { DENALI_CTL_17, 0x00002700 }, + { DENALI_CTL_18, 0x06060020 }, + { DENALI_CTL_19, 0x0600200B }, + { DENALI_CTL_20, 0x000C0406 }, + { DENALI_CTL_21, 0x0400DB60 }, + { DENALI_CTL_22, 0x00030305 }, + { DENALI_CTL_23, 0x01000C0B }, + { DENALI_CTL_24, 0x0B031701 }, + { DENALI_CTL_25, 0x0100000B }, + { DENALI_CTL_26, 0x00000101 }, + { DENALI_CTL_27, 0x00000000 }, + { DENALI_CTL_28, 0x00000000 }, + { DENALI_CTL_29, 0x00040301 }, + { DENALI_CTL_30, 0x00000058 }, + { DENALI_CTL_31, 0x00000610 }, + { DENALI_CTL_32, 0x00000005 }, + { DENALI_CTL_33, 0x00140005 }, + { DENALI_CTL_34, 0x00600200 }, + { DENALI_CTL_35, 0x00000060 }, + { DENALI_CTL_36, 0x01000201 }, + { DENALI_CTL_37, 0x80104002 }, + { DENALI_CTL_38, 0x00000000 }, + { DENALI_CTL_39, 0x00040000 }, + { DENALI_CTL_40, 0x00000000 }, + { DENALI_CTL_41, 0x00018400 }, + { DENALI_CTL_42, 0x000007D0 }, + { DENALI_CTL_43, 0x00018400 }, + { DENALI_CTL_44, 0x00018400 }, + { DENALI_CTL_45, 0x00018400 }, + { DENALI_CTL_46, 0x00000000 }, + { DENALI_CTL_47, 0x01000000 }, + { DENALI_CTL_48, 0x00000000 }, + { DENALI_CTL_49, 0x00000000 }, + { DENALI_CTL_50, 0x00000000 }, + { DENALI_CTL_51, 0x00000000 }, + { DENALI_CTL_52, 0x00000000 }, + { DENALI_CTL_53, 0x00000000 }, + { DENALI_CTL_54, 0x00000000 }, + { DENALI_CTL_55, 0x00212100 }, + { DENALI_CTL_56, 0x09070000 }, + { DENALI_CTL_57, 0x2F0E010A }, + { DENALI_CTL_58, 0x00000300 }, + { DENALI_CTL_59, 0x00010004 }, + { DENALI_CTL_60, 0x00000800 }, + { DENALI_CTL_61, 0x00000000 }, + { DENALI_CTL_62, 0x00000000 }, + { DENALI_CTL_63, 0x00000000 }, + { DENALI_CTL_64, 0x00000100 }, + { DENALI_CTL_65, 0x00000200 }, + { DENALI_CTL_66, 0x00001000 }, + { DENALI_CTL_67, 0x00000000 }, + { DENALI_CTL_68, 0x00000000 }, + { DENALI_CTL_69, 0x00000C70 }, + { DENALI_CTL_70, 0x00000004 }, + { DENALI_CTL_71, 0x00000018 }, + { DENALI_CTL_72, 0x00000C70 }, + { DENALI_CTL_73, 0x00000004 }, + { DENALI_CTL_74, 0x00000018 }, + { DENALI_CTL_75, 0x00000000 }, + { DENALI_CTL_76, 0x00000000 }, + { DENALI_CTL_77, 0x00000000 }, + { DENALI_CTL_78, 0x00000000 }, + { DENALI_CTL_79, 0x00000000 }, + { DENALI_CTL_80, 0x00000000 }, + { DENALI_CTL_81, 0x00000000 }, + { DENALI_CTL_82, 0x00000000 }, + { DENALI_CTL_83, 0x00000000 }, + { DENALI_CTL_84, 0x00000000 }, + { DENALI_CTL_85, 0x01010000 }, + { DENALI_CTL_86, 0x00000000 }, + { DENALI_CTL_87, 0x00000000 }, + { DENALI_CTL_88, 0x00000000 }, + { DENALI_CTL_89, 0x00000000 }, + { DENALI_CTL_90, 0x00000000 }, + { DENALI_CTL_91, 0x00000000 }, + { DENALI_CTL_92, 0x00000000 }, + { DENALI_CTL_93, 0x00000000 }, + { DENALI_CTL_94, 0x00000000 }, + { DENALI_CTL_95, 0x01000200 }, + { DENALI_CTL_96, 0x00010801 }, + { DENALI_CTL_97, 0x00000000 }, + { DENALI_CTL_98, 0x00000000 }, + { DENALI_CTL_99, 0x00000000 }, + { DENALI_CTL_100, 0x00000000 }, + { DENALI_CTL_101, 0x00000000 }, + { DENALI_CTL_102, 0x00000000 }, + { DENALI_CTL_103, 0x00000000 }, + { DENALI_CTL_104, 0x00000000 }, + { DENALI_CTL_105, 0x00000000 }, + { DENALI_CTL_106, 0x00000000 }, + { DENALI_CTL_107, 0x00000000 }, + { DENALI_CTL_108, 0x00000000 }, + { DENALI_CTL_109, 0x00000000 }, + { DENALI_CTL_110, 0x00000008 }, + { DENALI_CTL_111, 0x006403E8 }, + { DENALI_CTL_112, 0x00000000 }, + { DENALI_CTL_113, 0x00000000 }, + { DENALI_CTL_114, 0x00000000 }, + { DENALI_CTL_115, 0x15110000 }, + { DENALI_CTL_116, 0x00040C18 }, + { DENALI_CTL_117, 0x00BEBD03 }, + { DENALI_CTL_118, 0x0000C350 }, + { DENALI_CTL_119, 0x00000000 }, + { DENALI_CTL_120, 0x01000200 }, + { DENALI_CTL_121, 0x00000040 }, + { DENALI_CTL_122, 0x04010100 }, + { DENALI_CTL_123, 0x00010104 }, + { DENALI_CTL_124, 0x01FF0000 }, + { DENALI_CTL_125, 0x00003F00 }, + { DENALI_CTL_126, 0xFFFFFFFF }, + { DENALI_CTL_127, 0x00FFFF00 }, + { DENALI_CTL_128, 0xFFFF0A00 }, + { DENALI_CTL_129, 0x01010001 }, + { DENALI_CTL_130, 0x01010101 }, + { DENALI_CTL_131, 0x01030101 }, + { DENALI_CTL_132, 0x0C010000 }, + { DENALI_CTL_133, 0x01000000 }, + { DENALI_CTL_134, 0x00000000 }, + { DENALI_CTL_135, 0x00010000 }, + { DENALI_CTL_136, 0x00000000 }, + { DENALI_CTL_137, 0x00000000 }, + { DENALI_CTL_138, 0x00000000 }, + { DENALI_CTL_139, 0x00000000 }, + { DENALI_CTL_140, 0x00000000 }, + { DENALI_CTL_141, 0x00000000 }, + { DENALI_CTL_142, 0x00000000 }, + { DENALI_CTL_143, 0x00000000 }, + { DENALI_CTL_144, 0x00000000 }, + { DENALI_CTL_145, 0x00000000 }, + { DENALI_CTL_146, 0x00000000 }, + { DENALI_CTL_147, 0x00000000 }, + { DENALI_CTL_148, 0x00000000 }, + { DENALI_CTL_149, 0x00000000 }, + { DENALI_CTL_150, 0x00000000 }, + { DENALI_CTL_151, 0x00000000 }, + { DENALI_CTL_152, 0x00000000 }, + { DENALI_CTL_153, 0x00000000 }, + { DENALI_CTL_154, 0x00000000 }, + { DENALI_CTL_155, 0x00000000 }, + { DENALI_CTL_156, 0x00000000 }, + { DENALI_CTL_157, 0x00010000 }, + { DENALI_CTL_158, 0x00000000 }, + { DENALI_CTL_159, 0x00000800 }, + { DENALI_CTL_160, 0x00000000 }, + { DENALI_CTL_161, 0x00000898 }, + { DENALI_CTL_162, 0x03000000 }, + { DENALI_CTL_163, 0x00000408 }, + { DENALI_CTL_164, 0x00000000 }, + { DENALI_CTL_165, 0x00000000 }, + { DENALI_CTL_166, 0x00000000 }, + { DENALI_CTL_167, 0x00000000 }, + { DENALI_CTL_168, 0x00000000 }, + { DENALI_CTL_169, 0x00000000 }, + { DENALI_CTL_170, 0x00000000 }, + { DENALI_CTL_171, 0x00000000 }, + { DENALI_CTL_172, 0x00000000 }, + { DENALI_CTL_173, 0x00000000 }, + { DENALI_CTL_174, 0x00000000 }, + { DENALI_CTL_175, 0x06060700 }, + { DENALI_CTL_176, 0x03020001 }, + { DENALI_CTL_177, 0x01030101 }, + { DENALI_CTL_178, 0x03000302 }, + { DENALI_CTL_179, 0x00000000 }, + { DENALI_CTL_180, 0x00080801 }, + { DENALI_CTL_181, 0x00080801 }, + { DENALI_CTL_182, 0x00070601 }, + { DENALI_CTL_183, 0x00000000 }, + { DENALI_CTL_184, 0x000FFFFF }, + { DENALI_CTL_185, 0xFFFFFFFF }, + { DENALI_CTL_186, 0x000F000F }, + { DENALI_CTL_187, 0x00000000 }, + { DENALI_CTL_188, 0x030FFFFF }, + { DENALI_CTL_189, 0xFFFFFFFF }, + { DENALI_CTL_190, 0x000F000F }, + { DENALI_CTL_191, 0x00000000 }, + { DENALI_CTL_192, 0x030FFFFF }, + { DENALI_CTL_193, 0xFFFFFFFF }, + { DENALI_CTL_194, 0x000F000F }, + { DENALI_CTL_195, 0x00000000 }, + { DENALI_CTL_196, 0x030FFFFF }, + { DENALI_CTL_197, 0xFFFFFFFF }, + { DENALI_CTL_198, 0x000F000F }, + { DENALI_CTL_199, 0x00000000 }, + { DENALI_CTL_200, 0x030FFFFF }, + { DENALI_CTL_201, 0xFFFFFFFF }, + { DENALI_CTL_202, 0x000F000F }, + { DENALI_CTL_203, 0x00000000 }, + { DENALI_CTL_204, 0x030FFFFF }, + { DENALI_CTL_205, 0xFFFFFFFF }, + { DENALI_CTL_206, 0x000F000F }, + { DENALI_CTL_207, 0x00000000 }, + { DENALI_CTL_208, 0x030FFFFF }, + { DENALI_CTL_209, 0xFFFFFFFF }, + { DENALI_CTL_210, 0x000F000F }, + { DENALI_CTL_211, 0x00000000 }, + { DENALI_CTL_212, 0x030FFFFF }, + { DENALI_CTL_213, 0xFFFFFFFF }, + { DENALI_CTL_214, 0x000F000F }, + { DENALI_CTL_215, 0x00000000 }, + { DENALI_CTL_216, 0x030FFFFF }, + { DENALI_CTL_217, 0xFFFFFFFF }, + { DENALI_CTL_218, 0x000F000F }, + { DENALI_CTL_219, 0x00000000 }, + { DENALI_CTL_220, 0x030FFFFF }, + { DENALI_CTL_221, 0xFFFFFFFF }, + { DENALI_CTL_222, 0x000F000F }, + { DENALI_CTL_223, 0x00000000 }, + { DENALI_CTL_224, 0x030FFFFF }, + { DENALI_CTL_225, 0xFFFFFFFF }, + { DENALI_CTL_226, 0x000F000F }, + { DENALI_CTL_227, 0x00000000 }, + { DENALI_CTL_228, 0x030FFFFF }, + { DENALI_CTL_229, 0xFFFFFFFF }, + { DENALI_CTL_230, 0x000F000F }, + { DENALI_CTL_231, 0x00000000 }, + { DENALI_CTL_232, 0x030FFFFF }, + { DENALI_CTL_233, 0xFFFFFFFF }, + { DENALI_CTL_234, 0x000F000F }, + { DENALI_CTL_235, 0x00000000 }, + { DENALI_CTL_236, 0x030FFFFF }, + { DENALI_CTL_237, 0xFFFFFFFF }, + { DENALI_CTL_238, 0x000F000F }, + { DENALI_CTL_239, 0x00000000 }, + { DENALI_CTL_240, 0x030FFFFF }, + { DENALI_CTL_241, 0xFFFFFFFF }, + { DENALI_CTL_242, 0x000F000F }, + { DENALI_CTL_243, 0x00000000 }, + { DENALI_CTL_244, 0x030FFFFF }, + { DENALI_CTL_245, 0xFFFFFFFF }, + { DENALI_CTL_246, 0x000F000F }, + { DENALI_CTL_247, 0x00000000 }, + { DENALI_CTL_248, 0x000FFFFF }, + { DENALI_CTL_249, 0xFFFFFFFF }, + { DENALI_CTL_250, 0x000F000F }, + { DENALI_CTL_251, 0x00000000 }, + { DENALI_CTL_252, 0x030FFFFF }, + { DENALI_CTL_253, 0xFFFFFFFF }, + { DENALI_CTL_254, 0x000F000F }, + { DENALI_CTL_255, 0x00000000 }, + { DENALI_CTL_256, 0x030FFFFF }, + { DENALI_CTL_257, 0xFFFFFFFF }, + { DENALI_CTL_258, 0x000F000F }, + { DENALI_CTL_259, 0x00000000 }, + { DENALI_CTL_260, 0x030FFFFF }, + { DENALI_CTL_261, 0xFFFFFFFF }, + { DENALI_CTL_262, 0x000F000F }, + { DENALI_CTL_263, 0x00000000 }, + { DENALI_CTL_264, 0x030FFFFF }, + { DENALI_CTL_265, 0xFFFFFFFF }, + { DENALI_CTL_266, 0x000F000F }, + { DENALI_CTL_267, 0x00000000 }, + { DENALI_CTL_268, 0x030FFFFF }, + { DENALI_CTL_269, 0xFFFFFFFF }, + { DENALI_CTL_270, 0x000F000F }, + { DENALI_CTL_271, 0x00000000 }, + { DENALI_CTL_272, 0x030FFFFF }, + { DENALI_CTL_273, 0xFFFFFFFF }, + { DENALI_CTL_274, 0x000F000F }, + { DENALI_CTL_275, 0x00000000 }, + { DENALI_CTL_276, 0x030FFFFF }, + { DENALI_CTL_277, 0xFFFFFFFF }, + { DENALI_CTL_278, 0x000F000F }, + { DENALI_CTL_279, 0x00000000 }, + { DENALI_CTL_280, 0x030FFFFF }, + { DENALI_CTL_281, 0xFFFFFFFF }, + { DENALI_CTL_282, 0x000F000F }, + { DENALI_CTL_283, 0x00000000 }, + { DENALI_CTL_284, 0x030FFFFF }, + { DENALI_CTL_285, 0xFFFFFFFF }, + { DENALI_CTL_286, 0x000F000F }, + { DENALI_CTL_287, 0x00000000 }, + { DENALI_CTL_288, 0x030FFFFF }, + { DENALI_CTL_289, 0xFFFFFFFF }, + { DENALI_CTL_290, 0x000F000F }, + { DENALI_CTL_291, 0x00000000 }, + { DENALI_CTL_292, 0x030FFFFF }, + { DENALI_CTL_293, 0xFFFFFFFF }, + { DENALI_CTL_294, 0x000F000F }, + { DENALI_CTL_295, 0x00000000 }, + { DENALI_CTL_296, 0x030FFFFF }, + { DENALI_CTL_297, 0xFFFFFFFF }, + { DENALI_CTL_298, 0x000F000F }, + { DENALI_CTL_299, 0x00000000 }, + { DENALI_CTL_300, 0x030FFFFF }, + { DENALI_CTL_301, 0xFFFFFFFF }, + { DENALI_CTL_302, 0x000F000F }, + { DENALI_CTL_303, 0x00000000 }, + { DENALI_CTL_304, 0x030FFFFF }, + { DENALI_CTL_305, 0xFFFFFFFF }, + { DENALI_CTL_306, 0x000F000F }, + { DENALI_CTL_307, 0x00000000 }, + { DENALI_CTL_308, 0x030FFFFF }, + { DENALI_CTL_309, 0xFFFFFFFF }, + { DENALI_CTL_310, 0x000F000F }, + { DENALI_CTL_311, 0x00000000 }, + { DENALI_CTL_312, 0x000FFFFF }, + { DENALI_CTL_313, 0xFFFFFFFF }, + { DENALI_CTL_314, 0x000F000F }, + { DENALI_CTL_315, 0x00000000 }, + { DENALI_CTL_316, 0x030FFFFF }, + { DENALI_CTL_317, 0xFFFFFFFF }, + { DENALI_CTL_318, 0x000F000F }, + { DENALI_CTL_319, 0x00000000 }, + { DENALI_CTL_320, 0x030FFFFF }, + { DENALI_CTL_321, 0xFFFFFFFF }, + { DENALI_CTL_322, 0x000F000F }, + { DENALI_CTL_323, 0x00000000 }, + { DENALI_CTL_324, 0x030FFFFF }, + { DENALI_CTL_325, 0xFFFFFFFF }, + { DENALI_CTL_326, 0x000F000F }, + { DENALI_CTL_327, 0x00000000 }, + { DENALI_CTL_328, 0x030FFFFF }, + { DENALI_CTL_329, 0xFFFFFFFF }, + { DENALI_CTL_330, 0x000F000F }, + { DENALI_CTL_331, 0x00000000 }, + { DENALI_CTL_332, 0x030FFFFF }, + { DENALI_CTL_333, 0xFFFFFFFF }, + { DENALI_CTL_334, 0x000F000F }, + { DENALI_CTL_335, 0x00000000 }, + { DENALI_CTL_336, 0x030FFFFF }, + { DENALI_CTL_337, 0xFFFFFFFF }, + { DENALI_CTL_338, 0x000F000F }, + { DENALI_CTL_339, 0x00000000 }, + { DENALI_CTL_340, 0x030FFFFF }, + { DENALI_CTL_341, 0xFFFFFFFF }, + { DENALI_CTL_342, 0x000F000F }, + { DENALI_CTL_343, 0x00000000 }, + { DENALI_CTL_344, 0x030FFFFF }, + { DENALI_CTL_345, 0xFFFFFFFF }, + { DENALI_CTL_346, 0x000F000F }, + { DENALI_CTL_347, 0x00000000 }, + { DENALI_CTL_348, 0x030FFFFF }, + { DENALI_CTL_349, 0xFFFFFFFF }, + { DENALI_CTL_350, 0x000F000F }, + { DENALI_CTL_351, 0x00000000 }, + { DENALI_CTL_352, 0x030FFFFF }, + { DENALI_CTL_353, 0xFFFFFFFF }, + { DENALI_CTL_354, 0x000F000F }, + { DENALI_CTL_355, 0x00000000 }, + { DENALI_CTL_356, 0x030FFFFF }, + { DENALI_CTL_357, 0xFFFFFFFF }, + { DENALI_CTL_358, 0x000F000F }, + { DENALI_CTL_359, 0x00000000 }, + { DENALI_CTL_360, 0x030FFFFF }, + { DENALI_CTL_361, 0xFFFFFFFF }, + { DENALI_CTL_362, 0x000F000F }, + { DENALI_CTL_363, 0x00000000 }, + { DENALI_CTL_364, 0x030FFFFF }, + { DENALI_CTL_365, 0xFFFFFFFF }, + { DENALI_CTL_366, 0x000F000F }, + { DENALI_CTL_367, 0x00000000 }, + { DENALI_CTL_368, 0x030FFFFF }, + { DENALI_CTL_369, 0xFFFFFFFF }, + { DENALI_CTL_370, 0x000F000F }, + { DENALI_CTL_371, 0x00000000 }, + { DENALI_CTL_372, 0x030FFFFF }, + { DENALI_CTL_373, 0xFFFFFFFF }, + { DENALI_CTL_374, 0x000F000F }, + { DENALI_CTL_375, 0x03000000 }, + { DENALI_CTL_376, 0x03030303 }, + { DENALI_CTL_377, 0x03030303 }, + { DENALI_CTL_378, 0x03030303 }, + { DENALI_CTL_379, 0x00030303 }, + { DENALI_CTL_380, 0x02020064 }, + { DENALI_CTL_381, 0x02020202 }, + { DENALI_CTL_382, 0x02020202 }, + { DENALI_CTL_383, 0x02020202 }, + { DENALI_CTL_384, 0x00010202 }, + { DENALI_CTL_385, 0x01010064 }, + { DENALI_CTL_386, 0x01010101 }, + { DENALI_CTL_387, 0x01010101 }, + { DENALI_CTL_388, 0x01010101 }, + { DENALI_CTL_389, 0x00020101 }, + { DENALI_CTL_390, 0x00000064 }, + { DENALI_CTL_391, 0x00000006 }, + { DENALI_CTL_392, 0x000007D0 }, + { DENALI_CTL_393, 0x00000032 }, + { DENALI_CTL_394, 0x00000200 }, + { DENALI_CTL_395, 0x00000200 }, + { DENALI_CTL_396, 0x00000000 }, + { DENALI_CTL_397, 0x00000000 }, + { DENALI_CTL_398, 0x030A0205 }, + { DENALI_CTL_399, 0x00200307 }, + { DENALI_CTL_400, 0x00000000 }, + { DENALI_CTL_401, 0x0A000202 }, + { DENALI_CTL_402, 0x000C000A }, + { DENALI_CTL_403, 0x00000000 }, + { DENALI_CTL_404, 0x00000000 }, + { DENALI_CTL_405, 0x00000000 }, + { DENALI_CTL_406, 0x00000000 }, + { DENALI_CTL_407, 0x00000000 }, + { DENALI_CTL_408, 0x00000000 }, + { DENALI_CTL_409, 0x00000000 }, + { DENALI_CTL_410, 0x00000000 }, + { DENALI_CTL_411, 0x00000000 }, + { DENALI_CTL_412, 0x0000000F }, + { DENALI_CTL_413, 0x017104E2 }, + { DENALI_CTL_414, 0x4F5E64A8 }, + { DENALI_CTL_415, 0x00003C30 }, + { DENALI_CTL_416, 0x00003C28 }, + { DENALI_CTL_417, 0x00000000 }, + { DENALI_CTL_418, 0x00000000 }, + { DENALI_CTL_419, 0x00000000 }, + { DENALI_CTL_420, 0x00000000 }, + { DENALI_CTL_421, 0x00000000 }, + { DENALI_CTL_422, 0x00000000 }, + { DENALI_CTL_423, 0x00000000 }, + { DENALI_CTL_424, 0x00000000 }, + { DENALI_CTL_425, 0x00000000 }, + { DENALI_CTL_426, 0x00000000 }, + { DENALI_CTL_427, 0x00000000 }, + { DENALI_CTL_428, 0x00000000 }, + { DENALI_CTL_429, 0x00000000 }, + { DENALI_CTL_430, 0x00000000 }, + { DENALI_CTL_431, 0x00000000 }, + { DENALI_CTL_432, 0x00000000 }, + { DENALI_CTL_433, 0x00000000 }, + { DENALI_CTL_434, 0x00000000 }, + { DENALI_CTL_435, 0x00000000 } +}; diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/soc/a3m/drivers/ddr/param_mc_C-011_D3-02-1.c b/drivers/rz/ipl/rza/plat/renesas/rz/soc/a3m/drivers/ddr/param_mc_C-011_D3-02-1.c new file mode 100644 index 00000000..749db309 --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/soc/a3m/drivers/ddr/param_mc_C-011_D3-02-1.c @@ -0,0 +1,449 @@ +/* + * Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +const char ddr_an_version[] = "v0.0.32"; + +const uint32_t mc_init_tbl[][2] = { + { DENALI_CTL_00, 0x00000600 }, + { DENALI_CTL_01, 0x00000000 }, + { DENALI_CTL_02, 0x00000000 }, + { DENALI_CTL_03, 0x00000000 }, + { DENALI_CTL_04, 0x00000000 }, + { DENALI_CTL_05, 0x00000000 }, + { DENALI_CTL_06, 0x00000000 }, + { DENALI_CTL_07, 0x00000000 }, + { DENALI_CTL_08, 0x00000000 }, + { DENALI_CTL_09, 0x00000000 }, + { DENALI_CTL_10, 0x01000007 }, + { DENALI_CTL_11, 0x00100100 }, + { DENALI_CTL_12, 0x000208D6 }, + { DENALI_CTL_13, 0x00051616 }, + { DENALI_CTL_14, 0x07140200 }, + { DENALI_CTL_15, 0x00000000 }, + { DENALI_CTL_16, 0x05000404 }, + { DENALI_CTL_17, 0x00002100 }, + { DENALI_CTL_18, 0x0505001B }, + { DENALI_CTL_19, 0x05001B0A }, + { DENALI_CTL_20, 0x000C0405 }, + { DENALI_CTL_21, 0x0400B6D0 }, + { DENALI_CTL_22, 0x00030305 }, + { DENALI_CTL_23, 0x01000A0A }, + { DENALI_CTL_24, 0x0A031401 }, + { DENALI_CTL_25, 0x0100000A }, + { DENALI_CTL_26, 0x00000101 }, + { DENALI_CTL_27, 0x00000000 }, + { DENALI_CTL_28, 0x00000000 }, + { DENALI_CTL_29, 0x00040301 }, + { DENALI_CTL_30, 0x0000004A }, + { DENALI_CTL_31, 0x0000050C }, + { DENALI_CTL_32, 0x00000005 }, + { DENALI_CTL_33, 0x00100004 }, + { DENALI_CTL_34, 0x00500200 }, + { DENALI_CTL_35, 0x00000050 }, + { DENALI_CTL_36, 0x01000201 }, + { DENALI_CTL_37, 0x80104002 }, + { DENALI_CTL_38, 0x00000000 }, + { DENALI_CTL_39, 0x00040000 }, + { DENALI_CTL_40, 0x00000000 }, + { DENALI_CTL_41, 0x00014300 }, + { DENALI_CTL_42, 0x000007D0 }, + { DENALI_CTL_43, 0x00014300 }, + { DENALI_CTL_44, 0x00014300 }, + { DENALI_CTL_45, 0x00014300 }, + { DENALI_CTL_46, 0x00000000 }, + { DENALI_CTL_47, 0x01000000 }, + { DENALI_CTL_48, 0x00000000 }, + { DENALI_CTL_49, 0x00000000 }, + { DENALI_CTL_50, 0x00000000 }, + { DENALI_CTL_51, 0x00000000 }, + { DENALI_CTL_52, 0x00000000 }, + { DENALI_CTL_53, 0x00000000 }, + { DENALI_CTL_54, 0x00000000 }, + { DENALI_CTL_55, 0x00262600 }, + { DENALI_CTL_56, 0x09070000 }, + { DENALI_CTL_57, 0x2F0E010A }, + { DENALI_CTL_58, 0x00000300 }, + { DENALI_CTL_59, 0x00010004 }, + { DENALI_CTL_60, 0x00000800 }, + { DENALI_CTL_61, 0x00000000 }, + { DENALI_CTL_62, 0x00000000 }, + { DENALI_CTL_63, 0x00000000 }, + { DENALI_CTL_64, 0x00000100 }, + { DENALI_CTL_65, 0x00000200 }, + { DENALI_CTL_66, 0x00001000 }, + { DENALI_CTL_67, 0x00000000 }, + { DENALI_CTL_68, 0x00000000 }, + { DENALI_CTL_69, 0x00000A60 }, + { DENALI_CTL_70, 0x00000004 }, + { DENALI_CTL_71, 0x00000010 }, + { DENALI_CTL_72, 0x00000A60 }, + { DENALI_CTL_73, 0x00000004 }, + { DENALI_CTL_74, 0x00000010 }, + { DENALI_CTL_75, 0x00000000 }, + { DENALI_CTL_76, 0x00000000 }, + { DENALI_CTL_77, 0x00000000 }, + { DENALI_CTL_78, 0x00000000 }, + { DENALI_CTL_79, 0x00000000 }, + { DENALI_CTL_80, 0x00000000 }, + { DENALI_CTL_81, 0x00000000 }, + { DENALI_CTL_82, 0x00000000 }, + { DENALI_CTL_83, 0x00000000 }, + { DENALI_CTL_84, 0x00000000 }, + { DENALI_CTL_85, 0x01010000 }, + { DENALI_CTL_86, 0x00000000 }, + { DENALI_CTL_87, 0x00000000 }, + { DENALI_CTL_88, 0x00000000 }, + { DENALI_CTL_89, 0x00000000 }, + { DENALI_CTL_90, 0x00000000 }, + { DENALI_CTL_91, 0x00000000 }, + { DENALI_CTL_92, 0x00000000 }, + { DENALI_CTL_93, 0x00000000 }, + { DENALI_CTL_94, 0x00000000 }, + { DENALI_CTL_95, 0x01000200 }, + { DENALI_CTL_96, 0x00010801 }, + { DENALI_CTL_97, 0x00000000 }, + { DENALI_CTL_98, 0x00000000 }, + { DENALI_CTL_99, 0x00000000 }, + { DENALI_CTL_100, 0x00000000 }, + { DENALI_CTL_101, 0x00000000 }, + { DENALI_CTL_102, 0x00000000 }, + { DENALI_CTL_103, 0x00000000 }, + { DENALI_CTL_104, 0x00000000 }, + { DENALI_CTL_105, 0x00000000 }, + { DENALI_CTL_106, 0x00000000 }, + { DENALI_CTL_107, 0x00000000 }, + { DENALI_CTL_108, 0x00000000 }, + { DENALI_CTL_109, 0x00000000 }, + { DENALI_CTL_110, 0x00000008 }, + { DENALI_CTL_111, 0x006403E8 }, + { DENALI_CTL_112, 0x00000000 }, + { DENALI_CTL_113, 0x00000000 }, + { DENALI_CTL_114, 0x00000000 }, + { DENALI_CTL_115, 0x15110000 }, + { DENALI_CTL_116, 0x00040C18 }, + { DENALI_CTL_117, 0x009ECA03 }, + { DENALI_CTL_118, 0x0000A299 }, + { DENALI_CTL_119, 0x00000000 }, + { DENALI_CTL_120, 0x01000200 }, + { DENALI_CTL_121, 0x00000040 }, + { DENALI_CTL_122, 0x04010100 }, + { DENALI_CTL_123, 0x00010104 }, + { DENALI_CTL_124, 0x01FF0000 }, + { DENALI_CTL_125, 0x00003F00 }, + { DENALI_CTL_126, 0xFFFFFFFF }, + { DENALI_CTL_127, 0x00FFFF00 }, + { DENALI_CTL_128, 0xFFFF0A00 }, + { DENALI_CTL_129, 0x01010001 }, + { DENALI_CTL_130, 0x01010101 }, + { DENALI_CTL_131, 0x01030101 }, + { DENALI_CTL_132, 0x0C010000 }, + { DENALI_CTL_133, 0x01000000 }, + { DENALI_CTL_134, 0x00000000 }, + { DENALI_CTL_135, 0x00010000 }, + { DENALI_CTL_136, 0x00000000 }, + { DENALI_CTL_137, 0x00000000 }, + { DENALI_CTL_138, 0x00000000 }, + { DENALI_CTL_139, 0x00000000 }, + { DENALI_CTL_140, 0x00000000 }, + { DENALI_CTL_141, 0x00000000 }, + { DENALI_CTL_142, 0x00000000 }, + { DENALI_CTL_143, 0x00000000 }, + { DENALI_CTL_144, 0x00000000 }, + { DENALI_CTL_145, 0x00000000 }, + { DENALI_CTL_146, 0x00000000 }, + { DENALI_CTL_147, 0x00000000 }, + { DENALI_CTL_148, 0x00000000 }, + { DENALI_CTL_149, 0x00000000 }, + { DENALI_CTL_150, 0x00000000 }, + { DENALI_CTL_151, 0x00000000 }, + { DENALI_CTL_152, 0x00000000 }, + { DENALI_CTL_153, 0x00000000 }, + { DENALI_CTL_154, 0x00000000 }, + { DENALI_CTL_155, 0x00000000 }, + { DENALI_CTL_156, 0x00000000 }, + { DENALI_CTL_157, 0x00010000 }, + { DENALI_CTL_158, 0x00000000 }, + { DENALI_CTL_159, 0x00000800 }, + { DENALI_CTL_160, 0x00000000 }, + { DENALI_CTL_161, 0x00000898 }, + { DENALI_CTL_162, 0x03000000 }, + { DENALI_CTL_163, 0x00000408 }, + { DENALI_CTL_164, 0x00000000 }, + { DENALI_CTL_165, 0x00000000 }, + { DENALI_CTL_166, 0x00000000 }, + { DENALI_CTL_167, 0x00000000 }, + { DENALI_CTL_168, 0x00000000 }, + { DENALI_CTL_169, 0x00000000 }, + { DENALI_CTL_170, 0x00000000 }, + { DENALI_CTL_171, 0x00000000 }, + { DENALI_CTL_172, 0x00000000 }, + { DENALI_CTL_173, 0x00000000 }, + { DENALI_CTL_174, 0x00000000 }, + { DENALI_CTL_175, 0x06060600 }, + { DENALI_CTL_176, 0x03020001 }, + { DENALI_CTL_177, 0x01030101 }, + { DENALI_CTL_178, 0x03000302 }, + { DENALI_CTL_179, 0x00000000 }, + { DENALI_CTL_180, 0x00080801 }, + { DENALI_CTL_181, 0x00080801 }, + { DENALI_CTL_182, 0x00070601 }, + { DENALI_CTL_183, 0x00000000 }, + { DENALI_CTL_184, 0x000FFFFF }, + { DENALI_CTL_185, 0xFFFFFFFF }, + { DENALI_CTL_186, 0x000F000F }, + { DENALI_CTL_187, 0x00000000 }, + { DENALI_CTL_188, 0x030FFFFF }, + { DENALI_CTL_189, 0xFFFFFFFF }, + { DENALI_CTL_190, 0x000F000F }, + { DENALI_CTL_191, 0x00000000 }, + { DENALI_CTL_192, 0x030FFFFF }, + { DENALI_CTL_193, 0xFFFFFFFF }, + { DENALI_CTL_194, 0x000F000F }, + { DENALI_CTL_195, 0x00000000 }, + { DENALI_CTL_196, 0x030FFFFF }, + { DENALI_CTL_197, 0xFFFFFFFF }, + { DENALI_CTL_198, 0x000F000F }, + { DENALI_CTL_199, 0x00000000 }, + { DENALI_CTL_200, 0x030FFFFF }, + { DENALI_CTL_201, 0xFFFFFFFF }, + { DENALI_CTL_202, 0x000F000F }, + { DENALI_CTL_203, 0x00000000 }, + { DENALI_CTL_204, 0x030FFFFF }, + { DENALI_CTL_205, 0xFFFFFFFF }, + { DENALI_CTL_206, 0x000F000F }, + { DENALI_CTL_207, 0x00000000 }, + { DENALI_CTL_208, 0x030FFFFF }, + { DENALI_CTL_209, 0xFFFFFFFF }, + { DENALI_CTL_210, 0x000F000F }, + { DENALI_CTL_211, 0x00000000 }, + { DENALI_CTL_212, 0x030FFFFF }, + { DENALI_CTL_213, 0xFFFFFFFF }, + { DENALI_CTL_214, 0x000F000F }, + { DENALI_CTL_215, 0x00000000 }, + { DENALI_CTL_216, 0x030FFFFF }, + { DENALI_CTL_217, 0xFFFFFFFF }, + { DENALI_CTL_218, 0x000F000F }, + { DENALI_CTL_219, 0x00000000 }, + { DENALI_CTL_220, 0x030FFFFF }, + { DENALI_CTL_221, 0xFFFFFFFF }, + { DENALI_CTL_222, 0x000F000F }, + { DENALI_CTL_223, 0x00000000 }, + { DENALI_CTL_224, 0x030FFFFF }, + { DENALI_CTL_225, 0xFFFFFFFF }, + { DENALI_CTL_226, 0x000F000F }, + { DENALI_CTL_227, 0x00000000 }, + { DENALI_CTL_228, 0x030FFFFF }, + { DENALI_CTL_229, 0xFFFFFFFF }, + { DENALI_CTL_230, 0x000F000F }, + { DENALI_CTL_231, 0x00000000 }, + { DENALI_CTL_232, 0x030FFFFF }, + { DENALI_CTL_233, 0xFFFFFFFF }, + { DENALI_CTL_234, 0x000F000F }, + { DENALI_CTL_235, 0x00000000 }, + { DENALI_CTL_236, 0x030FFFFF }, + { DENALI_CTL_237, 0xFFFFFFFF }, + { DENALI_CTL_238, 0x000F000F }, + { DENALI_CTL_239, 0x00000000 }, + { DENALI_CTL_240, 0x030FFFFF }, + { DENALI_CTL_241, 0xFFFFFFFF }, + { DENALI_CTL_242, 0x000F000F }, + { DENALI_CTL_243, 0x00000000 }, + { DENALI_CTL_244, 0x030FFFFF }, + { DENALI_CTL_245, 0xFFFFFFFF }, + { DENALI_CTL_246, 0x000F000F }, + { DENALI_CTL_247, 0x00000000 }, + { DENALI_CTL_248, 0x000FFFFF }, + { DENALI_CTL_249, 0xFFFFFFFF }, + { DENALI_CTL_250, 0x000F000F }, + { DENALI_CTL_251, 0x00000000 }, + { DENALI_CTL_252, 0x030FFFFF }, + { DENALI_CTL_253, 0xFFFFFFFF }, + { DENALI_CTL_254, 0x000F000F }, + { DENALI_CTL_255, 0x00000000 }, + { DENALI_CTL_256, 0x030FFFFF }, + { DENALI_CTL_257, 0xFFFFFFFF }, + { DENALI_CTL_258, 0x000F000F }, + { DENALI_CTL_259, 0x00000000 }, + { DENALI_CTL_260, 0x030FFFFF }, + { DENALI_CTL_261, 0xFFFFFFFF }, + { DENALI_CTL_262, 0x000F000F }, + { DENALI_CTL_263, 0x00000000 }, + { DENALI_CTL_264, 0x030FFFFF }, + { DENALI_CTL_265, 0xFFFFFFFF }, + { DENALI_CTL_266, 0x000F000F }, + { DENALI_CTL_267, 0x00000000 }, + { DENALI_CTL_268, 0x030FFFFF }, + { DENALI_CTL_269, 0xFFFFFFFF }, + { DENALI_CTL_270, 0x000F000F }, + { DENALI_CTL_271, 0x00000000 }, + { DENALI_CTL_272, 0x030FFFFF }, + { DENALI_CTL_273, 0xFFFFFFFF }, + { DENALI_CTL_274, 0x000F000F }, + { DENALI_CTL_275, 0x00000000 }, + { DENALI_CTL_276, 0x030FFFFF }, + { DENALI_CTL_277, 0xFFFFFFFF }, + { DENALI_CTL_278, 0x000F000F }, + { DENALI_CTL_279, 0x00000000 }, + { DENALI_CTL_280, 0x030FFFFF }, + { DENALI_CTL_281, 0xFFFFFFFF }, + { DENALI_CTL_282, 0x000F000F }, + { DENALI_CTL_283, 0x00000000 }, + { DENALI_CTL_284, 0x030FFFFF }, + { DENALI_CTL_285, 0xFFFFFFFF }, + { DENALI_CTL_286, 0x000F000F }, + { DENALI_CTL_287, 0x00000000 }, + { DENALI_CTL_288, 0x030FFFFF }, + { DENALI_CTL_289, 0xFFFFFFFF }, + { DENALI_CTL_290, 0x000F000F }, + { DENALI_CTL_291, 0x00000000 }, + { DENALI_CTL_292, 0x030FFFFF }, + { DENALI_CTL_293, 0xFFFFFFFF }, + { DENALI_CTL_294, 0x000F000F }, + { DENALI_CTL_295, 0x00000000 }, + { DENALI_CTL_296, 0x030FFFFF }, + { DENALI_CTL_297, 0xFFFFFFFF }, + { DENALI_CTL_298, 0x000F000F }, + { DENALI_CTL_299, 0x00000000 }, + { DENALI_CTL_300, 0x030FFFFF }, + { DENALI_CTL_301, 0xFFFFFFFF }, + { DENALI_CTL_302, 0x000F000F }, + { DENALI_CTL_303, 0x00000000 }, + { DENALI_CTL_304, 0x030FFFFF }, + { DENALI_CTL_305, 0xFFFFFFFF }, + { DENALI_CTL_306, 0x000F000F }, + { DENALI_CTL_307, 0x00000000 }, + { DENALI_CTL_308, 0x030FFFFF }, + { DENALI_CTL_309, 0xFFFFFFFF }, + { DENALI_CTL_310, 0x000F000F }, + { DENALI_CTL_311, 0x00000000 }, + { DENALI_CTL_312, 0x000FFFFF }, + { DENALI_CTL_313, 0xFFFFFFFF }, + { DENALI_CTL_314, 0x000F000F }, + { DENALI_CTL_315, 0x00000000 }, + { DENALI_CTL_316, 0x030FFFFF }, + { DENALI_CTL_317, 0xFFFFFFFF }, + { DENALI_CTL_318, 0x000F000F }, + { DENALI_CTL_319, 0x00000000 }, + { DENALI_CTL_320, 0x030FFFFF }, + { DENALI_CTL_321, 0xFFFFFFFF }, + { DENALI_CTL_322, 0x000F000F }, + { DENALI_CTL_323, 0x00000000 }, + { DENALI_CTL_324, 0x030FFFFF }, + { DENALI_CTL_325, 0xFFFFFFFF }, + { DENALI_CTL_326, 0x000F000F }, + { DENALI_CTL_327, 0x00000000 }, + { DENALI_CTL_328, 0x030FFFFF }, + { DENALI_CTL_329, 0xFFFFFFFF }, + { DENALI_CTL_330, 0x000F000F }, + { DENALI_CTL_331, 0x00000000 }, + { DENALI_CTL_332, 0x030FFFFF }, + { DENALI_CTL_333, 0xFFFFFFFF }, + { DENALI_CTL_334, 0x000F000F }, + { DENALI_CTL_335, 0x00000000 }, + { DENALI_CTL_336, 0x030FFFFF }, + { DENALI_CTL_337, 0xFFFFFFFF }, + { DENALI_CTL_338, 0x000F000F }, + { DENALI_CTL_339, 0x00000000 }, + { DENALI_CTL_340, 0x030FFFFF }, + { DENALI_CTL_341, 0xFFFFFFFF }, + { DENALI_CTL_342, 0x000F000F }, + { DENALI_CTL_343, 0x00000000 }, + { DENALI_CTL_344, 0x030FFFFF }, + { DENALI_CTL_345, 0xFFFFFFFF }, + { DENALI_CTL_346, 0x000F000F }, + { DENALI_CTL_347, 0x00000000 }, + { DENALI_CTL_348, 0x030FFFFF }, + { DENALI_CTL_349, 0xFFFFFFFF }, + { DENALI_CTL_350, 0x000F000F }, + { DENALI_CTL_351, 0x00000000 }, + { DENALI_CTL_352, 0x030FFFFF }, + { DENALI_CTL_353, 0xFFFFFFFF }, + { DENALI_CTL_354, 0x000F000F }, + { DENALI_CTL_355, 0x00000000 }, + { DENALI_CTL_356, 0x030FFFFF }, + { DENALI_CTL_357, 0xFFFFFFFF }, + { DENALI_CTL_358, 0x000F000F }, + { DENALI_CTL_359, 0x00000000 }, + { DENALI_CTL_360, 0x030FFFFF }, + { DENALI_CTL_361, 0xFFFFFFFF }, + { DENALI_CTL_362, 0x000F000F }, + { DENALI_CTL_363, 0x00000000 }, + { DENALI_CTL_364, 0x030FFFFF }, + { DENALI_CTL_365, 0xFFFFFFFF }, + { DENALI_CTL_366, 0x000F000F }, + { DENALI_CTL_367, 0x00000000 }, + { DENALI_CTL_368, 0x030FFFFF }, + { DENALI_CTL_369, 0xFFFFFFFF }, + { DENALI_CTL_370, 0x000F000F }, + { DENALI_CTL_371, 0x00000000 }, + { DENALI_CTL_372, 0x030FFFFF }, + { DENALI_CTL_373, 0xFFFFFFFF }, + { DENALI_CTL_374, 0x000F000F }, + { DENALI_CTL_375, 0x03000000 }, + { DENALI_CTL_376, 0x03030303 }, + { DENALI_CTL_377, 0x03030303 }, + { DENALI_CTL_378, 0x03030303 }, + { DENALI_CTL_379, 0x00030303 }, + { DENALI_CTL_380, 0x02020064 }, + { DENALI_CTL_381, 0x02020202 }, + { DENALI_CTL_382, 0x02020202 }, + { DENALI_CTL_383, 0x02020202 }, + { DENALI_CTL_384, 0x00010202 }, + { DENALI_CTL_385, 0x01010064 }, + { DENALI_CTL_386, 0x01010101 }, + { DENALI_CTL_387, 0x01010101 }, + { DENALI_CTL_388, 0x01010101 }, + { DENALI_CTL_389, 0x00020101 }, + { DENALI_CTL_390, 0x00000064 }, + { DENALI_CTL_391, 0x00000006 }, + { DENALI_CTL_392, 0x000007D0 }, + { DENALI_CTL_393, 0x00000032 }, + { DENALI_CTL_394, 0x00000200 }, + { DENALI_CTL_395, 0x00000200 }, + { DENALI_CTL_396, 0x00000000 }, + { DENALI_CTL_397, 0x00000000 }, + { DENALI_CTL_398, 0x01090205 }, + { DENALI_CTL_399, 0x00200106 }, + { DENALI_CTL_400, 0x00000000 }, + { DENALI_CTL_401, 0x0A000202 }, + { DENALI_CTL_402, 0x000C000A }, + { DENALI_CTL_403, 0x00000000 }, + { DENALI_CTL_404, 0x00000000 }, + { DENALI_CTL_405, 0x00000000 }, + { DENALI_CTL_406, 0x00000000 }, + { DENALI_CTL_407, 0x00000000 }, + { DENALI_CTL_408, 0x00000000 }, + { DENALI_CTL_409, 0x00000000 }, + { DENALI_CTL_410, 0x00000000 }, + { DENALI_CTL_411, 0x00000000 }, + { DENALI_CTL_412, 0x0000000F }, + { DENALI_CTL_413, 0x017105DD }, + { DENALI_CTL_414, 0x4F5E64A8 }, + { DENALI_CTL_415, 0x00003C30 }, + { DENALI_CTL_416, 0x00003C28 }, + { DENALI_CTL_417, 0x00000000 }, + { DENALI_CTL_418, 0x00000000 }, + { DENALI_CTL_419, 0x00000000 }, + { DENALI_CTL_420, 0x00000000 }, + { DENALI_CTL_421, 0x00000000 }, + { DENALI_CTL_422, 0x00000000 }, + { DENALI_CTL_423, 0x00000000 }, + { DENALI_CTL_424, 0x00000000 }, + { DENALI_CTL_425, 0x00000000 }, + { DENALI_CTL_426, 0x00000000 }, + { DENALI_CTL_427, 0x00000000 }, + { DENALI_CTL_428, 0x00000000 }, + { DENALI_CTL_429, 0x00000000 }, + { DENALI_CTL_430, 0x00000000 }, + { DENALI_CTL_431, 0x00000000 }, + { DENALI_CTL_432, 0x00000000 }, + { DENALI_CTL_433, 0x00000000 }, + { DENALI_CTL_434, 0x00000000 }, + { DENALI_CTL_435, 0x00000000 } +}; diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/soc/a3m/drivers/xspi.c b/drivers/rz/ipl/rza/plat/renesas/rz/soc/a3m/drivers/xspi.c new file mode 100644 index 00000000..ca7c8179 --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/soc/a3m/drivers/xspi.c @@ -0,0 +1,68 @@ +#include +#include +#include +#include +#include + +static int sub_init_xip(const xspidevice_instance_t *inst) +{ + int result; + result = inst->api->open(inst->ctrl, inst->cfg); + if (!result) { + result = inst->api->enter_xip(inst->ctrl); + inst->api->close(inst->ctrl); + } + return result; +} + +static int sub_post_init_xip(const xspi_instance_t *xspi) +{ + int result; + result = xspi->api->open(xspi->ctrl, xspi->cfg); + if (!result) { + xspi->api->enable_auto_calibration(xspi->ctrl); + result = xspi->api->post_init(xspi->ctrl); + xspi->api->close(xspi->ctrl); + } + return result; +} + +void xspi_setup(void) +{ + int i; + int result = 0; + +#ifdef XSPI_DEVICE_TYPE + RZA_PRINTF("Configure %s Flash Memory\n", XSPI_DEVICE_TYPE); +#endif + for (i = 0; result >= 0 && i < xspidevices_count; i++) { + result = sub_init_xip(xspidevices[i]); + if (result < 0) { + ERROR("xspi.c: abort on sub_init_xip (#%d)\n", i); + panic(); + } + } + for (i = 0; result >= 0 && i < xspidevices_count; i++) { + result = sub_post_init_xip(xspidevices[i]->cfg->xspi); + if (result < 0) { + ERROR("xspi.c: abort on sub_post_init_xip (#%d)\n", i); + panic(); + } + } +} + +/** + * memcpy for xspi + */ +int rz_xspi_read(void* to, uint64_t offset, size_t length) { + int result; + const xspidevice_instance_t *inst = xspidevices[0]; + if (!inst) return -1; + + result = inst->api->open(inst->ctrl, inst->cfg); + if (!result) { + inst->api->read(inst->ctrl, to, (size_t)offset, length); + inst->api->close(inst->ctrl); + } + return result; +} diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/soc/a3m/include/cpg_opt.h b/drivers/rz/ipl/rza/plat/renesas/rz/soc/a3m/include/cpg_opt.h new file mode 100644 index 00000000..5ebd116f --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/soc/a3m/include/cpg_opt.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __CPG_OPT_H__ +#define __CPG_OPT_H__ + +#define CPG_RST_DDR_OPT_VALUE (0x00000000) + +#endif // __CPG_OPT_H__ diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/soc/a3m/include/ddr_mc_if.h b/drivers/rz/ipl/rza/plat/renesas/rz/soc/a3m/include/ddr_mc_if.h new file mode 100644 index 00000000..ad1d0ade --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/soc/a3m/include/ddr_mc_if.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __DDR_MC_IF_H__ +#define __DDR_MC_IF_H__ + +#include + +#define MC_INIT_NUM (436) + +#define LP_CMD_OFFSET (0) + +#define DDRMC_R000 DENALI_CTL_00 +#define DDRMC_R001 DENALI_CTL_11 +#define DDRMC_R002 DENALI_CTL_14 +#define DDRMC_R003 DENALI_CTL_15 +#define DDRMC_R004 DENALI_CTL_56 +#define DDRMC_R005 DENALI_CTL_59 +#define DDRMC_R006 DENALI_CTL_60 +#define DDRMC_R007 DENALI_CTL_64 +#define DDRMC_R008 DENALI_CTL_67 +#define DDRMC_R009 DENALI_CTL_70 +#define DDRMC_R010 DENALI_CTL_71 +#define DDRMC_R011 DENALI_CTL_73 +#define DDRMC_R012 DENALI_CTL_74 +#define DDRMC_R013 DENALI_CTL_75 +#define DDRMC_R014 DENALI_CTL_76 +#define DDRMC_R015 DENALI_CTL_81 +#define DDRMC_R016 DENALI_CTL_82 +#define DDRMC_R017 DENALI_CTL_83 +#define DDRMC_R018 DENALI_CTL_84 +#define DDRMC_R019 DENALI_CTL_133 +#define DDRMC_R020 DENALI_CTL_134 +#define DDRMC_R021 DENALI_CTL_146 +#define DDRMC_R022 DENALI_CTL_147 +#define DDRMC_R023 DENALI_CTL_154 +#define DDRMC_R024 DENALI_CTL_155 +#define DDRMC_R025 DENALI_CTL_176 +#define DDRMC_R026 DENALI_CTL_177 +#define DDRMC_R027 DENALI_CTL_391 +#define DDRMC_R028 DENALI_CTL_398 +#define DDRMC_R029 DENALI_CTL_401 +#define DDRMC_R030 DENALI_CTL_403 +#define DDRMC_R031 DENALI_CTL_404 +#define DDRMC_R032 DENALI_CTL_405 +#define DDRMC_R033 DENALI_CTL_406 +#define DDRMC_R034 DENALI_CTL_407 +#define DDRMC_R035 DENALI_CTL_408 +#define DDRMC_R036 DENALI_CTL_409 +#define DDRMC_R037 DENALI_CTL_410 +#define DDRMC_R038 DENALI_CTL_411 +#define DDRMC_R039 DENALI_CTL_413 +#define DDRMC_R040 DENALI_CTL_414 +#define DDRMC_R041 DENALI_CTL_415 +#define DDRMC_R042 DENALI_CTL_416 +#define DDRMC_R043 DENALI_CTL_417 +#define DDRMC_R044 DENALI_CTL_418 + +#endif // __DDR_MC_IF_H__ diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/soc/a3m/include/ddr_mc_regs.h b/drivers/rz/ipl/rza/plat/renesas/rz/soc/a3m/include/ddr_mc_regs.h new file mode 100644 index 00000000..dabe9085 --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/soc/a3m/include/ddr_mc_regs.h @@ -0,0 +1,470 @@ +/* + * Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __DDR_MC_REGS_H__ +#define __DDR_MC_REGS_H__ + +#include + +#define DDR_MC_BASE RZG2L_DDR_MEMC_BASE +#define MC_INIT_NUM (436) + +#define BASE_MC DDR_MC_BASE +#define USER_DEF_REG_0_ADDR (BASE_MC + 0x064C) +#define USER_DEF_REG_1_ADDR (BASE_MC + 0x0650) +#define USER_DEF_REG_2_ADDR (BASE_MC + 0x0654) +#define USER_DEF_REG_3_ADDR (BASE_MC + 0x0658) +#define USER_DEF_REG_4_ADDR (BASE_MC + 0x065C) +#define USER_DEF_REG_5_ADDR (BASE_MC + 0x0660) +#define USER_DEF_REG_6_ADDR (BASE_MC + 0x0664) +#define USER_DEF_REG_7_ADDR (BASE_MC + 0x0668) +#define USER_DEF_REG_8_ADDR (BASE_MC + 0x066C) +#define USER_DEF_REG_9_ADDR (BASE_MC + 0x0670) +#define USER_DEF_REG_10_ADDR (BASE_MC + 0x0674) +#define USER_DEF_REG_11_ADDR (BASE_MC + 0x0678) +#define USER_DEF_REG_12_ADDR (BASE_MC + 0x067C) +#define USER_DEF_REG_13_ADDR (BASE_MC + 0x0680) +#define USER_DEF_REG_14_ADDR (BASE_MC + 0x0684) +#define USER_DEF_REG_15_ADDR (BASE_MC + 0x0688) + +#define DENALI_CTL_00 (0x0000) +#define DENALI_CTL_01 (0x0004) +#define DENALI_CTL_02 (0x0008) +#define DENALI_CTL_03 (0x000C) +#define DENALI_CTL_04 (0x0010) +#define DENALI_CTL_05 (0x0014) +#define DENALI_CTL_06 (0x0018) +#define DENALI_CTL_07 (0x001C) +#define DENALI_CTL_08 (0x0020) +#define DENALI_CTL_09 (0x0024) +#define DENALI_CTL_10 (0x0028) +#define DENALI_CTL_11 (0x002C) +#define DENALI_CTL_12 (0x0030) +#define DENALI_CTL_13 (0x0034) +#define DENALI_CTL_14 (0x0038) +#define DENALI_CTL_15 (0x003C) +#define DENALI_CTL_16 (0x0040) +#define DENALI_CTL_17 (0x0044) +#define DENALI_CTL_18 (0x0048) +#define DENALI_CTL_19 (0x004C) +#define DENALI_CTL_20 (0x0050) +#define DENALI_CTL_21 (0x0054) +#define DENALI_CTL_22 (0x0058) +#define DENALI_CTL_23 (0x005C) +#define DENALI_CTL_24 (0x0060) +#define DENALI_CTL_25 (0x0064) +#define DENALI_CTL_26 (0x0068) +#define DENALI_CTL_27 (0x006C) +#define DENALI_CTL_28 (0x0070) +#define DENALI_CTL_29 (0x0074) +#define DENALI_CTL_30 (0x0078) +#define DENALI_CTL_31 (0x007C) +#define DENALI_CTL_32 (0x0080) +#define DENALI_CTL_33 (0x0084) +#define DENALI_CTL_34 (0x0088) +#define DENALI_CTL_35 (0x008C) +#define DENALI_CTL_36 (0x0090) +#define DENALI_CTL_37 (0x0094) +#define DENALI_CTL_38 (0x0098) +#define DENALI_CTL_39 (0x009C) +#define DENALI_CTL_40 (0x00A0) +#define DENALI_CTL_41 (0x00A4) +#define DENALI_CTL_42 (0x00A8) +#define DENALI_CTL_43 (0x00AC) +#define DENALI_CTL_44 (0x00B0) +#define DENALI_CTL_45 (0x00B4) +#define DENALI_CTL_46 (0x00B8) +#define DENALI_CTL_47 (0x00BC) +#define DENALI_CTL_48 (0x00C0) +#define DENALI_CTL_49 (0x00C4) +#define DENALI_CTL_50 (0x00C8) +#define DENALI_CTL_51 (0x00CC) +#define DENALI_CTL_52 (0x00D0) +#define DENALI_CTL_53 (0x00D4) +#define DENALI_CTL_54 (0x00D8) +#define DENALI_CTL_55 (0x00DC) +#define DENALI_CTL_56 (0x00E0) +#define DENALI_CTL_57 (0x00E4) +#define DENALI_CTL_58 (0x00E8) +#define DENALI_CTL_59 (0x00EC) +#define DENALI_CTL_60 (0x00F0) +#define DENALI_CTL_61 (0x00F4) +#define DENALI_CTL_62 (0x00F8) +#define DENALI_CTL_63 (0x00FC) +#define DENALI_CTL_64 (0x0100) +#define DENALI_CTL_65 (0x0104) +#define DENALI_CTL_66 (0x0108) +#define DENALI_CTL_67 (0x010C) +#define DENALI_CTL_68 (0x0110) +#define DENALI_CTL_69 (0x0114) +#define DENALI_CTL_70 (0x0118) +#define DENALI_CTL_71 (0x011C) +#define DENALI_CTL_72 (0x0120) +#define DENALI_CTL_73 (0x0124) +#define DENALI_CTL_74 (0x0128) +#define DENALI_CTL_75 (0x012C) +#define DENALI_CTL_76 (0x0130) +#define DENALI_CTL_77 (0x0134) +#define DENALI_CTL_78 (0x0138) +#define DENALI_CTL_79 (0x013C) +#define DENALI_CTL_80 (0x0140) +#define DENALI_CTL_81 (0x0144) +#define DENALI_CTL_82 (0x0148) +#define DENALI_CTL_83 (0x014C) +#define DENALI_CTL_84 (0x0150) +#define DENALI_CTL_85 (0x0154) +#define DENALI_CTL_86 (0x0158) +#define DENALI_CTL_87 (0x015C) +#define DENALI_CTL_88 (0x0160) +#define DENALI_CTL_89 (0x0164) +#define DENALI_CTL_90 (0x0168) +#define DENALI_CTL_91 (0x016C) +#define DENALI_CTL_92 (0x0170) +#define DENALI_CTL_93 (0x0174) +#define DENALI_CTL_94 (0x0178) +#define DENALI_CTL_95 (0x017C) +#define DENALI_CTL_96 (0x0180) +#define DENALI_CTL_97 (0x0184) +#define DENALI_CTL_98 (0x0188) +#define DENALI_CTL_99 (0x018C) +#define DENALI_CTL_100 (0x0190) +#define DENALI_CTL_101 (0x0194) +#define DENALI_CTL_102 (0x0198) +#define DENALI_CTL_103 (0x019C) +#define DENALI_CTL_104 (0x01A0) +#define DENALI_CTL_105 (0x01A4) +#define DENALI_CTL_106 (0x01A8) +#define DENALI_CTL_107 (0x01AC) +#define DENALI_CTL_108 (0x01B0) +#define DENALI_CTL_109 (0x01B4) +#define DENALI_CTL_110 (0x01B8) +#define DENALI_CTL_111 (0x01BC) +#define DENALI_CTL_112 (0x01C0) +#define DENALI_CTL_113 (0x01C4) +#define DENALI_CTL_114 (0x01C8) +#define DENALI_CTL_115 (0x01CC) +#define DENALI_CTL_116 (0x01D0) +#define DENALI_CTL_117 (0x01D4) +#define DENALI_CTL_118 (0x01D8) +#define DENALI_CTL_119 (0x01DC) +#define DENALI_CTL_120 (0x01E0) +#define DENALI_CTL_121 (0x01E4) +#define DENALI_CTL_122 (0x01E8) +#define DENALI_CTL_123 (0x01EC) +#define DENALI_CTL_124 (0x01F0) +#define DENALI_CTL_125 (0x01F4) +#define DENALI_CTL_126 (0x01F8) +#define DENALI_CTL_127 (0x01FC) +#define DENALI_CTL_128 (0x0200) +#define DENALI_CTL_129 (0x0204) +#define DENALI_CTL_130 (0x0208) +#define DENALI_CTL_131 (0x020C) +#define DENALI_CTL_132 (0x0210) +#define DENALI_CTL_133 (0x0214) +#define DENALI_CTL_134 (0x0218) +#define DENALI_CTL_135 (0x021C) +#define DENALI_CTL_136 (0x0220) +#define DENALI_CTL_137 (0x0224) +#define DENALI_CTL_138 (0x0228) +#define DENALI_CTL_139 (0x022C) +#define DENALI_CTL_140 (0x0230) +#define DENALI_CTL_141 (0x0234) +#define DENALI_CTL_142 (0x0238) +#define DENALI_CTL_143 (0x023C) +#define DENALI_CTL_144 (0x0240) +#define DENALI_CTL_145 (0x0244) +#define DENALI_CTL_146 (0x0248) +#define DENALI_CTL_147 (0x024C) +#define DENALI_CTL_148 (0x0250) +#define DENALI_CTL_149 (0x0254) +#define DENALI_CTL_150 (0x0258) +#define DENALI_CTL_151 (0x025C) +#define DENALI_CTL_152 (0x0260) +#define DENALI_CTL_153 (0x0264) +#define DENALI_CTL_154 (0x0268) +#define DENALI_CTL_155 (0x026C) +#define DENALI_CTL_156 (0x0270) +#define DENALI_CTL_157 (0x0274) +#define DENALI_CTL_158 (0x0278) +#define DENALI_CTL_159 (0x027C) +#define DENALI_CTL_160 (0x0280) +#define DENALI_CTL_161 (0x0284) +#define DENALI_CTL_162 (0x0288) +#define DENALI_CTL_163 (0x028C) +#define DENALI_CTL_164 (0x0290) +#define DENALI_CTL_165 (0x0294) +#define DENALI_CTL_166 (0x0298) +#define DENALI_CTL_167 (0x029C) +#define DENALI_CTL_168 (0x02A0) +#define DENALI_CTL_169 (0x02A4) +#define DENALI_CTL_170 (0x02A8) +#define DENALI_CTL_171 (0x02AC) +#define DENALI_CTL_172 (0x02B0) +#define DENALI_CTL_173 (0x02B4) +#define DENALI_CTL_174 (0x02B8) +#define DENALI_CTL_175 (0x02BC) +#define DENALI_CTL_176 (0x02C0) +#define DENALI_CTL_177 (0x02C4) +#define DENALI_CTL_178 (0x02C8) +#define DENALI_CTL_179 (0x02CC) +#define DENALI_CTL_180 (0x02D0) +#define DENALI_CTL_181 (0x02D4) +#define DENALI_CTL_182 (0x02D8) +#define DENALI_CTL_183 (0x02DC) +#define DENALI_CTL_184 (0x02E0) +#define DENALI_CTL_185 (0x02E4) +#define DENALI_CTL_186 (0x02E8) +#define DENALI_CTL_187 (0x02EC) +#define DENALI_CTL_188 (0x02F0) +#define DENALI_CTL_189 (0x02F4) +#define DENALI_CTL_190 (0x02F8) +#define DENALI_CTL_191 (0x02FC) +#define DENALI_CTL_192 (0x0300) +#define DENALI_CTL_193 (0x0304) +#define DENALI_CTL_194 (0x0308) +#define DENALI_CTL_195 (0x030C) +#define DENALI_CTL_196 (0x0310) +#define DENALI_CTL_197 (0x0314) +#define DENALI_CTL_198 (0x0318) +#define DENALI_CTL_199 (0x031C) +#define DENALI_CTL_200 (0x0320) +#define DENALI_CTL_201 (0x0324) +#define DENALI_CTL_202 (0x0328) +#define DENALI_CTL_203 (0x032C) +#define DENALI_CTL_204 (0x0330) +#define DENALI_CTL_205 (0x0334) +#define DENALI_CTL_206 (0x0338) +#define DENALI_CTL_207 (0x033C) +#define DENALI_CTL_208 (0x0340) +#define DENALI_CTL_209 (0x0344) +#define DENALI_CTL_210 (0x0348) +#define DENALI_CTL_211 (0x034C) +#define DENALI_CTL_212 (0x0350) +#define DENALI_CTL_213 (0x0354) +#define DENALI_CTL_214 (0x0358) +#define DENALI_CTL_215 (0x035C) +#define DENALI_CTL_216 (0x0360) +#define DENALI_CTL_217 (0x0364) +#define DENALI_CTL_218 (0x0368) +#define DENALI_CTL_219 (0x036C) +#define DENALI_CTL_220 (0x0370) +#define DENALI_CTL_221 (0x0374) +#define DENALI_CTL_222 (0x0378) +#define DENALI_CTL_223 (0x037C) +#define DENALI_CTL_224 (0x0380) +#define DENALI_CTL_225 (0x0384) +#define DENALI_CTL_226 (0x0388) +#define DENALI_CTL_227 (0x038C) +#define DENALI_CTL_228 (0x0390) +#define DENALI_CTL_229 (0x0394) +#define DENALI_CTL_230 (0x0398) +#define DENALI_CTL_231 (0x039C) +#define DENALI_CTL_232 (0x03A0) +#define DENALI_CTL_233 (0x03A4) +#define DENALI_CTL_234 (0x03A8) +#define DENALI_CTL_235 (0x03AC) +#define DENALI_CTL_236 (0x03B0) +#define DENALI_CTL_237 (0x03B4) +#define DENALI_CTL_238 (0x03B8) +#define DENALI_CTL_239 (0x03BC) +#define DENALI_CTL_240 (0x03C0) +#define DENALI_CTL_241 (0x03C4) +#define DENALI_CTL_242 (0x03C8) +#define DENALI_CTL_243 (0x03CC) +#define DENALI_CTL_244 (0x03D0) +#define DENALI_CTL_245 (0x03D4) +#define DENALI_CTL_246 (0x03D8) +#define DENALI_CTL_247 (0x03DC) +#define DENALI_CTL_248 (0x03E0) +#define DENALI_CTL_249 (0x03E4) +#define DENALI_CTL_250 (0x03E8) +#define DENALI_CTL_251 (0x03EC) +#define DENALI_CTL_252 (0x03F0) +#define DENALI_CTL_253 (0x03F4) +#define DENALI_CTL_254 (0x03F8) +#define DENALI_CTL_255 (0x03FC) +#define DENALI_CTL_256 (0x0400) +#define DENALI_CTL_257 (0x0404) +#define DENALI_CTL_258 (0x0408) +#define DENALI_CTL_259 (0x040C) +#define DENALI_CTL_260 (0x0410) +#define DENALI_CTL_261 (0x0414) +#define DENALI_CTL_262 (0x0418) +#define DENALI_CTL_263 (0x041C) +#define DENALI_CTL_264 (0x0420) +#define DENALI_CTL_265 (0x0424) +#define DENALI_CTL_266 (0x0428) +#define DENALI_CTL_267 (0x042C) +#define DENALI_CTL_268 (0x0430) +#define DENALI_CTL_269 (0x0434) +#define DENALI_CTL_270 (0x0438) +#define DENALI_CTL_271 (0x043C) +#define DENALI_CTL_272 (0x0440) +#define DENALI_CTL_273 (0x0444) +#define DENALI_CTL_274 (0x0448) +#define DENALI_CTL_275 (0x044C) +#define DENALI_CTL_276 (0x0450) +#define DENALI_CTL_277 (0x0454) +#define DENALI_CTL_278 (0x0458) +#define DENALI_CTL_279 (0x045C) +#define DENALI_CTL_280 (0x0460) +#define DENALI_CTL_281 (0x0464) +#define DENALI_CTL_282 (0x0468) +#define DENALI_CTL_283 (0x046C) +#define DENALI_CTL_284 (0x0470) +#define DENALI_CTL_285 (0x0474) +#define DENALI_CTL_286 (0x0478) +#define DENALI_CTL_287 (0x047C) +#define DENALI_CTL_288 (0x0480) +#define DENALI_CTL_289 (0x0484) +#define DENALI_CTL_290 (0x0488) +#define DENALI_CTL_291 (0x048C) +#define DENALI_CTL_292 (0x0490) +#define DENALI_CTL_293 (0x0494) +#define DENALI_CTL_294 (0x0498) +#define DENALI_CTL_295 (0x049C) +#define DENALI_CTL_296 (0x04A0) +#define DENALI_CTL_297 (0x04A4) +#define DENALI_CTL_298 (0x04A8) +#define DENALI_CTL_299 (0x04AC) +#define DENALI_CTL_300 (0x04B0) +#define DENALI_CTL_301 (0x04B4) +#define DENALI_CTL_302 (0x04B8) +#define DENALI_CTL_303 (0x04BC) +#define DENALI_CTL_304 (0x04C0) +#define DENALI_CTL_305 (0x04C4) +#define DENALI_CTL_306 (0x04C8) +#define DENALI_CTL_307 (0x04CC) +#define DENALI_CTL_308 (0x04D0) +#define DENALI_CTL_309 (0x04D4) +#define DENALI_CTL_310 (0x04D8) +#define DENALI_CTL_311 (0x04DC) +#define DENALI_CTL_312 (0x04E0) +#define DENALI_CTL_313 (0x04E4) +#define DENALI_CTL_314 (0x04E8) +#define DENALI_CTL_315 (0x04EC) +#define DENALI_CTL_316 (0x04F0) +#define DENALI_CTL_317 (0x04F4) +#define DENALI_CTL_318 (0x04F8) +#define DENALI_CTL_319 (0x04FC) +#define DENALI_CTL_320 (0x0500) +#define DENALI_CTL_321 (0x0504) +#define DENALI_CTL_322 (0x0508) +#define DENALI_CTL_323 (0x050C) +#define DENALI_CTL_324 (0x0510) +#define DENALI_CTL_325 (0x0514) +#define DENALI_CTL_326 (0x0518) +#define DENALI_CTL_327 (0x051C) +#define DENALI_CTL_328 (0x0520) +#define DENALI_CTL_329 (0x0524) +#define DENALI_CTL_330 (0x0528) +#define DENALI_CTL_331 (0x052C) +#define DENALI_CTL_332 (0x0530) +#define DENALI_CTL_333 (0x0534) +#define DENALI_CTL_334 (0x0538) +#define DENALI_CTL_335 (0x053C) +#define DENALI_CTL_336 (0x0540) +#define DENALI_CTL_337 (0x0544) +#define DENALI_CTL_338 (0x0548) +#define DENALI_CTL_339 (0x054C) +#define DENALI_CTL_340 (0x0550) +#define DENALI_CTL_341 (0x0554) +#define DENALI_CTL_342 (0x0558) +#define DENALI_CTL_343 (0x055C) +#define DENALI_CTL_344 (0x0560) +#define DENALI_CTL_345 (0x0564) +#define DENALI_CTL_346 (0x0568) +#define DENALI_CTL_347 (0x056C) +#define DENALI_CTL_348 (0x0570) +#define DENALI_CTL_349 (0x0574) +#define DENALI_CTL_350 (0x0578) +#define DENALI_CTL_351 (0x057C) +#define DENALI_CTL_352 (0x0580) +#define DENALI_CTL_353 (0x0584) +#define DENALI_CTL_354 (0x0588) +#define DENALI_CTL_355 (0x058C) +#define DENALI_CTL_356 (0x0590) +#define DENALI_CTL_357 (0x0594) +#define DENALI_CTL_358 (0x0598) +#define DENALI_CTL_359 (0x059C) +#define DENALI_CTL_360 (0x05A0) +#define DENALI_CTL_361 (0x05A4) +#define DENALI_CTL_362 (0x05A8) +#define DENALI_CTL_363 (0x05AC) +#define DENALI_CTL_364 (0x05B0) +#define DENALI_CTL_365 (0x05B4) +#define DENALI_CTL_366 (0x05B8) +#define DENALI_CTL_367 (0x05BC) +#define DENALI_CTL_368 (0x05C0) +#define DENALI_CTL_369 (0x05C4) +#define DENALI_CTL_370 (0x05C8) +#define DENALI_CTL_371 (0x05CC) +#define DENALI_CTL_372 (0x05D0) +#define DENALI_CTL_373 (0x05D4) +#define DENALI_CTL_374 (0x05D8) +#define DENALI_CTL_375 (0x05DC) +#define DENALI_CTL_376 (0x05E0) +#define DENALI_CTL_377 (0x05E4) +#define DENALI_CTL_378 (0x05E8) +#define DENALI_CTL_379 (0x05EC) +#define DENALI_CTL_380 (0x05F0) +#define DENALI_CTL_381 (0x05F4) +#define DENALI_CTL_382 (0x05F8) +#define DENALI_CTL_383 (0x05FC) +#define DENALI_CTL_384 (0x0600) +#define DENALI_CTL_385 (0x0604) +#define DENALI_CTL_386 (0x0608) +#define DENALI_CTL_387 (0x060C) +#define DENALI_CTL_388 (0x0610) +#define DENALI_CTL_389 (0x0614) +#define DENALI_CTL_390 (0x0618) +#define DENALI_CTL_391 (0x061C) +#define DENALI_CTL_392 (0x0620) +#define DENALI_CTL_393 (0x0624) +#define DENALI_CTL_394 (0x0628) +#define DENALI_CTL_395 (0x062C) +#define DENALI_CTL_396 (0x0630) +#define DENALI_CTL_397 (0x0634) +#define DENALI_CTL_398 (0x0638) +#define DENALI_CTL_399 (0x063C) +#define DENALI_CTL_400 (0x0640) +#define DENALI_CTL_401 (0x0644) +#define DENALI_CTL_402 (0x0648) +#define DENALI_CTL_403 (0x064C) +#define DENALI_CTL_404 (0x0650) +#define DENALI_CTL_405 (0x0654) +#define DENALI_CTL_406 (0x0658) +#define DENALI_CTL_407 (0x065C) +#define DENALI_CTL_408 (0x0660) +#define DENALI_CTL_409 (0x0664) +#define DENALI_CTL_410 (0x0668) +#define DENALI_CTL_411 (0x066C) +#define DENALI_CTL_412 (0x0670) +#define DENALI_CTL_413 (0x0674) +#define DENALI_CTL_414 (0x0678) +#define DENALI_CTL_415 (0x067C) +#define DENALI_CTL_416 (0x0680) +#define DENALI_CTL_417 (0x0684) +#define DENALI_CTL_418 (0x0688) +#define DENALI_CTL_419 (0x068C) +#define DENALI_CTL_420 (0x0690) +#define DENALI_CTL_421 (0x0694) +#define DENALI_CTL_422 (0x0698) +#define DENALI_CTL_423 (0x069C) +#define DENALI_CTL_424 (0x06A0) +#define DENALI_CTL_425 (0x06A4) +#define DENALI_CTL_426 (0x06A8) +#define DENALI_CTL_427 (0x06AC) +#define DENALI_CTL_428 (0x06B0) +#define DENALI_CTL_429 (0x06B4) +#define DENALI_CTL_430 (0x06B8) +#define DENALI_CTL_431 (0x06BC) +#define DENALI_CTL_432 (0x06C0) +#define DENALI_CTL_433 (0x06C4) +#define DENALI_CTL_434 (0x06C8) +#define DENALI_CTL_435 (0x06CC) + +#endif // __DDR_MC_REGS_H__ diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/soc/a3m/include/ddr_phy_regs.h b/drivers/rz/ipl/rza/plat/renesas/rz/soc/a3m/include/ddr_phy_regs.h new file mode 100644 index 00000000..10c04731 --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/soc/a3m/include/ddr_phy_regs.h @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __DDR_PHY_REGS_H__ +#define __DDR_PHY_REGS_H__ + +#include + +#define DDR_PHY_BASE RZG2L_DDR_PHY_BASE + +#define DDRPHY_R00 (0x040) +#define DDRPHY_R01 (0x044) +#define DDRPHY_R02 (0x048) +#define DDRPHY_R03 (0x04C) +#define DDRPHY_R04 (0x050) +#define DDRPHY_R05 (0x058) +#define DDRPHY_R06 (0x05C) +#define DDRPHY_R07 (0x060) +#define DDRPHY_R08 (0x064) +#define DDRPHY_R09 (0x068) +#define DDRPHY_R10 (0x09C) +#define DDRPHY_R11 (0x0A8) +#define DDRPHY_R12 (0x0C0) +#define DDRPHY_R13 (0x0C4) +#define DDRPHY_R14 (0x0C8) +#define DDRPHY_R15 (0x0CC) +#define DDRPHY_R16 (0x0D0) +#define DDRPHY_R17 (0x0E8) +#define DDRPHY_R18 (0x100) +#define DDRPHY_R19 (0x104) +#define DDRPHY_R20 (0x108) +#define DDRPHY_R21 (0x10C) +#define DDRPHY_R22 (0x110) +#define DDRPHY_R23 (0x114) +#define DDRPHY_R24 (0x118) +#define DDRPHY_R25 (0x11C) +#define DDRPHY_R26 (0x120) +#define DDRPHY_R27 (0x124) +#define DDRPHY_R28 (0x128) +#define DDRPHY_R29 (0x12C) +#define DDRPHY_R30 (0x130) +#define DDRPHY_R31 (0x134) +#define DDRPHY_R32 (0x138) +#define DDRPHY_R33 (0x13C) +#define DDRPHY_R34 (0x140) +#define DDRPHY_R35 (0x144) +#define DDRPHY_R36 (0x148) +#define DDRPHY_R37 (0x14C) +#define DDRPHY_R38 (0x150) +#define DDRPHY_R39 (0x154) +#define DDRPHY_R40 (0x158) +#define DDRPHY_R41 (0x15C) +#define DDRPHY_R42 (0x160) +#define DDRPHY_R43 (0x164) +#define DDRPHY_R44 (0x168) +#define DDRPHY_R45 (0x16C) +#define DDRPHY_R46 (0x170) +#define DDRPHY_R47 (0x174) +#define DDRPHY_R48 (0x178) +#define DDRPHY_R49 (0x17C) +#define DDRPHY_R50 (0x180) +#define DDRPHY_R51 (0x188) +#define DDRPHY_R52 (0x18C) +#define DDRPHY_R53 (0x190) +#define DDRPHY_R54 (0x194) +#define DDRPHY_R55 (0x19C) +#define DDRPHY_R56 (0x1A0) +#define DDRPHY_R57 (0x1A4) +#define DDRPHY_R58 (0x1A8) +#define DDRPHY_R59 (0x1AC) +#define DDRPHY_R60 (0x1B0) +#define DDRPHY_R61 (0x1B4) +#define DDRPHY_R62 (0x1B8) +#define DDRPHY_R63 (0x1BC) +#define DDRPHY_R64 (0x1C0) +#define DDRPHY_R65 (0x1C4) +#define DDRPHY_R66 (0x1C8) +#define DDRPHY_R67 (0x1CC) +#define DDRPHY_R68 (0x1D0) +#define DDRPHY_R69 (0x1D4) +#define DDRPHY_R70 (0x1D8) +#define DDRPHY_R71 (0x1DC) +#define DDRPHY_R72 (0x1E0) +#define DDRPHY_R73 (0x1E4) +#define DDRPHY_R74 (0x1E8) +#define DDRPHY_R75 (0x1EC) +#define DDRPHY_R76 (0x1F0) +#define DDRPHY_R77 (0x200) +#define DDRPHY_R78 (0x204) +#define DDRPHY_R79 (0x240) + +#endif // __DDR_PHY_REGS_H__ diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/soc/a3m/platform.mk b/drivers/rz/ipl/rza/plat/renesas/rz/soc/a3m/platform.mk new file mode 100644 index 00000000..eda4c68a --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/soc/a3m/platform.mk @@ -0,0 +1,70 @@ +# +# Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +APPLOAD?=RZ_NOFIP +$(eval $(call add_define,APPLOAD)) +include plat/renesas/rz/common/rz_common.mk +include plat/renesas/rz/board/${BOARD}/rz_board.mk +include plat/renesas/rz/soc/${PLAT}/rz_xspi.mk + +PLAT_INCLUDES += -Iplat/renesas/rz/soc/a3m/include + +DDR_SOURCES += plat/renesas/rz/soc/a3m/drivers/ddr/ddr_a3m.c + +RZA3 := 1 +RZA3M := 1 +DEVICE_TYPE := 1 +ARCH_TYPE := ARMv8A +LOG_LEVEL := 10 +ifeq (${SOC_TYPE},2) +DEVICE_TYPE := 2 +endif +RZA3_XSPI_MEMORY_BASE := 0x20000000 + +$(eval $(call add_define,RZA3)) +$(eval $(call add_define,RZA3M)) +$(eval $(call add_define,DEVICE_TYPE)) +$(eval $(call add_define,ARCH_TYPE)) +$(eval $(call add_define,RZA3_XSPI_MEMORY_BASE)) + +# set file name +RZ_ELF:=$(BUILD_PLAT)/rz$(BOARD)_ipl.elf +BL2_ELF:=$(BUILD_PLAT)/bl2/bl2.elf +RZ_BIN:=$(BUILD_PLAT)/rz$(BOARD)_ipl.bin +BL2_BIN:=$(BUILD_PLAT)/bl2.bin +RZ_MAP:=$(BUILD_PLAT)/rz$(BOARD)_ipl.map +BL2_MAP:=$(BUILD_PLAT)/bl2/bl2.map +RZ_DUMP:=$(BUILD_PLAT)/rz$(BOARD)_ipl.dump +BL2_DUMP:=$(BUILD_PLAT)/bl2/bl2.dump +RZ_SREC:=$(BUILD_PLAT)/rz$(BOARD)_ipl.srec + +bl2: $(RZ_ELF) $(RZ_BIN) $(RZ_LINKER) $(RZ_MAP) $(RZ_DUMP) $(RZ_SREC) + +$(RZ_ELF): $(BL2_ELF) + $(call SHELL_COPY,$<,$@) + +$(RZ_BIN): $(BL2_BIN) + @echo " IMG $@" +ifeq ($(NAND),1) + $(Q)/usr/bin/perl ./plat/renesas/rz/soc/a3m/rz_image_nand.pl "$<" "$@" +else + $(Q)/usr/bin/perl ./plat/renesas/rz/soc/a3m/rz_image.pl "$<" "$@" +endif + +$(BL2_MAP): $(BL2_ELF) +$(RZ_MAP): $(BL2_MAP) + $(call SHELL_COPY,$<,$@) + +$(RZ_DUMP): $(BL2_DUMP) + $(call SHELL_COPY,$<,$@) + +$(RZ_SREC): $(RZ_BIN) + @echo " SREC $@" + $(Q)$(OC) -I binary -O srec --adjust-vma=0x20000000 --srec-forceS3 "$<" "$@" + +ifeq (${RZ_TEST},1) +-include plat/renesas/rz/common/drivers/tests/rz_test.mk +endif diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/soc/a3m/rz_image.pl b/drivers/rz/ipl/rza/plat/renesas/rz/soc/a3m/rz_image.pl new file mode 100644 index 00000000..d15ae58a --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/soc/a3m/rz_image.pl @@ -0,0 +1,124 @@ +#!/usr/bin/perl -w +# Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause + +use strict; +use bigint; +use Digest::SHA; + +sub padding256 { + my ($f, $size, $fourth) = @_; + + for(my $i=1;$i<4;$i++) { + $f->print(pack('C', 0)); + } + $f->print(pack('C', $fourth)); + for(my $i=5;$i<57;$i++) { + $f->print(pack('C', 0)); + } + $f->print(pack('C',($size & (0b111 << 29)) >> 29)); + for(my $i=58;$i<61;$i++) { + $f->print(pack('C', 0)); + } + $f->print(pack('C',($size & (0x1F << 0)) << 3)); + $f->print(pack('C',($size & (0xFF << 5)) >> 5)); + $f->print(pack('C',($size & (0xFF << 13)) >> 13)); + $f->print(pack('C',($size & (0xFF << 21)) >> 21)); + for(my $i=65;$i<257;$i++) { + $f->print(pack('C', 0)); + } +} + +my $size_limit = 0x1D000; + +die("Not enough parameter\n") if ($#ARGV < 0); + +# Open input file +my $name = shift(@ARGV); +my $outname; +if ($#ARGV < 0) { + $outname = "rz_" . $name; +} +else { + $outname = shift(@ARGV); +} +my $tmpname = $outname.".tmp"; +open(my $origin, '<', $name) or die("Can not open input file"); +binmode $origin; + +# Obtaining size ($st[7]) +my @st = stat($origin); + +# Check appended size +my $size = ($st[7] + 255) & "0xffffffffffffff00"; +my $msg; +if ($size != $st[7]) {$msg = "Appended size";} else {$msg="Size";} +die("$msg too big ($size > $size_limit)") if ($size > $size_limit); + +open(my $tmp, '>', $tmpname) or die("Can not open temporary file"); +binmode $tmp; + +# WritePadding +my $buf; +read($origin, $buf, $st[7]); +$tmp->print($buf); +#print "size:$size st:$st[7]\n"; +if ($size != $st[7]) { + $tmp->print(pack('C', 0x80)); + for(my $i=($st[7] + 1);$i<$size;$i++) { + $tmp->print(pack('C', 0)); + } + padding256($tmp, $st[7], 0); +} else { + padding256($tmp, $st[7], 0x80); +} +close($tmp); +open($tmp, '<', $tmpname) or die("Can not open temporary file"); +# Sha256 +my $sha = Digest::SHA->new(256); +$sha->addfile($tmpname); +my $digest = $sha->digest(); + +seek($origin, 0,0); +$size += 256; + +# Create bin file +open(my $out, '>', $outname) or die("Can not open output file"); +binmode $out; +# Write header +$out->print(pack('L', $size)); +for(my $i = 1; $i < 4; $i++) { + $out->print(pack('L', 0xffffffff)); +} +$out->print($digest); +for(my $i = 12; $i < 112; $i++) { + $out->print(pack('L', 0xffffffff)); +} +$out->print(pack('L', 0xffff0000)); +$out->print(pack('L', 0x000800ff)); +$out->print(pack('L', 0x00fff700)); +$out->print(pack('L', 0xf700f708)); +$out->print(pack('L', 0xffffffff)); +$out->print(pack('L', 0xffffffff)); +$out->print(pack('L', 0xffffffff)); +$out->print(pack('L', 0xffffffff)); +$out->print(pack('L', 0xffffffff)); +$out->print(pack('L', 0xffffffff)); +$out->print(pack('L', 0xffffffff)); +$out->print(pack('L', 0xffffffff)); +$out->print(pack('L', 0xffffffff)); +$out->print(pack('L', 0xffffffff)); +$out->print(pack('L', 0xffffffff)); +$out->print(pack('L', 0xaa55ffff)); + +# Append original data to temporary file +read($tmp, $buf, $size); +$out->print($buf); +$out->flush; + +close($tmp); +#unlink($tmpname); +# close +close $out; +close $origin; diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/soc/a3m/rz_image_nand.pl b/drivers/rz/ipl/rza/plat/renesas/rz/soc/a3m/rz_image_nand.pl new file mode 100644 index 00000000..51cf5ae0 --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/soc/a3m/rz_image_nand.pl @@ -0,0 +1,143 @@ +#!/usr/bin/perl -w +# Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause + +use strict; +use bigint; +use Digest::SHA; + +sub padding256 { + my ($f, $size, $fourth) = @_; + + for(my $i=1;$i<4;$i++) { + $f->print(pack('C', 0)); + } + $f->print(pack('C', $fourth)); + for(my $i=5;$i<57;$i++) { + $f->print(pack('C', 0)); + } + $f->print(pack('C',($size & (0b111 << 29)) >> 29)); + for(my $i=58;$i<61;$i++) { + $f->print(pack('C', 0)); + } + $f->print(pack('C',($size & (0x1F << 0)) << 3)); + $f->print(pack('C',($size & (0xFF << 5)) >> 5)); + $f->print(pack('C',($size & (0xFF << 13)) >> 13)); + $f->print(pack('C',($size & (0xFF << 21)) >> 21)); + for(my $i=65;$i<257;$i++) { + $f->print(pack('C', 0)); + } +} + +my $size_limit = 0x1D000; + +die("Not enough parameter\n") if ($#ARGV < 0); + +# Open input file +my $name = shift(@ARGV); +my $outname; +if ($#ARGV < 0) { + $outname = "rz_" . $name; +} +else { + $outname = shift(@ARGV); +} +my $tmpname = $outname.".tmp"; +my $headername = $outname.".header"; +open(my $origin, '<', $name) or die("Can not open input file"); +binmode $origin; + +# Obtaining size ($st[7]) +my @st = stat($origin); + +# Check appended size +my $size = ($st[7] + 255) & "0xffffffffffffff00"; +my $msg; +if ($size != $st[7]) {$msg = "Appended size";} else {$msg="Size";} +die("$msg too big ($size > $size_limit)") if ($size > $size_limit); + +open(my $tmp, '>', $tmpname) or die("Can not open temporary file"); +binmode $tmp; + +# WritePadding +my $buf; +read($origin, $buf, $st[7]); +$tmp->print($buf); +#print "size:$size st:$st[7]\n"; +if ($size != $st[7]) { + $tmp->print(pack('C', 0x80)); + for(my $i=($st[7] + 1);$i<$size;$i++) { + $tmp->print(pack('C', 0)); + } + padding256($tmp, $st[7], 0); +} else { + padding256($tmp, $st[7], 0x80); +} +close($tmp); +open($tmp, '<', $tmpname) or die("Can not open temporary file"); +# Sha256 +my $sha = Digest::SHA->new(256); +$sha->addfile($tmpname); +my $digest = $sha->digest(); + +seek($origin, 0,0); +$size += 256; + +# Create bin file +open(my $out, '>', $outname) or die("Can not open output file"); +open(my $header, '>', $headername) or die("Can not open output file"); + +binmode $out; +binmode $header; +# Write header +$header->print(pack('L', $size)); +for(my $i = 1; $i < 4; $i++) { + $header->print(pack('L', 0xffffffff)); +} +$header->print($digest); +for(my $i = 12; $i < 112; $i++) { + $header->print(pack('L', 0xffffffff)); +} +$header->print(pack('L', 0xffff0000)); +$header->print(pack('L', 0x000800ff)); +$header->print(pack('L', 0x00fff700)); +$header->print(pack('L', 0xf700f708)); +$header->print(pack('L', 0xffffffff)); +$header->print(pack('L', 0xffffffff)); +$header->print(pack('L', 0xffffffff)); +$header->print(pack('L', 0xffffffff)); +$header->print(pack('L', 0xffffffff)); +$header->print(pack('L', 0xffffffff)); +$header->print(pack('L', 0xffffffff)); +$header->print(pack('L', 0xffffffff)); +$header->print(pack('L', 0xffffffff)); +$header->print(pack('L', 0xffffffff)); +$header->print(pack('L', 0xffffffff)); +$header->print(pack('L', 0xaa55ffff)); +close($header); +open($header, '<', $headername) or die("Can not open output file"); +binmode $header; + +read($header, my $hbuf, 0x200); +my @head = unpack('C512', $hbuf); + +for(my $h = 0;$h<2;$h++) { + for my $i (0..$#head){ + $out->print(pack('C', $head[$i])); + } + for my $i (0..$#head){ + $out->print(pack('C', 255 - $head[$i])); + } +} + +# Append original data to temporary file +read($tmp, $buf, $size); +$out->print($buf); +$out->flush; + +close($tmp); +#unlink($tmpname); +# close +close $out; +close $origin; diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/soc/a3m/rz_xspi.mk b/drivers/rz/ipl/rza/plat/renesas/rz/soc/a3m/rz_xspi.mk new file mode 100644 index 00000000..9beb1462 --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/soc/a3m/rz_xspi.mk @@ -0,0 +1,34 @@ +# +# Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# +RZ_XSPI_DRIVER_PATH:=plat/renesas/rz/common/drivers/xspi + +RZ_XSPI_CONFIGS:=XSPI0 XSPI1 XSPI2 +RZ_XSPI_SOURCES:=plat/renesas/rz/soc/a3m/drivers/xspi.c +RZ_XSPI_HEADERS:= +RZ_XSPI0_IF:=spim +RZ_XSPI0_IF_CONFIG:=.channel=0, .base=0x10060000 +RZ_XSPI1_IF:=octa +RZ_XSPI1_IF_CONFIG:=.channel=0, .base=0x10080000 +RZ_XSPI2_IF:=octa +RZ_XSPI2_IF_CONFIG:=.channel=1, .base=0x10080000 +RZ_XSPI_EXCLUSIVE_SELECTOR:=1 +RZ_SPIM_SDR_FREQ_LIMIT:=66625000 +RZ_OCTA_FREQ_LIMIT:=100000000 + +ifneq ($(strip $(XSPI0_DEVICE)),) + ifneq ($(strip $(XSPI1_DEVICE)),) + $(error XSPI0_DEVICE and XSPI1_DEVICE can not be specified at the same time.) + endif + ifneq ($(strip $(XSPI2_DEVICE)),) + $(error XSPI0_DEVICE and XSPI2_DEVICE can not be specified at the same time.) + endif +endif + +include plat/renesas/rz/common/rz_xspi_common.mk + +$(eval $(call add_define,RZ_XSPI_EXCLUSIVE_SELECTOR)) +$(eval $(call add_define,RZ_SPIM_SDR_FREQ_LIMIT)) +$(eval $(call add_define,RZ_OCTA_FREQ_LIMIT)) diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/soc/a3ul/drivers/ddr/ddr_a3ul.c b/drivers/rz/ipl/rza/plat/renesas/rz/soc/a3ul/drivers/ddr/ddr_a3ul.c new file mode 100644 index 00000000..3c656cfb --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/soc/a3ul/drivers/ddr/ddr_a3ul.c @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +void ddr_ctrl_reten_en_n(uint8_t val) +{ + val &= 1; + write_phy_reg(DDRPHY_R79, (val << 1)); +} + diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/soc/a3ul/drivers/ddr/param_mc_C-010_D3-02-2.c b/drivers/rz/ipl/rza/plat/renesas/rz/soc/a3ul/drivers/ddr/param_mc_C-010_D3-02-2.c new file mode 100644 index 00000000..81640137 --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/soc/a3ul/drivers/ddr/param_mc_C-010_D3-02-2.c @@ -0,0 +1,449 @@ +/* + * Copyright (c) 2020-2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +const char ddr_an_version[] = "v0.0.0"; + +const uint32_t mc_init_tbl[MC_INIT_NUM][2] = { + { DENALI_CTL_00, 0x00000600 }, + { DENALI_CTL_01, 0x00000000 }, + { DENALI_CTL_02, 0x00000000 }, + { DENALI_CTL_03, 0x00000000 }, + { DENALI_CTL_04, 0x00000000 }, + { DENALI_CTL_05, 0x00000000 }, + { DENALI_CTL_06, 0x00000000 }, + { DENALI_CTL_07, 0x00000000 }, + { DENALI_CTL_08, 0x00000000 }, + { DENALI_CTL_09, 0x00000000 }, + { DENALI_CTL_10, 0x01000007 }, + { DENALI_CTL_11, 0x00100100 }, + { DENALI_CTL_12, 0x000208D6 }, + { DENALI_CTL_13, 0x00051616 }, + { DENALI_CTL_14, 0x07120200 }, + { DENALI_CTL_15, 0x00000000 }, + { DENALI_CTL_16, 0x05000404 }, + { DENALI_CTL_17, 0x00002100 }, + { DENALI_CTL_18, 0x0505001E }, + { DENALI_CTL_19, 0x05001E09 }, + { DENALI_CTL_20, 0x000C0405 }, + { DENALI_CTL_21, 0x0400B6D0 }, + { DENALI_CTL_22, 0x00030305 }, + { DENALI_CTL_23, 0x01000A09 }, + { DENALI_CTL_24, 0x09031301 }, + { DENALI_CTL_25, 0x01000009 }, + { DENALI_CTL_26, 0x00000101 }, + { DENALI_CTL_27, 0x00000000 }, + { DENALI_CTL_28, 0x00000000 }, + { DENALI_CTL_29, 0x00040301 }, + { DENALI_CTL_30, 0x000000AE }, + { DENALI_CTL_31, 0x00001448 }, + { DENALI_CTL_32, 0x00000005 }, + { DENALI_CTL_33, 0x00100004 }, + { DENALI_CTL_34, 0x00B40200 }, + { DENALI_CTL_35, 0x000000B4 }, + { DENALI_CTL_36, 0x01000201 }, + { DENALI_CTL_37, 0x80104002 }, + { DENALI_CTL_38, 0x00000000 }, + { DENALI_CTL_39, 0x00040000 }, + { DENALI_CTL_40, 0x00000000 }, + { DENALI_CTL_41, 0x00051200 }, + { DENALI_CTL_42, 0x000007D0 }, + { DENALI_CTL_43, 0x00051200 }, + { DENALI_CTL_44, 0x00051200 }, + { DENALI_CTL_45, 0x00051200 }, + { DENALI_CTL_46, 0x00000000 }, + { DENALI_CTL_47, 0x01000000 }, + { DENALI_CTL_48, 0x00000000 }, + { DENALI_CTL_49, 0x00000000 }, + { DENALI_CTL_50, 0x00000000 }, + { DENALI_CTL_51, 0x00000000 }, + { DENALI_CTL_52, 0x00000000 }, + { DENALI_CTL_53, 0x00000000 }, + { DENALI_CTL_54, 0x00000000 }, + { DENALI_CTL_55, 0x00262600 }, + { DENALI_CTL_56, 0x09070000 }, + { DENALI_CTL_57, 0x2F0E010A }, + { DENALI_CTL_58, 0x00000300 }, + { DENALI_CTL_59, 0x00010004 }, + { DENALI_CTL_60, 0x00000800 }, + { DENALI_CTL_61, 0x00000000 }, + { DENALI_CTL_62, 0x00000000 }, + { DENALI_CTL_63, 0x00000000 }, + { DENALI_CTL_64, 0x00000100 }, + { DENALI_CTL_65, 0x00000200 }, + { DENALI_CTL_66, 0x00001000 }, + { DENALI_CTL_67, 0x00000000 }, + { DENALI_CTL_68, 0x00000000 }, + { DENALI_CTL_69, 0x00000A50 }, + { DENALI_CTL_70, 0x00000206 }, + { DENALI_CTL_71, 0x00000210 }, + { DENALI_CTL_72, 0x00000A50 }, + { DENALI_CTL_73, 0x00000206 }, + { DENALI_CTL_74, 0x00000210 }, + { DENALI_CTL_75, 0x00000000 }, + { DENALI_CTL_76, 0x00000000 }, + { DENALI_CTL_77, 0x00000000 }, + { DENALI_CTL_78, 0x00000000 }, + { DENALI_CTL_79, 0x00000000 }, + { DENALI_CTL_80, 0x00000000 }, + { DENALI_CTL_81, 0x00000000 }, + { DENALI_CTL_82, 0x00000000 }, + { DENALI_CTL_83, 0x00000000 }, + { DENALI_CTL_84, 0x00000000 }, + { DENALI_CTL_85, 0x01010000 }, + { DENALI_CTL_86, 0x00000000 }, + { DENALI_CTL_87, 0x00000000 }, + { DENALI_CTL_88, 0x00000000 }, + { DENALI_CTL_89, 0x00000000 }, + { DENALI_CTL_90, 0x00000000 }, + { DENALI_CTL_91, 0x00000000 }, + { DENALI_CTL_92, 0x00000000 }, + { DENALI_CTL_93, 0x00000000 }, + { DENALI_CTL_94, 0x00000000 }, + { DENALI_CTL_95, 0x01000200 }, + { DENALI_CTL_96, 0x00010801 }, + { DENALI_CTL_97, 0x00000000 }, + { DENALI_CTL_98, 0x00000000 }, + { DENALI_CTL_99, 0x00000000 }, + { DENALI_CTL_100, 0x00000000 }, + { DENALI_CTL_101, 0x00000000 }, + { DENALI_CTL_102, 0x00000000 }, + { DENALI_CTL_103, 0x00000000 }, + { DENALI_CTL_104, 0x00000000 }, + { DENALI_CTL_105, 0x00000000 }, + { DENALI_CTL_106, 0x00000000 }, + { DENALI_CTL_107, 0x00000000 }, + { DENALI_CTL_108, 0x00000000 }, + { DENALI_CTL_109, 0x00000000 }, + { DENALI_CTL_110, 0x00000008 }, + { DENALI_CTL_111, 0x006403E8 }, + { DENALI_CTL_112, 0x00000000 }, + { DENALI_CTL_113, 0x00000000 }, + { DENALI_CTL_114, 0x00000000 }, + { DENALI_CTL_115, 0x15110000 }, + { DENALI_CTL_116, 0x00040C18 }, + { DENALI_CTL_117, 0x009ECA03 }, + { DENALI_CTL_118, 0x0000A299 }, + { DENALI_CTL_119, 0x00000000 }, + { DENALI_CTL_120, 0x01000200 }, + { DENALI_CTL_121, 0x00000040 }, + { DENALI_CTL_122, 0x02010100 }, + { DENALI_CTL_123, 0x00010102 }, + { DENALI_CTL_124, 0x07FF0000 }, + { DENALI_CTL_125, 0x0000FF00 }, + { DENALI_CTL_126, 0x0FFF0800 }, + { DENALI_CTL_127, 0x0100FF00 }, + { DENALI_CTL_128, 0xFFFF0A00 }, + { DENALI_CTL_129, 0x01010001 }, + { DENALI_CTL_130, 0x01010101 }, + { DENALI_CTL_131, 0x01030101 }, + { DENALI_CTL_132, 0x0C030000 }, + { DENALI_CTL_133, 0x01000000 }, + { DENALI_CTL_134, 0x00000000 }, + { DENALI_CTL_135, 0x00010000 }, + { DENALI_CTL_136, 0x00000000 }, + { DENALI_CTL_137, 0x00000000 }, + { DENALI_CTL_138, 0x00000000 }, + { DENALI_CTL_139, 0x00000000 }, + { DENALI_CTL_140, 0x00000000 }, + { DENALI_CTL_141, 0x00000000 }, + { DENALI_CTL_142, 0x00000000 }, + { DENALI_CTL_143, 0x00000000 }, + { DENALI_CTL_144, 0x00000000 }, + { DENALI_CTL_145, 0x00000000 }, + { DENALI_CTL_146, 0x00000000 }, + { DENALI_CTL_147, 0x00000000 }, + { DENALI_CTL_148, 0x00000000 }, + { DENALI_CTL_149, 0x00000000 }, + { DENALI_CTL_150, 0x00000000 }, + { DENALI_CTL_151, 0x00000000 }, + { DENALI_CTL_152, 0x00000000 }, + { DENALI_CTL_153, 0x00000000 }, + { DENALI_CTL_154, 0x00000000 }, + { DENALI_CTL_155, 0x00000000 }, + { DENALI_CTL_156, 0x00000000 }, + { DENALI_CTL_157, 0x00010000 }, + { DENALI_CTL_158, 0x00000000 }, + { DENALI_CTL_159, 0x00000800 }, + { DENALI_CTL_160, 0x00000000 }, + { DENALI_CTL_161, 0x00000898 }, + { DENALI_CTL_162, 0x03000000 }, + { DENALI_CTL_163, 0x00000408 }, + { DENALI_CTL_164, 0x00000000 }, + { DENALI_CTL_165, 0x00000000 }, + { DENALI_CTL_166, 0x00000000 }, + { DENALI_CTL_167, 0x00000000 }, + { DENALI_CTL_168, 0x00000000 }, + { DENALI_CTL_169, 0x00000000 }, + { DENALI_CTL_170, 0x00000000 }, + { DENALI_CTL_171, 0x00000000 }, + { DENALI_CTL_172, 0x00000000 }, + { DENALI_CTL_173, 0x00000000 }, + { DENALI_CTL_174, 0x00000000 }, + { DENALI_CTL_175, 0x06060600 }, + { DENALI_CTL_176, 0x02020001 }, + { DENALI_CTL_177, 0x01020101 }, + { DENALI_CTL_178, 0x03000302 }, + { DENALI_CTL_179, 0x00000000 }, + { DENALI_CTL_180, 0x00080801 }, + { DENALI_CTL_181, 0x00080801 }, + { DENALI_CTL_182, 0x00070601 }, + { DENALI_CTL_183, 0x00000000 }, + { DENALI_CTL_184, 0x000FFFFF }, + { DENALI_CTL_185, 0xFFFFFFFF }, + { DENALI_CTL_186, 0x000F000F }, + { DENALI_CTL_187, 0x00000000 }, + { DENALI_CTL_188, 0x030FFFFF }, + { DENALI_CTL_189, 0xFFFFFFFF }, + { DENALI_CTL_190, 0x000F000F }, + { DENALI_CTL_191, 0x00000000 }, + { DENALI_CTL_192, 0x030FFFFF }, + { DENALI_CTL_193, 0xFFFFFFFF }, + { DENALI_CTL_194, 0x000F000F }, + { DENALI_CTL_195, 0x00000000 }, + { DENALI_CTL_196, 0x030FFFFF }, + { DENALI_CTL_197, 0xFFFFFFFF }, + { DENALI_CTL_198, 0x000F000F }, + { DENALI_CTL_199, 0x00000000 }, + { DENALI_CTL_200, 0x030FFFFF }, + { DENALI_CTL_201, 0xFFFFFFFF }, + { DENALI_CTL_202, 0x000F000F }, + { DENALI_CTL_203, 0x00000000 }, + { DENALI_CTL_204, 0x030FFFFF }, + { DENALI_CTL_205, 0xFFFFFFFF }, + { DENALI_CTL_206, 0x000F000F }, + { DENALI_CTL_207, 0x00000000 }, + { DENALI_CTL_208, 0x030FFFFF }, + { DENALI_CTL_209, 0xFFFFFFFF }, + { DENALI_CTL_210, 0x000F000F }, + { DENALI_CTL_211, 0x00000000 }, + { DENALI_CTL_212, 0x030FFFFF }, + { DENALI_CTL_213, 0xFFFFFFFF }, + { DENALI_CTL_214, 0x000F000F }, + { DENALI_CTL_215, 0x00000000 }, + { DENALI_CTL_216, 0x030FFFFF }, + { DENALI_CTL_217, 0xFFFFFFFF }, + { DENALI_CTL_218, 0x000F000F }, + { DENALI_CTL_219, 0x00000000 }, + { DENALI_CTL_220, 0x030FFFFF }, + { DENALI_CTL_221, 0xFFFFFFFF }, + { DENALI_CTL_222, 0x000F000F }, + { DENALI_CTL_223, 0x00000000 }, + { DENALI_CTL_224, 0x030FFFFF }, + { DENALI_CTL_225, 0xFFFFFFFF }, + { DENALI_CTL_226, 0x000F000F }, + { DENALI_CTL_227, 0x00000000 }, + { DENALI_CTL_228, 0x030FFFFF }, + { DENALI_CTL_229, 0xFFFFFFFF }, + { DENALI_CTL_230, 0x000F000F }, + { DENALI_CTL_231, 0x00000000 }, + { DENALI_CTL_232, 0x030FFFFF }, + { DENALI_CTL_233, 0xFFFFFFFF }, + { DENALI_CTL_234, 0x000F000F }, + { DENALI_CTL_235, 0x00000000 }, + { DENALI_CTL_236, 0x030FFFFF }, + { DENALI_CTL_237, 0xFFFFFFFF }, + { DENALI_CTL_238, 0x000F000F }, + { DENALI_CTL_239, 0x00000000 }, + { DENALI_CTL_240, 0x030FFFFF }, + { DENALI_CTL_241, 0xFFFFFFFF }, + { DENALI_CTL_242, 0x000F000F }, + { DENALI_CTL_243, 0x00000000 }, + { DENALI_CTL_244, 0x030FFFFF }, + { DENALI_CTL_245, 0xFFFFFFFF }, + { DENALI_CTL_246, 0x000F000F }, + { DENALI_CTL_247, 0x00000000 }, + { DENALI_CTL_248, 0x000FFFFF }, + { DENALI_CTL_249, 0xFFFFFFFF }, + { DENALI_CTL_250, 0x000F000F }, + { DENALI_CTL_251, 0x00000000 }, + { DENALI_CTL_252, 0x030FFFFF }, + { DENALI_CTL_253, 0xFFFFFFFF }, + { DENALI_CTL_254, 0x000F000F }, + { DENALI_CTL_255, 0x00000000 }, + { DENALI_CTL_256, 0x030FFFFF }, + { DENALI_CTL_257, 0xFFFFFFFF }, + { DENALI_CTL_258, 0x000F000F }, + { DENALI_CTL_259, 0x00000000 }, + { DENALI_CTL_260, 0x030FFFFF }, + { DENALI_CTL_261, 0xFFFFFFFF }, + { DENALI_CTL_262, 0x000F000F }, + { DENALI_CTL_263, 0x00000000 }, + { DENALI_CTL_264, 0x030FFFFF }, + { DENALI_CTL_265, 0xFFFFFFFF }, + { DENALI_CTL_266, 0x000F000F }, + { DENALI_CTL_267, 0x00000000 }, + { DENALI_CTL_268, 0x030FFFFF }, + { DENALI_CTL_269, 0xFFFFFFFF }, + { DENALI_CTL_270, 0x000F000F }, + { DENALI_CTL_271, 0x00000000 }, + { DENALI_CTL_272, 0x030FFFFF }, + { DENALI_CTL_273, 0xFFFFFFFF }, + { DENALI_CTL_274, 0x000F000F }, + { DENALI_CTL_275, 0x00000000 }, + { DENALI_CTL_276, 0x030FFFFF }, + { DENALI_CTL_277, 0xFFFFFFFF }, + { DENALI_CTL_278, 0x000F000F }, + { DENALI_CTL_279, 0x00000000 }, + { DENALI_CTL_280, 0x030FFFFF }, + { DENALI_CTL_281, 0xFFFFFFFF }, + { DENALI_CTL_282, 0x000F000F }, + { DENALI_CTL_283, 0x00000000 }, + { DENALI_CTL_284, 0x030FFFFF }, + { DENALI_CTL_285, 0xFFFFFFFF }, + { DENALI_CTL_286, 0x000F000F }, + { DENALI_CTL_287, 0x00000000 }, + { DENALI_CTL_288, 0x030FFFFF }, + { DENALI_CTL_289, 0xFFFFFFFF }, + { DENALI_CTL_290, 0x000F000F }, + { DENALI_CTL_291, 0x00000000 }, + { DENALI_CTL_292, 0x030FFFFF }, + { DENALI_CTL_293, 0xFFFFFFFF }, + { DENALI_CTL_294, 0x000F000F }, + { DENALI_CTL_295, 0x00000000 }, + { DENALI_CTL_296, 0x030FFFFF }, + { DENALI_CTL_297, 0xFFFFFFFF }, + { DENALI_CTL_298, 0x000F000F }, + { DENALI_CTL_299, 0x00000000 }, + { DENALI_CTL_300, 0x030FFFFF }, + { DENALI_CTL_301, 0xFFFFFFFF }, + { DENALI_CTL_302, 0x000F000F }, + { DENALI_CTL_303, 0x00000000 }, + { DENALI_CTL_304, 0x030FFFFF }, + { DENALI_CTL_305, 0xFFFFFFFF }, + { DENALI_CTL_306, 0x000F000F }, + { DENALI_CTL_307, 0x00000000 }, + { DENALI_CTL_308, 0x030FFFFF }, + { DENALI_CTL_309, 0xFFFFFFFF }, + { DENALI_CTL_310, 0x000F000F }, + { DENALI_CTL_311, 0x00000000 }, + { DENALI_CTL_312, 0x000FFFFF }, + { DENALI_CTL_313, 0xFFFFFFFF }, + { DENALI_CTL_314, 0x000F000F }, + { DENALI_CTL_315, 0x00000000 }, + { DENALI_CTL_316, 0x030FFFFF }, + { DENALI_CTL_317, 0xFFFFFFFF }, + { DENALI_CTL_318, 0x000F000F }, + { DENALI_CTL_319, 0x00000000 }, + { DENALI_CTL_320, 0x030FFFFF }, + { DENALI_CTL_321, 0xFFFFFFFF }, + { DENALI_CTL_322, 0x000F000F }, + { DENALI_CTL_323, 0x00000000 }, + { DENALI_CTL_324, 0x030FFFFF }, + { DENALI_CTL_325, 0xFFFFFFFF }, + { DENALI_CTL_326, 0x000F000F }, + { DENALI_CTL_327, 0x00000000 }, + { DENALI_CTL_328, 0x030FFFFF }, + { DENALI_CTL_329, 0xFFFFFFFF }, + { DENALI_CTL_330, 0x000F000F }, + { DENALI_CTL_331, 0x00000000 }, + { DENALI_CTL_332, 0x030FFFFF }, + { DENALI_CTL_333, 0xFFFFFFFF }, + { DENALI_CTL_334, 0x000F000F }, + { DENALI_CTL_335, 0x00000000 }, + { DENALI_CTL_336, 0x030FFFFF }, + { DENALI_CTL_337, 0xFFFFFFFF }, + { DENALI_CTL_338, 0x000F000F }, + { DENALI_CTL_339, 0x00000000 }, + { DENALI_CTL_340, 0x030FFFFF }, + { DENALI_CTL_341, 0xFFFFFFFF }, + { DENALI_CTL_342, 0x000F000F }, + { DENALI_CTL_343, 0x00000000 }, + { DENALI_CTL_344, 0x030FFFFF }, + { DENALI_CTL_345, 0xFFFFFFFF }, + { DENALI_CTL_346, 0x000F000F }, + { DENALI_CTL_347, 0x00000000 }, + { DENALI_CTL_348, 0x030FFFFF }, + { DENALI_CTL_349, 0xFFFFFFFF }, + { DENALI_CTL_350, 0x000F000F }, + { DENALI_CTL_351, 0x00000000 }, + { DENALI_CTL_352, 0x030FFFFF }, + { DENALI_CTL_353, 0xFFFFFFFF }, + { DENALI_CTL_354, 0x000F000F }, + { DENALI_CTL_355, 0x00000000 }, + { DENALI_CTL_356, 0x030FFFFF }, + { DENALI_CTL_357, 0xFFFFFFFF }, + { DENALI_CTL_358, 0x000F000F }, + { DENALI_CTL_359, 0x00000000 }, + { DENALI_CTL_360, 0x030FFFFF }, + { DENALI_CTL_361, 0xFFFFFFFF }, + { DENALI_CTL_362, 0x000F000F }, + { DENALI_CTL_363, 0x00000000 }, + { DENALI_CTL_364, 0x030FFFFF }, + { DENALI_CTL_365, 0xFFFFFFFF }, + { DENALI_CTL_366, 0x000F000F }, + { DENALI_CTL_367, 0x00000000 }, + { DENALI_CTL_368, 0x030FFFFF }, + { DENALI_CTL_369, 0xFFFFFFFF }, + { DENALI_CTL_370, 0x000F000F }, + { DENALI_CTL_371, 0x00000000 }, + { DENALI_CTL_372, 0x030FFFFF }, + { DENALI_CTL_373, 0xFFFFFFFF }, + { DENALI_CTL_374, 0x000F000F }, + { DENALI_CTL_375, 0x03000000 }, + { DENALI_CTL_376, 0x03030303 }, + { DENALI_CTL_377, 0x03030303 }, + { DENALI_CTL_378, 0x03030303 }, + { DENALI_CTL_379, 0x00030303 }, + { DENALI_CTL_380, 0x02020064 }, + { DENALI_CTL_381, 0x02020202 }, + { DENALI_CTL_382, 0x02020202 }, + { DENALI_CTL_383, 0x02020202 }, + { DENALI_CTL_384, 0x00010202 }, + { DENALI_CTL_385, 0x01010064 }, + { DENALI_CTL_386, 0x01010101 }, + { DENALI_CTL_387, 0x01010101 }, + { DENALI_CTL_388, 0x01010101 }, + { DENALI_CTL_389, 0x00020101 }, + { DENALI_CTL_390, 0x00000064 }, + { DENALI_CTL_391, 0x00000006 }, + { DENALI_CTL_392, 0x000007D0 }, + { DENALI_CTL_393, 0x00000032 }, + { DENALI_CTL_394, 0x00000200 }, + { DENALI_CTL_395, 0x00000200 }, + { DENALI_CTL_396, 0x00000000 }, + { DENALI_CTL_397, 0x00000000 }, + { DENALI_CTL_398, 0x01080205 }, + { DENALI_CTL_399, 0x00200106 }, + { DENALI_CTL_400, 0x00000000 }, + { DENALI_CTL_401, 0x0A000200 }, + { DENALI_CTL_402, 0x000C000A }, + { DENALI_CTL_403, 0x00000000 }, + { DENALI_CTL_404, 0x00000000 }, + { DENALI_CTL_405, 0x00000000 }, + { DENALI_CTL_406, 0x00000000 }, + { DENALI_CTL_407, 0x00000000 }, + { DENALI_CTL_408, 0x00000000 }, + { DENALI_CTL_409, 0x00000000 }, + { DENALI_CTL_410, 0x00000000 }, + { DENALI_CTL_411, 0x00000000 }, + { DENALI_CTL_412, 0x0000000F }, + { DENALI_CTL_413, 0x017105DD }, + { DENALI_CTL_414, 0x4F6C01E8 }, + { DENALI_CTL_415, 0x00007822 }, + { DENALI_CTL_416, 0x1E1E3C22 }, + { DENALI_CTL_417, 0x00000000 }, + { DENALI_CTL_418, 0x00000000 }, + { DENALI_CTL_419, 0x00000000 }, + { DENALI_CTL_420, 0x00000000 }, + { DENALI_CTL_421, 0x00000000 }, + { DENALI_CTL_422, 0x00000000 }, + { DENALI_CTL_423, 0x00000000 }, + { DENALI_CTL_424, 0x00000000 }, + { DENALI_CTL_425, 0x00000000 }, + { DENALI_CTL_426, 0x00000000 }, + { DENALI_CTL_427, 0x00000000 }, + { DENALI_CTL_428, 0x00000000 }, + { DENALI_CTL_429, 0x00000000 }, + { DENALI_CTL_430, 0x00000000 }, + { DENALI_CTL_431, 0x00000000 }, + { DENALI_CTL_432, 0x00000000 }, + { DENALI_CTL_433, 0x00000000 }, + { DENALI_CTL_434, 0x00000000 }, + { DENALI_CTL_435, 0x00000000 } +}; diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/soc/a3ul/drivers/ddr/param_mc_C-011_D3-01-2.c b/drivers/rz/ipl/rza/plat/renesas/rz/soc/a3ul/drivers/ddr/param_mc_C-011_D3-01-2.c new file mode 100644 index 00000000..f4e3ec66 --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/soc/a3ul/drivers/ddr/param_mc_C-011_D3-01-2.c @@ -0,0 +1,449 @@ +/* + * Copyright (c) 2020-2022, Renesas Electronics Corporation. All rights reserved. + * SPDX-License-Identifier: BSD-3-Clause + * This code was generated with RZ/G2L, G2UL, Five, A3UL DDR config generation tool v3.0.0 + */ + +#include +#include + +const char ddr_an_version[] = "v3.0.0"; + +const uint32_t mc_init_tbl[MC_INIT_NUM][2] = { + { DENALI_CTL_00, 0x00000600 }, + { DENALI_CTL_01, 0x00000000 }, + { DENALI_CTL_02, 0x00000000 }, + { DENALI_CTL_03, 0x00000000 }, + { DENALI_CTL_04, 0x00000000 }, + { DENALI_CTL_05, 0x00000000 }, + { DENALI_CTL_06, 0x00000000 }, + { DENALI_CTL_07, 0x00000000 }, + { DENALI_CTL_08, 0x00000000 }, + { DENALI_CTL_09, 0x00000000 }, + { DENALI_CTL_10, 0x01000007 }, + { DENALI_CTL_11, 0x00100100 }, + { DENALI_CTL_12, 0x000208D6 }, + { DENALI_CTL_13, 0x00051616 }, + { DENALI_CTL_14, 0x07140200 }, + { DENALI_CTL_15, 0x00000000 }, + { DENALI_CTL_16, 0x05000404 }, + { DENALI_CTL_17, 0x00002200 }, + { DENALI_CTL_18, 0x0505001E }, + { DENALI_CTL_19, 0x05001E0A }, + { DENALI_CTL_20, 0x000C0405 }, + { DENALI_CTL_21, 0x0400B6D0 }, + { DENALI_CTL_22, 0x00030305 }, + { DENALI_CTL_23, 0x01000A0A }, + { DENALI_CTL_24, 0x0A031401 }, + { DENALI_CTL_25, 0x0100000A }, + { DENALI_CTL_26, 0x00000101 }, + { DENALI_CTL_27, 0x00000000 }, + { DENALI_CTL_28, 0x00000000 }, + { DENALI_CTL_29, 0x00040301 }, + { DENALI_CTL_30, 0x000000EA }, + { DENALI_CTL_31, 0x00001448 }, + { DENALI_CTL_32, 0x00000005 }, + { DENALI_CTL_33, 0x00100004 }, + { DENALI_CTL_34, 0x00F00200 }, + { DENALI_CTL_35, 0x000000F0 }, + { DENALI_CTL_36, 0x01000201 }, + { DENALI_CTL_37, 0x80104002 }, + { DENALI_CTL_38, 0x00000000 }, + { DENALI_CTL_39, 0x00040000 }, + { DENALI_CTL_40, 0x00000000 }, + { DENALI_CTL_41, 0x00051200 }, + { DENALI_CTL_42, 0x000007D0 }, + { DENALI_CTL_43, 0x00051200 }, + { DENALI_CTL_44, 0x00051200 }, + { DENALI_CTL_45, 0x00051200 }, + { DENALI_CTL_46, 0x00000000 }, + { DENALI_CTL_47, 0x01000000 }, + { DENALI_CTL_48, 0x00000000 }, + { DENALI_CTL_49, 0x00000000 }, + { DENALI_CTL_50, 0x00000000 }, + { DENALI_CTL_51, 0x00000000 }, + { DENALI_CTL_52, 0x00000000 }, + { DENALI_CTL_53, 0x00000000 }, + { DENALI_CTL_54, 0x00000000 }, + { DENALI_CTL_55, 0x00262600 }, + { DENALI_CTL_56, 0x09070000 }, + { DENALI_CTL_57, 0x2F0E010A }, + { DENALI_CTL_58, 0x00000300 }, + { DENALI_CTL_59, 0x00010004 }, + { DENALI_CTL_60, 0x00000800 }, + { DENALI_CTL_61, 0x00000000 }, + { DENALI_CTL_62, 0x00000000 }, + { DENALI_CTL_63, 0x00000000 }, + { DENALI_CTL_64, 0x00000100 }, + { DENALI_CTL_65, 0x00000200 }, + { DENALI_CTL_66, 0x00001000 }, + { DENALI_CTL_67, 0x00000000 }, + { DENALI_CTL_68, 0x00000000 }, + { DENALI_CTL_69, 0x00000A60 }, + { DENALI_CTL_70, 0x00000006 }, + { DENALI_CTL_71, 0x00000010 }, + { DENALI_CTL_72, 0x00000A60 }, + { DENALI_CTL_73, 0x00000006 }, + { DENALI_CTL_74, 0x00000010 }, + { DENALI_CTL_75, 0x00000000 }, + { DENALI_CTL_76, 0x00000000 }, + { DENALI_CTL_77, 0x00000000 }, + { DENALI_CTL_78, 0x00000000 }, + { DENALI_CTL_79, 0x00000000 }, + { DENALI_CTL_80, 0x00000000 }, + { DENALI_CTL_81, 0x00000000 }, + { DENALI_CTL_82, 0x00000000 }, + { DENALI_CTL_83, 0x00000000 }, + { DENALI_CTL_84, 0x00000000 }, + { DENALI_CTL_85, 0x01010000 }, + { DENALI_CTL_86, 0x00000000 }, + { DENALI_CTL_87, 0x00000000 }, + { DENALI_CTL_88, 0x00000000 }, + { DENALI_CTL_89, 0x00000000 }, + { DENALI_CTL_90, 0x00000000 }, + { DENALI_CTL_91, 0x00000000 }, + { DENALI_CTL_92, 0x00000000 }, + { DENALI_CTL_93, 0x00000000 }, + { DENALI_CTL_94, 0x00000000 }, + { DENALI_CTL_95, 0x01000200 }, + { DENALI_CTL_96, 0x00010801 }, + { DENALI_CTL_97, 0x00000000 }, + { DENALI_CTL_98, 0x00000000 }, + { DENALI_CTL_99, 0x00000000 }, + { DENALI_CTL_100, 0x00000000 }, + { DENALI_CTL_101, 0x00000000 }, + { DENALI_CTL_102, 0x00000000 }, + { DENALI_CTL_103, 0x00000000 }, + { DENALI_CTL_104, 0x00000000 }, + { DENALI_CTL_105, 0x00000000 }, + { DENALI_CTL_106, 0x00000000 }, + { DENALI_CTL_107, 0x00000000 }, + { DENALI_CTL_108, 0x00000000 }, + { DENALI_CTL_109, 0x00000000 }, + { DENALI_CTL_110, 0x00000008 }, + { DENALI_CTL_111, 0x006403E8 }, + { DENALI_CTL_112, 0x00000000 }, + { DENALI_CTL_113, 0x00000000 }, + { DENALI_CTL_114, 0x00000000 }, + { DENALI_CTL_115, 0x15110000 }, + { DENALI_CTL_116, 0x00040C18 }, + { DENALI_CTL_117, 0x009ECA03 }, + { DENALI_CTL_118, 0x0000A299 }, + { DENALI_CTL_119, 0x00000000 }, + { DENALI_CTL_120, 0x01000200 }, + { DENALI_CTL_121, 0x00000040 }, + { DENALI_CTL_122, 0x01010100 }, + { DENALI_CTL_123, 0x00010101 }, + { DENALI_CTL_124, 0x0FFF0000 }, + { DENALI_CTL_125, 0x0001FF00 }, + { DENALI_CTL_126, 0xFFFFFFFF }, + { DENALI_CTL_127, 0x00FFFF00 }, + { DENALI_CTL_128, 0xFFFF0A00 }, + { DENALI_CTL_129, 0x01010001 }, + { DENALI_CTL_130, 0x01010101 }, + { DENALI_CTL_131, 0x01030101 }, + { DENALI_CTL_132, 0x0C010000 }, + { DENALI_CTL_133, 0x01000000 }, + { DENALI_CTL_134, 0x00000000 }, + { DENALI_CTL_135, 0x00010000 }, + { DENALI_CTL_136, 0x00000000 }, + { DENALI_CTL_137, 0x00000000 }, + { DENALI_CTL_138, 0x00000000 }, + { DENALI_CTL_139, 0x00000000 }, + { DENALI_CTL_140, 0x00000000 }, + { DENALI_CTL_141, 0x00000000 }, + { DENALI_CTL_142, 0x00000000 }, + { DENALI_CTL_143, 0x00000000 }, + { DENALI_CTL_144, 0x00000000 }, + { DENALI_CTL_145, 0x00000000 }, + { DENALI_CTL_146, 0x00000000 }, + { DENALI_CTL_147, 0x00000000 }, + { DENALI_CTL_148, 0x00000000 }, + { DENALI_CTL_149, 0x00000000 }, + { DENALI_CTL_150, 0x00000000 }, + { DENALI_CTL_151, 0x00000000 }, + { DENALI_CTL_152, 0x00000000 }, + { DENALI_CTL_153, 0x00000000 }, + { DENALI_CTL_154, 0x00000000 }, + { DENALI_CTL_155, 0x00000000 }, + { DENALI_CTL_156, 0x00000000 }, + { DENALI_CTL_157, 0x00010000 }, + { DENALI_CTL_158, 0x00000000 }, + { DENALI_CTL_159, 0x00000800 }, + { DENALI_CTL_160, 0x00000000 }, + { DENALI_CTL_161, 0x00000898 }, + { DENALI_CTL_162, 0x03000000 }, + { DENALI_CTL_163, 0x00000408 }, + { DENALI_CTL_164, 0x00000000 }, + { DENALI_CTL_165, 0x00000000 }, + { DENALI_CTL_166, 0x00000000 }, + { DENALI_CTL_167, 0x00000000 }, + { DENALI_CTL_168, 0x00000000 }, + { DENALI_CTL_169, 0x00000000 }, + { DENALI_CTL_170, 0x00000000 }, + { DENALI_CTL_171, 0x00000000 }, + { DENALI_CTL_172, 0x00000000 }, + { DENALI_CTL_173, 0x00000000 }, + { DENALI_CTL_174, 0x00000000 }, + { DENALI_CTL_175, 0x06060600 }, + { DENALI_CTL_176, 0x03020001 }, + { DENALI_CTL_177, 0x01030101 }, + { DENALI_CTL_178, 0x03000302 }, + { DENALI_CTL_179, 0x00000000 }, + { DENALI_CTL_180, 0x00080801 }, + { DENALI_CTL_181, 0x00080801 }, + { DENALI_CTL_182, 0x00070601 }, + { DENALI_CTL_183, 0x00000000 }, + { DENALI_CTL_184, 0x000FFFFF }, + { DENALI_CTL_185, 0xFFFFFFFF }, + { DENALI_CTL_186, 0x000F000F }, + { DENALI_CTL_187, 0x00000000 }, + { DENALI_CTL_188, 0x030FFFFF }, + { DENALI_CTL_189, 0xFFFFFFFF }, + { DENALI_CTL_190, 0x000F000F }, + { DENALI_CTL_191, 0x00000000 }, + { DENALI_CTL_192, 0x030FFFFF }, + { DENALI_CTL_193, 0xFFFFFFFF }, + { DENALI_CTL_194, 0x000F000F }, + { DENALI_CTL_195, 0x00000000 }, + { DENALI_CTL_196, 0x030FFFFF }, + { DENALI_CTL_197, 0xFFFFFFFF }, + { DENALI_CTL_198, 0x000F000F }, + { DENALI_CTL_199, 0x00000000 }, + { DENALI_CTL_200, 0x030FFFFF }, + { DENALI_CTL_201, 0xFFFFFFFF }, + { DENALI_CTL_202, 0x000F000F }, + { DENALI_CTL_203, 0x00000000 }, + { DENALI_CTL_204, 0x030FFFFF }, + { DENALI_CTL_205, 0xFFFFFFFF }, + { DENALI_CTL_206, 0x000F000F }, + { DENALI_CTL_207, 0x00000000 }, + { DENALI_CTL_208, 0x030FFFFF }, + { DENALI_CTL_209, 0xFFFFFFFF }, + { DENALI_CTL_210, 0x000F000F }, + { DENALI_CTL_211, 0x00000000 }, + { DENALI_CTL_212, 0x030FFFFF }, + { DENALI_CTL_213, 0xFFFFFFFF }, + { DENALI_CTL_214, 0x000F000F }, + { DENALI_CTL_215, 0x00000000 }, + { DENALI_CTL_216, 0x030FFFFF }, + { DENALI_CTL_217, 0xFFFFFFFF }, + { DENALI_CTL_218, 0x000F000F }, + { DENALI_CTL_219, 0x00000000 }, + { DENALI_CTL_220, 0x030FFFFF }, + { DENALI_CTL_221, 0xFFFFFFFF }, + { DENALI_CTL_222, 0x000F000F }, + { DENALI_CTL_223, 0x00000000 }, + { DENALI_CTL_224, 0x030FFFFF }, + { DENALI_CTL_225, 0xFFFFFFFF }, + { DENALI_CTL_226, 0x000F000F }, + { DENALI_CTL_227, 0x00000000 }, + { DENALI_CTL_228, 0x030FFFFF }, + { DENALI_CTL_229, 0xFFFFFFFF }, + { DENALI_CTL_230, 0x000F000F }, + { DENALI_CTL_231, 0x00000000 }, + { DENALI_CTL_232, 0x030FFFFF }, + { DENALI_CTL_233, 0xFFFFFFFF }, + { DENALI_CTL_234, 0x000F000F }, + { DENALI_CTL_235, 0x00000000 }, + { DENALI_CTL_236, 0x030FFFFF }, + { DENALI_CTL_237, 0xFFFFFFFF }, + { DENALI_CTL_238, 0x000F000F }, + { DENALI_CTL_239, 0x00000000 }, + { DENALI_CTL_240, 0x030FFFFF }, + { DENALI_CTL_241, 0xFFFFFFFF }, + { DENALI_CTL_242, 0x000F000F }, + { DENALI_CTL_243, 0x00000000 }, + { DENALI_CTL_244, 0x030FFFFF }, + { DENALI_CTL_245, 0xFFFFFFFF }, + { DENALI_CTL_246, 0x000F000F }, + { DENALI_CTL_247, 0x00000000 }, + { DENALI_CTL_248, 0x000FFFFF }, + { DENALI_CTL_249, 0xFFFFFFFF }, + { DENALI_CTL_250, 0x000F000F }, + { DENALI_CTL_251, 0x00000000 }, + { DENALI_CTL_252, 0x030FFFFF }, + { DENALI_CTL_253, 0xFFFFFFFF }, + { DENALI_CTL_254, 0x000F000F }, + { DENALI_CTL_255, 0x00000000 }, + { DENALI_CTL_256, 0x030FFFFF }, + { DENALI_CTL_257, 0xFFFFFFFF }, + { DENALI_CTL_258, 0x000F000F }, + { DENALI_CTL_259, 0x00000000 }, + { DENALI_CTL_260, 0x030FFFFF }, + { DENALI_CTL_261, 0xFFFFFFFF }, + { DENALI_CTL_262, 0x000F000F }, + { DENALI_CTL_263, 0x00000000 }, + { DENALI_CTL_264, 0x030FFFFF }, + { DENALI_CTL_265, 0xFFFFFFFF }, + { DENALI_CTL_266, 0x000F000F }, + { DENALI_CTL_267, 0x00000000 }, + { DENALI_CTL_268, 0x030FFFFF }, + { DENALI_CTL_269, 0xFFFFFFFF }, + { DENALI_CTL_270, 0x000F000F }, + { DENALI_CTL_271, 0x00000000 }, + { DENALI_CTL_272, 0x030FFFFF }, + { DENALI_CTL_273, 0xFFFFFFFF }, + { DENALI_CTL_274, 0x000F000F }, + { DENALI_CTL_275, 0x00000000 }, + { DENALI_CTL_276, 0x030FFFFF }, + { DENALI_CTL_277, 0xFFFFFFFF }, + { DENALI_CTL_278, 0x000F000F }, + { DENALI_CTL_279, 0x00000000 }, + { DENALI_CTL_280, 0x030FFFFF }, + { DENALI_CTL_281, 0xFFFFFFFF }, + { DENALI_CTL_282, 0x000F000F }, + { DENALI_CTL_283, 0x00000000 }, + { DENALI_CTL_284, 0x030FFFFF }, + { DENALI_CTL_285, 0xFFFFFFFF }, + { DENALI_CTL_286, 0x000F000F }, + { DENALI_CTL_287, 0x00000000 }, + { DENALI_CTL_288, 0x030FFFFF }, + { DENALI_CTL_289, 0xFFFFFFFF }, + { DENALI_CTL_290, 0x000F000F }, + { DENALI_CTL_291, 0x00000000 }, + { DENALI_CTL_292, 0x030FFFFF }, + { DENALI_CTL_293, 0xFFFFFFFF }, + { DENALI_CTL_294, 0x000F000F }, + { DENALI_CTL_295, 0x00000000 }, + { DENALI_CTL_296, 0x030FFFFF }, + { DENALI_CTL_297, 0xFFFFFFFF }, + { DENALI_CTL_298, 0x000F000F }, + { DENALI_CTL_299, 0x00000000 }, + { DENALI_CTL_300, 0x030FFFFF }, + { DENALI_CTL_301, 0xFFFFFFFF }, + { DENALI_CTL_302, 0x000F000F }, + { DENALI_CTL_303, 0x00000000 }, + { DENALI_CTL_304, 0x030FFFFF }, + { DENALI_CTL_305, 0xFFFFFFFF }, + { DENALI_CTL_306, 0x000F000F }, + { DENALI_CTL_307, 0x00000000 }, + { DENALI_CTL_308, 0x030FFFFF }, + { DENALI_CTL_309, 0xFFFFFFFF }, + { DENALI_CTL_310, 0x000F000F }, + { DENALI_CTL_311, 0x00000000 }, + { DENALI_CTL_312, 0x000FFFFF }, + { DENALI_CTL_313, 0xFFFFFFFF }, + { DENALI_CTL_314, 0x000F000F }, + { DENALI_CTL_315, 0x00000000 }, + { DENALI_CTL_316, 0x030FFFFF }, + { DENALI_CTL_317, 0xFFFFFFFF }, + { DENALI_CTL_318, 0x000F000F }, + { DENALI_CTL_319, 0x00000000 }, + { DENALI_CTL_320, 0x030FFFFF }, + { DENALI_CTL_321, 0xFFFFFFFF }, + { DENALI_CTL_322, 0x000F000F }, + { DENALI_CTL_323, 0x00000000 }, + { DENALI_CTL_324, 0x030FFFFF }, + { DENALI_CTL_325, 0xFFFFFFFF }, + { DENALI_CTL_326, 0x000F000F }, + { DENALI_CTL_327, 0x00000000 }, + { DENALI_CTL_328, 0x030FFFFF }, + { DENALI_CTL_329, 0xFFFFFFFF }, + { DENALI_CTL_330, 0x000F000F }, + { DENALI_CTL_331, 0x00000000 }, + { DENALI_CTL_332, 0x030FFFFF }, + { DENALI_CTL_333, 0xFFFFFFFF }, + { DENALI_CTL_334, 0x000F000F }, + { DENALI_CTL_335, 0x00000000 }, + { DENALI_CTL_336, 0x030FFFFF }, + { DENALI_CTL_337, 0xFFFFFFFF }, + { DENALI_CTL_338, 0x000F000F }, + { DENALI_CTL_339, 0x00000000 }, + { DENALI_CTL_340, 0x030FFFFF }, + { DENALI_CTL_341, 0xFFFFFFFF }, + { DENALI_CTL_342, 0x000F000F }, + { DENALI_CTL_343, 0x00000000 }, + { DENALI_CTL_344, 0x030FFFFF }, + { DENALI_CTL_345, 0xFFFFFFFF }, + { DENALI_CTL_346, 0x000F000F }, + { DENALI_CTL_347, 0x00000000 }, + { DENALI_CTL_348, 0x030FFFFF }, + { DENALI_CTL_349, 0xFFFFFFFF }, + { DENALI_CTL_350, 0x000F000F }, + { DENALI_CTL_351, 0x00000000 }, + { DENALI_CTL_352, 0x030FFFFF }, + { DENALI_CTL_353, 0xFFFFFFFF }, + { DENALI_CTL_354, 0x000F000F }, + { DENALI_CTL_355, 0x00000000 }, + { DENALI_CTL_356, 0x030FFFFF }, + { DENALI_CTL_357, 0xFFFFFFFF }, + { DENALI_CTL_358, 0x000F000F }, + { DENALI_CTL_359, 0x00000000 }, + { DENALI_CTL_360, 0x030FFFFF }, + { DENALI_CTL_361, 0xFFFFFFFF }, + { DENALI_CTL_362, 0x000F000F }, + { DENALI_CTL_363, 0x00000000 }, + { DENALI_CTL_364, 0x030FFFFF }, + { DENALI_CTL_365, 0xFFFFFFFF }, + { DENALI_CTL_366, 0x000F000F }, + { DENALI_CTL_367, 0x00000000 }, + { DENALI_CTL_368, 0x030FFFFF }, + { DENALI_CTL_369, 0xFFFFFFFF }, + { DENALI_CTL_370, 0x000F000F }, + { DENALI_CTL_371, 0x00000000 }, + { DENALI_CTL_372, 0x030FFFFF }, + { DENALI_CTL_373, 0xFFFFFFFF }, + { DENALI_CTL_374, 0x000F000F }, + { DENALI_CTL_375, 0x03000000 }, + { DENALI_CTL_376, 0x03030303 }, + { DENALI_CTL_377, 0x03030303 }, + { DENALI_CTL_378, 0x03030303 }, + { DENALI_CTL_379, 0x00030303 }, + { DENALI_CTL_380, 0x02020064 }, + { DENALI_CTL_381, 0x02020202 }, + { DENALI_CTL_382, 0x02020202 }, + { DENALI_CTL_383, 0x02020202 }, + { DENALI_CTL_384, 0x00010202 }, + { DENALI_CTL_385, 0x01010064 }, + { DENALI_CTL_386, 0x01010101 }, + { DENALI_CTL_387, 0x01010101 }, + { DENALI_CTL_388, 0x01010101 }, + { DENALI_CTL_389, 0x00020101 }, + { DENALI_CTL_390, 0x00000064 }, + { DENALI_CTL_391, 0x00000006 }, + { DENALI_CTL_392, 0x000007D0 }, + { DENALI_CTL_393, 0x00000032 }, + { DENALI_CTL_394, 0x00000200 }, + { DENALI_CTL_395, 0x00000200 }, + { DENALI_CTL_396, 0x00000000 }, + { DENALI_CTL_397, 0x00000000 }, + { DENALI_CTL_398, 0x01090205 }, + { DENALI_CTL_399, 0x00200106 }, + { DENALI_CTL_400, 0x00000000 }, + { DENALI_CTL_401, 0x0A000202 }, + { DENALI_CTL_402, 0x000C000A }, + { DENALI_CTL_403, 0x00000000 }, + { DENALI_CTL_404, 0x00000000 }, + { DENALI_CTL_405, 0x00000000 }, + { DENALI_CTL_406, 0x00000000 }, + { DENALI_CTL_407, 0x00000000 }, + { DENALI_CTL_408, 0x00000000 }, + { DENALI_CTL_409, 0x00000000 }, + { DENALI_CTL_410, 0x00000000 }, + { DENALI_CTL_411, 0x00000000 }, + { DENALI_CTL_412, 0x0000000F }, + { DENALI_CTL_413, 0x017105DD }, + { DENALI_CTL_414, 0x4F6306E8 }, + { DENALI_CTL_415, 0x00002822 }, + { DENALI_CTL_416, 0x00003C22 }, + { DENALI_CTL_417, 0x00000000 }, + { DENALI_CTL_418, 0x00000000 }, + { DENALI_CTL_419, 0x00000000 }, + { DENALI_CTL_420, 0x00000000 }, + { DENALI_CTL_421, 0x00000000 }, + { DENALI_CTL_422, 0x00000000 }, + { DENALI_CTL_423, 0x00000000 }, + { DENALI_CTL_424, 0x00000000 }, + { DENALI_CTL_425, 0x00000000 }, + { DENALI_CTL_426, 0x00000000 }, + { DENALI_CTL_427, 0x00000000 }, + { DENALI_CTL_428, 0x00000000 }, + { DENALI_CTL_429, 0x00000000 }, + { DENALI_CTL_430, 0x00000000 }, + { DENALI_CTL_431, 0x00000000 }, + { DENALI_CTL_432, 0x00000000 }, + { DENALI_CTL_433, 0x00000000 }, + { DENALI_CTL_434, 0x00000000 }, + { DENALI_CTL_435, 0x00000000 } +}; diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/soc/a3ul/drivers/ddr/param_mc_C-011_D3-02-2.c b/drivers/rz/ipl/rza/plat/renesas/rz/soc/a3ul/drivers/ddr/param_mc_C-011_D3-02-2.c new file mode 100644 index 00000000..89e003a3 --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/soc/a3ul/drivers/ddr/param_mc_C-011_D3-02-2.c @@ -0,0 +1,449 @@ +/* + * Copyright (c) 2020-2022, Renesas Electronics Corporation. All rights reserved. + * SPDX-License-Identifier: BSD-3-Clause + * This code was generated with RZ/G2L, G2UL, Five, A3UL DDR config generation tool v3.0.0 + */ + +#include +#include + +const char ddr_an_version[] = "v3.0.0"; + +const uint32_t mc_init_tbl[MC_INIT_NUM][2] = { + { DENALI_CTL_00, 0x00000600 }, + { DENALI_CTL_01, 0x00000000 }, + { DENALI_CTL_02, 0x00000000 }, + { DENALI_CTL_03, 0x00000000 }, + { DENALI_CTL_04, 0x00000000 }, + { DENALI_CTL_05, 0x00000000 }, + { DENALI_CTL_06, 0x00000000 }, + { DENALI_CTL_07, 0x00000000 }, + { DENALI_CTL_08, 0x00000000 }, + { DENALI_CTL_09, 0x00000000 }, + { DENALI_CTL_10, 0x01000007 }, + { DENALI_CTL_11, 0x00100100 }, + { DENALI_CTL_12, 0x000208D6 }, + { DENALI_CTL_13, 0x00051616 }, + { DENALI_CTL_14, 0x07120200 }, + { DENALI_CTL_15, 0x00000000 }, + { DENALI_CTL_16, 0x05000404 }, + { DENALI_CTL_17, 0x00002100 }, + { DENALI_CTL_18, 0x0505001E }, + { DENALI_CTL_19, 0x05001E09 }, + { DENALI_CTL_20, 0x000C0405 }, + { DENALI_CTL_21, 0x0400B6D0 }, + { DENALI_CTL_22, 0x00030305 }, + { DENALI_CTL_23, 0x01000A09 }, + { DENALI_CTL_24, 0x09031301 }, + { DENALI_CTL_25, 0x01000009 }, + { DENALI_CTL_26, 0x00000101 }, + { DENALI_CTL_27, 0x00000000 }, + { DENALI_CTL_28, 0x00000000 }, + { DENALI_CTL_29, 0x00040301 }, + { DENALI_CTL_30, 0x000000AE }, + { DENALI_CTL_31, 0x00001448 }, + { DENALI_CTL_32, 0x00000005 }, + { DENALI_CTL_33, 0x00100004 }, + { DENALI_CTL_34, 0x00B40200 }, + { DENALI_CTL_35, 0x000000B4 }, + { DENALI_CTL_36, 0x01000201 }, + { DENALI_CTL_37, 0x80104002 }, + { DENALI_CTL_38, 0x00000000 }, + { DENALI_CTL_39, 0x00040000 }, + { DENALI_CTL_40, 0x00000000 }, + { DENALI_CTL_41, 0x00051200 }, + { DENALI_CTL_42, 0x000007D0 }, + { DENALI_CTL_43, 0x00051200 }, + { DENALI_CTL_44, 0x00051200 }, + { DENALI_CTL_45, 0x00051200 }, + { DENALI_CTL_46, 0x00000000 }, + { DENALI_CTL_47, 0x01000000 }, + { DENALI_CTL_48, 0x00000000 }, + { DENALI_CTL_49, 0x00000000 }, + { DENALI_CTL_50, 0x00000000 }, + { DENALI_CTL_51, 0x00000000 }, + { DENALI_CTL_52, 0x00000000 }, + { DENALI_CTL_53, 0x00000000 }, + { DENALI_CTL_54, 0x00000000 }, + { DENALI_CTL_55, 0x00262600 }, + { DENALI_CTL_56, 0x09070000 }, + { DENALI_CTL_57, 0x2F0E010A }, + { DENALI_CTL_58, 0x00000300 }, + { DENALI_CTL_59, 0x00010004 }, + { DENALI_CTL_60, 0x00000800 }, + { DENALI_CTL_61, 0x00000000 }, + { DENALI_CTL_62, 0x00000000 }, + { DENALI_CTL_63, 0x00000000 }, + { DENALI_CTL_64, 0x00000100 }, + { DENALI_CTL_65, 0x00000200 }, + { DENALI_CTL_66, 0x00001000 }, + { DENALI_CTL_67, 0x00000000 }, + { DENALI_CTL_68, 0x00000000 }, + { DENALI_CTL_69, 0x00000A50 }, + { DENALI_CTL_70, 0x00000006 }, + { DENALI_CTL_71, 0x00000010 }, + { DENALI_CTL_72, 0x00000A50 }, + { DENALI_CTL_73, 0x00000006 }, + { DENALI_CTL_74, 0x00000010 }, + { DENALI_CTL_75, 0x00000000 }, + { DENALI_CTL_76, 0x00000000 }, + { DENALI_CTL_77, 0x00000000 }, + { DENALI_CTL_78, 0x00000000 }, + { DENALI_CTL_79, 0x00000000 }, + { DENALI_CTL_80, 0x00000000 }, + { DENALI_CTL_81, 0x00000000 }, + { DENALI_CTL_82, 0x00000000 }, + { DENALI_CTL_83, 0x00000000 }, + { DENALI_CTL_84, 0x00000000 }, + { DENALI_CTL_85, 0x01010000 }, + { DENALI_CTL_86, 0x00000000 }, + { DENALI_CTL_87, 0x00000000 }, + { DENALI_CTL_88, 0x00000000 }, + { DENALI_CTL_89, 0x00000000 }, + { DENALI_CTL_90, 0x00000000 }, + { DENALI_CTL_91, 0x00000000 }, + { DENALI_CTL_92, 0x00000000 }, + { DENALI_CTL_93, 0x00000000 }, + { DENALI_CTL_94, 0x00000000 }, + { DENALI_CTL_95, 0x01000200 }, + { DENALI_CTL_96, 0x00010801 }, + { DENALI_CTL_97, 0x00000000 }, + { DENALI_CTL_98, 0x00000000 }, + { DENALI_CTL_99, 0x00000000 }, + { DENALI_CTL_100, 0x00000000 }, + { DENALI_CTL_101, 0x00000000 }, + { DENALI_CTL_102, 0x00000000 }, + { DENALI_CTL_103, 0x00000000 }, + { DENALI_CTL_104, 0x00000000 }, + { DENALI_CTL_105, 0x00000000 }, + { DENALI_CTL_106, 0x00000000 }, + { DENALI_CTL_107, 0x00000000 }, + { DENALI_CTL_108, 0x00000000 }, + { DENALI_CTL_109, 0x00000000 }, + { DENALI_CTL_110, 0x00000008 }, + { DENALI_CTL_111, 0x006403E8 }, + { DENALI_CTL_112, 0x00000000 }, + { DENALI_CTL_113, 0x00000000 }, + { DENALI_CTL_114, 0x00000000 }, + { DENALI_CTL_115, 0x15110000 }, + { DENALI_CTL_116, 0x00040C18 }, + { DENALI_CTL_117, 0x009ECA03 }, + { DENALI_CTL_118, 0x0000A299 }, + { DENALI_CTL_119, 0x00000000 }, + { DENALI_CTL_120, 0x01000200 }, + { DENALI_CTL_121, 0x00000040 }, + { DENALI_CTL_122, 0x02010100 }, + { DENALI_CTL_123, 0x00010102 }, + { DENALI_CTL_124, 0x07FF0000 }, + { DENALI_CTL_125, 0x0000FF00 }, + { DENALI_CTL_126, 0xFFFFFFFF }, + { DENALI_CTL_127, 0x00FFFF00 }, + { DENALI_CTL_128, 0xFFFF0A00 }, + { DENALI_CTL_129, 0x01010001 }, + { DENALI_CTL_130, 0x01010101 }, + { DENALI_CTL_131, 0x01030101 }, + { DENALI_CTL_132, 0x0C010000 }, + { DENALI_CTL_133, 0x01000000 }, + { DENALI_CTL_134, 0x00000000 }, + { DENALI_CTL_135, 0x00010000 }, + { DENALI_CTL_136, 0x00000000 }, + { DENALI_CTL_137, 0x00000000 }, + { DENALI_CTL_138, 0x00000000 }, + { DENALI_CTL_139, 0x00000000 }, + { DENALI_CTL_140, 0x00000000 }, + { DENALI_CTL_141, 0x00000000 }, + { DENALI_CTL_142, 0x00000000 }, + { DENALI_CTL_143, 0x00000000 }, + { DENALI_CTL_144, 0x00000000 }, + { DENALI_CTL_145, 0x00000000 }, + { DENALI_CTL_146, 0x00000000 }, + { DENALI_CTL_147, 0x00000000 }, + { DENALI_CTL_148, 0x00000000 }, + { DENALI_CTL_149, 0x00000000 }, + { DENALI_CTL_150, 0x00000000 }, + { DENALI_CTL_151, 0x00000000 }, + { DENALI_CTL_152, 0x00000000 }, + { DENALI_CTL_153, 0x00000000 }, + { DENALI_CTL_154, 0x00000000 }, + { DENALI_CTL_155, 0x00000000 }, + { DENALI_CTL_156, 0x00000000 }, + { DENALI_CTL_157, 0x00010000 }, + { DENALI_CTL_158, 0x00000000 }, + { DENALI_CTL_159, 0x00000800 }, + { DENALI_CTL_160, 0x00000000 }, + { DENALI_CTL_161, 0x00000898 }, + { DENALI_CTL_162, 0x03000000 }, + { DENALI_CTL_163, 0x00000408 }, + { DENALI_CTL_164, 0x00000000 }, + { DENALI_CTL_165, 0x00000000 }, + { DENALI_CTL_166, 0x00000000 }, + { DENALI_CTL_167, 0x00000000 }, + { DENALI_CTL_168, 0x00000000 }, + { DENALI_CTL_169, 0x00000000 }, + { DENALI_CTL_170, 0x00000000 }, + { DENALI_CTL_171, 0x00000000 }, + { DENALI_CTL_172, 0x00000000 }, + { DENALI_CTL_173, 0x00000000 }, + { DENALI_CTL_174, 0x00000000 }, + { DENALI_CTL_175, 0x06060600 }, + { DENALI_CTL_176, 0x03020001 }, + { DENALI_CTL_177, 0x01020101 }, + { DENALI_CTL_178, 0x03000302 }, + { DENALI_CTL_179, 0x00000000 }, + { DENALI_CTL_180, 0x00080801 }, + { DENALI_CTL_181, 0x00080801 }, + { DENALI_CTL_182, 0x00070601 }, + { DENALI_CTL_183, 0x00000000 }, + { DENALI_CTL_184, 0x000FFFFF }, + { DENALI_CTL_185, 0xFFFFFFFF }, + { DENALI_CTL_186, 0x000F000F }, + { DENALI_CTL_187, 0x00000000 }, + { DENALI_CTL_188, 0x030FFFFF }, + { DENALI_CTL_189, 0xFFFFFFFF }, + { DENALI_CTL_190, 0x000F000F }, + { DENALI_CTL_191, 0x00000000 }, + { DENALI_CTL_192, 0x030FFFFF }, + { DENALI_CTL_193, 0xFFFFFFFF }, + { DENALI_CTL_194, 0x000F000F }, + { DENALI_CTL_195, 0x00000000 }, + { DENALI_CTL_196, 0x030FFFFF }, + { DENALI_CTL_197, 0xFFFFFFFF }, + { DENALI_CTL_198, 0x000F000F }, + { DENALI_CTL_199, 0x00000000 }, + { DENALI_CTL_200, 0x030FFFFF }, + { DENALI_CTL_201, 0xFFFFFFFF }, + { DENALI_CTL_202, 0x000F000F }, + { DENALI_CTL_203, 0x00000000 }, + { DENALI_CTL_204, 0x030FFFFF }, + { DENALI_CTL_205, 0xFFFFFFFF }, + { DENALI_CTL_206, 0x000F000F }, + { DENALI_CTL_207, 0x00000000 }, + { DENALI_CTL_208, 0x030FFFFF }, + { DENALI_CTL_209, 0xFFFFFFFF }, + { DENALI_CTL_210, 0x000F000F }, + { DENALI_CTL_211, 0x00000000 }, + { DENALI_CTL_212, 0x030FFFFF }, + { DENALI_CTL_213, 0xFFFFFFFF }, + { DENALI_CTL_214, 0x000F000F }, + { DENALI_CTL_215, 0x00000000 }, + { DENALI_CTL_216, 0x030FFFFF }, + { DENALI_CTL_217, 0xFFFFFFFF }, + { DENALI_CTL_218, 0x000F000F }, + { DENALI_CTL_219, 0x00000000 }, + { DENALI_CTL_220, 0x030FFFFF }, + { DENALI_CTL_221, 0xFFFFFFFF }, + { DENALI_CTL_222, 0x000F000F }, + { DENALI_CTL_223, 0x00000000 }, + { DENALI_CTL_224, 0x030FFFFF }, + { DENALI_CTL_225, 0xFFFFFFFF }, + { DENALI_CTL_226, 0x000F000F }, + { DENALI_CTL_227, 0x00000000 }, + { DENALI_CTL_228, 0x030FFFFF }, + { DENALI_CTL_229, 0xFFFFFFFF }, + { DENALI_CTL_230, 0x000F000F }, + { DENALI_CTL_231, 0x00000000 }, + { DENALI_CTL_232, 0x030FFFFF }, + { DENALI_CTL_233, 0xFFFFFFFF }, + { DENALI_CTL_234, 0x000F000F }, + { DENALI_CTL_235, 0x00000000 }, + { DENALI_CTL_236, 0x030FFFFF }, + { DENALI_CTL_237, 0xFFFFFFFF }, + { DENALI_CTL_238, 0x000F000F }, + { DENALI_CTL_239, 0x00000000 }, + { DENALI_CTL_240, 0x030FFFFF }, + { DENALI_CTL_241, 0xFFFFFFFF }, + { DENALI_CTL_242, 0x000F000F }, + { DENALI_CTL_243, 0x00000000 }, + { DENALI_CTL_244, 0x030FFFFF }, + { DENALI_CTL_245, 0xFFFFFFFF }, + { DENALI_CTL_246, 0x000F000F }, + { DENALI_CTL_247, 0x00000000 }, + { DENALI_CTL_248, 0x000FFFFF }, + { DENALI_CTL_249, 0xFFFFFFFF }, + { DENALI_CTL_250, 0x000F000F }, + { DENALI_CTL_251, 0x00000000 }, + { DENALI_CTL_252, 0x030FFFFF }, + { DENALI_CTL_253, 0xFFFFFFFF }, + { DENALI_CTL_254, 0x000F000F }, + { DENALI_CTL_255, 0x00000000 }, + { DENALI_CTL_256, 0x030FFFFF }, + { DENALI_CTL_257, 0xFFFFFFFF }, + { DENALI_CTL_258, 0x000F000F }, + { DENALI_CTL_259, 0x00000000 }, + { DENALI_CTL_260, 0x030FFFFF }, + { DENALI_CTL_261, 0xFFFFFFFF }, + { DENALI_CTL_262, 0x000F000F }, + { DENALI_CTL_263, 0x00000000 }, + { DENALI_CTL_264, 0x030FFFFF }, + { DENALI_CTL_265, 0xFFFFFFFF }, + { DENALI_CTL_266, 0x000F000F }, + { DENALI_CTL_267, 0x00000000 }, + { DENALI_CTL_268, 0x030FFFFF }, + { DENALI_CTL_269, 0xFFFFFFFF }, + { DENALI_CTL_270, 0x000F000F }, + { DENALI_CTL_271, 0x00000000 }, + { DENALI_CTL_272, 0x030FFFFF }, + { DENALI_CTL_273, 0xFFFFFFFF }, + { DENALI_CTL_274, 0x000F000F }, + { DENALI_CTL_275, 0x00000000 }, + { DENALI_CTL_276, 0x030FFFFF }, + { DENALI_CTL_277, 0xFFFFFFFF }, + { DENALI_CTL_278, 0x000F000F }, + { DENALI_CTL_279, 0x00000000 }, + { DENALI_CTL_280, 0x030FFFFF }, + { DENALI_CTL_281, 0xFFFFFFFF }, + { DENALI_CTL_282, 0x000F000F }, + { DENALI_CTL_283, 0x00000000 }, + { DENALI_CTL_284, 0x030FFFFF }, + { DENALI_CTL_285, 0xFFFFFFFF }, + { DENALI_CTL_286, 0x000F000F }, + { DENALI_CTL_287, 0x00000000 }, + { DENALI_CTL_288, 0x030FFFFF }, + { DENALI_CTL_289, 0xFFFFFFFF }, + { DENALI_CTL_290, 0x000F000F }, + { DENALI_CTL_291, 0x00000000 }, + { DENALI_CTL_292, 0x030FFFFF }, + { DENALI_CTL_293, 0xFFFFFFFF }, + { DENALI_CTL_294, 0x000F000F }, + { DENALI_CTL_295, 0x00000000 }, + { DENALI_CTL_296, 0x030FFFFF }, + { DENALI_CTL_297, 0xFFFFFFFF }, + { DENALI_CTL_298, 0x000F000F }, + { DENALI_CTL_299, 0x00000000 }, + { DENALI_CTL_300, 0x030FFFFF }, + { DENALI_CTL_301, 0xFFFFFFFF }, + { DENALI_CTL_302, 0x000F000F }, + { DENALI_CTL_303, 0x00000000 }, + { DENALI_CTL_304, 0x030FFFFF }, + { DENALI_CTL_305, 0xFFFFFFFF }, + { DENALI_CTL_306, 0x000F000F }, + { DENALI_CTL_307, 0x00000000 }, + { DENALI_CTL_308, 0x030FFFFF }, + { DENALI_CTL_309, 0xFFFFFFFF }, + { DENALI_CTL_310, 0x000F000F }, + { DENALI_CTL_311, 0x00000000 }, + { DENALI_CTL_312, 0x000FFFFF }, + { DENALI_CTL_313, 0xFFFFFFFF }, + { DENALI_CTL_314, 0x000F000F }, + { DENALI_CTL_315, 0x00000000 }, + { DENALI_CTL_316, 0x030FFFFF }, + { DENALI_CTL_317, 0xFFFFFFFF }, + { DENALI_CTL_318, 0x000F000F }, + { DENALI_CTL_319, 0x00000000 }, + { DENALI_CTL_320, 0x030FFFFF }, + { DENALI_CTL_321, 0xFFFFFFFF }, + { DENALI_CTL_322, 0x000F000F }, + { DENALI_CTL_323, 0x00000000 }, + { DENALI_CTL_324, 0x030FFFFF }, + { DENALI_CTL_325, 0xFFFFFFFF }, + { DENALI_CTL_326, 0x000F000F }, + { DENALI_CTL_327, 0x00000000 }, + { DENALI_CTL_328, 0x030FFFFF }, + { DENALI_CTL_329, 0xFFFFFFFF }, + { DENALI_CTL_330, 0x000F000F }, + { DENALI_CTL_331, 0x00000000 }, + { DENALI_CTL_332, 0x030FFFFF }, + { DENALI_CTL_333, 0xFFFFFFFF }, + { DENALI_CTL_334, 0x000F000F }, + { DENALI_CTL_335, 0x00000000 }, + { DENALI_CTL_336, 0x030FFFFF }, + { DENALI_CTL_337, 0xFFFFFFFF }, + { DENALI_CTL_338, 0x000F000F }, + { DENALI_CTL_339, 0x00000000 }, + { DENALI_CTL_340, 0x030FFFFF }, + { DENALI_CTL_341, 0xFFFFFFFF }, + { DENALI_CTL_342, 0x000F000F }, + { DENALI_CTL_343, 0x00000000 }, + { DENALI_CTL_344, 0x030FFFFF }, + { DENALI_CTL_345, 0xFFFFFFFF }, + { DENALI_CTL_346, 0x000F000F }, + { DENALI_CTL_347, 0x00000000 }, + { DENALI_CTL_348, 0x030FFFFF }, + { DENALI_CTL_349, 0xFFFFFFFF }, + { DENALI_CTL_350, 0x000F000F }, + { DENALI_CTL_351, 0x00000000 }, + { DENALI_CTL_352, 0x030FFFFF }, + { DENALI_CTL_353, 0xFFFFFFFF }, + { DENALI_CTL_354, 0x000F000F }, + { DENALI_CTL_355, 0x00000000 }, + { DENALI_CTL_356, 0x030FFFFF }, + { DENALI_CTL_357, 0xFFFFFFFF }, + { DENALI_CTL_358, 0x000F000F }, + { DENALI_CTL_359, 0x00000000 }, + { DENALI_CTL_360, 0x030FFFFF }, + { DENALI_CTL_361, 0xFFFFFFFF }, + { DENALI_CTL_362, 0x000F000F }, + { DENALI_CTL_363, 0x00000000 }, + { DENALI_CTL_364, 0x030FFFFF }, + { DENALI_CTL_365, 0xFFFFFFFF }, + { DENALI_CTL_366, 0x000F000F }, + { DENALI_CTL_367, 0x00000000 }, + { DENALI_CTL_368, 0x030FFFFF }, + { DENALI_CTL_369, 0xFFFFFFFF }, + { DENALI_CTL_370, 0x000F000F }, + { DENALI_CTL_371, 0x00000000 }, + { DENALI_CTL_372, 0x030FFFFF }, + { DENALI_CTL_373, 0xFFFFFFFF }, + { DENALI_CTL_374, 0x000F000F }, + { DENALI_CTL_375, 0x03000000 }, + { DENALI_CTL_376, 0x03030303 }, + { DENALI_CTL_377, 0x03030303 }, + { DENALI_CTL_378, 0x03030303 }, + { DENALI_CTL_379, 0x00030303 }, + { DENALI_CTL_380, 0x02020064 }, + { DENALI_CTL_381, 0x02020202 }, + { DENALI_CTL_382, 0x02020202 }, + { DENALI_CTL_383, 0x02020202 }, + { DENALI_CTL_384, 0x00010202 }, + { DENALI_CTL_385, 0x01010064 }, + { DENALI_CTL_386, 0x01010101 }, + { DENALI_CTL_387, 0x01010101 }, + { DENALI_CTL_388, 0x01010101 }, + { DENALI_CTL_389, 0x00020101 }, + { DENALI_CTL_390, 0x00000064 }, + { DENALI_CTL_391, 0x00000006 }, + { DENALI_CTL_392, 0x000007D0 }, + { DENALI_CTL_393, 0x00000032 }, + { DENALI_CTL_394, 0x00000200 }, + { DENALI_CTL_395, 0x00000200 }, + { DENALI_CTL_396, 0x00000000 }, + { DENALI_CTL_397, 0x00000000 }, + { DENALI_CTL_398, 0x01080205 }, + { DENALI_CTL_399, 0x00200106 }, + { DENALI_CTL_400, 0x00000000 }, + { DENALI_CTL_401, 0x0A000202 }, + { DENALI_CTL_402, 0x000C000A }, + { DENALI_CTL_403, 0x00000000 }, + { DENALI_CTL_404, 0x00000000 }, + { DENALI_CTL_405, 0x00000000 }, + { DENALI_CTL_406, 0x00000000 }, + { DENALI_CTL_407, 0x00000000 }, + { DENALI_CTL_408, 0x00000000 }, + { DENALI_CTL_409, 0x00000000 }, + { DENALI_CTL_410, 0x00000000 }, + { DENALI_CTL_411, 0x00000000 }, + { DENALI_CTL_412, 0x0000000F }, + { DENALI_CTL_413, 0x017105DD }, + { DENALI_CTL_414, 0x4F6306E8 }, + { DENALI_CTL_415, 0x00002822 }, + { DENALI_CTL_416, 0x00003C22 }, + { DENALI_CTL_417, 0x00000000 }, + { DENALI_CTL_418, 0x00000000 }, + { DENALI_CTL_419, 0x00000000 }, + { DENALI_CTL_420, 0x00000000 }, + { DENALI_CTL_421, 0x00000000 }, + { DENALI_CTL_422, 0x00000000 }, + { DENALI_CTL_423, 0x00000000 }, + { DENALI_CTL_424, 0x00000000 }, + { DENALI_CTL_425, 0x00000000 }, + { DENALI_CTL_426, 0x00000000 }, + { DENALI_CTL_427, 0x00000000 }, + { DENALI_CTL_428, 0x00000000 }, + { DENALI_CTL_429, 0x00000000 }, + { DENALI_CTL_430, 0x00000000 }, + { DENALI_CTL_431, 0x00000000 }, + { DENALI_CTL_432, 0x00000000 }, + { DENALI_CTL_433, 0x00000000 }, + { DENALI_CTL_434, 0x00000000 }, + { DENALI_CTL_435, 0x00000000 } +}; diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/soc/a3ul/drivers/ddr/param_mc_C-011_D4-01-2.c b/drivers/rz/ipl/rza/plat/renesas/rz/soc/a3ul/drivers/ddr/param_mc_C-011_D4-01-2.c new file mode 100644 index 00000000..af241132 --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/soc/a3ul/drivers/ddr/param_mc_C-011_D4-01-2.c @@ -0,0 +1,449 @@ +/* + * Copyright (c) 2020-2022, Renesas Electronics Corporation. All rights reserved. + * SPDX-License-Identifier: BSD-3-Clause + * This code was generated with RZ/G2L, G2UL, Five, A3UL DDR config generation tool v3.0.0 + */ + +#include +#include + +const char ddr_an_version[] = "v3.0.0"; + +const uint32_t mc_init_tbl[MC_INIT_NUM][2] = { + { DENALI_CTL_00, 0x00000A00 }, + { DENALI_CTL_01, 0x00000000 }, + { DENALI_CTL_02, 0x00000000 }, + { DENALI_CTL_03, 0x00000000 }, + { DENALI_CTL_04, 0x00000000 }, + { DENALI_CTL_05, 0x00000000 }, + { DENALI_CTL_06, 0x00000000 }, + { DENALI_CTL_07, 0x00000000 }, + { DENALI_CTL_08, 0x00000000 }, + { DENALI_CTL_09, 0x00000000 }, + { DENALI_CTL_10, 0x01000008 }, + { DENALI_CTL_11, 0x00100100 }, + { DENALI_CTL_12, 0x00027100 }, + { DENALI_CTL_13, 0x00061A80 }, + { DENALI_CTL_14, 0x09180255 }, + { DENALI_CTL_15, 0x18180000 }, + { DENALI_CTL_16, 0x05050404 }, + { DENALI_CTL_17, 0x00002806 }, + { DENALI_CTL_18, 0x0602001C }, + { DENALI_CTL_19, 0x06001C0C }, + { DENALI_CTL_20, 0x00180806 }, + { DENALI_CTL_21, 0x0400DB60 }, + { DENALI_CTL_22, 0x00030305 }, + { DENALI_CTL_23, 0x01000C0C }, + { DENALI_CTL_24, 0x0C031801 }, + { DENALI_CTL_25, 0x0100000C }, + { DENALI_CTL_26, 0x00000101 }, + { DENALI_CTL_27, 0x00000000 }, + { DENALI_CTL_28, 0x00000000 }, + { DENALI_CTL_29, 0x00040301 }, + { DENALI_CTL_30, 0x00000118 }, + { DENALI_CTL_31, 0x00001860 }, + { DENALI_CTL_32, 0x00000005 }, + { DENALI_CTL_33, 0x00140005 }, + { DENALI_CTL_34, 0x01200255 }, + { DENALI_CTL_35, 0x00000120 }, + { DENALI_CTL_36, 0x01000201 }, + { DENALI_CTL_37, 0x80104002 }, + { DENALI_CTL_38, 0x00000000 }, + { DENALI_CTL_39, 0x00040000 }, + { DENALI_CTL_40, 0x00000000 }, + { DENALI_CTL_41, 0x00061800 }, + { DENALI_CTL_42, 0x000007D0 }, + { DENALI_CTL_43, 0x00061800 }, + { DENALI_CTL_44, 0x00061800 }, + { DENALI_CTL_45, 0x00061800 }, + { DENALI_CTL_46, 0x00000000 }, + { DENALI_CTL_47, 0x01000000 }, + { DENALI_CTL_48, 0x00000000 }, + { DENALI_CTL_49, 0x00000000 }, + { DENALI_CTL_50, 0x00000000 }, + { DENALI_CTL_51, 0x00000000 }, + { DENALI_CTL_52, 0x00000000 }, + { DENALI_CTL_53, 0x00000000 }, + { DENALI_CTL_54, 0x00000000 }, + { DENALI_CTL_55, 0x00212100 }, + { DENALI_CTL_56, 0x09070000 }, + { DENALI_CTL_57, 0x2F0E010A }, + { DENALI_CTL_58, 0x00000300 }, + { DENALI_CTL_59, 0x00010004 }, + { DENALI_CTL_60, 0x00000800 }, + { DENALI_CTL_61, 0x00000000 }, + { DENALI_CTL_62, 0x00000000 }, + { DENALI_CTL_63, 0x00000000 }, + { DENALI_CTL_64, 0x00000100 }, + { DENALI_CTL_65, 0x00000200 }, + { DENALI_CTL_66, 0x00001000 }, + { DENALI_CTL_67, 0x00000000 }, + { DENALI_CTL_68, 0x00000000 }, + { DENALI_CTL_69, 0x00000214 }, + { DENALI_CTL_70, 0x00000101 }, + { DENALI_CTL_71, 0x00000000 }, + { DENALI_CTL_72, 0x00000214 }, + { DENALI_CTL_73, 0x00000101 }, + { DENALI_CTL_74, 0x00000000 }, + { DENALI_CTL_75, 0x00000000 }, + { DENALI_CTL_76, 0x00000000 }, + { DENALI_CTL_77, 0x00000000 }, + { DENALI_CTL_78, 0x00000000 }, + { DENALI_CTL_79, 0x00000000 }, + { DENALI_CTL_80, 0x00000000 }, + { DENALI_CTL_81, 0x00000080 }, + { DENALI_CTL_82, 0x00000080 }, + { DENALI_CTL_83, 0x0000040F }, + { DENALI_CTL_84, 0x0000040F }, + { DENALI_CTL_85, 0x01010000 }, + { DENALI_CTL_86, 0x00000000 }, + { DENALI_CTL_87, 0x00000000 }, + { DENALI_CTL_88, 0x00000000 }, + { DENALI_CTL_89, 0x00000000 }, + { DENALI_CTL_90, 0x00000000 }, + { DENALI_CTL_91, 0x00000000 }, + { DENALI_CTL_92, 0x00000000 }, + { DENALI_CTL_93, 0x00000000 }, + { DENALI_CTL_94, 0x00000000 }, + { DENALI_CTL_95, 0x01000200 }, + { DENALI_CTL_96, 0x00010801 }, + { DENALI_CTL_97, 0x00000000 }, + { DENALI_CTL_98, 0x00000000 }, + { DENALI_CTL_99, 0x00000000 }, + { DENALI_CTL_100, 0x00000000 }, + { DENALI_CTL_101, 0x00000000 }, + { DENALI_CTL_102, 0x00000000 }, + { DENALI_CTL_103, 0x00000000 }, + { DENALI_CTL_104, 0x00000000 }, + { DENALI_CTL_105, 0x00000000 }, + { DENALI_CTL_106, 0x00000000 }, + { DENALI_CTL_107, 0x00000000 }, + { DENALI_CTL_108, 0x00000000 }, + { DENALI_CTL_109, 0x00000000 }, + { DENALI_CTL_110, 0x00000008 }, + { DENALI_CTL_111, 0x006403E8 }, + { DENALI_CTL_112, 0x00000000 }, + { DENALI_CTL_113, 0x00000000 }, + { DENALI_CTL_114, 0x00000000 }, + { DENALI_CTL_115, 0x15110000 }, + { DENALI_CTL_116, 0x00040C18 }, + { DENALI_CTL_117, 0x00BEBD03 }, + { DENALI_CTL_118, 0x0000C350 }, + { DENALI_CTL_119, 0x00000000 }, + { DENALI_CTL_120, 0x02000400 }, + { DENALI_CTL_121, 0x00000080 }, + { DENALI_CTL_122, 0x01010100 }, + { DENALI_CTL_123, 0x00010101 }, + { DENALI_CTL_124, 0x0FFF0000 }, + { DENALI_CTL_125, 0x0001FF00 }, + { DENALI_CTL_126, 0xFFFFFFFF }, + { DENALI_CTL_127, 0x00FFFF00 }, + { DENALI_CTL_128, 0xFFFF0A00 }, + { DENALI_CTL_129, 0x01010001 }, + { DENALI_CTL_130, 0x01010101 }, + { DENALI_CTL_131, 0x01030101 }, + { DENALI_CTL_132, 0x0C010000 }, + { DENALI_CTL_133, 0x01000000 }, + { DENALI_CTL_134, 0x00000000 }, + { DENALI_CTL_135, 0x00010000 }, + { DENALI_CTL_136, 0x00000000 }, + { DENALI_CTL_137, 0x00000001 }, + { DENALI_CTL_138, 0x00000000 }, + { DENALI_CTL_139, 0x00000000 }, + { DENALI_CTL_140, 0x00000000 }, + { DENALI_CTL_141, 0x00000000 }, + { DENALI_CTL_142, 0x00000000 }, + { DENALI_CTL_143, 0x00000000 }, + { DENALI_CTL_144, 0x00000000 }, + { DENALI_CTL_145, 0x00000000 }, + { DENALI_CTL_146, 0x00000000 }, + { DENALI_CTL_147, 0x00000000 }, + { DENALI_CTL_148, 0x00000000 }, + { DENALI_CTL_149, 0x00000000 }, + { DENALI_CTL_150, 0x00000000 }, + { DENALI_CTL_151, 0x00000000 }, + { DENALI_CTL_152, 0x00000000 }, + { DENALI_CTL_153, 0x00000000 }, + { DENALI_CTL_154, 0x00000000 }, + { DENALI_CTL_155, 0x00000000 }, + { DENALI_CTL_156, 0x00000000 }, + { DENALI_CTL_157, 0x00010000 }, + { DENALI_CTL_158, 0x00000000 }, + { DENALI_CTL_159, 0x00000800 }, + { DENALI_CTL_160, 0x00000000 }, + { DENALI_CTL_161, 0x00000898 }, + { DENALI_CTL_162, 0x03000000 }, + { DENALI_CTL_163, 0x00000408 }, + { DENALI_CTL_164, 0x00000000 }, + { DENALI_CTL_165, 0x00000000 }, + { DENALI_CTL_166, 0x00000000 }, + { DENALI_CTL_167, 0x00000000 }, + { DENALI_CTL_168, 0x00000000 }, + { DENALI_CTL_169, 0x00000000 }, + { DENALI_CTL_170, 0x00000000 }, + { DENALI_CTL_171, 0x00000000 }, + { DENALI_CTL_172, 0x00000000 }, + { DENALI_CTL_173, 0x00000000 }, + { DENALI_CTL_174, 0x00000000 }, + { DENALI_CTL_175, 0x06060800 }, + { DENALI_CTL_176, 0x01000001 }, + { DENALI_CTL_177, 0x01030000 }, + { DENALI_CTL_178, 0x03000302 }, + { DENALI_CTL_179, 0x00000000 }, + { DENALI_CTL_180, 0x00080801 }, + { DENALI_CTL_181, 0x00080801 }, + { DENALI_CTL_182, 0x00070601 }, + { DENALI_CTL_183, 0x00000000 }, + { DENALI_CTL_184, 0x000FFFFF }, + { DENALI_CTL_185, 0xFFFFFFFF }, + { DENALI_CTL_186, 0x000F000F }, + { DENALI_CTL_187, 0x00000000 }, + { DENALI_CTL_188, 0x030FFFFF }, + { DENALI_CTL_189, 0xFFFFFFFF }, + { DENALI_CTL_190, 0x000F000F }, + { DENALI_CTL_191, 0x00000000 }, + { DENALI_CTL_192, 0x030FFFFF }, + { DENALI_CTL_193, 0xFFFFFFFF }, + { DENALI_CTL_194, 0x000F000F }, + { DENALI_CTL_195, 0x00000000 }, + { DENALI_CTL_196, 0x030FFFFF }, + { DENALI_CTL_197, 0xFFFFFFFF }, + { DENALI_CTL_198, 0x000F000F }, + { DENALI_CTL_199, 0x00000000 }, + { DENALI_CTL_200, 0x030FFFFF }, + { DENALI_CTL_201, 0xFFFFFFFF }, + { DENALI_CTL_202, 0x000F000F }, + { DENALI_CTL_203, 0x00000000 }, + { DENALI_CTL_204, 0x030FFFFF }, + { DENALI_CTL_205, 0xFFFFFFFF }, + { DENALI_CTL_206, 0x000F000F }, + { DENALI_CTL_207, 0x00000000 }, + { DENALI_CTL_208, 0x030FFFFF }, + { DENALI_CTL_209, 0xFFFFFFFF }, + { DENALI_CTL_210, 0x000F000F }, + { DENALI_CTL_211, 0x00000000 }, + { DENALI_CTL_212, 0x030FFFFF }, + { DENALI_CTL_213, 0xFFFFFFFF }, + { DENALI_CTL_214, 0x000F000F }, + { DENALI_CTL_215, 0x00000000 }, + { DENALI_CTL_216, 0x030FFFFF }, + { DENALI_CTL_217, 0xFFFFFFFF }, + { DENALI_CTL_218, 0x000F000F }, + { DENALI_CTL_219, 0x00000000 }, + { DENALI_CTL_220, 0x030FFFFF }, + { DENALI_CTL_221, 0xFFFFFFFF }, + { DENALI_CTL_222, 0x000F000F }, + { DENALI_CTL_223, 0x00000000 }, + { DENALI_CTL_224, 0x030FFFFF }, + { DENALI_CTL_225, 0xFFFFFFFF }, + { DENALI_CTL_226, 0x000F000F }, + { DENALI_CTL_227, 0x00000000 }, + { DENALI_CTL_228, 0x030FFFFF }, + { DENALI_CTL_229, 0xFFFFFFFF }, + { DENALI_CTL_230, 0x000F000F }, + { DENALI_CTL_231, 0x00000000 }, + { DENALI_CTL_232, 0x030FFFFF }, + { DENALI_CTL_233, 0xFFFFFFFF }, + { DENALI_CTL_234, 0x000F000F }, + { DENALI_CTL_235, 0x00000000 }, + { DENALI_CTL_236, 0x030FFFFF }, + { DENALI_CTL_237, 0xFFFFFFFF }, + { DENALI_CTL_238, 0x000F000F }, + { DENALI_CTL_239, 0x00000000 }, + { DENALI_CTL_240, 0x030FFFFF }, + { DENALI_CTL_241, 0xFFFFFFFF }, + { DENALI_CTL_242, 0x000F000F }, + { DENALI_CTL_243, 0x00000000 }, + { DENALI_CTL_244, 0x030FFFFF }, + { DENALI_CTL_245, 0xFFFFFFFF }, + { DENALI_CTL_246, 0x000F000F }, + { DENALI_CTL_247, 0x00000000 }, + { DENALI_CTL_248, 0x000FFFFF }, + { DENALI_CTL_249, 0xFFFFFFFF }, + { DENALI_CTL_250, 0x000F000F }, + { DENALI_CTL_251, 0x00000000 }, + { DENALI_CTL_252, 0x030FFFFF }, + { DENALI_CTL_253, 0xFFFFFFFF }, + { DENALI_CTL_254, 0x000F000F }, + { DENALI_CTL_255, 0x00000000 }, + { DENALI_CTL_256, 0x030FFFFF }, + { DENALI_CTL_257, 0xFFFFFFFF }, + { DENALI_CTL_258, 0x000F000F }, + { DENALI_CTL_259, 0x00000000 }, + { DENALI_CTL_260, 0x030FFFFF }, + { DENALI_CTL_261, 0xFFFFFFFF }, + { DENALI_CTL_262, 0x000F000F }, + { DENALI_CTL_263, 0x00000000 }, + { DENALI_CTL_264, 0x030FFFFF }, + { DENALI_CTL_265, 0xFFFFFFFF }, + { DENALI_CTL_266, 0x000F000F }, + { DENALI_CTL_267, 0x00000000 }, + { DENALI_CTL_268, 0x030FFFFF }, + { DENALI_CTL_269, 0xFFFFFFFF }, + { DENALI_CTL_270, 0x000F000F }, + { DENALI_CTL_271, 0x00000000 }, + { DENALI_CTL_272, 0x030FFFFF }, + { DENALI_CTL_273, 0xFFFFFFFF }, + { DENALI_CTL_274, 0x000F000F }, + { DENALI_CTL_275, 0x00000000 }, + { DENALI_CTL_276, 0x030FFFFF }, + { DENALI_CTL_277, 0xFFFFFFFF }, + { DENALI_CTL_278, 0x000F000F }, + { DENALI_CTL_279, 0x00000000 }, + { DENALI_CTL_280, 0x030FFFFF }, + { DENALI_CTL_281, 0xFFFFFFFF }, + { DENALI_CTL_282, 0x000F000F }, + { DENALI_CTL_283, 0x00000000 }, + { DENALI_CTL_284, 0x030FFFFF }, + { DENALI_CTL_285, 0xFFFFFFFF }, + { DENALI_CTL_286, 0x000F000F }, + { DENALI_CTL_287, 0x00000000 }, + { DENALI_CTL_288, 0x030FFFFF }, + { DENALI_CTL_289, 0xFFFFFFFF }, + { DENALI_CTL_290, 0x000F000F }, + { DENALI_CTL_291, 0x00000000 }, + { DENALI_CTL_292, 0x030FFFFF }, + { DENALI_CTL_293, 0xFFFFFFFF }, + { DENALI_CTL_294, 0x000F000F }, + { DENALI_CTL_295, 0x00000000 }, + { DENALI_CTL_296, 0x030FFFFF }, + { DENALI_CTL_297, 0xFFFFFFFF }, + { DENALI_CTL_298, 0x000F000F }, + { DENALI_CTL_299, 0x00000000 }, + { DENALI_CTL_300, 0x030FFFFF }, + { DENALI_CTL_301, 0xFFFFFFFF }, + { DENALI_CTL_302, 0x000F000F }, + { DENALI_CTL_303, 0x00000000 }, + { DENALI_CTL_304, 0x030FFFFF }, + { DENALI_CTL_305, 0xFFFFFFFF }, + { DENALI_CTL_306, 0x000F000F }, + { DENALI_CTL_307, 0x00000000 }, + { DENALI_CTL_308, 0x030FFFFF }, + { DENALI_CTL_309, 0xFFFFFFFF }, + { DENALI_CTL_310, 0x000F000F }, + { DENALI_CTL_311, 0x00000000 }, + { DENALI_CTL_312, 0x000FFFFF }, + { DENALI_CTL_313, 0xFFFFFFFF }, + { DENALI_CTL_314, 0x000F000F }, + { DENALI_CTL_315, 0x00000000 }, + { DENALI_CTL_316, 0x030FFFFF }, + { DENALI_CTL_317, 0xFFFFFFFF }, + { DENALI_CTL_318, 0x000F000F }, + { DENALI_CTL_319, 0x00000000 }, + { DENALI_CTL_320, 0x030FFFFF }, + { DENALI_CTL_321, 0xFFFFFFFF }, + { DENALI_CTL_322, 0x000F000F }, + { DENALI_CTL_323, 0x00000000 }, + { DENALI_CTL_324, 0x030FFFFF }, + { DENALI_CTL_325, 0xFFFFFFFF }, + { DENALI_CTL_326, 0x000F000F }, + { DENALI_CTL_327, 0x00000000 }, + { DENALI_CTL_328, 0x030FFFFF }, + { DENALI_CTL_329, 0xFFFFFFFF }, + { DENALI_CTL_330, 0x000F000F }, + { DENALI_CTL_331, 0x00000000 }, + { DENALI_CTL_332, 0x030FFFFF }, + { DENALI_CTL_333, 0xFFFFFFFF }, + { DENALI_CTL_334, 0x000F000F }, + { DENALI_CTL_335, 0x00000000 }, + { DENALI_CTL_336, 0x030FFFFF }, + { DENALI_CTL_337, 0xFFFFFFFF }, + { DENALI_CTL_338, 0x000F000F }, + { DENALI_CTL_339, 0x00000000 }, + { DENALI_CTL_340, 0x030FFFFF }, + { DENALI_CTL_341, 0xFFFFFFFF }, + { DENALI_CTL_342, 0x000F000F }, + { DENALI_CTL_343, 0x00000000 }, + { DENALI_CTL_344, 0x030FFFFF }, + { DENALI_CTL_345, 0xFFFFFFFF }, + { DENALI_CTL_346, 0x000F000F }, + { DENALI_CTL_347, 0x00000000 }, + { DENALI_CTL_348, 0x030FFFFF }, + { DENALI_CTL_349, 0xFFFFFFFF }, + { DENALI_CTL_350, 0x000F000F }, + { DENALI_CTL_351, 0x00000000 }, + { DENALI_CTL_352, 0x030FFFFF }, + { DENALI_CTL_353, 0xFFFFFFFF }, + { DENALI_CTL_354, 0x000F000F }, + { DENALI_CTL_355, 0x00000000 }, + { DENALI_CTL_356, 0x030FFFFF }, + { DENALI_CTL_357, 0xFFFFFFFF }, + { DENALI_CTL_358, 0x000F000F }, + { DENALI_CTL_359, 0x00000000 }, + { DENALI_CTL_360, 0x030FFFFF }, + { DENALI_CTL_361, 0xFFFFFFFF }, + { DENALI_CTL_362, 0x000F000F }, + { DENALI_CTL_363, 0x00000000 }, + { DENALI_CTL_364, 0x030FFFFF }, + { DENALI_CTL_365, 0xFFFFFFFF }, + { DENALI_CTL_366, 0x000F000F }, + { DENALI_CTL_367, 0x00000000 }, + { DENALI_CTL_368, 0x030FFFFF }, + { DENALI_CTL_369, 0xFFFFFFFF }, + { DENALI_CTL_370, 0x000F000F }, + { DENALI_CTL_371, 0x00000000 }, + { DENALI_CTL_372, 0x030FFFFF }, + { DENALI_CTL_373, 0xFFFFFFFF }, + { DENALI_CTL_374, 0x000F000F }, + { DENALI_CTL_375, 0x03000000 }, + { DENALI_CTL_376, 0x03030303 }, + { DENALI_CTL_377, 0x03030303 }, + { DENALI_CTL_378, 0x03030303 }, + { DENALI_CTL_379, 0x00030303 }, + { DENALI_CTL_380, 0x02020064 }, + { DENALI_CTL_381, 0x02020202 }, + { DENALI_CTL_382, 0x02020202 }, + { DENALI_CTL_383, 0x02020202 }, + { DENALI_CTL_384, 0x00010202 }, + { DENALI_CTL_385, 0x01010064 }, + { DENALI_CTL_386, 0x01010101 }, + { DENALI_CTL_387, 0x01010101 }, + { DENALI_CTL_388, 0x01010101 }, + { DENALI_CTL_389, 0x00020101 }, + { DENALI_CTL_390, 0x00000064 }, + { DENALI_CTL_391, 0x00000006 }, + { DENALI_CTL_392, 0x000007D0 }, + { DENALI_CTL_393, 0x00000032 }, + { DENALI_CTL_394, 0x00000200 }, + { DENALI_CTL_395, 0x00000200 }, + { DENALI_CTL_396, 0x00000000 }, + { DENALI_CTL_397, 0x00000000 }, + { DENALI_CTL_398, 0x030B0205 }, + { DENALI_CTL_399, 0x00200308 }, + { DENALI_CTL_400, 0x00000000 }, + { DENALI_CTL_401, 0x0A000202 }, + { DENALI_CTL_402, 0x000C000A }, + { DENALI_CTL_403, 0x00000000 }, + { DENALI_CTL_404, 0x00000000 }, + { DENALI_CTL_405, 0x00000000 }, + { DENALI_CTL_406, 0x00000000 }, + { DENALI_CTL_407, 0x00000000 }, + { DENALI_CTL_408, 0x00000000 }, + { DENALI_CTL_409, 0x00000000 }, + { DENALI_CTL_410, 0x00000000 }, + { DENALI_CTL_411, 0x00000000 }, + { DENALI_CTL_412, 0x0000000F }, + { DENALI_CTL_413, 0x037204E2 }, + { DENALI_CTL_414, 0x57630BB8 }, + { DENALI_CTL_415, 0x00002828 }, + { DENALI_CTL_416, 0x00003C22 }, + { DENALI_CTL_417, 0x00102611 }, + { DENALI_CTL_418, 0x00000000 }, + { DENALI_CTL_419, 0x00000000 }, + { DENALI_CTL_420, 0x00000000 }, + { DENALI_CTL_421, 0x00000000 }, + { DENALI_CTL_422, 0x00000000 }, + { DENALI_CTL_423, 0x00000000 }, + { DENALI_CTL_424, 0x00000000 }, + { DENALI_CTL_425, 0x00000000 }, + { DENALI_CTL_426, 0x00000000 }, + { DENALI_CTL_427, 0x00000000 }, + { DENALI_CTL_428, 0x00000000 }, + { DENALI_CTL_429, 0x00000000 }, + { DENALI_CTL_430, 0x00000000 }, + { DENALI_CTL_431, 0x00000000 }, + { DENALI_CTL_432, 0x00000000 }, + { DENALI_CTL_433, 0x00000000 }, + { DENALI_CTL_434, 0x00000000 }, + { DENALI_CTL_435, 0x00000000 } +}; diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/soc/a3ul/drivers/xspi.c b/drivers/rz/ipl/rza/plat/renesas/rz/soc/a3ul/drivers/xspi.c new file mode 100644 index 00000000..bcf5add0 --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/soc/a3ul/drivers/xspi.c @@ -0,0 +1,68 @@ +#include +#include +#include +#include +#include + +static int sub_init_xip(const xspidevice_instance_t *inst) +{ + int result; + result = inst->api->open(inst->ctrl, inst->cfg); + if (!result) { + result = inst->api->enter_xip(inst->ctrl); + inst->api->close(inst->ctrl); + } + return result; +} + +static int sub_post_init_xip(const xspi_instance_t *xspi) +{ + int result; + result = xspi->api->open(xspi->ctrl, xspi->cfg); + if (!result) { + xspi->api->enable_auto_calibration(xspi->ctrl); + result = xspi->api->post_init(xspi->ctrl); + xspi->api->close(xspi->ctrl); + } + return result; +} + +void xspi_setup(void) +{ + int i; + int result = 0; + +#ifdef XSPI_DEVICE_TYPE + RZA_PRINTF("Configure %s Flash Memory\n", XSPI_DEVICE_TYPE); +#endif + for (i = 0; result >= 0 && i < xspidevices_count; i++) { + result = sub_init_xip(xspidevices[i]); + if (result < 0) { + ERROR("xspi.c: abort on sub_init_xip (#%d)\n", i); + panic(); + } + } + for (i = 0; result >= 0 && i < xspidevices_count; i++) { + result = sub_post_init_xip(xspidevices[i]->cfg->xspi); + if (result < 0) { + ERROR("xspi.c: abort on sub_post_init_xip (#%d)\n", i); + panic(); + } + } +} + +/** + * memcpy for xspi + */ +int rz_xspi_read(void* to, uint64_t offset, size_t length) { + int result; + const xspidevice_instance_t *inst = xspidevices[0]; + if (!inst) return -1; + + result = inst->api->open(inst->ctrl, inst->cfg); + if (!result) { + inst->api->read(inst->ctrl, to, (size_t)offset, length); + inst->api->close(inst->ctrl); + } + return result; +} diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/soc/a3ul/include/cpg_opt.h b/drivers/rz/ipl/rza/plat/renesas/rz/soc/a3ul/include/cpg_opt.h new file mode 100644 index 00000000..5ebd116f --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/soc/a3ul/include/cpg_opt.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __CPG_OPT_H__ +#define __CPG_OPT_H__ + +#define CPG_RST_DDR_OPT_VALUE (0x00000000) + +#endif // __CPG_OPT_H__ diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/soc/a3ul/include/ddr_mc_if.h b/drivers/rz/ipl/rza/plat/renesas/rz/soc/a3ul/include/ddr_mc_if.h new file mode 100644 index 00000000..ad1d0ade --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/soc/a3ul/include/ddr_mc_if.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __DDR_MC_IF_H__ +#define __DDR_MC_IF_H__ + +#include + +#define MC_INIT_NUM (436) + +#define LP_CMD_OFFSET (0) + +#define DDRMC_R000 DENALI_CTL_00 +#define DDRMC_R001 DENALI_CTL_11 +#define DDRMC_R002 DENALI_CTL_14 +#define DDRMC_R003 DENALI_CTL_15 +#define DDRMC_R004 DENALI_CTL_56 +#define DDRMC_R005 DENALI_CTL_59 +#define DDRMC_R006 DENALI_CTL_60 +#define DDRMC_R007 DENALI_CTL_64 +#define DDRMC_R008 DENALI_CTL_67 +#define DDRMC_R009 DENALI_CTL_70 +#define DDRMC_R010 DENALI_CTL_71 +#define DDRMC_R011 DENALI_CTL_73 +#define DDRMC_R012 DENALI_CTL_74 +#define DDRMC_R013 DENALI_CTL_75 +#define DDRMC_R014 DENALI_CTL_76 +#define DDRMC_R015 DENALI_CTL_81 +#define DDRMC_R016 DENALI_CTL_82 +#define DDRMC_R017 DENALI_CTL_83 +#define DDRMC_R018 DENALI_CTL_84 +#define DDRMC_R019 DENALI_CTL_133 +#define DDRMC_R020 DENALI_CTL_134 +#define DDRMC_R021 DENALI_CTL_146 +#define DDRMC_R022 DENALI_CTL_147 +#define DDRMC_R023 DENALI_CTL_154 +#define DDRMC_R024 DENALI_CTL_155 +#define DDRMC_R025 DENALI_CTL_176 +#define DDRMC_R026 DENALI_CTL_177 +#define DDRMC_R027 DENALI_CTL_391 +#define DDRMC_R028 DENALI_CTL_398 +#define DDRMC_R029 DENALI_CTL_401 +#define DDRMC_R030 DENALI_CTL_403 +#define DDRMC_R031 DENALI_CTL_404 +#define DDRMC_R032 DENALI_CTL_405 +#define DDRMC_R033 DENALI_CTL_406 +#define DDRMC_R034 DENALI_CTL_407 +#define DDRMC_R035 DENALI_CTL_408 +#define DDRMC_R036 DENALI_CTL_409 +#define DDRMC_R037 DENALI_CTL_410 +#define DDRMC_R038 DENALI_CTL_411 +#define DDRMC_R039 DENALI_CTL_413 +#define DDRMC_R040 DENALI_CTL_414 +#define DDRMC_R041 DENALI_CTL_415 +#define DDRMC_R042 DENALI_CTL_416 +#define DDRMC_R043 DENALI_CTL_417 +#define DDRMC_R044 DENALI_CTL_418 + +#endif // __DDR_MC_IF_H__ diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/soc/a3ul/include/ddr_mc_regs.h b/drivers/rz/ipl/rza/plat/renesas/rz/soc/a3ul/include/ddr_mc_regs.h new file mode 100644 index 00000000..5c350dc5 --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/soc/a3ul/include/ddr_mc_regs.h @@ -0,0 +1,452 @@ +/* + * Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __DDR_MC_REGS_H__ +#define __DDR_MC_REGS_H__ + +#include + +#define DDR_MC_BASE RZG2L_DDR_MEMC_BASE +#define MC_INIT_NUM (436) + +#define DENALI_CTL_00 (0x0000) +#define DENALI_CTL_01 (0x0004) +#define DENALI_CTL_02 (0x0008) +#define DENALI_CTL_03 (0x000C) +#define DENALI_CTL_04 (0x0010) +#define DENALI_CTL_05 (0x0014) +#define DENALI_CTL_06 (0x0018) +#define DENALI_CTL_07 (0x001C) +#define DENALI_CTL_08 (0x0020) +#define DENALI_CTL_09 (0x0024) +#define DENALI_CTL_10 (0x0028) +#define DENALI_CTL_11 (0x002C) +#define DENALI_CTL_12 (0x0030) +#define DENALI_CTL_13 (0x0034) +#define DENALI_CTL_14 (0x0038) +#define DENALI_CTL_15 (0x003C) +#define DENALI_CTL_16 (0x0040) +#define DENALI_CTL_17 (0x0044) +#define DENALI_CTL_18 (0x0048) +#define DENALI_CTL_19 (0x004C) +#define DENALI_CTL_20 (0x0050) +#define DENALI_CTL_21 (0x0054) +#define DENALI_CTL_22 (0x0058) +#define DENALI_CTL_23 (0x005C) +#define DENALI_CTL_24 (0x0060) +#define DENALI_CTL_25 (0x0064) +#define DENALI_CTL_26 (0x0068) +#define DENALI_CTL_27 (0x006C) +#define DENALI_CTL_28 (0x0070) +#define DENALI_CTL_29 (0x0074) +#define DENALI_CTL_30 (0x0078) +#define DENALI_CTL_31 (0x007C) +#define DENALI_CTL_32 (0x0080) +#define DENALI_CTL_33 (0x0084) +#define DENALI_CTL_34 (0x0088) +#define DENALI_CTL_35 (0x008C) +#define DENALI_CTL_36 (0x0090) +#define DENALI_CTL_37 (0x0094) +#define DENALI_CTL_38 (0x0098) +#define DENALI_CTL_39 (0x009C) +#define DENALI_CTL_40 (0x00A0) +#define DENALI_CTL_41 (0x00A4) +#define DENALI_CTL_42 (0x00A8) +#define DENALI_CTL_43 (0x00AC) +#define DENALI_CTL_44 (0x00B0) +#define DENALI_CTL_45 (0x00B4) +#define DENALI_CTL_46 (0x00B8) +#define DENALI_CTL_47 (0x00BC) +#define DENALI_CTL_48 (0x00C0) +#define DENALI_CTL_49 (0x00C4) +#define DENALI_CTL_50 (0x00C8) +#define DENALI_CTL_51 (0x00CC) +#define DENALI_CTL_52 (0x00D0) +#define DENALI_CTL_53 (0x00D4) +#define DENALI_CTL_54 (0x00D8) +#define DENALI_CTL_55 (0x00DC) +#define DENALI_CTL_56 (0x00E0) +#define DENALI_CTL_57 (0x00E4) +#define DENALI_CTL_58 (0x00E8) +#define DENALI_CTL_59 (0x00EC) +#define DENALI_CTL_60 (0x00F0) +#define DENALI_CTL_61 (0x00F4) +#define DENALI_CTL_62 (0x00F8) +#define DENALI_CTL_63 (0x00FC) +#define DENALI_CTL_64 (0x0100) +#define DENALI_CTL_65 (0x0104) +#define DENALI_CTL_66 (0x0108) +#define DENALI_CTL_67 (0x010C) +#define DENALI_CTL_68 (0x0110) +#define DENALI_CTL_69 (0x0114) +#define DENALI_CTL_70 (0x0118) +#define DENALI_CTL_71 (0x011C) +#define DENALI_CTL_72 (0x0120) +#define DENALI_CTL_73 (0x0124) +#define DENALI_CTL_74 (0x0128) +#define DENALI_CTL_75 (0x012C) +#define DENALI_CTL_76 (0x0130) +#define DENALI_CTL_77 (0x0134) +#define DENALI_CTL_78 (0x0138) +#define DENALI_CTL_79 (0x013C) +#define DENALI_CTL_80 (0x0140) +#define DENALI_CTL_81 (0x0144) +#define DENALI_CTL_82 (0x0148) +#define DENALI_CTL_83 (0x014C) +#define DENALI_CTL_84 (0x0150) +#define DENALI_CTL_85 (0x0154) +#define DENALI_CTL_86 (0x0158) +#define DENALI_CTL_87 (0x015C) +#define DENALI_CTL_88 (0x0160) +#define DENALI_CTL_89 (0x0164) +#define DENALI_CTL_90 (0x0168) +#define DENALI_CTL_91 (0x016C) +#define DENALI_CTL_92 (0x0170) +#define DENALI_CTL_93 (0x0174) +#define DENALI_CTL_94 (0x0178) +#define DENALI_CTL_95 (0x017C) +#define DENALI_CTL_96 (0x0180) +#define DENALI_CTL_97 (0x0184) +#define DENALI_CTL_98 (0x0188) +#define DENALI_CTL_99 (0x018C) +#define DENALI_CTL_100 (0x0190) +#define DENALI_CTL_101 (0x0194) +#define DENALI_CTL_102 (0x0198) +#define DENALI_CTL_103 (0x019C) +#define DENALI_CTL_104 (0x01A0) +#define DENALI_CTL_105 (0x01A4) +#define DENALI_CTL_106 (0x01A8) +#define DENALI_CTL_107 (0x01AC) +#define DENALI_CTL_108 (0x01B0) +#define DENALI_CTL_109 (0x01B4) +#define DENALI_CTL_110 (0x01B8) +#define DENALI_CTL_111 (0x01BC) +#define DENALI_CTL_112 (0x01C0) +#define DENALI_CTL_113 (0x01C4) +#define DENALI_CTL_114 (0x01C8) +#define DENALI_CTL_115 (0x01CC) +#define DENALI_CTL_116 (0x01D0) +#define DENALI_CTL_117 (0x01D4) +#define DENALI_CTL_118 (0x01D8) +#define DENALI_CTL_119 (0x01DC) +#define DENALI_CTL_120 (0x01E0) +#define DENALI_CTL_121 (0x01E4) +#define DENALI_CTL_122 (0x01E8) +#define DENALI_CTL_123 (0x01EC) +#define DENALI_CTL_124 (0x01F0) +#define DENALI_CTL_125 (0x01F4) +#define DENALI_CTL_126 (0x01F8) +#define DENALI_CTL_127 (0x01FC) +#define DENALI_CTL_128 (0x0200) +#define DENALI_CTL_129 (0x0204) +#define DENALI_CTL_130 (0x0208) +#define DENALI_CTL_131 (0x020C) +#define DENALI_CTL_132 (0x0210) +#define DENALI_CTL_133 (0x0214) +#define DENALI_CTL_134 (0x0218) +#define DENALI_CTL_135 (0x021C) +#define DENALI_CTL_136 (0x0220) +#define DENALI_CTL_137 (0x0224) +#define DENALI_CTL_138 (0x0228) +#define DENALI_CTL_139 (0x022C) +#define DENALI_CTL_140 (0x0230) +#define DENALI_CTL_141 (0x0234) +#define DENALI_CTL_142 (0x0238) +#define DENALI_CTL_143 (0x023C) +#define DENALI_CTL_144 (0x0240) +#define DENALI_CTL_145 (0x0244) +#define DENALI_CTL_146 (0x0248) +#define DENALI_CTL_147 (0x024C) +#define DENALI_CTL_148 (0x0250) +#define DENALI_CTL_149 (0x0254) +#define DENALI_CTL_150 (0x0258) +#define DENALI_CTL_151 (0x025C) +#define DENALI_CTL_152 (0x0260) +#define DENALI_CTL_153 (0x0264) +#define DENALI_CTL_154 (0x0268) +#define DENALI_CTL_155 (0x026C) +#define DENALI_CTL_156 (0x0270) +#define DENALI_CTL_157 (0x0274) +#define DENALI_CTL_158 (0x0278) +#define DENALI_CTL_159 (0x027C) +#define DENALI_CTL_160 (0x0280) +#define DENALI_CTL_161 (0x0284) +#define DENALI_CTL_162 (0x0288) +#define DENALI_CTL_163 (0x028C) +#define DENALI_CTL_164 (0x0290) +#define DENALI_CTL_165 (0x0294) +#define DENALI_CTL_166 (0x0298) +#define DENALI_CTL_167 (0x029C) +#define DENALI_CTL_168 (0x02A0) +#define DENALI_CTL_169 (0x02A4) +#define DENALI_CTL_170 (0x02A8) +#define DENALI_CTL_171 (0x02AC) +#define DENALI_CTL_172 (0x02B0) +#define DENALI_CTL_173 (0x02B4) +#define DENALI_CTL_174 (0x02B8) +#define DENALI_CTL_175 (0x02BC) +#define DENALI_CTL_176 (0x02C0) +#define DENALI_CTL_177 (0x02C4) +#define DENALI_CTL_178 (0x02C8) +#define DENALI_CTL_179 (0x02CC) +#define DENALI_CTL_180 (0x02D0) +#define DENALI_CTL_181 (0x02D4) +#define DENALI_CTL_182 (0x02D8) +#define DENALI_CTL_183 (0x02DC) +#define DENALI_CTL_184 (0x02E0) +#define DENALI_CTL_185 (0x02E4) +#define DENALI_CTL_186 (0x02E8) +#define DENALI_CTL_187 (0x02EC) +#define DENALI_CTL_188 (0x02F0) +#define DENALI_CTL_189 (0x02F4) +#define DENALI_CTL_190 (0x02F8) +#define DENALI_CTL_191 (0x02FC) +#define DENALI_CTL_192 (0x0300) +#define DENALI_CTL_193 (0x0304) +#define DENALI_CTL_194 (0x0308) +#define DENALI_CTL_195 (0x030C) +#define DENALI_CTL_196 (0x0310) +#define DENALI_CTL_197 (0x0314) +#define DENALI_CTL_198 (0x0318) +#define DENALI_CTL_199 (0x031C) +#define DENALI_CTL_200 (0x0320) +#define DENALI_CTL_201 (0x0324) +#define DENALI_CTL_202 (0x0328) +#define DENALI_CTL_203 (0x032C) +#define DENALI_CTL_204 (0x0330) +#define DENALI_CTL_205 (0x0334) +#define DENALI_CTL_206 (0x0338) +#define DENALI_CTL_207 (0x033C) +#define DENALI_CTL_208 (0x0340) +#define DENALI_CTL_209 (0x0344) +#define DENALI_CTL_210 (0x0348) +#define DENALI_CTL_211 (0x034C) +#define DENALI_CTL_212 (0x0350) +#define DENALI_CTL_213 (0x0354) +#define DENALI_CTL_214 (0x0358) +#define DENALI_CTL_215 (0x035C) +#define DENALI_CTL_216 (0x0360) +#define DENALI_CTL_217 (0x0364) +#define DENALI_CTL_218 (0x0368) +#define DENALI_CTL_219 (0x036C) +#define DENALI_CTL_220 (0x0370) +#define DENALI_CTL_221 (0x0374) +#define DENALI_CTL_222 (0x0378) +#define DENALI_CTL_223 (0x037C) +#define DENALI_CTL_224 (0x0380) +#define DENALI_CTL_225 (0x0384) +#define DENALI_CTL_226 (0x0388) +#define DENALI_CTL_227 (0x038C) +#define DENALI_CTL_228 (0x0390) +#define DENALI_CTL_229 (0x0394) +#define DENALI_CTL_230 (0x0398) +#define DENALI_CTL_231 (0x039C) +#define DENALI_CTL_232 (0x03A0) +#define DENALI_CTL_233 (0x03A4) +#define DENALI_CTL_234 (0x03A8) +#define DENALI_CTL_235 (0x03AC) +#define DENALI_CTL_236 (0x03B0) +#define DENALI_CTL_237 (0x03B4) +#define DENALI_CTL_238 (0x03B8) +#define DENALI_CTL_239 (0x03BC) +#define DENALI_CTL_240 (0x03C0) +#define DENALI_CTL_241 (0x03C4) +#define DENALI_CTL_242 (0x03C8) +#define DENALI_CTL_243 (0x03CC) +#define DENALI_CTL_244 (0x03D0) +#define DENALI_CTL_245 (0x03D4) +#define DENALI_CTL_246 (0x03D8) +#define DENALI_CTL_247 (0x03DC) +#define DENALI_CTL_248 (0x03E0) +#define DENALI_CTL_249 (0x03E4) +#define DENALI_CTL_250 (0x03E8) +#define DENALI_CTL_251 (0x03EC) +#define DENALI_CTL_252 (0x03F0) +#define DENALI_CTL_253 (0x03F4) +#define DENALI_CTL_254 (0x03F8) +#define DENALI_CTL_255 (0x03FC) +#define DENALI_CTL_256 (0x0400) +#define DENALI_CTL_257 (0x0404) +#define DENALI_CTL_258 (0x0408) +#define DENALI_CTL_259 (0x040C) +#define DENALI_CTL_260 (0x0410) +#define DENALI_CTL_261 (0x0414) +#define DENALI_CTL_262 (0x0418) +#define DENALI_CTL_263 (0x041C) +#define DENALI_CTL_264 (0x0420) +#define DENALI_CTL_265 (0x0424) +#define DENALI_CTL_266 (0x0428) +#define DENALI_CTL_267 (0x042C) +#define DENALI_CTL_268 (0x0430) +#define DENALI_CTL_269 (0x0434) +#define DENALI_CTL_270 (0x0438) +#define DENALI_CTL_271 (0x043C) +#define DENALI_CTL_272 (0x0440) +#define DENALI_CTL_273 (0x0444) +#define DENALI_CTL_274 (0x0448) +#define DENALI_CTL_275 (0x044C) +#define DENALI_CTL_276 (0x0450) +#define DENALI_CTL_277 (0x0454) +#define DENALI_CTL_278 (0x0458) +#define DENALI_CTL_279 (0x045C) +#define DENALI_CTL_280 (0x0460) +#define DENALI_CTL_281 (0x0464) +#define DENALI_CTL_282 (0x0468) +#define DENALI_CTL_283 (0x046C) +#define DENALI_CTL_284 (0x0470) +#define DENALI_CTL_285 (0x0474) +#define DENALI_CTL_286 (0x0478) +#define DENALI_CTL_287 (0x047C) +#define DENALI_CTL_288 (0x0480) +#define DENALI_CTL_289 (0x0484) +#define DENALI_CTL_290 (0x0488) +#define DENALI_CTL_291 (0x048C) +#define DENALI_CTL_292 (0x0490) +#define DENALI_CTL_293 (0x0494) +#define DENALI_CTL_294 (0x0498) +#define DENALI_CTL_295 (0x049C) +#define DENALI_CTL_296 (0x04A0) +#define DENALI_CTL_297 (0x04A4) +#define DENALI_CTL_298 (0x04A8) +#define DENALI_CTL_299 (0x04AC) +#define DENALI_CTL_300 (0x04B0) +#define DENALI_CTL_301 (0x04B4) +#define DENALI_CTL_302 (0x04B8) +#define DENALI_CTL_303 (0x04BC) +#define DENALI_CTL_304 (0x04C0) +#define DENALI_CTL_305 (0x04C4) +#define DENALI_CTL_306 (0x04C8) +#define DENALI_CTL_307 (0x04CC) +#define DENALI_CTL_308 (0x04D0) +#define DENALI_CTL_309 (0x04D4) +#define DENALI_CTL_310 (0x04D8) +#define DENALI_CTL_311 (0x04DC) +#define DENALI_CTL_312 (0x04E0) +#define DENALI_CTL_313 (0x04E4) +#define DENALI_CTL_314 (0x04E8) +#define DENALI_CTL_315 (0x04EC) +#define DENALI_CTL_316 (0x04F0) +#define DENALI_CTL_317 (0x04F4) +#define DENALI_CTL_318 (0x04F8) +#define DENALI_CTL_319 (0x04FC) +#define DENALI_CTL_320 (0x0500) +#define DENALI_CTL_321 (0x0504) +#define DENALI_CTL_322 (0x0508) +#define DENALI_CTL_323 (0x050C) +#define DENALI_CTL_324 (0x0510) +#define DENALI_CTL_325 (0x0514) +#define DENALI_CTL_326 (0x0518) +#define DENALI_CTL_327 (0x051C) +#define DENALI_CTL_328 (0x0520) +#define DENALI_CTL_329 (0x0524) +#define DENALI_CTL_330 (0x0528) +#define DENALI_CTL_331 (0x052C) +#define DENALI_CTL_332 (0x0530) +#define DENALI_CTL_333 (0x0534) +#define DENALI_CTL_334 (0x0538) +#define DENALI_CTL_335 (0x053C) +#define DENALI_CTL_336 (0x0540) +#define DENALI_CTL_337 (0x0544) +#define DENALI_CTL_338 (0x0548) +#define DENALI_CTL_339 (0x054C) +#define DENALI_CTL_340 (0x0550) +#define DENALI_CTL_341 (0x0554) +#define DENALI_CTL_342 (0x0558) +#define DENALI_CTL_343 (0x055C) +#define DENALI_CTL_344 (0x0560) +#define DENALI_CTL_345 (0x0564) +#define DENALI_CTL_346 (0x0568) +#define DENALI_CTL_347 (0x056C) +#define DENALI_CTL_348 (0x0570) +#define DENALI_CTL_349 (0x0574) +#define DENALI_CTL_350 (0x0578) +#define DENALI_CTL_351 (0x057C) +#define DENALI_CTL_352 (0x0580) +#define DENALI_CTL_353 (0x0584) +#define DENALI_CTL_354 (0x0588) +#define DENALI_CTL_355 (0x058C) +#define DENALI_CTL_356 (0x0590) +#define DENALI_CTL_357 (0x0594) +#define DENALI_CTL_358 (0x0598) +#define DENALI_CTL_359 (0x059C) +#define DENALI_CTL_360 (0x05A0) +#define DENALI_CTL_361 (0x05A4) +#define DENALI_CTL_362 (0x05A8) +#define DENALI_CTL_363 (0x05AC) +#define DENALI_CTL_364 (0x05B0) +#define DENALI_CTL_365 (0x05B4) +#define DENALI_CTL_366 (0x05B8) +#define DENALI_CTL_367 (0x05BC) +#define DENALI_CTL_368 (0x05C0) +#define DENALI_CTL_369 (0x05C4) +#define DENALI_CTL_370 (0x05C8) +#define DENALI_CTL_371 (0x05CC) +#define DENALI_CTL_372 (0x05D0) +#define DENALI_CTL_373 (0x05D4) +#define DENALI_CTL_374 (0x05D8) +#define DENALI_CTL_375 (0x05DC) +#define DENALI_CTL_376 (0x05E0) +#define DENALI_CTL_377 (0x05E4) +#define DENALI_CTL_378 (0x05E8) +#define DENALI_CTL_379 (0x05EC) +#define DENALI_CTL_380 (0x05F0) +#define DENALI_CTL_381 (0x05F4) +#define DENALI_CTL_382 (0x05F8) +#define DENALI_CTL_383 (0x05FC) +#define DENALI_CTL_384 (0x0600) +#define DENALI_CTL_385 (0x0604) +#define DENALI_CTL_386 (0x0608) +#define DENALI_CTL_387 (0x060C) +#define DENALI_CTL_388 (0x0610) +#define DENALI_CTL_389 (0x0614) +#define DENALI_CTL_390 (0x0618) +#define DENALI_CTL_391 (0x061C) +#define DENALI_CTL_392 (0x0620) +#define DENALI_CTL_393 (0x0624) +#define DENALI_CTL_394 (0x0628) +#define DENALI_CTL_395 (0x062C) +#define DENALI_CTL_396 (0x0630) +#define DENALI_CTL_397 (0x0634) +#define DENALI_CTL_398 (0x0638) +#define DENALI_CTL_399 (0x063C) +#define DENALI_CTL_400 (0x0640) +#define DENALI_CTL_401 (0x0644) +#define DENALI_CTL_402 (0x0648) +#define DENALI_CTL_403 (0x064C) +#define DENALI_CTL_404 (0x0650) +#define DENALI_CTL_405 (0x0654) +#define DENALI_CTL_406 (0x0658) +#define DENALI_CTL_407 (0x065C) +#define DENALI_CTL_408 (0x0660) +#define DENALI_CTL_409 (0x0664) +#define DENALI_CTL_410 (0x0668) +#define DENALI_CTL_411 (0x066C) +#define DENALI_CTL_412 (0x0670) +#define DENALI_CTL_413 (0x0674) +#define DENALI_CTL_414 (0x0678) +#define DENALI_CTL_415 (0x067C) +#define DENALI_CTL_416 (0x0680) +#define DENALI_CTL_417 (0x0684) +#define DENALI_CTL_418 (0x0688) +#define DENALI_CTL_419 (0x068C) +#define DENALI_CTL_420 (0x0690) +#define DENALI_CTL_421 (0x0694) +#define DENALI_CTL_422 (0x0698) +#define DENALI_CTL_423 (0x069C) +#define DENALI_CTL_424 (0x06A0) +#define DENALI_CTL_425 (0x06A4) +#define DENALI_CTL_426 (0x06A8) +#define DENALI_CTL_427 (0x06AC) +#define DENALI_CTL_428 (0x06B0) +#define DENALI_CTL_429 (0x06B4) +#define DENALI_CTL_430 (0x06B8) +#define DENALI_CTL_431 (0x06BC) +#define DENALI_CTL_432 (0x06C0) +#define DENALI_CTL_433 (0x06C4) +#define DENALI_CTL_434 (0x06C8) +#define DENALI_CTL_435 (0x06CC) + +#endif // __DDR_MC_REGS_H__ diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/soc/a3ul/include/ddr_phy_regs.h b/drivers/rz/ipl/rza/plat/renesas/rz/soc/a3ul/include/ddr_phy_regs.h new file mode 100644 index 00000000..10c04731 --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/soc/a3ul/include/ddr_phy_regs.h @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __DDR_PHY_REGS_H__ +#define __DDR_PHY_REGS_H__ + +#include + +#define DDR_PHY_BASE RZG2L_DDR_PHY_BASE + +#define DDRPHY_R00 (0x040) +#define DDRPHY_R01 (0x044) +#define DDRPHY_R02 (0x048) +#define DDRPHY_R03 (0x04C) +#define DDRPHY_R04 (0x050) +#define DDRPHY_R05 (0x058) +#define DDRPHY_R06 (0x05C) +#define DDRPHY_R07 (0x060) +#define DDRPHY_R08 (0x064) +#define DDRPHY_R09 (0x068) +#define DDRPHY_R10 (0x09C) +#define DDRPHY_R11 (0x0A8) +#define DDRPHY_R12 (0x0C0) +#define DDRPHY_R13 (0x0C4) +#define DDRPHY_R14 (0x0C8) +#define DDRPHY_R15 (0x0CC) +#define DDRPHY_R16 (0x0D0) +#define DDRPHY_R17 (0x0E8) +#define DDRPHY_R18 (0x100) +#define DDRPHY_R19 (0x104) +#define DDRPHY_R20 (0x108) +#define DDRPHY_R21 (0x10C) +#define DDRPHY_R22 (0x110) +#define DDRPHY_R23 (0x114) +#define DDRPHY_R24 (0x118) +#define DDRPHY_R25 (0x11C) +#define DDRPHY_R26 (0x120) +#define DDRPHY_R27 (0x124) +#define DDRPHY_R28 (0x128) +#define DDRPHY_R29 (0x12C) +#define DDRPHY_R30 (0x130) +#define DDRPHY_R31 (0x134) +#define DDRPHY_R32 (0x138) +#define DDRPHY_R33 (0x13C) +#define DDRPHY_R34 (0x140) +#define DDRPHY_R35 (0x144) +#define DDRPHY_R36 (0x148) +#define DDRPHY_R37 (0x14C) +#define DDRPHY_R38 (0x150) +#define DDRPHY_R39 (0x154) +#define DDRPHY_R40 (0x158) +#define DDRPHY_R41 (0x15C) +#define DDRPHY_R42 (0x160) +#define DDRPHY_R43 (0x164) +#define DDRPHY_R44 (0x168) +#define DDRPHY_R45 (0x16C) +#define DDRPHY_R46 (0x170) +#define DDRPHY_R47 (0x174) +#define DDRPHY_R48 (0x178) +#define DDRPHY_R49 (0x17C) +#define DDRPHY_R50 (0x180) +#define DDRPHY_R51 (0x188) +#define DDRPHY_R52 (0x18C) +#define DDRPHY_R53 (0x190) +#define DDRPHY_R54 (0x194) +#define DDRPHY_R55 (0x19C) +#define DDRPHY_R56 (0x1A0) +#define DDRPHY_R57 (0x1A4) +#define DDRPHY_R58 (0x1A8) +#define DDRPHY_R59 (0x1AC) +#define DDRPHY_R60 (0x1B0) +#define DDRPHY_R61 (0x1B4) +#define DDRPHY_R62 (0x1B8) +#define DDRPHY_R63 (0x1BC) +#define DDRPHY_R64 (0x1C0) +#define DDRPHY_R65 (0x1C4) +#define DDRPHY_R66 (0x1C8) +#define DDRPHY_R67 (0x1CC) +#define DDRPHY_R68 (0x1D0) +#define DDRPHY_R69 (0x1D4) +#define DDRPHY_R70 (0x1D8) +#define DDRPHY_R71 (0x1DC) +#define DDRPHY_R72 (0x1E0) +#define DDRPHY_R73 (0x1E4) +#define DDRPHY_R74 (0x1E8) +#define DDRPHY_R75 (0x1EC) +#define DDRPHY_R76 (0x1F0) +#define DDRPHY_R77 (0x200) +#define DDRPHY_R78 (0x204) +#define DDRPHY_R79 (0x240) + +#endif // __DDR_PHY_REGS_H__ diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/soc/a3ul/platform.mk b/drivers/rz/ipl/rza/plat/renesas/rz/soc/a3ul/platform.mk new file mode 100644 index 00000000..56c315d3 --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/soc/a3ul/platform.mk @@ -0,0 +1,66 @@ +# +# Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +APPLOAD?=RZ_NOFIP +$(eval $(call add_define,APPLOAD)) +include plat/renesas/rz/common/rz_common.mk +include plat/renesas/rz/board/${BOARD}/rz_board.mk +include plat/renesas/rz/soc/${PLAT}/rz_xspi.mk + +PLAT_INCLUDES += -Iplat/renesas/rz/soc/a3ul/include + +DDR_SOURCES += plat/renesas/rz/soc/a3ul/drivers/ddr/ddr_a3ul.c + +RZA3 := 1 +RZA3UL := 1 +DEVICE_TYPE := 1 +ARCH_TYPE := ARMv8A +LOG_LEVEL := 10 +ifeq (${SOC_TYPE},2) +DEVICE_TYPE := 2 +endif +RZA3_XSPI_MEMORY_BASE := 0x20000000 + +$(eval $(call add_define,RZA3)) +$(eval $(call add_define,RZA3UL)) +$(eval $(call add_define,DEVICE_TYPE)) +$(eval $(call add_define,ARCH_TYPE)) +$(eval $(call add_define,RZA3_XSPI_MEMORY_BASE)) + +# set file name +RZ_ELF:=$(BUILD_PLAT)/rz$(BOARD)_ipl.elf +BL2_ELF:=$(BUILD_PLAT)/bl2/bl2.elf +RZ_BIN:=$(BUILD_PLAT)/rz$(BOARD)_ipl.bin +BL2_BIN:=$(BUILD_PLAT)/bl2.bin +RZ_MAP:=$(BUILD_PLAT)/rz$(BOARD)_ipl.map +BL2_MAP:=$(BUILD_PLAT)/bl2/bl2.map +RZ_DUMP:=$(BUILD_PLAT)/rz$(BOARD)_ipl.dump +BL2_DUMP:=$(BUILD_PLAT)/bl2/bl2.dump +RZ_SREC:=$(BUILD_PLAT)/rz$(BOARD)_ipl.srec + +bl2: $(RZ_ELF) $(RZ_BIN) $(RZ_LINKER) $(RZ_MAP) $(RZ_DUMP) $(RZ_SREC) + +$(RZ_ELF): $(BL2_ELF) + $(call SHELL_COPY,$<,$@) + +$(RZ_BIN): $(BL2_BIN) + @echo " IMG $@" + $(Q)/usr/bin/perl ./plat/renesas/rz/soc/a3ul/rz_image.pl "$<" "$@" + +$(BL2_MAP): $(BL2_ELF) +$(RZ_MAP): $(BL2_MAP) + $(call SHELL_COPY,$<,$@) + +$(RZ_DUMP): $(BL2_DUMP) + $(call SHELL_COPY,$<,$@) + +$(RZ_SREC): $(RZ_BIN) + @echo " SREC $@" + $(Q)$(OC) -I binary -O srec --adjust-vma=0x20000000 --srec-forceS3 "$<" "$@" + +ifeq (${RZ_TEST},1) +-include plat/renesas/rz/common/drivers/tests/rz_test.mk +endif diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/soc/a3ul/rz_image.pl b/drivers/rz/ipl/rza/plat/renesas/rz/soc/a3ul/rz_image.pl new file mode 100644 index 00000000..73a2e355 --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/soc/a3ul/rz_image.pl @@ -0,0 +1,74 @@ +#!/usr/bin/perl -w +# Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause + +use strict; +use bigint; +my $size_limit = 0x1D000; + +die("Not enough parameter\n") if ($#ARGV < 0); + +# Open input file +my $name = shift(@ARGV); +my $outname; +if ($#ARGV < 0) { + $outname = "rz_" . $name; +} +else { + $outname = shift(@ARGV); +} +open(my $origin, '<', $name) or die("Can not open input file"); +binmode $origin; + +# Obtaining size ($st[7]) +my @st = stat($origin); + +# Check appended size +my $size = ($st[7] + 3) & "0xfffffffffffffffc"; +my $msg; +if ($size != $st[7]) {$msg = "Appended size";} else {$msg="Size";} +die("$msg too big ($size > $size_limit)") if ($size > $size_limit); + +# Create temporary file +open(my $out, '>', $outname) or die("Can not open output file"); +binmode $out; + +# Write header +$out->print(pack('L', $size)); +for(my $i = 1; $i < 112; $i++) { + $out->print(pack('L', 0xffffffff)); +} +$out->print(pack('L', 0xffff0000)); +$out->print(pack('L', 0x000800ff)); +$out->print(pack('L', 0x00fff700)); +$out->print(pack('L', 0xf700f708)); +$out->print(pack('L', 0xffffffff)); +$out->print(pack('L', 0xffffffff)); +$out->print(pack('L', 0xffffffff)); +$out->print(pack('L', 0xffffffff)); +$out->print(pack('L', 0xffffffff)); +$out->print(pack('L', 0xffffffff)); +$out->print(pack('L', 0xffffffff)); +$out->print(pack('L', 0xffffffff)); +$out->print(pack('L', 0xffffffff)); +$out->print(pack('L', 0xffffffff)); +$out->print(pack('L', 0xffffffff)); +$out->print(pack('L', 0xaa55ffff)); + +# Append original data to temporary file +my $buf; +read($origin, $buf, $st[7]); +$out->print($buf); +if($st[7] < $size) { + warn "Not aligned. Append " . ($size-$st[7]) . " zero(s)"; + # Append zero + for(;$st[7] < $size; $size--) { + $out->print(pack('C', 0)); + } +} +$out->flush; + +# close +close $out; +close $origin; diff --git a/drivers/rz/ipl/rza/plat/renesas/rz/soc/a3ul/rz_xspi.mk b/drivers/rz/ipl/rza/plat/renesas/rz/soc/a3ul/rz_xspi.mk new file mode 100644 index 00000000..840fe662 --- /dev/null +++ b/drivers/rz/ipl/rza/plat/renesas/rz/soc/a3ul/rz_xspi.mk @@ -0,0 +1,34 @@ +# +# Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# +RZ_XSPI_DRIVER_PATH:=plat/renesas/rz/common/drivers/xspi + +RZ_XSPI_CONFIGS:=XSPI0 XSPI1 XSPI2 +RZ_XSPI_SOURCES:=plat/renesas/rz/soc/a3ul/drivers/xspi.c +RZ_XSPI_HEADERS:= +RZ_XSPI0_IF:=spim +RZ_XSPI0_IF_CONFIG:=.channel=0, .base=0x10060000 +RZ_XSPI1_IF:=octa +RZ_XSPI1_IF_CONFIG:=.channel=0, .base=0x10080000 +RZ_XSPI2_IF:=octa +RZ_XSPI2_IF_CONFIG:=.channel=1, .base=0x10080000 +RZ_XSPI_EXCLUSIVE_SELECTOR:=1 +RZ_SPIM_SDR_FREQ_LIMIT:=66625000 +RZ_OCTA_FREQ_LIMIT:=100000000 + +ifneq ($(strip $(XSPI0_DEVICE)),) + ifneq ($(strip $(XSPI1_DEVICE)),) + $(error XSPI0_DEVICE and XSPI1_DEVICE can not be specified at the same time.) + endif + ifneq ($(strip $(XSPI2_DEVICE)),) + $(error XSPI0_DEVICE and XSPI2_DEVICE can not be specified at the same time.) + endif +endif + +include plat/renesas/rz/common/rz_xspi_common.mk + +$(eval $(call add_define,RZ_XSPI_EXCLUSIVE_SELECTOR)) +$(eval $(call add_define,RZ_SPIM_SDR_FREQ_LIMIT)) +$(eval $(call add_define,RZ_OCTA_FREQ_LIMIT)) diff --git a/drivers/rz/ipl/rza/tools/cert_create/Makefile b/drivers/rz/ipl/rza/tools/cert_create/Makefile new file mode 100644 index 00000000..77d2007d --- /dev/null +++ b/drivers/rz/ipl/rza/tools/cert_create/Makefile @@ -0,0 +1,90 @@ +# +# Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +PLAT := none +V ?= 0 +DEBUG := 0 +CRTTOOL ?= cert_create${BIN_EXT} +BINARY := $(notdir ${CRTTOOL}) +OPENSSL_DIR := /usr +COT := tbbr + +MAKE_HELPERS_DIRECTORY := ../../make_helpers/ +include ${MAKE_HELPERS_DIRECTORY}build_macros.mk +include ${MAKE_HELPERS_DIRECTORY}build_env.mk + +ifneq (${PLAT},none) +TF_PLATFORM_ROOT := ../../plat/ +include ${MAKE_HELPERS_DIRECTORY}plat_helpers.mk +PLAT_CERT_CREATE_HELPER_MK := ${PLAT_DIR}/cert_create_tbbr.mk +endif + +# Common source files. +OBJECTS := src/cert.o \ + src/cmd_opt.o \ + src/ext.o \ + src/key.o \ + src/main.o \ + src/sha.o + +# Chain of trust. +ifeq (${COT},tbbr) + include src/tbbr/tbbr.mk +else ifeq (${COT},dualroot) + include src/dualroot/cot.mk +else + $(error Unknown chain of trust ${COT}) +endif + +ifneq (,$(wildcard ${PLAT_CERT_CREATE_HELPER_MK})) +include ${PLAT_CERT_CREATE_HELPER_MK} +endif + +HOSTCCFLAGS := -Wall -std=c99 + +ifeq (${DEBUG},1) + HOSTCCFLAGS += -g -O0 -DDEBUG -DLOG_LEVEL=40 +else + HOSTCCFLAGS += -O2 -DLOG_LEVEL=20 +endif + +ifeq (${V},0) + Q := @ +else + Q := +endif + +HOSTCCFLAGS += ${DEFINES} + +# Make soft links and include from local directory otherwise wrong headers +# could get pulled in from firmware tree. +INC_DIR += -I ./include -I ${PLAT_INCLUDE} -I ${OPENSSL_DIR}/include +LIB_DIR := -L ${OPENSSL_DIR}/lib +LIB := -lssl -lcrypto + +HOSTCC ?= gcc + +.PHONY: all clean realclean + +all: ${BINARY} + +${BINARY}: ${OBJECTS} Makefile + @echo " HOSTLD $@" + @echo 'const char build_msg[] = "Built : "__TIME__", "__DATE__; \ + const char platform_msg[] = "${PLAT_MSG}";' | \ + ${HOSTCC} -c ${HOSTCCFLAGS} -xc - -o src/build_msg.o + ${Q}${HOSTCC} src/build_msg.o ${OBJECTS} ${LIB_DIR} ${LIB} -o $@ + +%.o: %.c + @echo " HOSTCC $<" + ${Q}${HOSTCC} -c ${HOSTCCFLAGS} ${INC_DIR} $< -o $@ + +clean: + $(call SHELL_DELETE_ALL, src/build_msg.o ${OBJECTS}) + +realclean: clean + $(call SHELL_DELETE,${BINARY}) + diff --git a/drivers/rz/ipl/rza/tools/cert_create/include/cert.h b/drivers/rz/ipl/rza/tools/cert_create/include/cert.h new file mode 100644 index 00000000..e63b4740 --- /dev/null +++ b/drivers/rz/ipl/rza/tools/cert_create/include/cert.h @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CERT_H +#define CERT_H + +#include +#include +#include "ext.h" +#include "key.h" + +#define CERT_MAX_EXT 9 + +/* + * This structure contains information related to the generation of the + * certificates. All these fields must be known and specified at build time + * except for the file name, which is picked up from the command line at + * run time. + * + * One instance of this structure must be created for each of the certificates + * present in the chain of trust. + * + * If the issuer points to this same instance, the generated certificate will + * be self-signed. + */ +typedef struct cert_s cert_t; +struct cert_s { + int id; /* Unique identifier */ + + const char *opt; /* Command line option to pass filename */ + const char *fn; /* Filename to save the certificate */ + const char *cn; /* Subject CN (Company Name) */ + const char *help_msg; /* Help message */ + + /* These fields must be defined statically */ + int key; /* Key to be signed */ + int issuer; /* Issuer certificate */ + int ext[CERT_MAX_EXT]; /* Certificate extensions */ + int num_ext; /* Number of extensions in the certificate */ + + X509 *x; /* X509 certificate container */ +}; + +/* Exported API */ +int cert_init(void); +cert_t *cert_get_by_opt(const char *opt); +int cert_add_ext(X509 *issuer, X509 *subject, int nid, char *value); +int cert_new( + int md_alg, + cert_t *cert, + int days, + int ca, + STACK_OF(X509_EXTENSION) * sk); + +/* Macro to register the certificates used in the CoT */ +#define REGISTER_COT(_certs) \ + cert_t *def_certs = &_certs[0]; \ + const unsigned int num_def_certs = sizeof(_certs)/sizeof(_certs[0]) + +/* Macro to register the platform defined certificates used in the CoT */ +#define PLAT_REGISTER_COT(_pdef_certs) \ + cert_t *pdef_certs = &_pdef_certs[0]; \ + const unsigned int num_pdef_certs = sizeof(_pdef_certs)/sizeof(_pdef_certs[0]) + +/* Exported variables */ +extern cert_t *def_certs; +extern const unsigned int num_def_certs; +extern cert_t *pdef_certs; +extern const unsigned int num_pdef_certs; + +extern cert_t *certs; +extern unsigned int num_certs; +#endif /* CERT_H */ diff --git a/drivers/rz/ipl/rza/tools/cert_create/include/cmd_opt.h b/drivers/rz/ipl/rza/tools/cert_create/include/cmd_opt.h new file mode 100644 index 00000000..10df00ea --- /dev/null +++ b/drivers/rz/ipl/rza/tools/cert_create/include/cmd_opt.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CMD_OPT_H +#define CMD_OPT_H + +#include + +#define CMD_OPT_MAX_NUM 64 + +/* Supported long command line option types */ +enum { + CMD_OPT_CERT, + CMD_OPT_KEY, + CMD_OPT_EXT +}; + +/* Structure to define a command line option */ +typedef struct cmd_opt_s { + struct option long_opt; + const char *help_msg; +} cmd_opt_t; + +/* Exported API*/ +void cmd_opt_add(const cmd_opt_t *cmd_opt); +const struct option *cmd_opt_get_array(void); +const char *cmd_opt_get_name(int idx); +const char *cmd_opt_get_help_msg(int idx); + +#endif /* CMD_OPT_H */ diff --git a/drivers/rz/ipl/rza/tools/cert_create/include/debug.h b/drivers/rz/ipl/rza/tools/cert_create/include/debug.h new file mode 100644 index 00000000..ee8f1f51 --- /dev/null +++ b/drivers/rz/ipl/rza/tools/cert_create/include/debug.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef DEBUG_H +#define DEBUG_H + +#include + +/* The log output macros print output to the console. These macros produce + * compiled log output only if the LOG_LEVEL defined in the makefile (or the + * make command line) is greater or equal than the level required for that + * type of log output. + * The format expected is the same as for printf(). For example: + * INFO("Info %s.\n", "message") -> INFO: Info message. + * WARN("Warning %s.\n", "message") -> WARNING: Warning message. + */ + +#define LOG_LEVEL_NONE 0 +#define LOG_LEVEL_ERROR 10 +#define LOG_LEVEL_NOTICE 20 +#define LOG_LEVEL_WARNING 30 +#define LOG_LEVEL_INFO 40 +#define LOG_LEVEL_VERBOSE 50 + + +#if LOG_LEVEL >= LOG_LEVEL_NOTICE +# define NOTICE(...) printf("NOTICE: " __VA_ARGS__) +#else +# define NOTICE(...) +#endif + +#if LOG_LEVEL >= LOG_LEVEL_ERROR +# define ERROR(...) printf("ERROR: " __VA_ARGS__) +#else +# define ERROR(...) +#endif + +#if LOG_LEVEL >= LOG_LEVEL_WARNING +# define WARN(...) printf("WARNING: " __VA_ARGS__) +#else +# define WARN(...) +#endif + +#if LOG_LEVEL >= LOG_LEVEL_INFO +# define INFO(...) printf("INFO: " __VA_ARGS__) +#else +# define INFO(...) +#endif + +#if LOG_LEVEL >= LOG_LEVEL_VERBOSE +# define VERBOSE(...) printf("VERBOSE: " __VA_ARGS__) +#else +# define VERBOSE(...) +#endif + +#endif /* DEBUG_H */ diff --git a/drivers/rz/ipl/rza/tools/cert_create/include/dualroot/cot.h b/drivers/rz/ipl/rza/tools/cert_create/include/dualroot/cot.h new file mode 100644 index 00000000..3e50c898 --- /dev/null +++ b/drivers/rz/ipl/rza/tools/cert_create/include/dualroot/cot.h @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef DUALROOT_COT_H +#define DUALROOT_COT_H + +/* Certificates. */ +enum { + /* Certificates owned by the silicon provider. */ + TRUSTED_BOOT_FW_CERT, + TRUSTED_KEY_CERT, + SCP_FW_KEY_CERT, + SCP_FW_CONTENT_CERT, + SOC_FW_KEY_CERT, + SOC_FW_CONTENT_CERT, + TRUSTED_OS_FW_KEY_CERT, + TRUSTED_OS_FW_CONTENT_CERT, + SIP_SECURE_PARTITION_CONTENT_CERT, + FWU_CERT, + + /* Certificates owned by the platform owner. */ + NON_TRUSTED_FW_CONTENT_CERT, + PLAT_SECURE_PARTITION_CONTENT_CERT, +}; + +/* Certificate extensions. */ +enum { + /* Extensions used in certificates owned by the silicon provider. */ + TRUSTED_FW_NVCOUNTER_EXT, + TRUSTED_BOOT_FW_HASH_EXT, + TRUSTED_BOOT_FW_CONFIG_HASH_EXT, + HW_CONFIG_HASH_EXT, + FW_CONFIG_HASH_EXT, + TRUSTED_WORLD_PK_EXT, + SCP_FW_CONTENT_CERT_PK_EXT, + SCP_FW_HASH_EXT, + SOC_FW_CONTENT_CERT_PK_EXT, + SOC_AP_FW_HASH_EXT, + SOC_FW_CONFIG_HASH_EXT, + TRUSTED_OS_FW_CONTENT_CERT_PK_EXT, + TRUSTED_OS_FW_HASH_EXT, + TRUSTED_OS_FW_EXTRA1_HASH_EXT, + TRUSTED_OS_FW_EXTRA2_HASH_EXT, + TRUSTED_OS_FW_CONFIG_HASH_EXT, + SP_PKG1_HASH_EXT, + SP_PKG2_HASH_EXT, + SP_PKG3_HASH_EXT, + SP_PKG4_HASH_EXT, + SP_PKG5_HASH_EXT, + SP_PKG6_HASH_EXT, + SP_PKG7_HASH_EXT, + SP_PKG8_HASH_EXT, + SCP_FWU_CFG_HASH_EXT, + AP_FWU_CFG_HASH_EXT, + FWU_HASH_EXT, + + /* Extensions used in certificates owned by the platform owner. */ + PROT_PK_EXT, + NON_TRUSTED_FW_NVCOUNTER_EXT, + NON_TRUSTED_FW_CONTENT_CERT_PK_EXT, + NON_TRUSTED_WORLD_BOOTLOADER_HASH_EXT, + NON_TRUSTED_FW_CONFIG_HASH_EXT, +}; + +/* Keys. */ +enum { + /* Keys owned by the silicon provider. */ + ROT_KEY, + TRUSTED_WORLD_KEY, + SCP_FW_CONTENT_CERT_KEY, + SOC_FW_CONTENT_CERT_KEY, + TRUSTED_OS_FW_CONTENT_CERT_KEY, + + /* Keys owned by the platform owner. */ + PROT_KEY, +}; + +#endif /* DUALROOT_COT_H */ diff --git a/drivers/rz/ipl/rza/tools/cert_create/include/ext.h b/drivers/rz/ipl/rza/tools/cert_create/include/ext.h new file mode 100644 index 00000000..e900a6dc --- /dev/null +++ b/drivers/rz/ipl/rza/tools/cert_create/include/ext.h @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef EXT_H +#define EXT_H + +#include +#include "key.h" + +/* Extension types supported */ +enum ext_type_e { + EXT_TYPE_NVCOUNTER, + EXT_TYPE_PKEY, + EXT_TYPE_HASH +}; + +/* NV-Counter types */ +enum nvctr_type_e { + NVCTR_TYPE_TFW, + NVCTR_TYPE_NTFW +}; + +/* + * This structure contains the relevant information to create the extensions + * to be included in the certificates. This extensions will be used to + * establish the chain of trust. + */ +typedef struct ext_s { + const char *oid; /* OID of the extension */ + const char *sn; /* Short name */ + const char *ln; /* Long description */ + const char *opt; /* Command line option to specify data */ + const char *help_msg; /* Help message */ + const char *arg; /* Argument passed from command line */ + int asn1_type; /* OpenSSL ASN1 type of the extension data. + * Supported types are: + * - V_ASN1_INTEGER + * - V_ASN1_OCTET_STRING + */ + int type; /* See ext_type_e */ + + /* Extension attributes (depends on extension type) */ + union { + int nvctr_type; /* See nvctr_type_e */ + int key; /* Index into array of registered public keys */ + } attr; + + int alias; /* In case OpenSSL provides an standard + * extension of the same type, add the new + * extension as an alias of this one + */ + + X509V3_EXT_METHOD method; /* This field may be used to define a custom + * function to print the contents of the + * extension */ + + int optional; /* This field may be used optionally to exclude an image */ +} ext_t; + +enum { + EXT_NON_CRIT = 0, + EXT_CRIT = !EXT_NON_CRIT, +}; + +/* Exported API */ +int ext_init(void); +ext_t *ext_get_by_opt(const char *opt); +X509_EXTENSION *ext_new_hash(int nid, int crit, const EVP_MD *md, + unsigned char *buf, size_t len); +X509_EXTENSION *ext_new_nvcounter(int nid, int crit, int value); +X509_EXTENSION *ext_new_key(int nid, int crit, EVP_PKEY *k); + +/* Macro to register the extensions used in the CoT */ +#define REGISTER_EXTENSIONS(_ext) \ + ext_t *def_extensions = &_ext[0]; \ + const unsigned int num_def_extensions = sizeof(_ext)/sizeof(_ext[0]) + +/* Macro to register the platform defined extensions used in the CoT */ +#define PLAT_REGISTER_EXTENSIONS(_pdef_ext) \ + ext_t *pdef_extensions = &_pdef_ext[0]; \ + const unsigned int num_pdef_extensions = sizeof(_pdef_ext)/sizeof(_pdef_ext[0]) + +/* Exported variables */ +extern ext_t *def_extensions; +extern const unsigned int num_def_extensions; +extern ext_t *pdef_extensions; +extern const unsigned int num_pdef_extensions; + +extern ext_t *extensions; +extern unsigned int num_extensions; +#endif /* EXT_H */ diff --git a/drivers/rz/ipl/rza/tools/cert_create/include/key.h b/drivers/rz/ipl/rza/tools/cert_create/include/key.h new file mode 100644 index 00000000..128e7f7b --- /dev/null +++ b/drivers/rz/ipl/rza/tools/cert_create/include/key.h @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef KEY_H +#define KEY_H + +#include + +/* Error codes */ +enum { + KEY_ERR_NONE, + KEY_ERR_MALLOC, + KEY_ERR_FILENAME, + KEY_ERR_OPEN, + KEY_ERR_LOAD +}; + +/* Supported key algorithms */ +enum { + KEY_ALG_RSA, /* RSA PSS as defined by PKCS#1 v2.1 (default) */ +#ifndef OPENSSL_NO_EC + KEY_ALG_ECDSA, +#endif /* OPENSSL_NO_EC */ + KEY_ALG_MAX_NUM +}; + +/* Maximum number of valid key sizes per algorithm */ +#define KEY_SIZE_MAX_NUM 4 + +/* Supported hash algorithms */ +enum{ + HASH_ALG_SHA256, + HASH_ALG_SHA384, + HASH_ALG_SHA512, +}; + +/* Supported key sizes */ +/* NOTE: the first item in each array is the default key size */ +static const unsigned int KEY_SIZES[KEY_ALG_MAX_NUM][KEY_SIZE_MAX_NUM] = { + { 2048, 1024, 3072, 4096 }, /* KEY_ALG_RSA */ +#ifndef OPENSSL_NO_EC + {} /* KEY_ALG_ECDSA */ +#endif /* OPENSSL_NO_EC */ +}; + +/* + * This structure contains the relevant information to create the keys + * required to sign the certificates. + * + * One instance of this structure must be created for each key, usually in an + * array fashion. The filename is obtained at run time from the command line + * parameters + */ +typedef struct key_s { + int id; /* Key id */ + const char *opt; /* Command line option to specify a key */ + const char *help_msg; /* Help message */ + const char *desc; /* Key description (debug purposes) */ + char *fn; /* Filename to load/store the key */ + EVP_PKEY *key; /* Key container */ +} key_t; + +/* Exported API */ +int key_init(void); +key_t *key_get_by_opt(const char *opt); +int key_new(key_t *key); +int key_create(key_t *key, int type, int key_bits); +int key_load(key_t *key, unsigned int *err_code); +int key_store(key_t *key); + +/* Macro to register the keys used in the CoT */ +#define REGISTER_KEYS(_keys) \ + key_t *def_keys = &_keys[0]; \ + const unsigned int num_def_keys = sizeof(_keys)/sizeof(_keys[0]) + +/* Macro to register the platform defined keys used in the CoT */ +#define PLAT_REGISTER_KEYS(_pdef_keys) \ + key_t *pdef_keys = &_pdef_keys[0]; \ + const unsigned int num_pdef_keys = sizeof(_pdef_keys)/sizeof(_pdef_keys[0]) + +/* Exported variables */ +extern key_t *def_keys; +extern const unsigned int num_def_keys; +extern key_t *pdef_keys; +extern const unsigned int num_pdef_keys; + +extern key_t *keys; +extern unsigned int num_keys; +#endif /* KEY_H */ diff --git a/drivers/rz/ipl/rza/tools/cert_create/include/sha.h b/drivers/rz/ipl/rza/tools/cert_create/include/sha.h new file mode 100644 index 00000000..4c55f375 --- /dev/null +++ b/drivers/rz/ipl/rza/tools/cert_create/include/sha.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SHA_H +#define SHA_H + +int sha_file(int md_alg, const char *filename, unsigned char *md); + +#endif /* SHA_H */ diff --git a/drivers/rz/ipl/rza/tools/cert_create/include/tbbr/tbb_cert.h b/drivers/rz/ipl/rza/tools/cert_create/include/tbbr/tbb_cert.h new file mode 100644 index 00000000..e5fa3a23 --- /dev/null +++ b/drivers/rz/ipl/rza/tools/cert_create/include/tbbr/tbb_cert.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TBB_CERT_H +#define TBB_CERT_H + +#include "cert.h" + +/* + * Enumerate the certificates that are used to establish the chain of trust + */ +enum { + TRUSTED_BOOT_FW_CERT, + TRUSTED_KEY_CERT, + SCP_FW_KEY_CERT, + SCP_FW_CONTENT_CERT, + SOC_FW_KEY_CERT, + SOC_FW_CONTENT_CERT, + TRUSTED_OS_FW_KEY_CERT, + TRUSTED_OS_FW_CONTENT_CERT, + NON_TRUSTED_FW_KEY_CERT, + NON_TRUSTED_FW_CONTENT_CERT, + SIP_SECURE_PARTITION_CONTENT_CERT, + FWU_CERT +}; + +#endif /* TBB_CERT_H */ diff --git a/drivers/rz/ipl/rza/tools/cert_create/include/tbbr/tbb_ext.h b/drivers/rz/ipl/rza/tools/cert_create/include/tbbr/tbb_ext.h new file mode 100644 index 00000000..692b2d4d --- /dev/null +++ b/drivers/rz/ipl/rza/tools/cert_create/include/tbbr/tbb_ext.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef TBB_EXT_H +#define TBB_EXT_H + +#include "ext.h" + +/* TBBR extensions */ +enum { + TRUSTED_FW_NVCOUNTER_EXT, + NON_TRUSTED_FW_NVCOUNTER_EXT, + TRUSTED_BOOT_FW_HASH_EXT, + TRUSTED_BOOT_FW_CONFIG_HASH_EXT, + HW_CONFIG_HASH_EXT, + FW_CONFIG_HASH_EXT, + TRUSTED_WORLD_PK_EXT, + NON_TRUSTED_WORLD_PK_EXT, + SCP_FW_CONTENT_CERT_PK_EXT, + SCP_FW_HASH_EXT, + SOC_FW_CONTENT_CERT_PK_EXT, + SOC_AP_FW_HASH_EXT, + SOC_FW_CONFIG_HASH_EXT, + TRUSTED_OS_FW_CONTENT_CERT_PK_EXT, + TRUSTED_OS_FW_HASH_EXT, + TRUSTED_OS_FW_EXTRA1_HASH_EXT, + TRUSTED_OS_FW_EXTRA2_HASH_EXT, + TRUSTED_OS_FW_CONFIG_HASH_EXT, + NON_TRUSTED_FW_CONTENT_CERT_PK_EXT, + NON_TRUSTED_WORLD_BOOTLOADER_HASH_EXT, + NON_TRUSTED_FW_CONFIG_HASH_EXT, + SP_PKG1_HASH_EXT, + SP_PKG2_HASH_EXT, + SP_PKG3_HASH_EXT, + SP_PKG4_HASH_EXT, + SP_PKG5_HASH_EXT, + SP_PKG6_HASH_EXT, + SP_PKG7_HASH_EXT, + SP_PKG8_HASH_EXT, + SCP_FWU_CFG_HASH_EXT, + AP_FWU_CFG_HASH_EXT, + FWU_HASH_EXT +}; + +#endif /* TBB_EXT_H */ diff --git a/drivers/rz/ipl/rza/tools/cert_create/include/tbbr/tbb_key.h b/drivers/rz/ipl/rza/tools/cert_create/include/tbbr/tbb_key.h new file mode 100644 index 00000000..47ad1de0 --- /dev/null +++ b/drivers/rz/ipl/rza/tools/cert_create/include/tbbr/tbb_key.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TBB_KEY_H +#define TBB_KEY_H + +#include "key.h" + +/* + * Enumerate the keys that are used to establish the chain of trust + */ +enum { + ROT_KEY, + TRUSTED_WORLD_KEY, + NON_TRUSTED_WORLD_KEY, + SCP_FW_CONTENT_CERT_KEY, + SOC_FW_CONTENT_CERT_KEY, + TRUSTED_OS_FW_CONTENT_CERT_KEY, + NON_TRUSTED_FW_CONTENT_CERT_KEY +}; + +#endif /* TBB_KEY_H */ diff --git a/drivers/rz/ipl/rza/tools/cert_create/src/cert.c b/drivers/rz/ipl/rza/tools/cert_create/src/cert.c new file mode 100644 index 00000000..4b35d735 --- /dev/null +++ b/drivers/rz/ipl/rza/tools/cert_create/src/cert.c @@ -0,0 +1,274 @@ +/* + * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "cert.h" +#include "cmd_opt.h" +#include "debug.h" +#include "key.h" +#include "sha.h" + +#define SERIAL_RAND_BITS 64 +#define RSA_SALT_LEN 32 + +cert_t *certs; +unsigned int num_certs; + +int rand_serial(BIGNUM *b, ASN1_INTEGER *ai) +{ + BIGNUM *btmp; + int ret = 0; + if (b) + btmp = b; + else + btmp = BN_new(); + + if (!btmp) + return 0; + + if (!BN_pseudo_rand(btmp, SERIAL_RAND_BITS, 0, 0)) + goto error; + if (ai && !BN_to_ASN1_INTEGER(btmp, ai)) + goto error; + + ret = 1; + +error: + + if (!b) + BN_free(btmp); + + return ret; +} +const EVP_MD *get_digest(int alg) +{ + switch (alg) { + case HASH_ALG_SHA256: + return EVP_sha256(); + case HASH_ALG_SHA384: + return EVP_sha384(); + case HASH_ALG_SHA512: + return EVP_sha512(); + default: + return NULL; + } +} + +int cert_add_ext(X509 *issuer, X509 *subject, int nid, char *value) +{ + X509_EXTENSION *ex; + X509V3_CTX ctx; + + /* No configuration database */ + X509V3_set_ctx_nodb(&ctx); + + /* Set issuer and subject certificates in the context */ + X509V3_set_ctx(&ctx, issuer, subject, NULL, NULL, 0); + ex = X509V3_EXT_conf_nid(NULL, &ctx, nid, value); + if (!ex) { + ERR_print_errors_fp(stdout); + return 0; + } + + X509_add_ext(subject, ex, -1); + X509_EXTENSION_free(ex); + + return 1; +} + +int cert_new( + int md_alg, + cert_t *cert, + int days, + int ca, + STACK_OF(X509_EXTENSION) * sk) +{ + EVP_PKEY *pkey = keys[cert->key].key; + cert_t *issuer_cert = &certs[cert->issuer]; + EVP_PKEY *ikey = keys[issuer_cert->key].key; + X509 *issuer = issuer_cert->x; + X509 *x; + X509_EXTENSION *ex; + X509_NAME *name; + ASN1_INTEGER *sno; + int i, num, rc = 0; + EVP_MD_CTX *mdCtx; + EVP_PKEY_CTX *pKeyCtx = NULL; + + /* Create the certificate structure */ + x = X509_new(); + if (!x) { + return 0; + } + + /* If we do not have a key, use the issuer key (the certificate will + * become self signed). This happens in content certificates. */ + if (!pkey) { + pkey = ikey; + } + + /* If we do not have an issuer certificate, use our own (the certificate + * will become self signed) */ + if (!issuer) { + issuer = x; + } + + mdCtx = EVP_MD_CTX_create(); + if (mdCtx == NULL) { + ERR_print_errors_fp(stdout); + goto END; + } + + /* Sign the certificate with the issuer key */ + if (!EVP_DigestSignInit(mdCtx, &pKeyCtx, get_digest(md_alg), NULL, ikey)) { + ERR_print_errors_fp(stdout); + goto END; + } + + /* + * Set additional parameters if issuing public key algorithm is RSA. + * This is not required for ECDSA. + */ + if (EVP_PKEY_base_id(ikey) == EVP_PKEY_RSA) { + if (!EVP_PKEY_CTX_set_rsa_padding(pKeyCtx, RSA_PKCS1_PSS_PADDING)) { + ERR_print_errors_fp(stdout); + goto END; + } + + if (!EVP_PKEY_CTX_set_rsa_pss_saltlen(pKeyCtx, RSA_SALT_LEN)) { + ERR_print_errors_fp(stdout); + goto END; + } + + if (!EVP_PKEY_CTX_set_rsa_mgf1_md(pKeyCtx, get_digest(md_alg))) { + ERR_print_errors_fp(stdout); + goto END; + } + } + + /* x509.v3 */ + X509_set_version(x, 2); + + /* Random serial number */ + sno = ASN1_INTEGER_new(); + rand_serial(NULL, sno); + X509_set_serialNumber(x, sno); + ASN1_INTEGER_free(sno); + + X509_gmtime_adj(X509_get_notBefore(x), 0); + X509_gmtime_adj(X509_get_notAfter(x), (long)60*60*24*days); + X509_set_pubkey(x, pkey); + + /* Subject name */ + name = X509_get_subject_name(x); + X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, + (const unsigned char *)cert->cn, -1, -1, 0); + X509_set_subject_name(x, name); + + /* Issuer name */ + name = X509_get_issuer_name(x); + X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, + (const unsigned char *)issuer_cert->cn, -1, -1, 0); + X509_set_issuer_name(x, name); + + /* Add various extensions: standard extensions */ + cert_add_ext(issuer, x, NID_subject_key_identifier, "hash"); + cert_add_ext(issuer, x, NID_authority_key_identifier, "keyid:always"); + if (ca) { + cert_add_ext(issuer, x, NID_basic_constraints, "CA:TRUE"); + cert_add_ext(issuer, x, NID_key_usage, "keyCertSign"); + } else { + cert_add_ext(issuer, x, NID_basic_constraints, "CA:FALSE"); + } + + /* Add custom extensions */ + if (sk != NULL) { + num = sk_X509_EXTENSION_num(sk); + for (i = 0; i < num; i++) { + ex = sk_X509_EXTENSION_value(sk, i); + X509_add_ext(x, ex, -1); + } + } + + if (!X509_sign_ctx(x, mdCtx)) { + ERR_print_errors_fp(stdout); + goto END; + } + + /* X509 certificate signed successfully */ + rc = 1; + cert->x = x; + +END: + EVP_MD_CTX_destroy(mdCtx); + return rc; +} + +int cert_init(void) +{ + cmd_opt_t cmd_opt; + cert_t *cert; + unsigned int i; + + certs = malloc((num_def_certs * sizeof(def_certs[0])) +#ifdef PDEF_CERTS + + (num_pdef_certs * sizeof(pdef_certs[0])) +#endif + ); + if (certs == NULL) { + ERROR("%s:%d Failed to allocate memory.\n", __func__, __LINE__); + return 1; + } + + memcpy(&certs[0], &def_certs[0], + (num_def_certs * sizeof(def_certs[0]))); + +#ifdef PDEF_CERTS + memcpy(&certs[num_def_certs], &pdef_certs[0], + (num_pdef_certs * sizeof(pdef_certs[0]))); + + num_certs = num_def_certs + num_pdef_certs; +#else + num_certs = num_def_certs; +#endif + + for (i = 0; i < num_certs; i++) { + cert = &certs[i]; + cmd_opt.long_opt.name = cert->opt; + cmd_opt.long_opt.has_arg = required_argument; + cmd_opt.long_opt.flag = NULL; + cmd_opt.long_opt.val = CMD_OPT_CERT; + cmd_opt.help_msg = cert->help_msg; + cmd_opt_add(&cmd_opt); + } + + return 0; +} + +cert_t *cert_get_by_opt(const char *opt) +{ + cert_t *cert; + unsigned int i; + + for (i = 0; i < num_certs; i++) { + cert = &certs[i]; + if (0 == strcmp(cert->opt, opt)) { + return cert; + } + } + + return NULL; +} diff --git a/drivers/rz/ipl/rza/tools/cert_create/src/cmd_opt.c b/drivers/rz/ipl/rza/tools/cert_create/src/cmd_opt.c new file mode 100644 index 00000000..64180d1f --- /dev/null +++ b/drivers/rz/ipl/rza/tools/cert_create/src/cmd_opt.c @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include "debug.h" + +/* Command line options */ +static struct option long_opt[CMD_OPT_MAX_NUM+1]; +static const char *help_msg[CMD_OPT_MAX_NUM+1]; +static int num_reg_opt; + +void cmd_opt_add(const cmd_opt_t *cmd_opt) +{ + assert(cmd_opt != NULL); + + if (num_reg_opt >= CMD_OPT_MAX_NUM) { + ERROR("Out of memory. Please increase CMD_OPT_MAX_NUM\n"); + exit(1); + } + + long_opt[num_reg_opt].name = cmd_opt->long_opt.name; + long_opt[num_reg_opt].has_arg = cmd_opt->long_opt.has_arg; + long_opt[num_reg_opt].flag = 0; + long_opt[num_reg_opt].val = cmd_opt->long_opt.val; + + help_msg[num_reg_opt] = cmd_opt->help_msg; + + num_reg_opt++; +} + +const struct option *cmd_opt_get_array(void) +{ + return long_opt; +} + +const char *cmd_opt_get_name(int idx) +{ + if (idx >= num_reg_opt) { + return NULL; + } + + return long_opt[idx].name; +} + +const char *cmd_opt_get_help_msg(int idx) +{ + if (idx >= num_reg_opt) { + return NULL; + } + + return help_msg[idx]; +} diff --git a/drivers/rz/ipl/rza/tools/cert_create/src/dualroot/cot.c b/drivers/rz/ipl/rza/tools/cert_create/src/dualroot/cot.c new file mode 100644 index 00000000..4dd4cf03 --- /dev/null +++ b/drivers/rz/ipl/rza/tools/cert_create/src/dualroot/cot.c @@ -0,0 +1,583 @@ +/* + * Copyright (c) 2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include "cert.h" +#include "ext.h" +#include "key.h" + +#include "dualroot/cot.h" + +/* + * Certificates used in the chain of trust. + * + * All certificates are self-signed so the issuer certificate field points to + * itself. + */ +static cert_t cot_certs[] = { + [TRUSTED_BOOT_FW_CERT] = { + .id = TRUSTED_BOOT_FW_CERT, + .opt = "tb-fw-cert", + .help_msg = "Trusted Boot FW Certificate (output file)", + .cn = "Trusted Boot FW Certificate", + .key = ROT_KEY, + .issuer = TRUSTED_BOOT_FW_CERT, + .ext = { + TRUSTED_FW_NVCOUNTER_EXT, + TRUSTED_BOOT_FW_HASH_EXT, + TRUSTED_BOOT_FW_CONFIG_HASH_EXT, + HW_CONFIG_HASH_EXT, + FW_CONFIG_HASH_EXT + }, + .num_ext = 5 + }, + + [TRUSTED_KEY_CERT] = { + .id = TRUSTED_KEY_CERT, + .opt = "trusted-key-cert", + .help_msg = "Trusted Key Certificate (output file)", + .cn = "Trusted Key Certificate", + .key = ROT_KEY, + .issuer = TRUSTED_KEY_CERT, + .ext = { + TRUSTED_FW_NVCOUNTER_EXT, + TRUSTED_WORLD_PK_EXT, + }, + .num_ext = 2 + }, + + [SCP_FW_KEY_CERT] = { + .id = SCP_FW_KEY_CERT, + .opt = "scp-fw-key-cert", + .help_msg = "SCP Firmware Key Certificate (output file)", + .cn = "SCP Firmware Key Certificate", + .key = TRUSTED_WORLD_KEY, + .issuer = SCP_FW_KEY_CERT, + .ext = { + TRUSTED_FW_NVCOUNTER_EXT, + SCP_FW_CONTENT_CERT_PK_EXT + }, + .num_ext = 2 + }, + + [SCP_FW_CONTENT_CERT] = { + .id = SCP_FW_CONTENT_CERT, + .opt = "scp-fw-cert", + .help_msg = "SCP Firmware Content Certificate (output file)", + .cn = "SCP Firmware Content Certificate", + .key = SCP_FW_CONTENT_CERT_KEY, + .issuer = SCP_FW_CONTENT_CERT, + .ext = { + TRUSTED_FW_NVCOUNTER_EXT, + SCP_FW_HASH_EXT + }, + .num_ext = 2 + }, + + [SOC_FW_KEY_CERT] = { + .id = SOC_FW_KEY_CERT, + .opt = "soc-fw-key-cert", + .help_msg = "SoC Firmware Key Certificate (output file)", + .cn = "SoC Firmware Key Certificate", + .key = TRUSTED_WORLD_KEY, + .issuer = SOC_FW_KEY_CERT, + .ext = { + TRUSTED_FW_NVCOUNTER_EXT, + SOC_FW_CONTENT_CERT_PK_EXT + }, + .num_ext = 2 + }, + + [SOC_FW_CONTENT_CERT] = { + .id = SOC_FW_CONTENT_CERT, + .opt = "soc-fw-cert", + .help_msg = "SoC Firmware Content Certificate (output file)", + .cn = "SoC Firmware Content Certificate", + .key = SOC_FW_CONTENT_CERT_KEY, + .issuer = SOC_FW_CONTENT_CERT, + .ext = { + TRUSTED_FW_NVCOUNTER_EXT, + SOC_AP_FW_HASH_EXT, + SOC_FW_CONFIG_HASH_EXT, + }, + .num_ext = 3 + }, + + [TRUSTED_OS_FW_KEY_CERT] = { + .id = TRUSTED_OS_FW_KEY_CERT, + .opt = "tos-fw-key-cert", + .help_msg = "Trusted OS Firmware Key Certificate (output file)", + .cn = "Trusted OS Firmware Key Certificate", + .key = TRUSTED_WORLD_KEY, + .issuer = TRUSTED_OS_FW_KEY_CERT, + .ext = { + TRUSTED_FW_NVCOUNTER_EXT, + TRUSTED_OS_FW_CONTENT_CERT_PK_EXT + }, + .num_ext = 2 + }, + + [TRUSTED_OS_FW_CONTENT_CERT] = { + .id = TRUSTED_OS_FW_CONTENT_CERT, + .opt = "tos-fw-cert", + .help_msg = "Trusted OS Firmware Content Certificate (output file)", + .cn = "Trusted OS Firmware Content Certificate", + .key = TRUSTED_OS_FW_CONTENT_CERT_KEY, + .issuer = TRUSTED_OS_FW_CONTENT_CERT, + .ext = { + TRUSTED_FW_NVCOUNTER_EXT, + TRUSTED_OS_FW_HASH_EXT, + TRUSTED_OS_FW_EXTRA1_HASH_EXT, + TRUSTED_OS_FW_EXTRA2_HASH_EXT, + TRUSTED_OS_FW_CONFIG_HASH_EXT, + }, + .num_ext = 5 + }, + + [SIP_SECURE_PARTITION_CONTENT_CERT] = { + .id = SIP_SECURE_PARTITION_CONTENT_CERT, + .opt = "sip-sp-cert", + .help_msg = "SiP owned Secure Partition Content Certificate (output file)", + .fn = NULL, + .cn = "SiP owned Secure Partition Content Certificate", + .key = TRUSTED_WORLD_KEY, + .issuer = SIP_SECURE_PARTITION_CONTENT_CERT, + .ext = { + TRUSTED_FW_NVCOUNTER_EXT, + SP_PKG1_HASH_EXT, + SP_PKG2_HASH_EXT, + SP_PKG3_HASH_EXT, + SP_PKG4_HASH_EXT, + }, + .num_ext = 5 + }, + + [PLAT_SECURE_PARTITION_CONTENT_CERT] = { + .id = PLAT_SECURE_PARTITION_CONTENT_CERT, + .opt = "plat-sp-cert", + .help_msg = "Platform owned Secure Partition Content Certificate (output file)", + .fn = NULL, + .cn = "Platform owned Secure Partition Content Certificate", + .key = PROT_KEY, + .issuer = PLAT_SECURE_PARTITION_CONTENT_CERT, + .ext = { + NON_TRUSTED_FW_NVCOUNTER_EXT, + SP_PKG5_HASH_EXT, + SP_PKG6_HASH_EXT, + SP_PKG7_HASH_EXT, + SP_PKG8_HASH_EXT, + PROT_PK_EXT, + }, + .num_ext = 6 + }, + + [FWU_CERT] = { + .id = FWU_CERT, + .opt = "fwu-cert", + .help_msg = "Firmware Update Certificate (output file)", + .cn = "Firmware Update Certificate", + .key = ROT_KEY, + .issuer = FWU_CERT, + .ext = { + SCP_FWU_CFG_HASH_EXT, + AP_FWU_CFG_HASH_EXT, + FWU_HASH_EXT + }, + .num_ext = 3 + }, + + [NON_TRUSTED_FW_CONTENT_CERT] = { + .id = NON_TRUSTED_FW_CONTENT_CERT, + .opt = "nt-fw-cert", + .help_msg = "Non-Trusted Firmware Content Certificate (output file)", + .cn = "Non-Trusted Firmware Content Certificate", + .key = PROT_KEY, + .issuer = NON_TRUSTED_FW_CONTENT_CERT, + .ext = { + NON_TRUSTED_FW_NVCOUNTER_EXT, + NON_TRUSTED_WORLD_BOOTLOADER_HASH_EXT, + NON_TRUSTED_FW_CONFIG_HASH_EXT, + PROT_PK_EXT, + }, + .num_ext = 4 + }, +}; + +REGISTER_COT(cot_certs); + + +/* Certificate extensions. */ +static ext_t cot_ext[] = { + [TRUSTED_FW_NVCOUNTER_EXT] = { + .oid = TRUSTED_FW_NVCOUNTER_OID, + .opt = "tfw-nvctr", + .help_msg = "Trusted Firmware Non-Volatile counter value", + .sn = "TrustedWorldNVCounter", + .ln = "Trusted World Non-Volatile counter", + .asn1_type = V_ASN1_INTEGER, + .type = EXT_TYPE_NVCOUNTER, + .attr.nvctr_type = NVCTR_TYPE_TFW + }, + + [TRUSTED_BOOT_FW_HASH_EXT] = { + .oid = TRUSTED_BOOT_FW_HASH_OID, + .opt = "tb-fw", + .help_msg = "Trusted Boot Firmware image file", + .sn = "TrustedBootFirmwareHash", + .ln = "Trusted Boot Firmware hash (SHA256)", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH + }, + + [TRUSTED_BOOT_FW_CONFIG_HASH_EXT] = { + .oid = TRUSTED_BOOT_FW_CONFIG_HASH_OID, + .opt = "tb-fw-config", + .help_msg = "Trusted Boot Firmware Config file", + .sn = "TrustedBootFirmwareConfigHash", + .ln = "Trusted Boot Firmware Config hash", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH, + .optional = 1 + }, + + [HW_CONFIG_HASH_EXT] = { + .oid = HW_CONFIG_HASH_OID, + .opt = "hw-config", + .help_msg = "HW Config file", + .sn = "HWConfigHash", + .ln = "HW Config hash", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH, + .optional = 1 + }, + + [FW_CONFIG_HASH_EXT] = { + .oid = FW_CONFIG_HASH_OID, + .opt = "fw-config", + .help_msg = "Firmware Config file", + .sn = "FirmwareConfigHash", + .ln = "Firmware Config hash", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH, + .optional = 1 + }, + + [TRUSTED_WORLD_PK_EXT] = { + .oid = TRUSTED_WORLD_PK_OID, + .sn = "TrustedWorldPublicKey", + .ln = "Trusted World Public Key", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_PKEY, + .attr.key = TRUSTED_WORLD_KEY + }, + + [SCP_FW_CONTENT_CERT_PK_EXT] = { + .oid = SCP_FW_CONTENT_CERT_PK_OID, + .sn = "SCPFirmwareContentCertPK", + .ln = "SCP Firmware content certificate public key", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_PKEY, + .attr.key = SCP_FW_CONTENT_CERT_KEY + }, + + [SCP_FW_HASH_EXT] = { + .oid = SCP_FW_HASH_OID, + .opt = "scp-fw", + .help_msg = "SCP Firmware image file", + .sn = "SCPFirmwareHash", + .ln = "SCP Firmware hash (SHA256)", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH + }, + + [SOC_FW_CONTENT_CERT_PK_EXT] = { + .oid = SOC_FW_CONTENT_CERT_PK_OID, + .sn = "SoCFirmwareContentCertPK", + .ln = "SoC Firmware content certificate public key", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_PKEY, + .attr.key = SOC_FW_CONTENT_CERT_KEY + }, + + [SOC_AP_FW_HASH_EXT] = { + .oid = SOC_AP_FW_HASH_OID, + .opt = "soc-fw", + .help_msg = "SoC AP Firmware image file", + .sn = "SoCAPFirmwareHash", + .ln = "SoC AP Firmware hash (SHA256)", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH + }, + + [SOC_FW_CONFIG_HASH_EXT] = { + .oid = SOC_FW_CONFIG_HASH_OID, + .opt = "soc-fw-config", + .help_msg = "SoC Firmware Config file", + .sn = "SocFirmwareConfigHash", + .ln = "SoC Firmware Config hash", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH, + .optional = 1 + }, + + [TRUSTED_OS_FW_CONTENT_CERT_PK_EXT] = { + .oid = TRUSTED_OS_FW_CONTENT_CERT_PK_OID, + .sn = "TrustedOSFirmwareContentCertPK", + .ln = "Trusted OS Firmware content certificate public key", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_PKEY, + .attr.key = TRUSTED_OS_FW_CONTENT_CERT_KEY + }, + + [TRUSTED_OS_FW_HASH_EXT] = { + .oid = TRUSTED_OS_FW_HASH_OID, + .opt = "tos-fw", + .help_msg = "Trusted OS image file", + .sn = "TrustedOSHash", + .ln = "Trusted OS hash (SHA256)", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH + }, + + [TRUSTED_OS_FW_EXTRA1_HASH_EXT] = { + .oid = TRUSTED_OS_FW_EXTRA1_HASH_OID, + .opt = "tos-fw-extra1", + .help_msg = "Trusted OS Extra1 image file", + .sn = "TrustedOSExtra1Hash", + .ln = "Trusted OS Extra1 hash (SHA256)", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH, + .optional = 1 + }, + + [TRUSTED_OS_FW_EXTRA2_HASH_EXT] = { + .oid = TRUSTED_OS_FW_EXTRA2_HASH_OID, + .opt = "tos-fw-extra2", + .help_msg = "Trusted OS Extra2 image file", + .sn = "TrustedOSExtra2Hash", + .ln = "Trusted OS Extra2 hash (SHA256)", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH, + .optional = 1 + }, + + [TRUSTED_OS_FW_CONFIG_HASH_EXT] = { + .oid = TRUSTED_OS_FW_CONFIG_HASH_OID, + .opt = "tos-fw-config", + .help_msg = "Trusted OS Firmware Config file", + .sn = "TrustedOSFirmwareConfigHash", + .ln = "Trusted OS Firmware Config hash", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH, + .optional = 1 + }, + + [SP_PKG1_HASH_EXT] = { + .oid = SP_PKG1_HASH_OID, + .opt = "sp-pkg1", + .help_msg = "Secure Partition Package1 file", + .sn = "SPPkg1Hash", + .ln = "SP Pkg1 hash (SHA256)", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH, + .optional = 1 + }, + [SP_PKG2_HASH_EXT] = { + .oid = SP_PKG2_HASH_OID, + .opt = "sp-pkg2", + .help_msg = "Secure Partition Package2 file", + .sn = "SPPkg2Hash", + .ln = "SP Pkg2 hash (SHA256)", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH, + .optional = 1 + }, + [SP_PKG3_HASH_EXT] = { + .oid = SP_PKG3_HASH_OID, + .opt = "sp-pkg3", + .help_msg = "Secure Partition Package3 file", + .sn = "SPPkg3Hash", + .ln = "SP Pkg3 hash (SHA256)", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH, + .optional = 1 + }, + [SP_PKG4_HASH_EXT] = { + .oid = SP_PKG4_HASH_OID, + .opt = "sp-pkg4", + .help_msg = "Secure Partition Package4 file", + .sn = "SPPkg4Hash", + .ln = "SP Pkg4 hash (SHA256)", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH, + .optional = 1 + }, + [SP_PKG5_HASH_EXT] = { + .oid = SP_PKG5_HASH_OID, + .opt = "sp-pkg5", + .help_msg = "Secure Partition Package5 file", + .sn = "SPPkg5Hash", + .ln = "SP Pkg5 hash (SHA256)", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH, + .optional = 1 + }, + [SP_PKG6_HASH_EXT] = { + .oid = SP_PKG6_HASH_OID, + .opt = "sp-pkg6", + .help_msg = "Secure Partition Package6 file", + .sn = "SPPkg6Hash", + .ln = "SP Pkg6 hash (SHA256)", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH, + .optional = 1 + }, + [SP_PKG7_HASH_EXT] = { + .oid = SP_PKG7_HASH_OID, + .opt = "sp-pkg7", + .help_msg = "Secure Partition Package7 file", + .sn = "SPPkg7Hash", + .ln = "SP Pkg7 hash (SHA256)", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH, + .optional = 1 + }, + [SP_PKG8_HASH_EXT] = { + .oid = SP_PKG8_HASH_OID, + .opt = "sp-pkg8", + .help_msg = "Secure Partition Package8 file", + .sn = "SPPkg8Hash", + .ln = "SP Pkg8 hash (SHA256)", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH, + .optional = 1 + }, + + [SCP_FWU_CFG_HASH_EXT] = { + .oid = SCP_FWU_CFG_HASH_OID, + .opt = "scp-fwu-cfg", + .help_msg = "SCP Firmware Update Config image file", + .sn = "SCPFWUpdateConfig", + .ln = "SCP Firmware Update Config hash (SHA256)", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH, + .optional = 1 + }, + + [AP_FWU_CFG_HASH_EXT] = { + .oid = AP_FWU_CFG_HASH_OID, + .opt = "ap-fwu-cfg", + .help_msg = "AP Firmware Update Config image file", + .sn = "APFWUpdateConfig", + .ln = "AP Firmware Update Config hash (SHA256)", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH, + .optional = 1 + }, + + [FWU_HASH_EXT] = { + .oid = FWU_HASH_OID, + .opt = "fwu", + .help_msg = "Firmware Updater image file", + .sn = "FWUpdaterHash", + .ln = "Firmware Updater hash (SHA256)", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH, + .optional = 1 + }, + + [PROT_PK_EXT] = { + .oid = PROT_PK_OID, + .sn = "PlatformRoTKey", + .ln = "Platform Root of Trust Public Key", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_PKEY, + .attr.key = PROT_KEY + }, + + [NON_TRUSTED_FW_NVCOUNTER_EXT] = { + .oid = NON_TRUSTED_FW_NVCOUNTER_OID, + .opt = "ntfw-nvctr", + .help_msg = "Non-Trusted Firmware Non-Volatile counter value", + .sn = "NormalWorldNVCounter", + .ln = "Non-Trusted Firmware Non-Volatile counter", + .asn1_type = V_ASN1_INTEGER, + .type = EXT_TYPE_NVCOUNTER, + .attr.nvctr_type = NVCTR_TYPE_NTFW + }, + + [NON_TRUSTED_WORLD_BOOTLOADER_HASH_EXT] = { + .oid = NON_TRUSTED_WORLD_BOOTLOADER_HASH_OID, + .opt = "nt-fw", + .help_msg = "Non-Trusted World Bootloader image file", + .sn = "NonTrustedWorldBootloaderHash", + .ln = "Non-Trusted World hash (SHA256)", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH + }, + + [NON_TRUSTED_FW_CONFIG_HASH_EXT] = { + .oid = NON_TRUSTED_FW_CONFIG_HASH_OID, + .opt = "nt-fw-config", + .help_msg = "Non Trusted OS Firmware Config file", + .sn = "NonTrustedOSFirmwareConfigHash", + .ln = "Non-Trusted OS Firmware Config hash", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH, + .optional = 1 + }, +}; + +REGISTER_EXTENSIONS(cot_ext); + + +/* Keys used to establish the chain of trust. */ +static key_t cot_keys[] = { + [ROT_KEY] = { + .id = ROT_KEY, + .opt = "rot-key", + .help_msg = "Root Of Trust key (input/output file)", + .desc = "Root Of Trust key" + }, + + [TRUSTED_WORLD_KEY] = { + .id = TRUSTED_WORLD_KEY, + .opt = "trusted-world-key", + .help_msg = "Trusted World key (input/output file)", + .desc = "Trusted World key" + }, + + [SCP_FW_CONTENT_CERT_KEY] = { + .id = SCP_FW_CONTENT_CERT_KEY, + .opt = "scp-fw-key", + .help_msg = "SCP Firmware Content Certificate key (input/output file)", + .desc = "SCP Firmware Content Certificate key" + }, + + [SOC_FW_CONTENT_CERT_KEY] = { + .id = SOC_FW_CONTENT_CERT_KEY, + .opt = "soc-fw-key", + .help_msg = "SoC Firmware Content Certificate key (input/output file)", + .desc = "SoC Firmware Content Certificate key" + }, + + [TRUSTED_OS_FW_CONTENT_CERT_KEY] = { + .id = TRUSTED_OS_FW_CONTENT_CERT_KEY, + .opt = "tos-fw-key", + .help_msg = "Trusted OS Firmware Content Certificate key (input/output file)", + .desc = "Trusted OS Firmware Content Certificate key" + }, + + [PROT_KEY] = { + .id = PROT_KEY, + .opt = "prot-key", + .help_msg = "Platform Root of Trust key", + .desc = "Platform Root of Trust key" + }, +}; + +REGISTER_KEYS(cot_keys); diff --git a/drivers/rz/ipl/rza/tools/cert_create/src/dualroot/cot.mk b/drivers/rz/ipl/rza/tools/cert_create/src/dualroot/cot.mk new file mode 100644 index 00000000..a572484d --- /dev/null +++ b/drivers/rz/ipl/rza/tools/cert_create/src/dualroot/cot.mk @@ -0,0 +1,10 @@ +# +# Copyright (c) 2020, Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +PLAT_MSG := Dual root of trust +PLAT_INCLUDE := ../../include/tools_share + +OBJECTS += src/dualroot/cot.o diff --git a/drivers/rz/ipl/rza/tools/cert_create/src/ext.c b/drivers/rz/ipl/rza/tools/cert_create/src/ext.c new file mode 100644 index 00000000..28821238 --- /dev/null +++ b/drivers/rz/ipl/rza/tools/cert_create/src/ext.c @@ -0,0 +1,317 @@ +/* + * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "cmd_opt.h" +#include "debug.h" +#include "ext.h" + +ext_t *extensions; +unsigned int num_extensions; + +DECLARE_ASN1_ITEM(ASN1_INTEGER) +DECLARE_ASN1_ITEM(X509_ALGOR) +DECLARE_ASN1_ITEM(ASN1_OCTET_STRING) + +typedef struct { + X509_ALGOR *hashAlgorithm; + ASN1_OCTET_STRING *dataHash; +} HASH; + +ASN1_SEQUENCE(HASH) = { + ASN1_SIMPLE(HASH, hashAlgorithm, X509_ALGOR), + ASN1_SIMPLE(HASH, dataHash, ASN1_OCTET_STRING), +} ASN1_SEQUENCE_END(HASH) + +DECLARE_ASN1_FUNCTIONS(HASH) +IMPLEMENT_ASN1_FUNCTIONS(HASH) + +/* + * This function adds the CoT extensions to the internal extension list + * maintained by OpenSSL so they can be used later. + * + * It also initializes the methods to print the contents of the extension. If an + * alias is specified in the CoT extension, we reuse the methods of the alias. + * Otherwise, only methods for V_ASN1_INTEGER and V_ASN1_OCTET_STRING are + * provided. Any other type will be printed as a raw ascii string. + * + * Return: 0 = success, Otherwise: error + */ +int ext_init(void) +{ + cmd_opt_t cmd_opt; + ext_t *ext; + X509V3_EXT_METHOD *m; + int nid, ret; + unsigned int i; + + extensions = malloc((num_def_extensions * sizeof(def_extensions[0])) +#ifdef PDEF_EXTS + + (num_pdef_extensions * sizeof(pdef_extensions[0])) +#endif + ); + if (extensions == NULL) { + ERROR("%s:%d Failed to allocate memory.\n", __func__, __LINE__); + return 1; + } + + memcpy(&extensions[0], &def_extensions[0], + (num_def_extensions * sizeof(def_extensions[0]))); +#ifdef PDEF_EXTS + memcpy(&extensions[num_def_extensions], &pdef_extensions[0], + (num_pdef_extensions * sizeof(pdef_extensions[0]))); + num_extensions = num_def_extensions + num_pdef_extensions; +#else + num_extensions = num_def_extensions; +#endif + + for (i = 0; i < num_extensions; i++) { + ext = &extensions[i]; + /* Register command line option */ + if (ext->opt) { + cmd_opt.long_opt.name = ext->opt; + cmd_opt.long_opt.has_arg = required_argument; + cmd_opt.long_opt.flag = NULL; + cmd_opt.long_opt.val = CMD_OPT_EXT; + cmd_opt.help_msg = ext->help_msg; + cmd_opt_add(&cmd_opt); + } + /* Register the extension OID in OpenSSL */ + if (ext->oid == NULL) { + continue; + } + nid = OBJ_create(ext->oid, ext->sn, ext->ln); + if (ext->alias) { + X509V3_EXT_add_alias(nid, ext->alias); + } else { + m = &ext->method; + memset(m, 0x0, sizeof(X509V3_EXT_METHOD)); + switch (ext->asn1_type) { + case V_ASN1_INTEGER: + m->it = ASN1_ITEM_ref(ASN1_INTEGER); + m->i2s = (X509V3_EXT_I2S)i2s_ASN1_INTEGER; + m->s2i = (X509V3_EXT_S2I)s2i_ASN1_INTEGER; + break; + case V_ASN1_OCTET_STRING: + m->it = ASN1_ITEM_ref(ASN1_OCTET_STRING); + m->i2s = (X509V3_EXT_I2S)i2s_ASN1_OCTET_STRING; + m->s2i = (X509V3_EXT_S2I)s2i_ASN1_OCTET_STRING; + break; + default: + continue; + } + m->ext_nid = nid; + ret = X509V3_EXT_add(m); + if (!ret) { + ERR_print_errors_fp(stdout); + return 1; + } + } + } + return 0; +} + +/* + * Create a new extension + * + * Extension ::= SEQUENCE { + * id OBJECT IDENTIFIER, + * critical BOOLEAN DEFAULT FALSE, + * value OCTET STRING } + * + * Parameters: + * pex: OpenSSL extension pointer (output parameter) + * nid: extension identifier + * crit: extension critical (EXT_NON_CRIT, EXT_CRIT) + * data: extension data. This data will be encapsulated in an Octet String + * + * Return: Extension address, NULL if error + */ +static +X509_EXTENSION *ext_new(int nid, int crit, unsigned char *data, int len) +{ + X509_EXTENSION *ex; + ASN1_OCTET_STRING *ext_data; + + /* Octet string containing the extension data */ + ext_data = ASN1_OCTET_STRING_new(); + ASN1_OCTET_STRING_set(ext_data, data, len); + + /* Create the extension */ + ex = X509_EXTENSION_create_by_NID(NULL, nid, crit, ext_data); + + /* The extension makes a copy of the data, so we can free this object */ + ASN1_OCTET_STRING_free(ext_data); + + return ex; +} + +/* + * Creates a x509v3 extension containing a hash + * + * DigestInfo ::= SEQUENCE { + * digestAlgorithm AlgorithmIdentifier, + * digest OCTET STRING + * } + * + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL + * } + * + * Parameters: + * nid: extension identifier + * crit: extension critical (EXT_NON_CRIT, EXT_CRIT) + * md: hash algorithm + * buf: pointer to the buffer that contains the hash + * len: size of the hash in bytes + * + * Return: Extension address, NULL if error + */ +X509_EXTENSION *ext_new_hash(int nid, int crit, const EVP_MD *md, + unsigned char *buf, size_t len) +{ + X509_EXTENSION *ex; + HASH *hash; + ASN1_OBJECT *algorithm; + unsigned char *p = NULL; + int sz; + + /* HASH structure containing algorithm + hash */ + hash = HASH_new(); + if (hash == NULL) { + return NULL; + } + + /* OBJECT_IDENTIFIER with hash algorithm */ + algorithm = OBJ_nid2obj(EVP_MD_type(md)); + if (algorithm == NULL) { + HASH_free(hash); + return NULL; + } + + /* Create X509_ALGOR */ + hash->hashAlgorithm->algorithm = algorithm; + hash->hashAlgorithm->parameter = ASN1_TYPE_new(); + ASN1_TYPE_set(hash->hashAlgorithm->parameter, V_ASN1_NULL, NULL); + + /* OCTET_STRING with the actual hash */ + ASN1_OCTET_STRING_set(hash->dataHash, buf, len); + + /* DER encoded HASH */ + sz = i2d_HASH(hash, &p); + if ((sz <= 0) || (p == NULL)) { + HASH_free(hash); + return NULL; + } + + /* Create the extension */ + ex = ext_new(nid, crit, p, sz); + + /* Clean up */ + OPENSSL_free(p); + HASH_free(hash); + + return ex; +} + +/* + * Creates a x509v3 extension containing a nvcounter encapsulated in an ASN1 + * Integer + * + * Parameters: + * pex: OpenSSL extension pointer (output parameter) + * nid: extension identifier + * crit: extension critical (EXT_NON_CRIT, EXT_CRIT) + * value: nvcounter value + * + * Return: Extension address, NULL if error + */ +X509_EXTENSION *ext_new_nvcounter(int nid, int crit, int value) +{ + X509_EXTENSION *ex; + ASN1_INTEGER *counter; + unsigned char *p = NULL; + int sz; + + /* Encode counter */ + counter = ASN1_INTEGER_new(); + ASN1_INTEGER_set(counter, value); + sz = i2d_ASN1_INTEGER(counter, &p); + + /* Create the extension */ + ex = ext_new(nid, crit, p, sz); + + /* Free objects */ + OPENSSL_free(p); + ASN1_INTEGER_free(counter); + + return ex; +} + +/* + * Creates a x509v3 extension containing a public key in DER format: + * + * SubjectPublicKeyInfo ::= SEQUENCE { + * algorithm AlgorithmIdentifier, + * subjectPublicKey BIT STRING } + * + * Parameters: + * pex: OpenSSL extension pointer (output parameter) + * nid: extension identifier + * crit: extension critical (EXT_NON_CRIT, EXT_CRIT) + * k: key + * + * Return: Extension address, NULL if error + */ +X509_EXTENSION *ext_new_key(int nid, int crit, EVP_PKEY *k) +{ + X509_EXTENSION *ex; + unsigned char *p; + int sz; + + /* Encode key */ + BIO *mem = BIO_new(BIO_s_mem()); + if (i2d_PUBKEY_bio(mem, k) <= 0) { + ERR_print_errors_fp(stderr); + return NULL; + } + p = (unsigned char *)OPENSSL_malloc(4096); + sz = BIO_read(mem, p, 4096); + + /* Create the extension */ + ex = ext_new(nid, crit, p, sz); + + /* Clean up */ + BIO_free(mem); + OPENSSL_free(p); + + return ex; +} + +ext_t *ext_get_by_opt(const char *opt) +{ + ext_t *ext; + unsigned int i; + + /* Sequential search. This is not a performance concern since the number + * of extensions is bounded and the code runs on a host machine */ + for (i = 0; i < num_extensions; i++) { + ext = &extensions[i]; + if (ext->opt && !strcmp(ext->opt, opt)) { + return ext; + } + } + + return NULL; +} diff --git a/drivers/rz/ipl/rza/tools/cert_create/src/key.c b/drivers/rz/ipl/rza/tools/cert_create/src/key.c new file mode 100644 index 00000000..64359756 --- /dev/null +++ b/drivers/rz/ipl/rza/tools/cert_create/src/key.c @@ -0,0 +1,240 @@ +/* + * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +#include +#include +#include + +#include "cert.h" +#include "cmd_opt.h" +#include "debug.h" +#include "key.h" +#include "sha.h" + +#define MAX_FILENAME_LEN 1024 + +key_t *keys; +unsigned int num_keys; + +/* + * Create a new key container + */ +int key_new(key_t *key) +{ + /* Create key pair container */ + key->key = EVP_PKEY_new(); + if (key->key == NULL) { + return 0; + } + + return 1; +} + +static int key_create_rsa(key_t *key, int key_bits) +{ + BIGNUM *e; + RSA *rsa = NULL; + + e = BN_new(); + if (e == NULL) { + printf("Cannot create RSA exponent\n"); + goto err; + } + + if (!BN_set_word(e, RSA_F4)) { + printf("Cannot assign RSA exponent\n"); + goto err; + } + + rsa = RSA_new(); + if (rsa == NULL) { + printf("Cannot create RSA key\n"); + goto err; + } + + if (!RSA_generate_key_ex(rsa, key_bits, e, NULL)) { + printf("Cannot generate RSA key\n"); + goto err; + } + + if (!EVP_PKEY_assign_RSA(key->key, rsa)) { + printf("Cannot assign RSA key\n"); + goto err; + } + + BN_free(e); + return 1; +err: + RSA_free(rsa); + BN_free(e); + return 0; +} + +#ifndef OPENSSL_NO_EC +static int key_create_ecdsa(key_t *key, int key_bits) +{ + EC_KEY *ec; + + ec = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); + if (ec == NULL) { + printf("Cannot create EC key\n"); + goto err; + } + if (!EC_KEY_generate_key(ec)) { + printf("Cannot generate EC key\n"); + goto err; + } + EC_KEY_set_flags(ec, EC_PKEY_NO_PARAMETERS); + EC_KEY_set_asn1_flag(ec, OPENSSL_EC_NAMED_CURVE); + if (!EVP_PKEY_assign_EC_KEY(key->key, ec)) { + printf("Cannot assign EC key\n"); + goto err; + } + + return 1; +err: + EC_KEY_free(ec); + return 0; +} +#endif /* OPENSSL_NO_EC */ + +typedef int (*key_create_fn_t)(key_t *key, int key_bits); +static const key_create_fn_t key_create_fn[KEY_ALG_MAX_NUM] = { + key_create_rsa, /* KEY_ALG_RSA */ +#ifndef OPENSSL_NO_EC + key_create_ecdsa, /* KEY_ALG_ECDSA */ +#endif /* OPENSSL_NO_EC */ +}; + +int key_create(key_t *key, int type, int key_bits) +{ + if (type >= KEY_ALG_MAX_NUM) { + printf("Invalid key type\n"); + return 0; + } + + if (key_create_fn[type]) { + return key_create_fn[type](key, key_bits); + } + + return 0; +} + +int key_load(key_t *key, unsigned int *err_code) +{ + FILE *fp; + EVP_PKEY *k; + + if (key->fn) { + /* Load key from file */ + fp = fopen(key->fn, "r"); + if (fp) { + k = PEM_read_PrivateKey(fp, &key->key, NULL, NULL); + fclose(fp); + if (k) { + *err_code = KEY_ERR_NONE; + return 1; + } else { + ERROR("Cannot load key from %s\n", key->fn); + *err_code = KEY_ERR_LOAD; + } + } else { + WARN("Cannot open file %s\n", key->fn); + *err_code = KEY_ERR_OPEN; + } + } else { + WARN("Key filename not specified\n"); + *err_code = KEY_ERR_FILENAME; + } + + return 0; +} + +int key_store(key_t *key) +{ + FILE *fp; + + if (key->fn) { + fp = fopen(key->fn, "w"); + if (fp) { + PEM_write_PrivateKey(fp, key->key, + NULL, NULL, 0, NULL, NULL); + fclose(fp); + return 1; + } else { + ERROR("Cannot create file %s\n", key->fn); + } + } else { + ERROR("Key filename not specified\n"); + } + + return 0; +} + +int key_init(void) +{ + cmd_opt_t cmd_opt; + key_t *key; + unsigned int i; + + keys = malloc((num_def_keys * sizeof(def_keys[0])) +#ifdef PDEF_KEYS + + (num_pdef_keys * sizeof(pdef_keys[0])) +#endif + ); + + if (keys == NULL) { + ERROR("%s:%d Failed to allocate memory.\n", __func__, __LINE__); + return 1; + } + + memcpy(&keys[0], &def_keys[0], (num_def_keys * sizeof(def_keys[0]))); +#ifdef PDEF_KEYS + memcpy(&keys[num_def_keys], &pdef_keys[0], + (num_pdef_keys * sizeof(pdef_keys[0]))); + + num_keys = num_def_keys + num_pdef_keys; +#else + num_keys = num_def_keys; +#endif + ; + + for (i = 0; i < num_keys; i++) { + key = &keys[i]; + if (key->opt != NULL) { + cmd_opt.long_opt.name = key->opt; + cmd_opt.long_opt.has_arg = required_argument; + cmd_opt.long_opt.flag = NULL; + cmd_opt.long_opt.val = CMD_OPT_KEY; + cmd_opt.help_msg = key->help_msg; + cmd_opt_add(&cmd_opt); + } + } + + return 0; +} + +key_t *key_get_by_opt(const char *opt) +{ + key_t *key; + unsigned int i; + + /* Sequential search. This is not a performance concern since the number + * of keys is bounded and the code runs on a host machine */ + for (i = 0; i < num_keys; i++) { + key = &keys[i]; + if (0 == strcmp(key->opt, opt)) { + return key; + } + } + + return NULL; +} diff --git a/drivers/rz/ipl/rza/tools/cert_create/src/main.c b/drivers/rz/ipl/rza/tools/cert_create/src/main.c new file mode 100644 index 00000000..b39378ca --- /dev/null +++ b/drivers/rz/ipl/rza/tools/cert_create/src/main.c @@ -0,0 +1,634 @@ +/* + * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "cert.h" +#include "cmd_opt.h" +#include "debug.h" +#include "ext.h" +#include "key.h" +#include "sha.h" + +/* + * Helper macros to simplify the code. This macro assigns the return value of + * the 'fn' function to 'v' and exits if the value is NULL. + */ +#define CHECK_NULL(v, fn) \ + do { \ + v = fn; \ + if (v == NULL) { \ + ERROR("NULL object at %s:%d\n", __FILE__, __LINE__); \ + exit(1); \ + } \ + } while (0) + +/* + * This macro assigns the NID corresponding to 'oid' to 'v' and exits if the + * NID is undefined. + */ +#define CHECK_OID(v, oid) \ + do { \ + v = OBJ_txt2nid(oid); \ + if (v == NID_undef) { \ + ERROR("Cannot find extension %s\n", oid); \ + exit(1); \ + } \ + } while (0) + +#define MAX_FILENAME_LEN 1024 +#define VAL_DAYS 7300 +#define ID_TO_BIT_MASK(id) (1 << id) +#define NUM_ELEM(x) ((sizeof(x)) / (sizeof(x[0]))) +#define HELP_OPT_MAX_LEN 128 + +/* Global options */ +static int key_alg; +static int hash_alg; +static int key_size; +static int new_keys; +static int save_keys; +static int print_cert; + +/* Info messages created in the Makefile */ +extern const char build_msg[]; +extern const char platform_msg[]; + + +static char *strdup(const char *str) +{ + int n = strlen(str) + 1; + char *dup = malloc(n); + if (dup) { + strcpy(dup, str); + } + return dup; +} + +static const char *key_algs_str[] = { + [KEY_ALG_RSA] = "rsa", +#ifndef OPENSSL_NO_EC + [KEY_ALG_ECDSA] = "ecdsa" +#endif /* OPENSSL_NO_EC */ +}; + +static const char *hash_algs_str[] = { + [HASH_ALG_SHA256] = "sha256", + [HASH_ALG_SHA384] = "sha384", + [HASH_ALG_SHA512] = "sha512", +}; + +static void print_help(const char *cmd, const struct option *long_opt) +{ + int rem, i = 0; + const struct option *opt; + char line[HELP_OPT_MAX_LEN]; + char *p; + + assert(cmd != NULL); + assert(long_opt != NULL); + + printf("\n\n"); + printf("The certificate generation tool loads the binary images and\n" + "optionally the RSA keys, and outputs the key and content\n" + "certificates properly signed to implement the chain of trust.\n" + "If keys are provided, they must be in PEM format.\n" + "Certificates are generated in DER format.\n"); + printf("\n"); + printf("Usage:\n"); + printf("\t%s [OPTIONS]\n\n", cmd); + + printf("Available options:\n"); + opt = long_opt; + while (opt->name) { + p = line; + rem = HELP_OPT_MAX_LEN; + if (isalpha(opt->val)) { + /* Short format */ + sprintf(p, "-%c,", (char)opt->val); + p += 3; + rem -= 3; + } + snprintf(p, rem, "--%s %s", opt->name, + (opt->has_arg == required_argument) ? "" : ""); + printf("\t%-32s %s\n", line, cmd_opt_get_help_msg(i)); + opt++; + i++; + } + printf("\n"); +} + +static int get_key_alg(const char *key_alg_str) +{ + int i; + + for (i = 0 ; i < NUM_ELEM(key_algs_str) ; i++) { + if (0 == strcmp(key_alg_str, key_algs_str[i])) { + return i; + } + } + + return -1; +} + +static int get_key_size(const char *key_size_str) +{ + char *end; + long key_size; + + key_size = strtol(key_size_str, &end, 10); + if (*end != '\0') + return -1; + + return key_size; +} + +static int get_hash_alg(const char *hash_alg_str) +{ + int i; + + for (i = 0 ; i < NUM_ELEM(hash_algs_str) ; i++) { + if (0 == strcmp(hash_alg_str, hash_algs_str[i])) { + return i; + } + } + + return -1; +} + +static void check_cmd_params(void) +{ + cert_t *cert; + ext_t *ext; + key_t *key; + int i, j; + bool valid_size; + + /* Only save new keys */ + if (save_keys && !new_keys) { + ERROR("Only new keys can be saved to disk\n"); + exit(1); + } + + /* Validate key-size */ + valid_size = false; + for (i = 0; i < KEY_SIZE_MAX_NUM; i++) { + if (key_size == KEY_SIZES[key_alg][i]) { + valid_size = true; + break; + } + } + if (!valid_size) { + ERROR("'%d' is not a valid key size for '%s'\n", + key_size, key_algs_str[key_alg]); + NOTICE("Valid sizes are: "); + for (i = 0; i < KEY_SIZE_MAX_NUM && + KEY_SIZES[key_alg][i] != 0; i++) { + printf("%d ", KEY_SIZES[key_alg][i]); + } + printf("\n"); + exit(1); + } + + /* Check that all required options have been specified in the + * command line */ + for (i = 0; i < num_certs; i++) { + cert = &certs[i]; + if (cert->fn == NULL) { + /* Certificate not requested. Skip to the next one */ + continue; + } + + /* Check that all parameters required to create this certificate + * have been specified in the command line */ + for (j = 0; j < cert->num_ext; j++) { + ext = &extensions[cert->ext[j]]; + switch (ext->type) { + case EXT_TYPE_NVCOUNTER: + /* Counter value must be specified */ + if ((!ext->optional) && (ext->arg == NULL)) { + ERROR("Value for '%s' not specified\n", + ext->ln); + exit(1); + } + break; + case EXT_TYPE_PKEY: + /* Key filename must be specified */ + key = &keys[ext->attr.key]; + if (!new_keys && key->fn == NULL) { + ERROR("Key '%s' required by '%s' not " + "specified\n", key->desc, + cert->cn); + exit(1); + } + break; + case EXT_TYPE_HASH: + /* + * Binary image must be specified + * unless it is explicitly made optional. + */ + if ((!ext->optional) && (ext->arg == NULL)) { + ERROR("Image for '%s' not specified\n", + ext->ln); + exit(1); + } + break; + default: + ERROR("Unknown extension type '%d' in '%s'\n", + ext->type, ext->ln); + exit(1); + break; + } + } + } +} + +/* Common command line options */ +static const cmd_opt_t common_cmd_opt[] = { + { + { "help", no_argument, NULL, 'h' }, + "Print this message and exit" + }, + { + { "key-alg", required_argument, NULL, 'a' }, + "Key algorithm: 'rsa' (default)- RSAPSS scheme as per PKCS#1 v2.1, 'ecdsa'" + }, + { + { "key-size", required_argument, NULL, 'b' }, + "Key size (for supported algorithms)." + }, + { + { "hash-alg", required_argument, NULL, 's' }, + "Hash algorithm : 'sha256' (default), 'sha384', 'sha512'" + }, + { + { "save-keys", no_argument, NULL, 'k' }, + "Save key pairs into files. Filenames must be provided" + }, + { + { "new-keys", no_argument, NULL, 'n' }, + "Generate new key pairs if no key files are provided" + }, + { + { "print-cert", no_argument, NULL, 'p' }, + "Print the certificates in the standard output" + } +}; + +int main(int argc, char *argv[]) +{ + STACK_OF(X509_EXTENSION) * sk; + X509_EXTENSION *cert_ext = NULL; + ext_t *ext; + key_t *key; + cert_t *cert; + FILE *file; + int i, j, ext_nid, nvctr; + int c, opt_idx = 0; + const struct option *cmd_opt; + const char *cur_opt; + unsigned int err_code; + unsigned char md[SHA512_DIGEST_LENGTH]; + unsigned int md_len; + const EVP_MD *md_info; + + NOTICE("CoT Generation Tool: %s\n", build_msg); + NOTICE("Target platform: %s\n", platform_msg); + + /* Set default options */ + key_alg = KEY_ALG_RSA; + hash_alg = HASH_ALG_SHA256; + key_size = -1; + + /* Add common command line options */ + for (i = 0; i < NUM_ELEM(common_cmd_opt); i++) { + cmd_opt_add(&common_cmd_opt[i]); + } + + /* Initialize the certificates */ + if (cert_init() != 0) { + ERROR("Cannot initialize certificates\n"); + exit(1); + } + + /* Initialize the keys */ + if (key_init() != 0) { + ERROR("Cannot initialize keys\n"); + exit(1); + } + + /* Initialize the new types and register OIDs for the extensions */ + if (ext_init() != 0) { + ERROR("Cannot initialize extensions\n"); + exit(1); + } + + /* Get the command line options populated during the initialization */ + cmd_opt = cmd_opt_get_array(); + + while (1) { + /* getopt_long stores the option index here. */ + c = getopt_long(argc, argv, "a:b:hknps:", cmd_opt, &opt_idx); + + /* Detect the end of the options. */ + if (c == -1) { + break; + } + + switch (c) { + case 'a': + key_alg = get_key_alg(optarg); + if (key_alg < 0) { + ERROR("Invalid key algorithm '%s'\n", optarg); + exit(1); + } + break; + case 'b': + key_size = get_key_size(optarg); + if (key_size <= 0) { + ERROR("Invalid key size '%s'\n", optarg); + exit(1); + } + break; + case 'h': + print_help(argv[0], cmd_opt); + exit(0); + case 'k': + save_keys = 1; + break; + case 'n': + new_keys = 1; + break; + case 'p': + print_cert = 1; + break; + case 's': + hash_alg = get_hash_alg(optarg); + if (hash_alg < 0) { + ERROR("Invalid hash algorithm '%s'\n", optarg); + exit(1); + } + break; + case CMD_OPT_EXT: + cur_opt = cmd_opt_get_name(opt_idx); + ext = ext_get_by_opt(cur_opt); + ext->arg = strdup(optarg); + break; + case CMD_OPT_KEY: + cur_opt = cmd_opt_get_name(opt_idx); + key = key_get_by_opt(cur_opt); + key->fn = strdup(optarg); + break; + case CMD_OPT_CERT: + cur_opt = cmd_opt_get_name(opt_idx); + cert = cert_get_by_opt(cur_opt); + cert->fn = strdup(optarg); + break; + case '?': + default: + print_help(argv[0], cmd_opt); + exit(1); + } + } + + /* Select a reasonable default key-size */ + if (key_size == -1) { + key_size = KEY_SIZES[key_alg][0]; + } + + /* Check command line arguments */ + check_cmd_params(); + + /* Indicate SHA as image hash algorithm in the certificate + * extension */ + if (hash_alg == HASH_ALG_SHA384) { + md_info = EVP_sha384(); + md_len = SHA384_DIGEST_LENGTH; + } else if (hash_alg == HASH_ALG_SHA512) { + md_info = EVP_sha512(); + md_len = SHA512_DIGEST_LENGTH; + } else { + md_info = EVP_sha256(); + md_len = SHA256_DIGEST_LENGTH; + } + + /* Load private keys from files (or generate new ones) */ + for (i = 0 ; i < num_keys ; i++) { + if (!key_new(&keys[i])) { + ERROR("Failed to allocate key container\n"); + exit(1); + } + + /* First try to load the key from disk */ + if (key_load(&keys[i], &err_code)) { + /* Key loaded successfully */ + continue; + } + + /* Key not loaded. Check the error code */ + if (err_code == KEY_ERR_LOAD) { + /* File exists, but it does not contain a valid private + * key. Abort. */ + ERROR("Error loading '%s'\n", keys[i].fn); + exit(1); + } + + /* File does not exist, could not be opened or no filename was + * given */ + if (new_keys) { + /* Try to create a new key */ + NOTICE("Creating new key for '%s'\n", keys[i].desc); + if (!key_create(&keys[i], key_alg, key_size)) { + ERROR("Error creating key '%s'\n", keys[i].desc); + exit(1); + } + } else { + if (err_code == KEY_ERR_OPEN) { + ERROR("Error opening '%s'\n", keys[i].fn); + } else { + ERROR("Key '%s' not specified\n", keys[i].desc); + } + exit(1); + } + } + + /* Create the certificates */ + for (i = 0 ; i < num_certs ; i++) { + + cert = &certs[i]; + + if (cert->fn == NULL) { + /* Certificate not requested. Skip to the next one */ + continue; + } + + /* Create a new stack of extensions. This stack will be used + * to create the certificate */ + CHECK_NULL(sk, sk_X509_EXTENSION_new_null()); + + for (j = 0 ; j < cert->num_ext ; j++) { + + ext = &extensions[cert->ext[j]]; + + /* Get OpenSSL internal ID for this extension */ + CHECK_OID(ext_nid, ext->oid); + + /* + * Three types of extensions are currently supported: + * - EXT_TYPE_NVCOUNTER + * - EXT_TYPE_HASH + * - EXT_TYPE_PKEY + */ + switch (ext->type) { + case EXT_TYPE_NVCOUNTER: + if (ext->optional && ext->arg == NULL) { + /* Skip this NVCounter */ + continue; + } else { + /* Checked by `check_cmd_params` */ + assert(ext->arg != NULL); + nvctr = atoi(ext->arg); + CHECK_NULL(cert_ext, ext_new_nvcounter(ext_nid, + EXT_CRIT, nvctr)); + } + break; + case EXT_TYPE_HASH: + if (ext->arg == NULL) { + if (ext->optional) { + /* Include a hash filled with zeros */ + memset(md, 0x0, SHA512_DIGEST_LENGTH); + } else { + /* Do not include this hash in the certificate */ + continue; + } + } else { + /* Calculate the hash of the file */ + if (!sha_file(hash_alg, ext->arg, md)) { + ERROR("Cannot calculate hash of %s\n", + ext->arg); + exit(1); + } + } + CHECK_NULL(cert_ext, ext_new_hash(ext_nid, + EXT_CRIT, md_info, md, + md_len)); + break; + case EXT_TYPE_PKEY: + CHECK_NULL(cert_ext, ext_new_key(ext_nid, + EXT_CRIT, keys[ext->attr.key].key)); + break; + default: + ERROR("Unknown extension type '%d' in %s\n", + ext->type, cert->cn); + exit(1); + } + + /* Push the extension into the stack */ + sk_X509_EXTENSION_push(sk, cert_ext); + } + + /* Create certificate. Signed with corresponding key */ + if (!cert_new(hash_alg, cert, VAL_DAYS, 0, sk)) { + ERROR("Cannot create %s\n", cert->cn); + exit(1); + } + + for (cert_ext = sk_X509_EXTENSION_pop(sk); cert_ext != NULL; + cert_ext = sk_X509_EXTENSION_pop(sk)) { + X509_EXTENSION_free(cert_ext); + } + + sk_X509_EXTENSION_free(sk); + } + + + /* Print the certificates */ + if (print_cert) { + for (i = 0 ; i < num_certs ; i++) { + if (!certs[i].x) { + continue; + } + printf("\n\n=====================================\n\n"); + X509_print_fp(stdout, certs[i].x); + } + } + + /* Save created certificates to files */ + for (i = 0 ; i < num_certs ; i++) { + if (certs[i].x && certs[i].fn) { + file = fopen(certs[i].fn, "w"); + if (file != NULL) { + i2d_X509_fp(file, certs[i].x); + fclose(file); + } else { + ERROR("Cannot create file %s\n", certs[i].fn); + } + } + } + + /* Save keys */ + if (save_keys) { + for (i = 0 ; i < num_keys ; i++) { + if (!key_store(&keys[i])) { + ERROR("Cannot save %s\n", keys[i].desc); + } + } + } + + /* If we got here, then we must have filled the key array completely. + * We can then safely call free on all of the keys in the array + */ + for (i = 0; i < num_keys; i++) { + EVP_PKEY_free(keys[i].key); + } + +#ifndef OPENSSL_NO_ENGINE + ENGINE_cleanup(); +#endif + CRYPTO_cleanup_all_ex_data(); + + + /* We allocated strings through strdup, so now we have to free them */ + for (i = 0; i < num_keys; i++) { + if (keys[i].fn != NULL) { + void *ptr = keys[i].fn; + + keys[i].fn = NULL; + free(ptr); + } + } + for (i = 0; i < num_extensions; i++) { + if (extensions[i].arg != NULL) { + void *ptr = (void *)extensions[i].arg; + + extensions[i].arg = NULL; + free(ptr); + } + } + for (i = 0; i < num_certs; i++) { + if (certs[i].fn != NULL) { + void *ptr = (void *)certs[i].fn; + + certs[i].fn = NULL; + free(ptr); + } + } + + return 0; +} diff --git a/drivers/rz/ipl/rza/tools/cert_create/src/sha.c b/drivers/rz/ipl/rza/tools/cert_create/src/sha.c new file mode 100644 index 00000000..3d977fbf --- /dev/null +++ b/drivers/rz/ipl/rza/tools/cert_create/src/sha.c @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include "debug.h" +#include "key.h" + +#define BUFFER_SIZE 256 + +int sha_file(int md_alg, const char *filename, unsigned char *md) +{ + FILE *inFile; + SHA256_CTX shaContext; + SHA512_CTX sha512Context; + int bytes; + unsigned char data[BUFFER_SIZE]; + + if ((filename == NULL) || (md == NULL)) { + ERROR("%s(): NULL argument\n", __FUNCTION__); + return 0; + } + + inFile = fopen(filename, "rb"); + if (inFile == NULL) { + ERROR("Cannot read %s\n", filename); + return 0; + } + + if (md_alg == HASH_ALG_SHA384) { + SHA384_Init(&sha512Context); + while ((bytes = fread(data, 1, BUFFER_SIZE, inFile)) != 0) { + SHA384_Update(&sha512Context, data, bytes); + } + SHA384_Final(md, &sha512Context); + } else if (md_alg == HASH_ALG_SHA512) { + SHA512_Init(&sha512Context); + while ((bytes = fread(data, 1, BUFFER_SIZE, inFile)) != 0) { + SHA512_Update(&sha512Context, data, bytes); + } + SHA512_Final(md, &sha512Context); + } else { + SHA256_Init(&shaContext); + while ((bytes = fread(data, 1, BUFFER_SIZE, inFile)) != 0) { + SHA256_Update(&shaContext, data, bytes); + } + SHA256_Final(md, &shaContext); + } + + fclose(inFile); + return 1; +} diff --git a/drivers/rz/ipl/rza/tools/cert_create/src/tbbr/tbb_cert.c b/drivers/rz/ipl/rza/tools/cert_create/src/tbbr/tbb_cert.c new file mode 100644 index 00000000..f4fe63dc --- /dev/null +++ b/drivers/rz/ipl/rza/tools/cert_create/src/tbbr/tbb_cert.c @@ -0,0 +1,206 @@ +/* + * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "tbbr/tbb_cert.h" +#include "tbbr/tbb_ext.h" +#include "tbbr/tbb_key.h" + +/* + * Certificates used in the chain of trust + * + * The order of the certificates must follow the enumeration specified in + * tbb_cert.h. All certificates are self-signed, so the issuer certificate + * field points to itself. + */ +static cert_t tbb_certs[] = { + [TRUSTED_BOOT_FW_CERT] = { + .id = TRUSTED_BOOT_FW_CERT, + .opt = "tb-fw-cert", + .help_msg = "Trusted Boot FW Certificate (output file)", + .fn = NULL, + .cn = "Trusted Boot FW Certificate", + .key = ROT_KEY, + .issuer = TRUSTED_BOOT_FW_CERT, + .ext = { + TRUSTED_FW_NVCOUNTER_EXT, + TRUSTED_BOOT_FW_HASH_EXT, + TRUSTED_BOOT_FW_CONFIG_HASH_EXT, + HW_CONFIG_HASH_EXT, + FW_CONFIG_HASH_EXT + }, + .num_ext = 5 + }, + [TRUSTED_KEY_CERT] = { + .id = TRUSTED_KEY_CERT, + .opt = "trusted-key-cert", + .help_msg = "Trusted Key Certificate (output file)", + .fn = NULL, + .cn = "Trusted Key Certificate", + .key = ROT_KEY, + .issuer = TRUSTED_KEY_CERT, + .ext = { + TRUSTED_FW_NVCOUNTER_EXT, + TRUSTED_WORLD_PK_EXT, + NON_TRUSTED_WORLD_PK_EXT + }, + .num_ext = 3 + }, + [SCP_FW_KEY_CERT] = { + .id = SCP_FW_KEY_CERT, + .opt = "scp-fw-key-cert", + .help_msg = "SCP Firmware Key Certificate (output file)", + .fn = NULL, + .cn = "SCP Firmware Key Certificate", + .key = TRUSTED_WORLD_KEY, + .issuer = SCP_FW_KEY_CERT, + .ext = { + TRUSTED_FW_NVCOUNTER_EXT, + SCP_FW_CONTENT_CERT_PK_EXT + }, + .num_ext = 2 + }, + [SCP_FW_CONTENT_CERT] = { + .id = SCP_FW_CONTENT_CERT, + .opt = "scp-fw-cert", + .help_msg = "SCP Firmware Content Certificate (output file)", + .fn = NULL, + .cn = "SCP Firmware Content Certificate", + .key = SCP_FW_CONTENT_CERT_KEY, + .issuer = SCP_FW_CONTENT_CERT, + .ext = { + TRUSTED_FW_NVCOUNTER_EXT, + SCP_FW_HASH_EXT + }, + .num_ext = 2 + }, + [SOC_FW_KEY_CERT] = { + .id = SOC_FW_KEY_CERT, + .opt = "soc-fw-key-cert", + .help_msg = "SoC Firmware Key Certificate (output file)", + .fn = NULL, + .cn = "SoC Firmware Key Certificate", + .key = TRUSTED_WORLD_KEY, + .issuer = SOC_FW_KEY_CERT, + .ext = { + TRUSTED_FW_NVCOUNTER_EXT, + SOC_FW_CONTENT_CERT_PK_EXT + }, + .num_ext = 2 + }, + [SOC_FW_CONTENT_CERT] = { + .id = SOC_FW_CONTENT_CERT, + .opt = "soc-fw-cert", + .help_msg = "SoC Firmware Content Certificate (output file)", + .fn = NULL, + .cn = "SoC Firmware Content Certificate", + .key = SOC_FW_CONTENT_CERT_KEY, + .issuer = SOC_FW_CONTENT_CERT, + .ext = { + TRUSTED_FW_NVCOUNTER_EXT, + SOC_AP_FW_HASH_EXT, + SOC_FW_CONFIG_HASH_EXT, + }, + .num_ext = 3 + }, + [TRUSTED_OS_FW_KEY_CERT] = { + .id = TRUSTED_OS_FW_KEY_CERT, + .opt = "tos-fw-key-cert", + .help_msg = "Trusted OS Firmware Key Certificate (output file)", + .fn = NULL, + .cn = "Trusted OS Firmware Key Certificate", + .key = TRUSTED_WORLD_KEY, + .issuer = TRUSTED_OS_FW_KEY_CERT, + .ext = { + TRUSTED_FW_NVCOUNTER_EXT, + TRUSTED_OS_FW_CONTENT_CERT_PK_EXT + }, + .num_ext = 2 + }, + [TRUSTED_OS_FW_CONTENT_CERT] = { + .id = TRUSTED_OS_FW_CONTENT_CERT, + .opt = "tos-fw-cert", + .help_msg = "Trusted OS Firmware Content Certificate (output file)", + .fn = NULL, + .cn = "Trusted OS Firmware Content Certificate", + .key = TRUSTED_OS_FW_CONTENT_CERT_KEY, + .issuer = TRUSTED_OS_FW_CONTENT_CERT, + .ext = { + TRUSTED_FW_NVCOUNTER_EXT, + TRUSTED_OS_FW_HASH_EXT, + TRUSTED_OS_FW_EXTRA1_HASH_EXT, + TRUSTED_OS_FW_EXTRA2_HASH_EXT, + TRUSTED_OS_FW_CONFIG_HASH_EXT, + }, + .num_ext = 5 + }, + [NON_TRUSTED_FW_KEY_CERT] = { + .id = NON_TRUSTED_FW_KEY_CERT, + .opt = "nt-fw-key-cert", + .help_msg = "Non-Trusted Firmware Key Certificate (output file)", + .fn = NULL, + .cn = "Non-Trusted Firmware Key Certificate", + .key = NON_TRUSTED_WORLD_KEY, + .issuer = NON_TRUSTED_FW_KEY_CERT, + .ext = { + NON_TRUSTED_FW_NVCOUNTER_EXT, + NON_TRUSTED_FW_CONTENT_CERT_PK_EXT + }, + .num_ext = 2 + }, + [NON_TRUSTED_FW_CONTENT_CERT] = { + .id = NON_TRUSTED_FW_CONTENT_CERT, + .opt = "nt-fw-cert", + .help_msg = "Non-Trusted Firmware Content Certificate (output file)", + .fn = NULL, + .cn = "Non-Trusted Firmware Content Certificate", + .key = NON_TRUSTED_FW_CONTENT_CERT_KEY, + .issuer = NON_TRUSTED_FW_CONTENT_CERT, + .ext = { + NON_TRUSTED_FW_NVCOUNTER_EXT, + NON_TRUSTED_WORLD_BOOTLOADER_HASH_EXT, + NON_TRUSTED_FW_CONFIG_HASH_EXT, + }, + .num_ext = 3 + }, + [SIP_SECURE_PARTITION_CONTENT_CERT] = { + .id = SIP_SECURE_PARTITION_CONTENT_CERT, + .opt = "sip-sp-cert", + .help_msg = "SiP owned Secure Partition Content Certificate (output file)", + .fn = NULL, + .cn = "SiP owned Secure Partition Content Certificate", + .key = TRUSTED_WORLD_KEY, + .issuer = SIP_SECURE_PARTITION_CONTENT_CERT, + .ext = { + TRUSTED_FW_NVCOUNTER_EXT, + SP_PKG1_HASH_EXT, + SP_PKG2_HASH_EXT, + SP_PKG3_HASH_EXT, + SP_PKG4_HASH_EXT, + SP_PKG5_HASH_EXT, + SP_PKG6_HASH_EXT, + SP_PKG7_HASH_EXT, + SP_PKG8_HASH_EXT, + }, + .num_ext = 9 + }, + [FWU_CERT] = { + .id = FWU_CERT, + .opt = "fwu-cert", + .help_msg = "Firmware Update Certificate (output file)", + .fn = NULL, + .cn = "Firmware Update Certificate", + .key = ROT_KEY, + .issuer = FWU_CERT, + .ext = { + SCP_FWU_CFG_HASH_EXT, + AP_FWU_CFG_HASH_EXT, + FWU_HASH_EXT + }, + .num_ext = 3 + } +}; + +REGISTER_COT(tbb_certs); diff --git a/drivers/rz/ipl/rza/tools/cert_create/src/tbbr/tbb_ext.c b/drivers/rz/ipl/rza/tools/cert_create/src/tbbr/tbb_ext.c new file mode 100644 index 00000000..60bafb4b --- /dev/null +++ b/drivers/rz/ipl/rza/tools/cert_create/src/tbbr/tbb_ext.c @@ -0,0 +1,328 @@ +/* + * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +#if USE_TBBR_DEFS +#include +#else +#include +#endif + +#include "ext.h" +#include "tbbr/tbb_ext.h" +#include "tbbr/tbb_key.h" + +static ext_t tbb_ext[] = { + [TRUSTED_FW_NVCOUNTER_EXT] = { + .oid = TRUSTED_FW_NVCOUNTER_OID, + .opt = "tfw-nvctr", + .help_msg = "Trusted Firmware Non-Volatile counter value", + .sn = "TrustedWorldNVCounter", + .ln = "Trusted World Non-Volatile counter", + .asn1_type = V_ASN1_INTEGER, + .type = EXT_TYPE_NVCOUNTER, + .attr.nvctr_type = NVCTR_TYPE_TFW + }, + [NON_TRUSTED_FW_NVCOUNTER_EXT] = { + .oid = NON_TRUSTED_FW_NVCOUNTER_OID, + .opt = "ntfw-nvctr", + .help_msg = "Non-Trusted Firmware Non-Volatile counter value", + .sn = "NormalWorldNVCounter", + .ln = "Non-Trusted Firmware Non-Volatile counter", + .asn1_type = V_ASN1_INTEGER, + .type = EXT_TYPE_NVCOUNTER, + .attr.nvctr_type = NVCTR_TYPE_NTFW + }, + [TRUSTED_BOOT_FW_HASH_EXT] = { + .oid = TRUSTED_BOOT_FW_HASH_OID, + .opt = "tb-fw", + .help_msg = "Trusted Boot Firmware image file", + .sn = "TrustedBootFirmwareHash", + .ln = "Trusted Boot Firmware hash (SHA256)", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH + }, + [TRUSTED_BOOT_FW_CONFIG_HASH_EXT] = { + .oid = TRUSTED_BOOT_FW_CONFIG_HASH_OID, + .opt = "tb-fw-config", + .help_msg = "Trusted Boot Firmware Config file", + .sn = "TrustedBootFirmwareConfigHash", + .ln = "Trusted Boot Firmware Config hash", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH, + .optional = 1 + }, + [HW_CONFIG_HASH_EXT] = { + .oid = HW_CONFIG_HASH_OID, + .opt = "hw-config", + .help_msg = "HW Config file", + .sn = "HWConfigHash", + .ln = "HW Config hash", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH, + .optional = 1 + }, + [FW_CONFIG_HASH_EXT] = { + .oid = FW_CONFIG_HASH_OID, + .opt = "fw-config", + .help_msg = "Firmware Config file", + .sn = "FirmwareConfigHash", + .ln = "Firmware Config hash", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH, + .optional = 1 + }, + [TRUSTED_WORLD_PK_EXT] = { + .oid = TRUSTED_WORLD_PK_OID, + .sn = "TrustedWorldPublicKey", + .ln = "Trusted World Public Key", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_PKEY, + .attr.key = TRUSTED_WORLD_KEY + }, + [NON_TRUSTED_WORLD_PK_EXT] = { + .oid = NON_TRUSTED_WORLD_PK_OID, + .sn = "NonTrustedWorldPublicKey", + .ln = "Non-Trusted World Public Key", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_PKEY, + .attr.key = NON_TRUSTED_WORLD_KEY + }, + [SCP_FW_CONTENT_CERT_PK_EXT] = { + .oid = SCP_FW_CONTENT_CERT_PK_OID, + .sn = "SCPFirmwareContentCertPK", + .ln = "SCP Firmware content certificate public key", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_PKEY, + .attr.key = SCP_FW_CONTENT_CERT_KEY + }, + [SCP_FW_HASH_EXT] = { + .oid = SCP_FW_HASH_OID, + .opt = "scp-fw", + .help_msg = "SCP Firmware image file", + .sn = "SCPFirmwareHash", + .ln = "SCP Firmware hash (SHA256)", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH + }, + [SOC_FW_CONTENT_CERT_PK_EXT] = { + .oid = SOC_FW_CONTENT_CERT_PK_OID, + .sn = "SoCFirmwareContentCertPK", + .ln = "SoC Firmware content certificate public key", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_PKEY, + .attr.key = SOC_FW_CONTENT_CERT_KEY + }, + [SOC_AP_FW_HASH_EXT] = { + .oid = SOC_AP_FW_HASH_OID, + .opt = "soc-fw", + .help_msg = "SoC AP Firmware image file", + .sn = "SoCAPFirmwareHash", + .ln = "SoC AP Firmware hash (SHA256)", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH + }, + [SOC_FW_CONFIG_HASH_EXT] = { + .oid = SOC_FW_CONFIG_HASH_OID, + .opt = "soc-fw-config", + .help_msg = "SoC Firmware Config file", + .sn = "SocFirmwareConfigHash", + .ln = "SoC Firmware Config hash", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH, + .optional = 1 + }, + [TRUSTED_OS_FW_CONTENT_CERT_PK_EXT] = { + .oid = TRUSTED_OS_FW_CONTENT_CERT_PK_OID, + .sn = "TrustedOSFirmwareContentCertPK", + .ln = "Trusted OS Firmware content certificate public key", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_PKEY, + .attr.key = TRUSTED_OS_FW_CONTENT_CERT_KEY + }, + [TRUSTED_OS_FW_HASH_EXT] = { + .oid = TRUSTED_OS_FW_HASH_OID, + .opt = "tos-fw", + .help_msg = "Trusted OS image file", + .sn = "TrustedOSHash", + .ln = "Trusted OS hash (SHA256)", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH + }, + [TRUSTED_OS_FW_EXTRA1_HASH_EXT] = { + .oid = TRUSTED_OS_FW_EXTRA1_HASH_OID, + .opt = "tos-fw-extra1", + .help_msg = "Trusted OS Extra1 image file", + .sn = "TrustedOSExtra1Hash", + .ln = "Trusted OS Extra1 hash (SHA256)", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH, + .optional = 1 + }, + [TRUSTED_OS_FW_EXTRA2_HASH_EXT] = { + .oid = TRUSTED_OS_FW_EXTRA2_HASH_OID, + .opt = "tos-fw-extra2", + .help_msg = "Trusted OS Extra2 image file", + .sn = "TrustedOSExtra2Hash", + .ln = "Trusted OS Extra2 hash (SHA256)", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH, + .optional = 1 + }, + [TRUSTED_OS_FW_CONFIG_HASH_EXT] = { + .oid = TRUSTED_OS_FW_CONFIG_HASH_OID, + .opt = "tos-fw-config", + .help_msg = "Trusted OS Firmware Config file", + .sn = "TrustedOSFirmwareConfigHash", + .ln = "Trusted OS Firmware Config hash", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH, + .optional = 1 + }, + [NON_TRUSTED_FW_CONTENT_CERT_PK_EXT] = { + .oid = NON_TRUSTED_FW_CONTENT_CERT_PK_OID, + .sn = "NonTrustedFirmwareContentCertPK", + .ln = "Non-Trusted Firmware content certificate public key", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_PKEY, + .attr.key = NON_TRUSTED_FW_CONTENT_CERT_KEY + }, + [NON_TRUSTED_WORLD_BOOTLOADER_HASH_EXT] = { + .oid = NON_TRUSTED_WORLD_BOOTLOADER_HASH_OID, + .opt = "nt-fw", + .help_msg = "Non-Trusted World Bootloader image file", + .sn = "NonTrustedWorldBootloaderHash", + .ln = "Non-Trusted World hash (SHA256)", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH + }, + [NON_TRUSTED_FW_CONFIG_HASH_EXT] = { + .oid = NON_TRUSTED_FW_CONFIG_HASH_OID, + .opt = "nt-fw-config", + .help_msg = "Non Trusted OS Firmware Config file", + .sn = "NonTrustedOSFirmwareConfigHash", + .ln = "Non-Trusted OS Firmware Config hash", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH, + .optional = 1 + }, + [SP_PKG1_HASH_EXT] = { + .oid = SP_PKG1_HASH_OID, + .opt = "sp-pkg1", + .help_msg = "Secure Partition Package1 file", + .sn = "SPPkg1Hash", + .ln = "SP Pkg1 hash (SHA256)", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH, + .optional = 1 + }, + [SP_PKG2_HASH_EXT] = { + .oid = SP_PKG2_HASH_OID, + .opt = "sp-pkg2", + .help_msg = "Secure Partition Package2 file", + .sn = "SPPkg2Hash", + .ln = "SP Pkg2 hash (SHA256)", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH, + .optional = 1 + }, + [SP_PKG3_HASH_EXT] = { + .oid = SP_PKG3_HASH_OID, + .opt = "sp-pkg3", + .help_msg = "Secure Partition Package3 file", + .sn = "SPPkg3Hash", + .ln = "SP Pkg3 hash (SHA256)", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH, + .optional = 1 + }, + [SP_PKG4_HASH_EXT] = { + .oid = SP_PKG4_HASH_OID, + .opt = "sp-pkg4", + .help_msg = "Secure Partition Package4 file", + .sn = "SPPkg4Hash", + .ln = "SP Pkg4 hash (SHA256)", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH, + .optional = 1 + }, + [SP_PKG5_HASH_EXT] = { + .oid = SP_PKG5_HASH_OID, + .opt = "sp-pkg5", + .help_msg = "Secure Partition Package5 file", + .sn = "SPPkg5Hash", + .ln = "SP Pkg5 hash (SHA256)", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH, + .optional = 1 + }, + [SP_PKG6_HASH_EXT] = { + .oid = SP_PKG6_HASH_OID, + .opt = "sp-pkg6", + .help_msg = "Secure Partition Package6 file", + .sn = "SPPkg6Hash", + .ln = "SP Pkg6 hash (SHA256)", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH, + .optional = 1 + }, + [SP_PKG7_HASH_EXT] = { + .oid = SP_PKG7_HASH_OID, + .opt = "sp-pkg7", + .help_msg = "Secure Partition Package7 file", + .sn = "SPPkg7Hash", + .ln = "SP Pkg7 hash (SHA256)", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH, + .optional = 1 + }, + [SP_PKG8_HASH_EXT] = { + .oid = SP_PKG8_HASH_OID, + .opt = "sp-pkg8", + .help_msg = "Secure Partition Package8 file", + .sn = "SPPkg8Hash", + .ln = "SP Pkg8 hash (SHA256)", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH, + .optional = 1 + }, + [SCP_FWU_CFG_HASH_EXT] = { + .oid = SCP_FWU_CFG_HASH_OID, + .opt = "scp-fwu-cfg", + .help_msg = "SCP Firmware Update Config image file", + .sn = "SCPFWUpdateConfig", + .ln = "SCP Firmware Update Config hash (SHA256)", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH, + .optional = 1 + }, + [AP_FWU_CFG_HASH_EXT] = { + .oid = AP_FWU_CFG_HASH_OID, + .opt = "ap-fwu-cfg", + .help_msg = "AP Firmware Update Config image file", + .sn = "APFWUpdateConfig", + .ln = "AP Firmware Update Config hash (SHA256)", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH, + .optional = 1 + }, + [FWU_HASH_EXT] = { + .oid = FWU_HASH_OID, + .opt = "fwu", + .help_msg = "Firmware Updater image file", + .sn = "FWUpdaterHash", + .ln = "Firmware Updater hash (SHA256)", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH, + .optional = 1 + } +}; + +REGISTER_EXTENSIONS(tbb_ext); diff --git a/drivers/rz/ipl/rza/tools/cert_create/src/tbbr/tbb_key.c b/drivers/rz/ipl/rza/tools/cert_create/src/tbbr/tbb_key.c new file mode 100644 index 00000000..a81f0e44 --- /dev/null +++ b/drivers/rz/ipl/rza/tools/cert_create/src/tbbr/tbb_key.c @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "tbbr/tbb_key.h" + +/* + * Keys used to establish the chain of trust + * + * The order of the keys must follow the enumeration specified in tbb_key.h + */ +static key_t tbb_keys[] = { + [ROT_KEY] = { + .id = ROT_KEY, + .opt = "rot-key", + .help_msg = "Root Of Trust key (input/output file)", + .desc = "Root Of Trust key" + }, + [TRUSTED_WORLD_KEY] = { + .id = TRUSTED_WORLD_KEY, + .opt = "trusted-world-key", + .help_msg = "Trusted World key (input/output file)", + .desc = "Trusted World key" + }, + [NON_TRUSTED_WORLD_KEY] = { + .id = NON_TRUSTED_WORLD_KEY, + .opt = "non-trusted-world-key", + .help_msg = "Non Trusted World key (input/output file)", + .desc = "Non Trusted World key" + }, + [SCP_FW_CONTENT_CERT_KEY] = { + .id = SCP_FW_CONTENT_CERT_KEY, + .opt = "scp-fw-key", + .help_msg = "SCP Firmware Content Certificate key (input/output file)", + .desc = "SCP Firmware Content Certificate key" + }, + [SOC_FW_CONTENT_CERT_KEY] = { + .id = SOC_FW_CONTENT_CERT_KEY, + .opt = "soc-fw-key", + .help_msg = "SoC Firmware Content Certificate key (input/output file)", + .desc = "SoC Firmware Content Certificate key" + }, + [TRUSTED_OS_FW_CONTENT_CERT_KEY] = { + .id = TRUSTED_OS_FW_CONTENT_CERT_KEY, + .opt = "tos-fw-key", + .help_msg = "Trusted OS Firmware Content Certificate key (input/output file)", + .desc = "Trusted OS Firmware Content Certificate key" + }, + [NON_TRUSTED_FW_CONTENT_CERT_KEY] = { + .id = NON_TRUSTED_FW_CONTENT_CERT_KEY, + .opt = "nt-fw-key", + .help_msg = "Non Trusted Firmware Content Certificate key (input/output file)", + .desc = "Non Trusted Firmware Content Certificate key" + } +}; + +REGISTER_KEYS(tbb_keys); diff --git a/drivers/rz/ipl/rza/tools/cert_create/src/tbbr/tbbr.mk b/drivers/rz/ipl/rza/tools/cert_create/src/tbbr/tbbr.mk new file mode 100644 index 00000000..ee82d31e --- /dev/null +++ b/drivers/rz/ipl/rza/tools/cert_create/src/tbbr/tbbr.mk @@ -0,0 +1,29 @@ +# +# Copyright (c) 2020, Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +USE_TBBR_DEFS := 1 +$(eval $(call add_define,USE_TBBR_DEFS)) + +ifeq (${USE_TBBR_DEFS},1) +# In this case, cert_tool is platform-independent +PLAT_MSG := TBBR Generic +PLAT_INCLUDE := ../../include/tools_share +else +PLAT_MSG := ${PLAT} + +TF_PLATFORM_ROOT := ../../plat/ +include ${MAKE_HELPERS_DIRECTORY}plat_helpers.mk + +PLAT_INCLUDE := $(wildcard ${PLAT_DIR}include) + +ifeq ($(PLAT_INCLUDE),) + $(error "Error: Invalid platform '${PLAT}' has no include directory.") +endif +endif + +OBJECTS += src/tbbr/tbb_cert.o \ + src/tbbr/tbb_ext.o \ + src/tbbr/tbb_key.o diff --git a/drivers/rz/ipl/rza/tools/encrypt_fw/Makefile b/drivers/rz/ipl/rza/tools/encrypt_fw/Makefile new file mode 100644 index 00000000..96dff232 --- /dev/null +++ b/drivers/rz/ipl/rza/tools/encrypt_fw/Makefile @@ -0,0 +1,65 @@ +# +# Copyright (c) 2019-2020, Linaro Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +V ?= 0 +BUILD_INFO ?= 1 +DEBUG := 0 +ENCTOOL ?= encrypt_fw${BIN_EXT} +BINARY := $(notdir ${ENCTOOL}) +OPENSSL_DIR := /usr + +OBJECTS := src/encrypt.o \ + src/cmd_opt.o \ + src/main.o + +HOSTCCFLAGS := -Wall -std=c99 + +MAKE_HELPERS_DIRECTORY := ../../make_helpers/ +include ${MAKE_HELPERS_DIRECTORY}build_macros.mk +include ${MAKE_HELPERS_DIRECTORY}build_env.mk + +ifeq (${DEBUG},1) + HOSTCCFLAGS += -g -O0 -DDEBUG -DLOG_LEVEL=40 +else +ifeq (${BUILD_INFO},1) + HOSTCCFLAGS += -O2 -DLOG_LEVEL=20 +else + HOSTCCFLAGS += -O2 -DLOG_LEVEL=10 +endif +endif +ifeq (${V},0) + Q := @ +else + Q := +endif + +# Make soft links and include from local directory otherwise wrong headers +# could get pulled in from firmware tree. +INC_DIR := -I ./include -I ../../include/tools_share -I ${OPENSSL_DIR}/include +LIB_DIR := -L ${OPENSSL_DIR}/lib +LIB := -lssl -lcrypto + +HOSTCC ?= gcc + +.PHONY: all clean realclean + +all: ${BINARY} + +${BINARY}: ${OBJECTS} Makefile + @echo " HOSTLD $@" + @echo 'const char build_msg[] = "Built : "__TIME__", "__DATE__;' | \ + ${HOSTCC} -c ${HOSTCCFLAGS} -xc - -o src/build_msg.o + ${Q}${HOSTCC} src/build_msg.o ${OBJECTS} ${LIB_DIR} ${LIB} -o $@ + +%.o: %.c + @echo " HOSTCC $<" + ${Q}${HOSTCC} -c ${HOSTCCFLAGS} ${INC_DIR} $< -o $@ + +clean: + $(call SHELL_DELETE_ALL, src/build_msg.o ${OBJECTS}) + +realclean: clean + $(call SHELL_DELETE,${BINARY}) diff --git a/drivers/rz/ipl/rza/tools/encrypt_fw/include/cmd_opt.h b/drivers/rz/ipl/rza/tools/encrypt_fw/include/cmd_opt.h new file mode 100644 index 00000000..bd7d31f0 --- /dev/null +++ b/drivers/rz/ipl/rza/tools/encrypt_fw/include/cmd_opt.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2019, Linaro Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CMD_OPT_H +#define CMD_OPT_H + +#include + +#define CMD_OPT_MAX_NUM 64 + +/* Supported long command line option types */ +enum { + CMD_OPT_FW +}; + +/* Structure to define a command line option */ +typedef struct cmd_opt_s { + struct option long_opt; + const char *help_msg; +} cmd_opt_t; + +/* Exported API*/ +void cmd_opt_add(const cmd_opt_t *cmd_opt); +const struct option *cmd_opt_get_array(void); +const char *cmd_opt_get_name(int idx); +const char *cmd_opt_get_help_msg(int idx); + +#endif /* CMD_OPT_H */ diff --git a/drivers/rz/ipl/rza/tools/encrypt_fw/include/debug.h b/drivers/rz/ipl/rza/tools/encrypt_fw/include/debug.h new file mode 100644 index 00000000..ee8f1f51 --- /dev/null +++ b/drivers/rz/ipl/rza/tools/encrypt_fw/include/debug.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef DEBUG_H +#define DEBUG_H + +#include + +/* The log output macros print output to the console. These macros produce + * compiled log output only if the LOG_LEVEL defined in the makefile (or the + * make command line) is greater or equal than the level required for that + * type of log output. + * The format expected is the same as for printf(). For example: + * INFO("Info %s.\n", "message") -> INFO: Info message. + * WARN("Warning %s.\n", "message") -> WARNING: Warning message. + */ + +#define LOG_LEVEL_NONE 0 +#define LOG_LEVEL_ERROR 10 +#define LOG_LEVEL_NOTICE 20 +#define LOG_LEVEL_WARNING 30 +#define LOG_LEVEL_INFO 40 +#define LOG_LEVEL_VERBOSE 50 + + +#if LOG_LEVEL >= LOG_LEVEL_NOTICE +# define NOTICE(...) printf("NOTICE: " __VA_ARGS__) +#else +# define NOTICE(...) +#endif + +#if LOG_LEVEL >= LOG_LEVEL_ERROR +# define ERROR(...) printf("ERROR: " __VA_ARGS__) +#else +# define ERROR(...) +#endif + +#if LOG_LEVEL >= LOG_LEVEL_WARNING +# define WARN(...) printf("WARNING: " __VA_ARGS__) +#else +# define WARN(...) +#endif + +#if LOG_LEVEL >= LOG_LEVEL_INFO +# define INFO(...) printf("INFO: " __VA_ARGS__) +#else +# define INFO(...) +#endif + +#if LOG_LEVEL >= LOG_LEVEL_VERBOSE +# define VERBOSE(...) printf("VERBOSE: " __VA_ARGS__) +#else +# define VERBOSE(...) +#endif + +#endif /* DEBUG_H */ diff --git a/drivers/rz/ipl/rza/tools/encrypt_fw/include/encrypt.h b/drivers/rz/ipl/rza/tools/encrypt_fw/include/encrypt.h new file mode 100644 index 00000000..25d30117 --- /dev/null +++ b/drivers/rz/ipl/rza/tools/encrypt_fw/include/encrypt.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2019, Linaro Limited. All rights reserved. + * Author: Sumit Garg + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef ENCRYPT_H +#define ENCRYPT_H + +/* Supported key algorithms */ +enum { + KEY_ALG_GCM /* AES-GCM (default) */ +}; + +int encrypt_file(unsigned short fw_enc_status, int enc_alg, char *key_string, + char *nonce_string, const char *ip_name, const char *op_name); + +#endif /* ENCRYPT_H */ diff --git a/drivers/rz/ipl/rza/tools/encrypt_fw/src/cmd_opt.c b/drivers/rz/ipl/rza/tools/encrypt_fw/src/cmd_opt.c new file mode 100644 index 00000000..64180d1f --- /dev/null +++ b/drivers/rz/ipl/rza/tools/encrypt_fw/src/cmd_opt.c @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include "debug.h" + +/* Command line options */ +static struct option long_opt[CMD_OPT_MAX_NUM+1]; +static const char *help_msg[CMD_OPT_MAX_NUM+1]; +static int num_reg_opt; + +void cmd_opt_add(const cmd_opt_t *cmd_opt) +{ + assert(cmd_opt != NULL); + + if (num_reg_opt >= CMD_OPT_MAX_NUM) { + ERROR("Out of memory. Please increase CMD_OPT_MAX_NUM\n"); + exit(1); + } + + long_opt[num_reg_opt].name = cmd_opt->long_opt.name; + long_opt[num_reg_opt].has_arg = cmd_opt->long_opt.has_arg; + long_opt[num_reg_opt].flag = 0; + long_opt[num_reg_opt].val = cmd_opt->long_opt.val; + + help_msg[num_reg_opt] = cmd_opt->help_msg; + + num_reg_opt++; +} + +const struct option *cmd_opt_get_array(void) +{ + return long_opt; +} + +const char *cmd_opt_get_name(int idx) +{ + if (idx >= num_reg_opt) { + return NULL; + } + + return long_opt[idx].name; +} + +const char *cmd_opt_get_help_msg(int idx) +{ + if (idx >= num_reg_opt) { + return NULL; + } + + return help_msg[idx]; +} diff --git a/drivers/rz/ipl/rza/tools/encrypt_fw/src/encrypt.c b/drivers/rz/ipl/rza/tools/encrypt_fw/src/encrypt.c new file mode 100644 index 00000000..18a514cb --- /dev/null +++ b/drivers/rz/ipl/rza/tools/encrypt_fw/src/encrypt.c @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2019, Linaro Limited. All rights reserved. + * Author: Sumit Garg + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include "debug.h" +#include "encrypt.h" + +#define BUFFER_SIZE 256 +#define IV_SIZE 12 +#define IV_STRING_SIZE 24 +#define TAG_SIZE 16 +#define KEY_SIZE 32 +#define KEY_STRING_SIZE 64 + +static int gcm_encrypt(unsigned short fw_enc_status, char *key_string, + char *nonce_string, const char *ip_name, + const char *op_name) +{ + FILE *ip_file; + FILE *op_file; + EVP_CIPHER_CTX *ctx; + unsigned char data[BUFFER_SIZE], enc_data[BUFFER_SIZE]; + unsigned char key[KEY_SIZE], iv[IV_SIZE], tag[TAG_SIZE]; + int bytes, enc_len = 0, i, j, ret = 0; + struct fw_enc_hdr header; + + memset(&header, 0, sizeof(struct fw_enc_hdr)); + + if (strlen(key_string) != KEY_STRING_SIZE) { + ERROR("Unsupported key size: %lu\n", strlen(key_string)); + return -1; + } + + for (i = 0, j = 0; i < KEY_SIZE; i++, j += 2) { + if (sscanf(&key_string[j], "%02hhx", &key[i]) != 1) { + ERROR("Incorrect key format\n"); + return -1; + } + } + + if (strlen(nonce_string) != IV_STRING_SIZE) { + ERROR("Unsupported IV size: %lu\n", strlen(nonce_string)); + return -1; + } + + for (i = 0, j = 0; i < IV_SIZE; i++, j += 2) { + if (sscanf(&nonce_string[j], "%02hhx", &iv[i]) != 1) { + ERROR("Incorrect IV format\n"); + return -1; + } + } + + ip_file = fopen(ip_name, "rb"); + if (ip_file == NULL) { + ERROR("Cannot read %s\n", ip_name); + return -1; + } + + op_file = fopen(op_name, "wb"); + if (op_file == NULL) { + ERROR("Cannot write %s\n", op_name); + fclose(ip_file); + return -1; + } + + ret = fseek(op_file, sizeof(struct fw_enc_hdr), SEEK_SET); + if (ret) { + ERROR("fseek failed\n"); + goto out_file; + } + + ctx = EVP_CIPHER_CTX_new(); + if (ctx == NULL) { + ERROR("EVP_CIPHER_CTX_new failed\n"); + ret = -1; + goto out_file; + } + + ret = EVP_EncryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL); + if (ret != 1) { + ERROR("EVP_EncryptInit_ex failed\n"); + ret = -1; + goto out; + } + + ret = EVP_EncryptInit_ex(ctx, NULL, NULL, key, iv); + if (ret != 1) { + ERROR("EVP_EncryptInit_ex failed\n"); + goto out; + } + + while ((bytes = fread(data, 1, BUFFER_SIZE, ip_file)) != 0) { + ret = EVP_EncryptUpdate(ctx, enc_data, &enc_len, data, bytes); + if (ret != 1) { + ERROR("EVP_EncryptUpdate failed\n"); + ret = -1; + goto out; + } + + fwrite(enc_data, 1, enc_len, op_file); + } + + ret = EVP_EncryptFinal_ex(ctx, enc_data, &enc_len); + if (ret != 1) { + ERROR("EVP_EncryptFinal_ex failed\n"); + ret = -1; + goto out; + } + + ret = EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, TAG_SIZE, tag); + if (ret != 1) { + ERROR("EVP_CIPHER_CTX_ctrl failed\n"); + ret = -1; + goto out; + } + + header.magic = ENC_HEADER_MAGIC; + header.flags |= fw_enc_status & FW_ENC_STATUS_FLAG_MASK; + header.dec_algo = KEY_ALG_GCM; + header.iv_len = IV_SIZE; + header.tag_len = TAG_SIZE; + memcpy(header.iv, iv, IV_SIZE); + memcpy(header.tag, tag, TAG_SIZE); + + ret = fseek(op_file, 0, SEEK_SET); + if (ret) { + ERROR("fseek failed\n"); + goto out; + } + + fwrite(&header, 1, sizeof(struct fw_enc_hdr), op_file); + +out: + EVP_CIPHER_CTX_free(ctx); + +out_file: + fclose(ip_file); + fclose(op_file); + + /* + * EVP_* APIs returns 1 as success but enctool considers + * 0 as success. + */ + if (ret == 1) + ret = 0; + + return ret; +} + +int encrypt_file(unsigned short fw_enc_status, int enc_alg, char *key_string, + char *nonce_string, const char *ip_name, const char *op_name) +{ + switch (enc_alg) { + case KEY_ALG_GCM: + return gcm_encrypt(fw_enc_status, key_string, nonce_string, + ip_name, op_name); + default: + return -1; + } +} diff --git a/drivers/rz/ipl/rza/tools/encrypt_fw/src/main.c b/drivers/rz/ipl/rza/tools/encrypt_fw/src/main.c new file mode 100644 index 00000000..39b7af76 --- /dev/null +++ b/drivers/rz/ipl/rza/tools/encrypt_fw/src/main.c @@ -0,0 +1,224 @@ +/* + * Copyright (c) 2019, Linaro Limited. All rights reserved. + * Author: Sumit Garg + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "cmd_opt.h" +#include "debug.h" +#include "encrypt.h" +#include "firmware_encrypted.h" + +#define NUM_ELEM(x) ((sizeof(x)) / (sizeof(x[0]))) +#define HELP_OPT_MAX_LEN 128 + +/* Global options */ + +/* Info messages created in the Makefile */ +extern const char build_msg[]; + +static char *key_algs_str[] = { + [KEY_ALG_GCM] = "gcm", +}; + +static void print_help(const char *cmd, const struct option *long_opt) +{ + int rem, i = 0; + const struct option *opt; + char line[HELP_OPT_MAX_LEN]; + char *p; + + assert(cmd != NULL); + assert(long_opt != NULL); + + printf("\n\n"); + printf("The firmware encryption tool loads the binary image and\n" + "outputs encrypted binary image using an encryption key\n" + "provided as an input hex string.\n"); + printf("\n"); + printf("Usage:\n"); + printf("\t%s [OPTIONS]\n\n", cmd); + + printf("Available options:\n"); + opt = long_opt; + while (opt->name) { + p = line; + rem = HELP_OPT_MAX_LEN; + if (isalpha(opt->val)) { + /* Short format */ + sprintf(p, "-%c,", (char)opt->val); + p += 3; + rem -= 3; + } + snprintf(p, rem, "--%s %s", opt->name, + (opt->has_arg == required_argument) ? "" : ""); + printf("\t%-32s %s\n", line, cmd_opt_get_help_msg(i)); + opt++; + i++; + } + printf("\n"); +} + +static int get_key_alg(const char *key_alg_str) +{ + int i; + + for (i = 0 ; i < NUM_ELEM(key_algs_str) ; i++) { + if (strcmp(key_alg_str, key_algs_str[i]) == 0) { + return i; + } + } + + return -1; +} + +static void parse_fw_enc_status_flag(const char *arg, + unsigned short *fw_enc_status) +{ + unsigned long flag; + char *endptr; + + flag = strtoul(arg, &endptr, 16); + if (*endptr != '\0' || flag > FW_ENC_WITH_BSSK) { + ERROR("Invalid fw_enc_status flag '%s'\n", arg); + exit(1); + } + + *fw_enc_status = flag & FW_ENC_STATUS_FLAG_MASK; +} + +/* Common command line options */ +static const cmd_opt_t common_cmd_opt[] = { + { + { "help", no_argument, NULL, 'h' }, + "Print this message and exit" + }, + { + { "fw-enc-status", required_argument, NULL, 'f' }, + "Firmware encryption status flag (with SSK=0 or BSSK=1)." + }, + { + { "key-alg", required_argument, NULL, 'a' }, + "Encryption key algorithm: 'gcm' (default)" + }, + { + { "key", required_argument, NULL, 'k' }, + "Encryption key (for supported algorithm)." + }, + { + { "nonce", required_argument, NULL, 'n' }, + "Nonce or Initialization Vector (for supported algorithm)." + }, + { + { "in", required_argument, NULL, 'i' }, + "Input filename to be encrypted." + }, + { + { "out", required_argument, NULL, 'o' }, + "Encrypted output filename." + }, +}; + +int main(int argc, char *argv[]) +{ + int i, key_alg, ret; + int c, opt_idx = 0; + const struct option *cmd_opt; + char *key = NULL; + char *nonce = NULL; + char *in_fn = NULL; + char *out_fn = NULL; + unsigned short fw_enc_status = 0; + + NOTICE("Firmware Encryption Tool: %s\n", build_msg); + + /* Set default options */ + key_alg = KEY_ALG_GCM; + + /* Add common command line options */ + for (i = 0; i < NUM_ELEM(common_cmd_opt); i++) { + cmd_opt_add(&common_cmd_opt[i]); + } + + /* Get the command line options populated during the initialization */ + cmd_opt = cmd_opt_get_array(); + + while (1) { + /* getopt_long stores the option index here. */ + c = getopt_long(argc, argv, "a:f:hi:k:n:o:", cmd_opt, &opt_idx); + + /* Detect the end of the options. */ + if (c == -1) { + break; + } + + switch (c) { + case 'a': + key_alg = get_key_alg(optarg); + if (key_alg < 0) { + ERROR("Invalid key algorithm '%s'\n", optarg); + exit(1); + } + break; + case 'f': + parse_fw_enc_status_flag(optarg, &fw_enc_status); + break; + case 'k': + key = optarg; + break; + case 'i': + in_fn = optarg; + break; + case 'o': + out_fn = optarg; + break; + case 'n': + nonce = optarg; + break; + case 'h': + print_help(argv[0], cmd_opt); + exit(0); + case '?': + default: + print_help(argv[0], cmd_opt); + exit(1); + } + } + + if (!key) { + ERROR("Key must not be NULL\n"); + exit(1); + } + + if (!nonce) { + ERROR("Nonce must not be NULL\n"); + exit(1); + } + + if (!in_fn) { + ERROR("Input filename must not be NULL\n"); + exit(1); + } + + if (!out_fn) { + ERROR("Output filename must not be NULL\n"); + exit(1); + } + + ret = encrypt_file(fw_enc_status, key_alg, key, nonce, in_fn, out_fn); + + CRYPTO_cleanup_all_ex_data(); + + return ret; +} diff --git a/drivers/rz/ipl/rza/tools/fiptool/Makefile b/drivers/rz/ipl/rza/tools/fiptool/Makefile new file mode 100644 index 00000000..11d2e7b0 --- /dev/null +++ b/drivers/rz/ipl/rza/tools/fiptool/Makefile @@ -0,0 +1,61 @@ +# +# Copyright (c) 2014-2021, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +MAKE_HELPERS_DIRECTORY := ../../make_helpers/ +include ${MAKE_HELPERS_DIRECTORY}build_macros.mk +include ${MAKE_HELPERS_DIRECTORY}build_env.mk + +FIPTOOL ?= fiptool${BIN_EXT} +PROJECT := $(notdir ${FIPTOOL}) +OBJECTS := fiptool.o tbbr_config.o +V ?= 0 + +override CPPFLAGS += -D_GNU_SOURCE -D_XOPEN_SOURCE=700 +HOSTCCFLAGS := -Wall -Werror -pedantic -std=c99 +ifeq (${DEBUG},1) + HOSTCCFLAGS += -g -O0 -DDEBUG +else + HOSTCCFLAGS += -O2 +endif +LDLIBS := -lcrypto + +ifeq (${V},0) + Q := @ +else + Q := +endif + +INCLUDE_PATHS := -I../../include/tools_share + +HOSTCC ?= gcc + +ifneq (${PLAT},) +TF_PLATFORM_ROOT := ../../plat/ +include ${MAKE_HELPERS_DIRECTORY}plat_helpers.mk +PLAT_FIPTOOL_HELPER_MK := ${PLAT_DIR}/plat_fiptool.mk +endif + +ifneq (,$(wildcard ${PLAT_FIPTOOL_HELPER_MK})) +include ${PLAT_FIPTOOL_HELPER_MK} +endif + +.PHONY: all clean distclean + +all: ${PROJECT} + +${PROJECT}: ${OBJECTS} Makefile + @echo " HOSTLD $@" + ${Q}${HOSTCC} ${OBJECTS} -o $@ ${LDLIBS} + @${ECHO_BLANK_LINE} + @echo "Built $@ successfully" + @${ECHO_BLANK_LINE} + +%.o: %.c Makefile + @echo " HOSTCC $<" + ${Q}${HOSTCC} -c ${CPPFLAGS} ${HOSTCCFLAGS} ${INCLUDE_PATHS} $< -o $@ + +clean: + $(call SHELL_DELETE_ALL, ${PROJECT} ${OBJECTS}) diff --git a/drivers/rz/ipl/rza/tools/fiptool/Makefile.msvc b/drivers/rz/ipl/rza/tools/fiptool/Makefile.msvc new file mode 100644 index 00000000..9081bc64 --- /dev/null +++ b/drivers/rz/ipl/rza/tools/fiptool/Makefile.msvc @@ -0,0 +1,37 @@ +# +# Copyright (c) 2019-2020, Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +CC = cl.exe +LD = link.exe + +# FIPTOOLPATH and FIPTOOL are passed from the main makefile. + +OBJECTS = $(FIPTOOLPATH)\fiptool.obj \ + $(FIPTOOLPATH)\tbbr_config.obj \ + $(FIPTOOLPATH)\win_posix.obj + +INC = -I$(FIPTOOLPATH) -Iinclude\tools_share + +CFLAGS = $(CFLAGS) /nologo /Za /Zi /c /O2 /MT + +all: $(FIPTOOL) + +$(FIPTOOL): $(OBJECTS) + $(LD) /nologo /INCREMENTAL:NO /debug /nodefaultlib:libc.lib /out:$@ $(LIBS) $** + +.PHONY: clean realclean + +clean: + -@del /f /q $(OBJECTS) > nul + -@del /f /q $(FIPTOOLPATH)\*.pdb > nul + +realclean: + -@del /f /q $(OBJECTS) > nul + -@del /f /q $(FIPTOOLPATH)\*.pdb > nul + -@del /f /q $(FIPTOOL) > nul + +.c.obj: + $(CC) -c $(CFLAGS) $(INC) $< -Fo$@ diff --git a/drivers/rz/ipl/rza/tools/fiptool/fiptool.c b/drivers/rz/ipl/rza/tools/fiptool/fiptool.c new file mode 100644 index 00000000..d92c31d7 --- /dev/null +++ b/drivers/rz/ipl/rza/tools/fiptool/fiptool.c @@ -0,0 +1,1266 @@ +/* + * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "fiptool.h" +#include "tbbr_config.h" + +#define OPT_TOC_ENTRY 0 +#define OPT_PLAT_TOC_FLAGS 1 +#define OPT_ALIGN 2 + +static int info_cmd(int argc, char *argv[]); +static void info_usage(int); +static int create_cmd(int argc, char *argv[]); +static void create_usage(int); +static int update_cmd(int argc, char *argv[]); +static void update_usage(int); +static int unpack_cmd(int argc, char *argv[]); +static void unpack_usage(int); +static int remove_cmd(int argc, char *argv[]); +static void remove_usage(int); +static int version_cmd(int argc, char *argv[]); +static void version_usage(int); +static int help_cmd(int argc, char *argv[]); +static void usage(void); + +/* Available subcommands. */ +static cmd_t cmds[] = { + { .name = "info", .handler = info_cmd, .usage = info_usage }, + { .name = "create", .handler = create_cmd, .usage = create_usage }, + { .name = "update", .handler = update_cmd, .usage = update_usage }, + { .name = "unpack", .handler = unpack_cmd, .usage = unpack_usage }, + { .name = "remove", .handler = remove_cmd, .usage = remove_usage }, + { .name = "version", .handler = version_cmd, .usage = version_usage }, + { .name = "help", .handler = help_cmd, .usage = NULL }, +}; + +static image_desc_t *image_desc_head; +static size_t nr_image_descs; +static const uuid_t uuid_null; +static int verbose; + +static void vlog(int prio, const char *msg, va_list ap) +{ + char *prefix[] = { "DEBUG", "WARN", "ERROR" }; + + fprintf(stderr, "%s: ", prefix[prio]); + vfprintf(stderr, msg, ap); + fputc('\n', stderr); +} + +static void log_dbgx(const char *msg, ...) +{ + va_list ap; + + va_start(ap, msg); + vlog(LOG_DBG, msg, ap); + va_end(ap); +} + +static void log_warnx(const char *msg, ...) +{ + va_list ap; + + va_start(ap, msg); + vlog(LOG_WARN, msg, ap); + va_end(ap); +} + +static void log_err(const char *msg, ...) +{ + char buf[512]; + va_list ap; + + va_start(ap, msg); + snprintf(buf, sizeof(buf), "%s: %s", msg, strerror(errno)); + vlog(LOG_ERR, buf, ap); + va_end(ap); + exit(1); +} + +static void log_errx(const char *msg, ...) +{ + va_list ap; + + va_start(ap, msg); + vlog(LOG_ERR, msg, ap); + va_end(ap); + exit(1); +} + +static char *xstrdup(const char *s, const char *msg) +{ + char *d; + + d = strdup(s); + if (d == NULL) + log_errx("strdup: %s", msg); + return d; +} + +static void *xmalloc(size_t size, const char *msg) +{ + void *d; + + d = malloc(size); + if (d == NULL) + log_errx("malloc: %s", msg); + return d; +} + +static void *xzalloc(size_t size, const char *msg) +{ + return memset(xmalloc(size, msg), 0, size); +} + +static void xfwrite(void *buf, size_t size, FILE *fp, const char *filename) +{ + if (fwrite(buf, 1, size, fp) != size) + log_errx("Failed to write %s", filename); +} + +static image_desc_t *new_image_desc(const uuid_t *uuid, + const char *name, const char *cmdline_name) +{ + image_desc_t *desc; + + desc = xzalloc(sizeof(*desc), + "failed to allocate memory for image descriptor"); + memcpy(&desc->uuid, uuid, sizeof(uuid_t)); + desc->name = xstrdup(name, + "failed to allocate memory for image name"); + desc->cmdline_name = xstrdup(cmdline_name, + "failed to allocate memory for image command line name"); + desc->action = DO_UNSPEC; + return desc; +} + +static void set_image_desc_action(image_desc_t *desc, int action, + const char *arg) +{ + assert(desc != NULL); + + if (desc->action_arg != (char *)DO_UNSPEC) + free(desc->action_arg); + desc->action = action; + desc->action_arg = NULL; + if (arg != NULL) + desc->action_arg = xstrdup(arg, + "failed to allocate memory for argument"); +} + +static void free_image_desc(image_desc_t *desc) +{ + free(desc->name); + free(desc->cmdline_name); + free(desc->action_arg); + if (desc->image) { + free(desc->image->buffer); + free(desc->image); + } + free(desc); +} + +static void add_image_desc(image_desc_t *desc) +{ + image_desc_t **p = &image_desc_head; + + while (*p) + p = &(*p)->next; + + assert(*p == NULL); + *p = desc; + nr_image_descs++; +} + +static void free_image_descs(void) +{ + image_desc_t *desc = image_desc_head, *tmp; + + while (desc != NULL) { + tmp = desc->next; + free_image_desc(desc); + desc = tmp; + nr_image_descs--; + } + assert(nr_image_descs == 0); +} + +static void fill_image_descs(void) +{ + toc_entry_t *toc_entry; + + for (toc_entry = toc_entries; + toc_entry->cmdline_name != NULL; + toc_entry++) { + image_desc_t *desc; + + desc = new_image_desc(&toc_entry->uuid, + toc_entry->name, + toc_entry->cmdline_name); + add_image_desc(desc); + } +#ifdef PLAT_DEF_FIP_UUID + for (toc_entry = plat_def_toc_entries; + toc_entry->cmdline_name != NULL; + toc_entry++) { + image_desc_t *desc; + + desc = new_image_desc(&toc_entry->uuid, + toc_entry->name, + toc_entry->cmdline_name); + add_image_desc(desc); + } +#endif +} + +static image_desc_t *lookup_image_desc_from_uuid(const uuid_t *uuid) +{ + image_desc_t *desc; + + for (desc = image_desc_head; desc != NULL; desc = desc->next) + if (memcmp(&desc->uuid, uuid, sizeof(uuid_t)) == 0) + return desc; + return NULL; +} + +static image_desc_t *lookup_image_desc_from_opt(const char *opt) +{ + image_desc_t *desc; + + for (desc = image_desc_head; desc != NULL; desc = desc->next) + if (strcmp(desc->cmdline_name, opt) == 0) + return desc; + return NULL; +} + +static void uuid_to_str(char *s, size_t len, const uuid_t *u) +{ + assert(len >= (_UUID_STR_LEN + 1)); + + snprintf(s, len, + "%02X%02X%02X%02X-%02X%02X-%02X%02X-%04X-%04X%04X%04X", + u->time_low[0], u->time_low[1], u->time_low[2], u->time_low[3], + u->time_mid[0], u->time_mid[1], + u->time_hi_and_version[0], u->time_hi_and_version[1], + (u->clock_seq_hi_and_reserved << 8) | u->clock_seq_low, + (u->node[0] << 8) | u->node[1], + (u->node[2] << 8) | u->node[3], + (u->node[4] << 8) | u->node[5]); +} + +static void uuid_from_str(uuid_t *u, const char *s) +{ + int n; + + if (s == NULL) + log_errx("UUID cannot be NULL"); + if (strlen(s) != _UUID_STR_LEN) + log_errx("Invalid UUID: %s", s); + + n = sscanf(s, + "%2hhx%2hhx%2hhx%2hhx-%2hhx%2hhx-%2hhx%2hhx-%2hhx%2hhx-%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx", + &u->time_low[0], &u->time_low[1], &u->time_low[2], &u->time_low[3], + &u->time_mid[0], &u->time_mid[1], + &u->time_hi_and_version[0], &u->time_hi_and_version[1], + &u->clock_seq_hi_and_reserved, &u->clock_seq_low, + &u->node[0], &u->node[1], + &u->node[2], &u->node[3], + &u->node[4], &u->node[5]); + /* + * Given the format specifier above, we expect 16 items to be scanned + * for a properly formatted UUID. + */ + if (n != 16) + log_errx("Invalid UUID: %s", s); +} + +static int parse_fip(const char *filename, fip_toc_header_t *toc_header_out) +{ + struct BLD_PLAT_STAT st; + FILE *fp; + char *buf, *bufend; + fip_toc_header_t *toc_header; + fip_toc_entry_t *toc_entry; + int terminated = 0; + + fp = fopen(filename, "rb"); + if (fp == NULL) + log_err("fopen %s", filename); + + if (fstat(fileno(fp), &st) == -1) + log_err("fstat %s", filename); + + buf = xmalloc(st.st_size, "failed to load file into memory"); + if (fread(buf, 1, st.st_size, fp) != st.st_size) + log_errx("Failed to read %s", filename); + bufend = buf + st.st_size; + fclose(fp); + + if (st.st_size < sizeof(fip_toc_header_t)) + log_errx("FIP %s is truncated", filename); + + toc_header = (fip_toc_header_t *)buf; + toc_entry = (fip_toc_entry_t *)(toc_header + 1); + + if (toc_header->name != TOC_HEADER_NAME) + log_errx("%s is not a FIP file", filename); + + /* Return the ToC header if the caller wants it. */ + if (toc_header_out != NULL) + *toc_header_out = *toc_header; + + /* Walk through each ToC entry in the file. */ + while ((char *)toc_entry + sizeof(*toc_entry) - 1 < bufend) { + image_t *image; + image_desc_t *desc; + + /* Found the ToC terminator, we are done. */ + if (memcmp(&toc_entry->uuid, &uuid_null, sizeof(uuid_t)) == 0) { + terminated = 1; + break; + } + + /* + * Build a new image out of the ToC entry and add it to the + * table of images. + */ + image = xzalloc(sizeof(*image), + "failed to allocate memory for image"); + image->toc_e = *toc_entry; + image->buffer = xmalloc(toc_entry->size, + "failed to allocate image buffer, is FIP file corrupted?"); + /* Overflow checks before memory copy. */ + if (toc_entry->size > (uint64_t)-1 - toc_entry->offset_address) + log_errx("FIP %s is corrupted", filename); + if (toc_entry->size + toc_entry->offset_address > st.st_size) + log_errx("FIP %s is corrupted", filename); + + memcpy(image->buffer, buf + toc_entry->offset_address, + toc_entry->size); + + /* If this is an unknown image, create a descriptor for it. */ + desc = lookup_image_desc_from_uuid(&toc_entry->uuid); + if (desc == NULL) { + char name[_UUID_STR_LEN + 1], filename[PATH_MAX]; + + uuid_to_str(name, sizeof(name), &toc_entry->uuid); + snprintf(filename, sizeof(filename), "%s%s", + name, ".bin"); + desc = new_image_desc(&toc_entry->uuid, name, "blob"); + desc->action = DO_UNPACK; + desc->action_arg = xstrdup(filename, + "failed to allocate memory for blob filename"); + add_image_desc(desc); + } + + assert(desc->image == NULL); + desc->image = image; + + toc_entry++; + } + + if (terminated == 0) + log_errx("FIP %s does not have a ToC terminator entry", + filename); + free(buf); + return 0; +} + +static image_t *read_image_from_file(const uuid_t *uuid, const char *filename) +{ + struct BLD_PLAT_STAT st; + image_t *image; + FILE *fp; + + assert(uuid != NULL); + assert(filename != NULL); + + fp = fopen(filename, "rb"); + if (fp == NULL) + log_err("fopen %s", filename); + + if (fstat(fileno(fp), &st) == -1) + log_errx("fstat %s", filename); + + image = xzalloc(sizeof(*image), "failed to allocate memory for image"); + image->toc_e.uuid = *uuid; + image->buffer = xmalloc(st.st_size, "failed to allocate image buffer"); + if (fread(image->buffer, 1, st.st_size, fp) != st.st_size) + log_errx("Failed to read %s", filename); + image->toc_e.size = st.st_size; + + fclose(fp); + return image; +} + +static int write_image_to_file(const image_t *image, const char *filename) +{ + FILE *fp; + + fp = fopen(filename, "wb"); + if (fp == NULL) + log_err("fopen"); + xfwrite(image->buffer, image->toc_e.size, fp, filename); + fclose(fp); + return 0; +} + +static struct option *add_opt(struct option *opts, size_t *nr_opts, + const char *name, int has_arg, int val) +{ + opts = realloc(opts, (*nr_opts + 1) * sizeof(*opts)); + if (opts == NULL) + log_err("realloc"); + opts[*nr_opts].name = name; + opts[*nr_opts].has_arg = has_arg; + opts[*nr_opts].flag = NULL; + opts[*nr_opts].val = val; + ++*nr_opts; + return opts; +} + +static struct option *fill_common_opts(struct option *opts, size_t *nr_opts, + int has_arg) +{ + image_desc_t *desc; + + for (desc = image_desc_head; desc != NULL; desc = desc->next) + opts = add_opt(opts, nr_opts, desc->cmdline_name, has_arg, + OPT_TOC_ENTRY); + return opts; +} + +static void md_print(const unsigned char *md, size_t len) +{ + size_t i; + + for (i = 0; i < len; i++) + printf("%02x", md[i]); +} + +static int info_cmd(int argc, char *argv[]) +{ + image_desc_t *desc; + fip_toc_header_t toc_header; + + if (argc != 2) + info_usage(EXIT_FAILURE); + argc--, argv++; + + parse_fip(argv[0], &toc_header); + + if (verbose) { + log_dbgx("toc_header[name]: 0x%llX", + (unsigned long long)toc_header.name); + log_dbgx("toc_header[serial_number]: 0x%llX", + (unsigned long long)toc_header.serial_number); + log_dbgx("toc_header[flags]: 0x%llX", + (unsigned long long)toc_header.flags); + } + + for (desc = image_desc_head; desc != NULL; desc = desc->next) { + image_t *image = desc->image; + + if (image == NULL) + continue; + printf("%s: offset=0x%llX, size=0x%llX, cmdline=\"--%s\"", + desc->name, + (unsigned long long)image->toc_e.offset_address, + (unsigned long long)image->toc_e.size, + desc->cmdline_name); +#ifndef _MSC_VER /* We don't have SHA256 for Visual Studio. */ + if (verbose) { + unsigned char md[SHA256_DIGEST_LENGTH]; + + SHA256(image->buffer, image->toc_e.size, md); + printf(", sha256="); + md_print(md, sizeof(md)); + } +#endif + putchar('\n'); + } + + return 0; +} + +static void info_usage(int exit_status) +{ + printf("fiptool info FIP_FILENAME\n"); + exit(exit_status); +} + +static int pack_images(const char *filename, uint64_t toc_flags, unsigned long align) +{ + FILE *fp; + image_desc_t *desc; + fip_toc_header_t *toc_header; + fip_toc_entry_t *toc_entry; + char *buf; + uint64_t entry_offset, buf_size, payload_size = 0, pad_size; + size_t nr_images = 0; + + for (desc = image_desc_head; desc != NULL; desc = desc->next) + if (desc->image != NULL) + nr_images++; + + buf_size = sizeof(fip_toc_header_t) + + sizeof(fip_toc_entry_t) * (nr_images + 1); + buf = calloc(1, buf_size); + if (buf == NULL) + log_err("calloc"); + + /* Build up header and ToC entries from the image table. */ + toc_header = (fip_toc_header_t *)buf; + toc_header->name = TOC_HEADER_NAME; + toc_header->serial_number = TOC_HEADER_SERIAL_NUMBER; + toc_header->flags = toc_flags; + + toc_entry = (fip_toc_entry_t *)(toc_header + 1); + + entry_offset = buf_size; + for (desc = image_desc_head; desc != NULL; desc = desc->next) { + image_t *image = desc->image; + + if (image == NULL) + continue; + payload_size += image->toc_e.size; + entry_offset = (entry_offset + align - 1) & ~(align - 1); + image->toc_e.offset_address = entry_offset; + *toc_entry++ = image->toc_e; + entry_offset += image->toc_e.size; + } + + /* + * Append a null uuid entry to mark the end of ToC entries. + * NOTE the offset address for the last toc_entry must match the fip + * size. + */ + memset(toc_entry, 0, sizeof(*toc_entry)); + toc_entry->offset_address = (entry_offset + align - 1) & ~(align - 1); + + /* Generate the FIP file. */ + fp = fopen(filename, "wb"); + if (fp == NULL) + log_err("fopen %s", filename); + + if (verbose) + log_dbgx("Metadata size: %zu bytes", buf_size); + + xfwrite(buf, buf_size, fp, filename); + + if (verbose) + log_dbgx("Payload size: %zu bytes", payload_size); + + for (desc = image_desc_head; desc != NULL; desc = desc->next) { + image_t *image = desc->image; + + if (image == NULL) + continue; + if (fseek(fp, image->toc_e.offset_address, SEEK_SET)) + log_errx("Failed to set file position"); + + xfwrite(image->buffer, image->toc_e.size, fp, filename); + } + + if (fseek(fp, entry_offset, SEEK_SET)) + log_errx("Failed to set file position"); + + pad_size = toc_entry->offset_address - entry_offset; + while (pad_size--) + fputc(0x0, fp); + + free(buf); + fclose(fp); + return 0; +} + +/* + * This function is shared between the create and update subcommands. + * The difference between the two subcommands is that when the FIP file + * is created, the parsing of an existing FIP is skipped. This results + * in update_fip() creating the new FIP file from scratch because the + * internal image table is not populated. + */ +static void update_fip(void) +{ + image_desc_t *desc; + + /* Add or replace images in the FIP file. */ + for (desc = image_desc_head; desc != NULL; desc = desc->next) { + image_t *image; + + if (desc->action != DO_PACK) + continue; + + image = read_image_from_file(&desc->uuid, + desc->action_arg); + if (desc->image != NULL) { + if (verbose) { + log_dbgx("Replacing %s with %s", + desc->cmdline_name, + desc->action_arg); + } + free(desc->image); + desc->image = image; + } else { + if (verbose) + log_dbgx("Adding image %s", + desc->action_arg); + desc->image = image; + } + } +} + +static void parse_plat_toc_flags(const char *arg, unsigned long long *toc_flags) +{ + unsigned long long flags; + char *endptr; + + errno = 0; + flags = strtoull(arg, &endptr, 16); + if (*endptr != '\0' || flags > UINT16_MAX || errno != 0) + log_errx("Invalid platform ToC flags: %s", arg); + /* Platform ToC flags is a 16-bit field occupying bits [32-47]. */ + *toc_flags |= flags << 32; +} + +static int is_power_of_2(unsigned long x) +{ + return x && !(x & (x - 1)); +} + +static unsigned long get_image_align(char *arg) +{ + char *endptr; + unsigned long align; + + errno = 0; + align = strtoul(arg, &endptr, 0); + if (*endptr != '\0' || !is_power_of_2(align) || errno != 0) + log_errx("Invalid alignment: %s", arg); + + return align; +} + +static void parse_blob_opt(char *arg, uuid_t *uuid, char *filename, size_t len) +{ + char *p; + + for (p = strtok(arg, ","); p != NULL; p = strtok(NULL, ",")) { + if (strncmp(p, "uuid=", strlen("uuid=")) == 0) { + p += strlen("uuid="); + uuid_from_str(uuid, p); + } else if (strncmp(p, "file=", strlen("file=")) == 0) { + p += strlen("file="); + snprintf(filename, len, "%s", p); + } + } +} + +static int create_cmd(int argc, char *argv[]) +{ + struct option *opts = NULL; + size_t nr_opts = 0; + unsigned long long toc_flags = 0; + unsigned long align = 1; + + if (argc < 2) + create_usage(EXIT_FAILURE); + + opts = fill_common_opts(opts, &nr_opts, required_argument); + opts = add_opt(opts, &nr_opts, "plat-toc-flags", required_argument, + OPT_PLAT_TOC_FLAGS); + opts = add_opt(opts, &nr_opts, "align", required_argument, OPT_ALIGN); + opts = add_opt(opts, &nr_opts, "blob", required_argument, 'b'); + opts = add_opt(opts, &nr_opts, NULL, 0, 0); + + while (1) { + int c, opt_index = 0; + + c = getopt_long(argc, argv, "b:", opts, &opt_index); + if (c == -1) + break; + + switch (c) { + case OPT_TOC_ENTRY: { + image_desc_t *desc; + + desc = lookup_image_desc_from_opt(opts[opt_index].name); + set_image_desc_action(desc, DO_PACK, optarg); + break; + } + case OPT_PLAT_TOC_FLAGS: + parse_plat_toc_flags(optarg, &toc_flags); + break; + case OPT_ALIGN: + align = get_image_align(optarg); + break; + case 'b': { + char name[_UUID_STR_LEN + 1]; + char filename[PATH_MAX] = { 0 }; + uuid_t uuid = uuid_null; + image_desc_t *desc; + + parse_blob_opt(optarg, &uuid, + filename, sizeof(filename)); + + if (memcmp(&uuid, &uuid_null, sizeof(uuid_t)) == 0 || + filename[0] == '\0') + create_usage(EXIT_FAILURE); + + desc = lookup_image_desc_from_uuid(&uuid); + if (desc == NULL) { + uuid_to_str(name, sizeof(name), &uuid); + desc = new_image_desc(&uuid, name, "blob"); + add_image_desc(desc); + } + set_image_desc_action(desc, DO_PACK, filename); + break; + } + default: + create_usage(EXIT_FAILURE); + } + } + argc -= optind; + argv += optind; + free(opts); + + if (argc == 0) + create_usage(EXIT_SUCCESS); + + update_fip(); + + pack_images(argv[0], toc_flags, align); + return 0; +} + +static void create_usage(int exit_status) +{ + toc_entry_t *toc_entry = toc_entries; + + printf("fiptool create [opts] FIP_FILENAME\n"); + printf("\n"); + printf("Options:\n"); + printf(" --align \t\tEach image is aligned to (default: 1).\n"); + printf(" --blob uuid=...,file=...\tAdd an image with the given UUID pointed to by file.\n"); + printf(" --plat-toc-flags \t16-bit platform specific flag field occupying bits 32-47 in 64-bit ToC header.\n"); + printf("\n"); + printf("Specific images are packed with the following options:\n"); + for (; toc_entry->cmdline_name != NULL; toc_entry++) + printf(" --%-16s FILENAME\t%s\n", toc_entry->cmdline_name, + toc_entry->name); +#ifdef PLAT_DEF_FIP_UUID + toc_entry = plat_def_toc_entries; + for (; toc_entry->cmdline_name != NULL; toc_entry++) + printf(" --%-16s FILENAME\t%s\n", toc_entry->cmdline_name, + toc_entry->name); +#endif + exit(exit_status); +} + +static int update_cmd(int argc, char *argv[]) +{ + struct option *opts = NULL; + size_t nr_opts = 0; + char outfile[PATH_MAX] = { 0 }; + fip_toc_header_t toc_header = { 0 }; + unsigned long long toc_flags = 0; + unsigned long align = 1; + int pflag = 0; + + if (argc < 2) + update_usage(EXIT_FAILURE); + + opts = fill_common_opts(opts, &nr_opts, required_argument); + opts = add_opt(opts, &nr_opts, "align", required_argument, OPT_ALIGN); + opts = add_opt(opts, &nr_opts, "blob", required_argument, 'b'); + opts = add_opt(opts, &nr_opts, "out", required_argument, 'o'); + opts = add_opt(opts, &nr_opts, "plat-toc-flags", required_argument, + OPT_PLAT_TOC_FLAGS); + opts = add_opt(opts, &nr_opts, NULL, 0, 0); + + while (1) { + int c, opt_index = 0; + + c = getopt_long(argc, argv, "b:o:", opts, &opt_index); + if (c == -1) + break; + + switch (c) { + case OPT_TOC_ENTRY: { + image_desc_t *desc; + + desc = lookup_image_desc_from_opt(opts[opt_index].name); + set_image_desc_action(desc, DO_PACK, optarg); + break; + } + case OPT_PLAT_TOC_FLAGS: + parse_plat_toc_flags(optarg, &toc_flags); + pflag = 1; + break; + case 'b': { + char name[_UUID_STR_LEN + 1]; + char filename[PATH_MAX] = { 0 }; + uuid_t uuid = uuid_null; + image_desc_t *desc; + + parse_blob_opt(optarg, &uuid, + filename, sizeof(filename)); + + if (memcmp(&uuid, &uuid_null, sizeof(uuid_t)) == 0 || + filename[0] == '\0') + update_usage(EXIT_FAILURE); + + desc = lookup_image_desc_from_uuid(&uuid); + if (desc == NULL) { + uuid_to_str(name, sizeof(name), &uuid); + desc = new_image_desc(&uuid, name, "blob"); + add_image_desc(desc); + } + set_image_desc_action(desc, DO_PACK, filename); + break; + } + case OPT_ALIGN: + align = get_image_align(optarg); + break; + case 'o': + snprintf(outfile, sizeof(outfile), "%s", optarg); + break; + default: + update_usage(EXIT_FAILURE); + } + } + argc -= optind; + argv += optind; + free(opts); + + if (argc == 0) + update_usage(EXIT_SUCCESS); + + if (outfile[0] == '\0') + snprintf(outfile, sizeof(outfile), "%s", argv[0]); + + if (access(argv[0], F_OK) == 0) + parse_fip(argv[0], &toc_header); + + if (pflag) + toc_header.flags &= ~(0xffffULL << 32); + toc_flags = (toc_header.flags |= toc_flags); + + update_fip(); + + pack_images(outfile, toc_flags, align); + return 0; +} + +static void update_usage(int exit_status) +{ + toc_entry_t *toc_entry = toc_entries; + + printf("fiptool update [opts] FIP_FILENAME\n"); + printf("\n"); + printf("Options:\n"); + printf(" --align \t\tEach image is aligned to (default: 1).\n"); + printf(" --blob uuid=...,file=...\tAdd or update an image with the given UUID pointed to by file.\n"); + printf(" --out FIP_FILENAME\t\tSet an alternative output FIP file.\n"); + printf(" --plat-toc-flags \t16-bit platform specific flag field occupying bits 32-47 in 64-bit ToC header.\n"); + printf("\n"); + printf("Specific images are packed with the following options:\n"); + for (; toc_entry->cmdline_name != NULL; toc_entry++) + printf(" --%-16s FILENAME\t%s\n", toc_entry->cmdline_name, + toc_entry->name); +#ifdef PLAT_DEF_FIP_UUID + toc_entry = plat_def_toc_entries; + for (; toc_entry->cmdline_name != NULL; toc_entry++) + printf(" --%-16s FILENAME\t%s\n", toc_entry->cmdline_name, + toc_entry->name); +#endif + exit(exit_status); +} + +static int unpack_cmd(int argc, char *argv[]) +{ + struct option *opts = NULL; + size_t nr_opts = 0; + char outdir[PATH_MAX] = { 0 }; + image_desc_t *desc; + int fflag = 0; + int unpack_all = 1; + + if (argc < 2) + unpack_usage(EXIT_FAILURE); + + opts = fill_common_opts(opts, &nr_opts, required_argument); + opts = add_opt(opts, &nr_opts, "blob", required_argument, 'b'); + opts = add_opt(opts, &nr_opts, "force", no_argument, 'f'); + opts = add_opt(opts, &nr_opts, "out", required_argument, 'o'); + opts = add_opt(opts, &nr_opts, NULL, 0, 0); + + while (1) { + int c, opt_index = 0; + + c = getopt_long(argc, argv, "b:fo:", opts, &opt_index); + if (c == -1) + break; + + switch (c) { + case OPT_TOC_ENTRY: { + image_desc_t *desc; + + desc = lookup_image_desc_from_opt(opts[opt_index].name); + set_image_desc_action(desc, DO_UNPACK, optarg); + unpack_all = 0; + break; + } + case 'b': { + char name[_UUID_STR_LEN + 1]; + char filename[PATH_MAX] = { 0 }; + uuid_t uuid = uuid_null; + image_desc_t *desc; + + parse_blob_opt(optarg, &uuid, + filename, sizeof(filename)); + + if (memcmp(&uuid, &uuid_null, sizeof(uuid_t)) == 0 || + filename[0] == '\0') + unpack_usage(EXIT_FAILURE); + + desc = lookup_image_desc_from_uuid(&uuid); + if (desc == NULL) { + uuid_to_str(name, sizeof(name), &uuid); + desc = new_image_desc(&uuid, name, "blob"); + add_image_desc(desc); + } + set_image_desc_action(desc, DO_UNPACK, filename); + unpack_all = 0; + break; + } + case 'f': + fflag = 1; + break; + case 'o': + snprintf(outdir, sizeof(outdir), "%s", optarg); + break; + default: + unpack_usage(EXIT_FAILURE); + } + } + argc -= optind; + argv += optind; + free(opts); + + if (argc == 0) + unpack_usage(EXIT_SUCCESS); + + parse_fip(argv[0], NULL); + + if (outdir[0] != '\0') + if (chdir(outdir) == -1) + log_err("chdir %s", outdir); + + /* Unpack all specified images. */ + for (desc = image_desc_head; desc != NULL; desc = desc->next) { + char file[PATH_MAX]; + image_t *image = desc->image; + + if (!unpack_all && desc->action != DO_UNPACK) + continue; + + /* Build filename. */ + if (desc->action_arg == NULL) + snprintf(file, sizeof(file), "%s.bin", + desc->cmdline_name); + else + snprintf(file, sizeof(file), "%s", + desc->action_arg); + + if (image == NULL) { + if (!unpack_all) + log_warnx("%s does not exist in %s", + file, argv[0]); + continue; + } + + if (access(file, F_OK) != 0 || fflag) { + if (verbose) + log_dbgx("Unpacking %s", file); + write_image_to_file(image, file); + } else { + log_warnx("File %s already exists, use --force to overwrite it", + file); + } + } + + return 0; +} + +static void unpack_usage(int exit_status) +{ + toc_entry_t *toc_entry = toc_entries; + + printf("fiptool unpack [opts] FIP_FILENAME\n"); + printf("\n"); + printf("Options:\n"); + printf(" --blob uuid=...,file=...\tUnpack an image with the given UUID to file.\n"); + printf(" --force\t\t\tIf the output file already exists, use --force to overwrite it.\n"); + printf(" --out path\t\t\tSet the output directory path.\n"); + printf("\n"); + printf("Specific images are unpacked with the following options:\n"); + for (; toc_entry->cmdline_name != NULL; toc_entry++) + printf(" --%-16s FILENAME\t%s\n", toc_entry->cmdline_name, + toc_entry->name); +#ifdef PLAT_DEF_FIP_UUID + toc_entry = plat_def_toc_entries; + for (; toc_entry->cmdline_name != NULL; toc_entry++) + printf(" --%-16s FILENAME\t%s\n", toc_entry->cmdline_name, + toc_entry->name); +#endif + printf("\n"); + printf("If no options are provided, all images will be unpacked.\n"); + exit(exit_status); +} + +static int remove_cmd(int argc, char *argv[]) +{ + struct option *opts = NULL; + size_t nr_opts = 0; + char outfile[PATH_MAX] = { 0 }; + fip_toc_header_t toc_header; + image_desc_t *desc; + unsigned long align = 1; + int fflag = 0; + + if (argc < 2) + remove_usage(EXIT_FAILURE); + + opts = fill_common_opts(opts, &nr_opts, no_argument); + opts = add_opt(opts, &nr_opts, "align", required_argument, OPT_ALIGN); + opts = add_opt(opts, &nr_opts, "blob", required_argument, 'b'); + opts = add_opt(opts, &nr_opts, "force", no_argument, 'f'); + opts = add_opt(opts, &nr_opts, "out", required_argument, 'o'); + opts = add_opt(opts, &nr_opts, NULL, 0, 0); + + while (1) { + int c, opt_index = 0; + + c = getopt_long(argc, argv, "b:fo:", opts, &opt_index); + if (c == -1) + break; + + switch (c) { + case OPT_TOC_ENTRY: { + image_desc_t *desc; + + desc = lookup_image_desc_from_opt(opts[opt_index].name); + set_image_desc_action(desc, DO_REMOVE, NULL); + break; + } + case OPT_ALIGN: + align = get_image_align(optarg); + break; + case 'b': { + char name[_UUID_STR_LEN + 1], filename[PATH_MAX]; + uuid_t uuid = uuid_null; + image_desc_t *desc; + + parse_blob_opt(optarg, &uuid, + filename, sizeof(filename)); + + if (memcmp(&uuid, &uuid_null, sizeof(uuid_t)) == 0) + remove_usage(EXIT_FAILURE); + + desc = lookup_image_desc_from_uuid(&uuid); + if (desc == NULL) { + uuid_to_str(name, sizeof(name), &uuid); + desc = new_image_desc(&uuid, name, "blob"); + add_image_desc(desc); + } + set_image_desc_action(desc, DO_REMOVE, NULL); + break; + } + case 'f': + fflag = 1; + break; + case 'o': + snprintf(outfile, sizeof(outfile), "%s", optarg); + break; + default: + remove_usage(EXIT_FAILURE); + } + } + argc -= optind; + argv += optind; + free(opts); + + if (argc == 0) + remove_usage(EXIT_SUCCESS); + + if (outfile[0] != '\0' && access(outfile, F_OK) == 0 && !fflag) + log_errx("File %s already exists, use --force to overwrite it", + outfile); + + if (outfile[0] == '\0') + snprintf(outfile, sizeof(outfile), "%s", argv[0]); + + parse_fip(argv[0], &toc_header); + + for (desc = image_desc_head; desc != NULL; desc = desc->next) { + if (desc->action != DO_REMOVE) + continue; + + if (desc->image != NULL) { + if (verbose) + log_dbgx("Removing %s", + desc->cmdline_name); + free(desc->image); + desc->image = NULL; + } else { + log_warnx("%s does not exist in %s", + desc->cmdline_name, argv[0]); + } + } + + pack_images(outfile, toc_header.flags, align); + return 0; +} + +static void remove_usage(int exit_status) +{ + toc_entry_t *toc_entry = toc_entries; + + printf("fiptool remove [opts] FIP_FILENAME\n"); + printf("\n"); + printf("Options:\n"); + printf(" --align \tEach image is aligned to (default: 1).\n"); + printf(" --blob uuid=...\tRemove an image with the given UUID.\n"); + printf(" --force\t\tIf the output FIP file already exists, use --force to overwrite it.\n"); + printf(" --out FIP_FILENAME\tSet an alternative output FIP file.\n"); + printf("\n"); + printf("Specific images are removed with the following options:\n"); + for (; toc_entry->cmdline_name != NULL; toc_entry++) + printf(" --%-16s\t%s\n", toc_entry->cmdline_name, + toc_entry->name); +#ifdef PLAT_DEF_FIP_UUID + toc_entry = plat_def_toc_entries; + for (; toc_entry->cmdline_name != NULL; toc_entry++) + printf(" --%-16s\t%s\n", toc_entry->cmdline_name, + toc_entry->name); +#endif + exit(exit_status); +} + +static int version_cmd(int argc, char *argv[]) +{ +#ifdef VERSION + puts(VERSION); +#else + /* If built from fiptool directory, VERSION is not set. */ + puts("Unknown version"); +#endif + return 0; +} + +static void version_usage(int exit_status) +{ + printf("fiptool version\n"); + exit(exit_status); +} + +static int help_cmd(int argc, char *argv[]) +{ + int i; + + if (argc < 2) + usage(); + argc--, argv++; + + for (i = 0; i < NELEM(cmds); i++) { + if (strcmp(cmds[i].name, argv[0]) == 0 && + cmds[i].usage != NULL) + cmds[i].usage(EXIT_SUCCESS); + } + if (i == NELEM(cmds)) + printf("No help for subcommand '%s'\n", argv[0]); + return 0; +} + +static void usage(void) +{ + printf("usage: fiptool [--verbose] []\n"); + printf("Global options supported:\n"); + printf(" --verbose\tEnable verbose output for all commands.\n"); + printf("\n"); + printf("Commands supported:\n"); + printf(" info\t\tList images contained in FIP.\n"); + printf(" create\tCreate a new FIP with the given images.\n"); + printf(" update\tUpdate an existing FIP with the given images.\n"); + printf(" unpack\tUnpack images from FIP.\n"); + printf(" remove\tRemove images from FIP.\n"); + printf(" version\tShow fiptool version.\n"); + printf(" help\t\tShow help for given command.\n"); + exit(EXIT_SUCCESS); +} + +int main(int argc, char *argv[]) +{ + int i, ret = 0; + + while (1) { + int c, opt_index = 0; + static struct option opts[] = { + { "verbose", no_argument, NULL, 'v' }, + { NULL, no_argument, NULL, 0 } + }; + + /* + * Set POSIX mode so getopt stops at the first non-option + * which is the subcommand. + */ + c = getopt_long(argc, argv, "+v", opts, &opt_index); + if (c == -1) + break; + + switch (c) { + case 'v': + verbose = 1; + break; + default: + usage(); + } + } + argc -= optind; + argv += optind; + /* Reset optind for subsequent getopt processing. */ + optind = 0; + + if (argc == 0) + usage(); + + fill_image_descs(); + for (i = 0; i < NELEM(cmds); i++) { + if (strcmp(cmds[i].name, argv[0]) == 0) { + ret = cmds[i].handler(argc, argv); + break; + } + } + if (i == NELEM(cmds)) + usage(); + free_image_descs(); + return ret; +} diff --git a/drivers/rz/ipl/rza/tools/fiptool/fiptool.h b/drivers/rz/ipl/rza/tools/fiptool/fiptool.h new file mode 100644 index 00000000..88c4a7ed --- /dev/null +++ b/drivers/rz/ipl/rza/tools/fiptool/fiptool.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef FIPTOOL_H +#define FIPTOOL_H + +#include +#include + +#include +#include + +#include "fiptool_platform.h" + +#define NELEM(x) (sizeof (x) / sizeof *(x)) + +enum { + DO_UNSPEC = 0, + DO_PACK = 1, + DO_UNPACK = 2, + DO_REMOVE = 3 +}; + +enum { + LOG_DBG, + LOG_WARN, + LOG_ERR +}; + +typedef struct image_desc { + uuid_t uuid; + char *name; + char *cmdline_name; + int action; + char *action_arg; + struct image *image; + struct image_desc *next; +} image_desc_t; + +typedef struct image { + struct fip_toc_entry toc_e; + void *buffer; +} image_t; + +typedef struct cmd { + char *name; + int (*handler)(int, char **); + void (*usage)(int); +} cmd_t; + +#endif /* FIPTOOL_H */ diff --git a/drivers/rz/ipl/rza/tools/fiptool/fiptool_platform.h b/drivers/rz/ipl/rza/tools/fiptool/fiptool_platform.h new file mode 100644 index 00000000..9bfa298b --- /dev/null +++ b/drivers/rz/ipl/rza/tools/fiptool/fiptool_platform.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +/* + * Build platform specific handling. + * This allows for builds on non-Posix platforms + * e.g. Visual Studio on Windows + */ + +#ifndef FIPTOOL_PLATFORM_H +#define FIPTOOL_PLATFORM_H + +#ifndef _MSC_VER + +/* Not Visual Studio, so include Posix Headers. */ +# include +# include +# include + +# define BLD_PLAT_STAT stat + +#else + +/* Visual Studio. */ +# include "win_posix.h" + +#endif + +#endif /* FIPTOOL_PLATFORM_H */ diff --git a/drivers/rz/ipl/rza/tools/fiptool/tbbr_config.c b/drivers/rz/ipl/rza/tools/fiptool/tbbr_config.c new file mode 100644 index 00000000..c1e5217f --- /dev/null +++ b/drivers/rz/ipl/rza/tools/fiptool/tbbr_config.c @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include "tbbr_config.h" + +/* The images used depends on the platform. */ +toc_entry_t toc_entries[] = { + { + .name = "SCP Firmware Updater Configuration FWU SCP_BL2U", + .uuid = UUID_TRUSTED_UPDATE_FIRMWARE_SCP_BL2U, + .cmdline_name = "scp-fwu-cfg" + }, + { + .name = "AP Firmware Updater Configuration BL2U", + .uuid = UUID_TRUSTED_UPDATE_FIRMWARE_BL2U, + .cmdline_name = "ap-fwu-cfg" + }, + { + .name = "Firmware Updater NS_BL2U", + .uuid = UUID_TRUSTED_UPDATE_FIRMWARE_NS_BL2U, + .cmdline_name = "fwu" + }, + { + .name = "Non-Trusted Firmware Updater certificate", + .uuid = UUID_TRUSTED_FWU_CERT, + .cmdline_name = "fwu-cert" + }, + { + .name = "Trusted Boot Firmware BL2", + .uuid = UUID_TRUSTED_BOOT_FIRMWARE_BL2, + .cmdline_name = "tb-fw" + }, + { + .name = "SCP Firmware SCP_BL2", + .uuid = UUID_SCP_FIRMWARE_SCP_BL2, + .cmdline_name = "scp-fw" + }, + { + .name = "EL3 Runtime Firmware BL31", + .uuid = UUID_EL3_RUNTIME_FIRMWARE_BL31, + .cmdline_name = "soc-fw" + }, + { + .name = "Secure Payload BL32 (Trusted OS)", + .uuid = UUID_SECURE_PAYLOAD_BL32, + .cmdline_name = "tos-fw" + }, + { + .name = "Secure Payload BL32 Extra1 (Trusted OS Extra1)", + .uuid = UUID_SECURE_PAYLOAD_BL32_EXTRA1, + .cmdline_name = "tos-fw-extra1" + }, + { + .name = "Secure Payload BL32 Extra2 (Trusted OS Extra2)", + .uuid = UUID_SECURE_PAYLOAD_BL32_EXTRA2, + .cmdline_name = "tos-fw-extra2" + }, + { + .name = "Non-Trusted Firmware BL33", + .uuid = UUID_NON_TRUSTED_FIRMWARE_BL33, + .cmdline_name = "nt-fw" + }, + /* Dynamic Configs */ + { + .name = "FW_CONFIG", + .uuid = UUID_FW_CONFIG, + .cmdline_name = "fw-config" + }, + { + .name = "HW_CONFIG", + .uuid = UUID_HW_CONFIG, + .cmdline_name = "hw-config" + }, + { + .name = "TB_FW_CONFIG", + .uuid = UUID_TB_FW_CONFIG, + .cmdline_name = "tb-fw-config" + }, + { + .name = "SOC_FW_CONFIG", + .uuid = UUID_SOC_FW_CONFIG, + .cmdline_name = "soc-fw-config" + }, + { + .name = "TOS_FW_CONFIG", + .uuid = UUID_TOS_FW_CONFIG, + .cmdline_name = "tos-fw-config" + }, + { + .name = "NT_FW_CONFIG", + .uuid = UUID_NT_FW_CONFIG, + .cmdline_name = "nt-fw-config" + }, + /* Key Certificates */ + { + .name = "Root Of Trust key certificate", + .uuid = UUID_ROT_KEY_CERT, + .cmdline_name = "rot-cert" + }, + { + .name = "Trusted key certificate", + .uuid = UUID_TRUSTED_KEY_CERT, + .cmdline_name = "trusted-key-cert" + }, + { + .name = "SCP Firmware key certificate", + .uuid = UUID_SCP_FW_KEY_CERT, + .cmdline_name = "scp-fw-key-cert" + }, + { + .name = "SoC Firmware key certificate", + .uuid = UUID_SOC_FW_KEY_CERT, + .cmdline_name = "soc-fw-key-cert" + }, + { + .name = "Trusted OS Firmware key certificate", + .uuid = UUID_TRUSTED_OS_FW_KEY_CERT, + .cmdline_name = "tos-fw-key-cert" + }, + { + .name = "Non-Trusted Firmware key certificate", + .uuid = UUID_NON_TRUSTED_FW_KEY_CERT, + .cmdline_name = "nt-fw-key-cert" + }, + + /* Content certificates */ + { + .name = "Trusted Boot Firmware BL2 certificate", + .uuid = UUID_TRUSTED_BOOT_FW_CERT, + .cmdline_name = "tb-fw-cert" + }, + { + .name = "SCP Firmware content certificate", + .uuid = UUID_SCP_FW_CONTENT_CERT, + .cmdline_name = "scp-fw-cert" + }, + { + .name = "SoC Firmware content certificate", + .uuid = UUID_SOC_FW_CONTENT_CERT, + .cmdline_name = "soc-fw-cert" + }, + { + .name = "Trusted OS Firmware content certificate", + .uuid = UUID_TRUSTED_OS_FW_CONTENT_CERT, + .cmdline_name = "tos-fw-cert" + }, + { + .name = "Non-Trusted Firmware content certificate", + .uuid = UUID_NON_TRUSTED_FW_CONTENT_CERT, + .cmdline_name = "nt-fw-cert" + }, + { + .name = "SiP owned Secure Partition content certificate", + .uuid = UUID_SIP_SECURE_PARTITION_CONTENT_CERT, + .cmdline_name = "sip-sp-cert" + }, + { + .name = "Platform owned Secure Partition content certificate", + .uuid = UUID_PLAT_SECURE_PARTITION_CONTENT_CERT, + .cmdline_name = "plat-sp-cert" + }, + { + .name = NULL, + .uuid = { {0} }, + .cmdline_name = NULL, + } +}; diff --git a/drivers/rz/ipl/rza/tools/fiptool/tbbr_config.h b/drivers/rz/ipl/rza/tools/fiptool/tbbr_config.h new file mode 100644 index 00000000..b926ff0a --- /dev/null +++ b/drivers/rz/ipl/rza/tools/fiptool/tbbr_config.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TBBR_CONFIG_H +#define TBBR_CONFIG_H + +#include + +#include + +#define TOC_HEADER_SERIAL_NUMBER 0x12345678 + +typedef struct toc_entry { + char *name; + uuid_t uuid; + char *cmdline_name; +} toc_entry_t; + +extern toc_entry_t toc_entries[]; + +#ifdef PLAT_DEF_FIP_UUID +extern toc_entry_t plat_def_toc_entries[]; +#endif + +#endif /* TBBR_CONFIG_H */ diff --git a/drivers/rz/ipl/rza/tools/fiptool/win_posix.c b/drivers/rz/ipl/rza/tools/fiptool/win_posix.c new file mode 100644 index 00000000..33b44d4c --- /dev/null +++ b/drivers/rz/ipl/rza/tools/fiptool/win_posix.c @@ -0,0 +1,318 @@ +/* + * Copyright (c) 2017 - 2020, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include "win_posix.h" + +/* + * This variable is set by getopt to the index of the next element of the + * argv array to be processed. Once getopt has found all of the option + * arguments, you can use this variable to determine where the remaining + * non-option arguments begin. The initial value of this variable is 1. + */ +int optind = 1; + +/* + * If the value of this variable is nonzero, then getopt prints an error + * message to the standard error stream if it encounters an unknown option + * default character or an option with a missing required argument. + * If you set this variable to zero, getopt does not print any messages, + * but it still returns the character ? to indicate an error. + */ +const int opterr; /* = 0; */ +/* const because we do not implement error printing.*/ +/* Not initialised to conform with the coding standard. */ + +/* + * When getopt encounters an unknown option character or an option with a + * missing required argument, it stores that option character in this + * variable. + */ +int optopt; /* = 0; */ + +/* + * This variable is set by getopt to point at the value of the option + * argument, for those options that accept arguments. + */ +char *optarg; /* = 0; */ + +enum return_flags { + RET_ERROR = -1, + RET_END_OPT_LIST = -1, + RET_NO_PARAM = '?', + RET_NO_PARAM2 = ':', + RET_UNKNOWN_OPT = '?' +}; + +/* + * Common initialisation on entry. + */ +static +void getopt_init(void) +{ + optarg = (char *)0; + optopt = 0; + /* optind may be zero with some POSIX uses. + * For our purposes we just change it to 1. + */ + if (optind == 0) + optind = 1; +} + +/* + * Common handling for a single letter option. + */ +static +int getopt_1char(int argc, + char *const argv[], + const char *const opstring, + const int optchar) +{ + size_t nlen = (opstring == 0) ? 0 : strlen(opstring); + size_t loptn; + + for (loptn = 0; loptn < nlen; loptn++) { + if (optchar == opstring[loptn]) { + if (opstring[loptn + 1] == ':') { + /* Option has argument */ + if (optind < argc) { + /* Found argument. */ + assert(argv != 0); + optind++; + optarg = argv[optind++]; + return optchar; + } + /* Missing argument. */ + if (opstring[loptn + 2] == ':') { + /* OK if optional "x::". */ + optind++; + return optchar; + } + /* Actual missing value. */ + optopt = optchar; + return ((opstring[0] == ':') + ? RET_NO_PARAM2 + : RET_NO_PARAM); + } + /* No argument, just return option char */ + optind++; + return optchar; + } + } + /* + * If getopt finds an option character in argv that was not included in + * options, ... it returns '?' and sets the external variable optopt to + * the actual option character. + */ + optopt = optchar; + return RET_UNKNOWN_OPT; +} + +int getopt(int argc, + char *argv[], + char *opstring) +{ + int result = RET_END_OPT_LIST; + size_t argn = 0; + size_t nlen = strlen(opstring); + + getopt_init(); + /* If we have an argument left to play with */ + if ((argc > optind) && (argv != 0)) { + const char *arg = (const char *)argv[optind]; + + if ((arg != 0) && (arg[0] == '-')) + result = getopt_1char(argc, argv, opstring, arg[1]); + } + + return result; +} + +/* + * Match an argument value against an option name. + * Note that we only match over the shorter length of the pair, to allow + * for abbreviation or say --match=value + * Long option names may be abbreviated if the abbreviation is unique or an + * exact match for some defined option. This function does not check that the + * abbreviations are unique and should be handled by the caller. + * A long option may take a parameter, of the form --opt=param or --opt param. +*/ +static +int optmatch(const char *argval, const char *optname) +{ + int result = 0; + + while ((result == 0) && (*optname != 0) && (*argval != 0)) + result = (*argval++) - (*optname++); + return result; +} + +/* Handling for a single long option. */ +static +int getopt_1long(const int argc, + char *const argv[], + const struct option *const longopts, + const char *const optname, + int *const indexptr) +{ + int result = RET_UNKNOWN_OPT; + size_t loptn = 0; + bool match_found = false; + + /* + * Long option names may be abbreviated if the abbreviation + * is unique or an exact match for some defined option. + * To handle this: + * - First search for an exact match. + * - If exact match was not found search for a abbreviated match. + * By doing this an incorrect option selection can be avoided. + */ + + /* 1. Search for an exact match. */ + while (longopts[loptn].name != NULL) { + if (strcmp(optname, longopts[loptn].name) == 0) { + match_found = true; + break; + } + ++loptn; + } + + /* 2. If exact match was not found search for a abbreviated match. */ + if (!match_found) { + loptn = 0; + while (longopts[loptn].name != NULL) { + if (optmatch(optname, longopts[loptn].name) == 0) { + match_found = true; + break; + } + ++loptn; + } + } + + if (match_found) { + /* We found a match. */ + result = longopts[loptn].val; + if (indexptr != 0) { + *indexptr = loptn; + } + switch (longopts[loptn].has_arg) { + case required_argument: + if ((optind + 1) >= argc) { + /* Missing argument. */ + optopt = result; + return RET_NO_PARAM; + } + /* Fallthrough to get option value. */ + + case optional_argument: + if ((argc - optind) > 0) { + /* Found argument. */ + optarg = argv[++optind]; + } + /* Fallthrough to handle flag. */ + + case no_argument: + optind++; + if (longopts[loptn].flag != 0) { + *longopts[loptn].flag = result; + result = 0; + } + break; + + } + return result; + } + + /* + * If getopt finds an option character in argv that was not included + * in options, ... it returns '?' and sets the external variable + * optopt to the actual option character. + */ + return RET_UNKNOWN_OPT; +} + +/* + * getopt_long gets the next option argument from the argument list + * specified by the argv and argc arguments. Options may be either short + * (single letter) as for getopt, or longer names (preceded by --). + */ +int getopt_long(int argc, + char *argv[], + const char *shortopts, + const struct option *longopts, + int *indexptr) +{ + int result = RET_END_OPT_LIST; + + getopt_init(); + /* If we have an argument left to play with */ + if ((argc > optind) && (argv != 0)) { + const char *arg = argv[optind]; + + if ((arg != 0) && (arg[0] == '-')) { + if (arg[1] == '-') { + /* Looks like a long option. */ + result = getopt_1long(argc, + argv, + longopts, + &arg[2], + indexptr); + } else { + result = getopt_1char(argc, + argv, + shortopts, + arg[1]); + } + } + } + return result; +} + +/* + * getopt_long_only gets the next option argument from the argument list + * specified by the argv and argc arguments. Options may be either short + * or long as for getopt_long, but the long names may have a single '-' + * prefix too. + */ +int getopt_long_only(int argc, + char *argv[], + const char *shortopts, + const struct option *longopts, + int *indexptr) +{ + int result = RET_END_OPT_LIST; + + getopt_init(); + /* If we have an argument left to play with */ + if ((argc > optind) && (argv != 0)) { + const char *arg = argv[optind]; + + if ((arg != 0) && (arg[0] == '-')) { + if (arg[1] == '-') { + /* Looks like a long option. */ + result = getopt_1long(argc, + argv, + longopts, + &arg[2], + indexptr); + } else { + result = getopt_1long(argc, + argv, + longopts, + &arg[1], + indexptr); + if (result == RET_UNKNOWN_OPT) { + result = getopt_1char(argc, + argv, + shortopts, + arg[1]); + } + } + } + } + return result; +} diff --git a/drivers/rz/ipl/rza/tools/fiptool/win_posix.h b/drivers/rz/ipl/rza/tools/fiptool/win_posix.h new file mode 100644 index 00000000..6f0d8e6b --- /dev/null +++ b/drivers/rz/ipl/rza/tools/fiptool/win_posix.h @@ -0,0 +1,188 @@ +/* + * Copyright (c) 2017-2020, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef WIN_POSIX_H +#define WIN_POSIX_H + +#define _CRT_SECURE_NO_WARNINGS + +#include +#include +#include +#include +#include + +#include +#include + +#include "uuid.h" + +/* Derive or provide Windows equivalents of Posix/GCC/Unix stuff. */ +#ifndef PATH_MAX +# ifdef MAX_PATH +# define PATH_MAX MAX_PATH +# else +# ifdef _MAX_PATH +# define MAX_PATH _MAX_PATH +# define PATH_MAX _MAX_PATH +# else +# define PATH_MAX 260 +# endif +# endif +#endif + +#ifndef _CRT_SECURE_NO_WARNINGS +# define _CRT_SECURE_NO_WARNINGS 1 +#endif + +/* + * Platform specific names. + * + * Visual Studio deprecates a number of POSIX functions and only provides + * ISO C++ compliant alternatives (distinguished by their '_' prefix). + * These macros help provide a stopgap for that. + */ + +/* fileno cannot be an inline function, because _fileno is a macro. */ +#define fileno(fileptr) _fileno(fileptr) + +/* _fstat uses the _stat structure, not stat. */ +#define BLD_PLAT_STAT _stat + +/* Define flag values for _access. */ +#define F_OK 0 + + +/* getopt implementation for Windows: Data. */ + +/* Legitimate values for option.has_arg. */ +enum has_arg_values { + no_argument, /* No argument value required */ + required_argument, /* value must be specified. */ + optional_argument /* value may be specified. */ +}; + +/* Long option table entry for get_opt_long. */ +struct option { + /* The name of the option. */ + const char *name; + + /* + * Indicates whether the option takes an argument. + * Possible values: see has_arg_values above. + */ + int has_arg; + + /* If not null, when option present, *flag is set to val. */ + int *flag; + + /* + * The value associated with this option to return + * (and save in *flag when not null) + */ + int val; +}; + +/* + * This variable is set by getopt to point at the value of the option + * argument, for those options that accept arguments. + */ +extern char *optarg; + +/* + * When this variable is not zero, getopt emits an error message to stderr + * if it encounters an unspecified option, or a missing argument. + * Otherwise no message is reported. + */ +extern const int opterr; /* const as NOT used in this implementation. */ + +/* + * This variable is set by getopt to the index of the next element of the + * argv array to be processed. Once getopt has found all of the option + * arguments, you can use this variable to determine where the remaining + * non-option arguments begin. The initial value of this variable is 1. + */ +extern int optind; + +/* + * When getopt encounters an unknown option character or an option with a + * missing required argument, it stores that option character in this + * variable. + */ +extern int optopt; + + +/* + * Platform specific names. + * + * Visual Studio deprecates a number of POSIX functions and only provides + * ISO C++ compliant alternatives (distinguished by their '_' prefix). + * These inline functions provide a stopgap for that. + */ + +inline int access(const char *path, int mode) +{ + return _access(path, mode); +} + +inline int chdir(const char *s) +{ + return _chdir(s); +} + +inline int fstat(int fd, struct _stat *buffer) +{ + return _fstat(fd, buffer); +} + +inline char *strdup(const char *s) +{ + return _strdup(s); +} + +/* + * getopt implementation for Windows: Functions. + * + * Windows does not have the getopt family of functions, as it normally + * uses '/' instead of '-' as the command line option delimiter. + * These functions provide a Windows version that uses '-', which precludes + * using '-' as the intial letter of a program argument. + * This is not seen as a problem in the specific instance of fiptool, + * and enables existing makefiles to work on a Windows build environment. + */ + +/* + * The getopt function gets the next option argument from the argument list + * specified by the argv and argc arguments. + */ +int getopt(int argc, + char *argv[], + char *options); + +/* + * getopt_long gets the next option argument from the argument list + * specified by the argv and argc arguments. Options may be either short + * (single letter) as for getopt, or longer names (preceded by --). + */ +int getopt_long(int argc, + char *argv[], + const char *shortopts, + const struct option *longopts, + int *indexptr); + +/* + * getopt_long_only gets the next option argument from the argument list + * specified by the argv and argc arguments. Options may be either short + * or long as for getopt_long, but the long names may have a single '-' + * prefix, too. + */ +int getopt_long_only(int argc, + char *argv[], + const char *shortopts, + const struct option *longopts, + int *indexptr); + +#endif /* WIN_POSIX_H */